#include "views/gamelist/VideoGameListView.h" #include "views/ViewController.h" #include "Window.h" #include "animations/LambdaAnimation.h" #include #include VideoGameListView::VideoGameListView(Window* window, FileData* root) : BasicGameListView(window, root), mDescContainer(window), mDescription(window), mMarquee(window), mImage(window), mVideo(window), mVideoPlaying(false), mLblRating(window), mLblReleaseDate(window), mLblDeveloper(window), mLblPublisher(window), mLblGenre(window), mLblPlayers(window), mLblLastPlayed(window), mLblPlayCount(window), mRating(window), mReleaseDate(window), mDeveloper(window), mPublisher(window), mGenre(window), mPlayers(window), mLastPlayed(window), mPlayCount(window) { const float padding = 0.01f; mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y()); mList.setSize(mSize.x() * (0.50f - padding), mList.getSize().y()); mList.setAlignment(TextListComponent::ALIGN_LEFT); mList.setCursorChangedCallback([&](const CursorState& state) { updateInfoPanel(); }); // Marquee mMarquee.setOrigin(0.5f, 0.5f); mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f); mMarquee.setMaxSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.18f); addChild(&mMarquee); // Image mImage.setOrigin(0.5f, 0.5f); // Default to off the screen mImage.setPosition(2.0f, 2.0f); mImage.setMaxSize(1.0f, 1.0f); addChild(&mImage); // video mVideo.setOrigin(0.5f, 0.5f); mVideo.setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f); mVideo.setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f); addChild(&mVideo); // We want the video to be in front of the background but behind any 'extra' images for (std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) { if (*it == &mThemeExtras) { mChildren.insert(it, &mVideo); mChildren.pop_back(); break; } } // metadata labels + values mLblRating.setText("Rating: "); addChild(&mLblRating); addChild(&mRating); mLblReleaseDate.setText("Released: "); addChild(&mLblReleaseDate); addChild(&mReleaseDate); mLblDeveloper.setText("Developer: "); addChild(&mLblDeveloper); addChild(&mDeveloper); mLblPublisher.setText("Publisher: "); addChild(&mLblPublisher); addChild(&mPublisher); mLblGenre.setText("Genre: "); addChild(&mLblGenre); addChild(&mGenre); mLblPlayers.setText("Players: "); addChild(&mLblPlayers); addChild(&mPlayers); mLblLastPlayed.setText("Last played: "); addChild(&mLblLastPlayed); mLastPlayed.setDisplayMode(DateTimeComponent::DISP_RELATIVE_TO_NOW); addChild(&mLastPlayed); mLblPlayCount.setText("Times played: "); addChild(&mLblPlayCount); addChild(&mPlayCount); mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y()); mDescContainer.setAutoScroll(true); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); mDescription.setSize(mDescContainer.getSize().x(), 0); mDescContainer.addChild(&mDescription); initMDLabels(); initMDValues(); } VideoGameListView::~VideoGameListView() { } void VideoGameListView::onThemeChanged(const std::shared_ptr& theme) { BasicGameListView::onThemeChanged(theme); using namespace ThemeFlags; mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE); mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE); mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY); initMDLabels(); std::vector labels = getMDLabels(); assert(labels.size() == 8); const char* lblElements[8] = { "md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher", "md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount" }; for(unsigned int i = 0; i < labels.size(); i++) { labels[i]->applyTheme(theme, getName(), lblElements[i], ALL); } initMDValues(); std::vector values = getMDValues(); assert(values.size() == 8); const char* valElements[8] = { "md_rating", "md_releasedate", "md_developer", "md_publisher", "md_genre", "md_players", "md_lastplayed", "md_playcount" }; for(unsigned int i = 0; i < values.size(); i++) { values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); } mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE); mDescription.setSize(mDescContainer.getSize().x(), 0); mDescription.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT)); } void VideoGameListView::initMDLabels() { using namespace Eigen; std::vector components = getMDLabels(); const unsigned int colCount = 2; const unsigned int rowCount = components.size() / 2; Vector3f start(mSize.x() * 0.01f, mSize.y() * 0.625f, 0.0f); const float colSize = (mSize.x() * 0.48f) / colCount; const float rowPadding = 0.01f * mSize.y(); for(unsigned int i = 0; i < components.size(); i++) { const unsigned int row = i % rowCount; Vector3f pos(0.0f, 0.0f, 0.0f); if(row == 0) { pos = start + Vector3f(colSize * (i / rowCount), 0, 0); }else{ // work from the last component GuiComponent* lc = components[i-1]; pos = lc->getPosition() + Vector3f(0, lc->getSize().y() + rowPadding, 0); } components[i]->setFont(Font::get(FONT_SIZE_SMALL)); components[i]->setPosition(pos); } } void VideoGameListView::initMDValues() { using namespace Eigen; std::vector labels = getMDLabels(); std::vector values = getMDValues(); std::shared_ptr defaultFont = Font::get(FONT_SIZE_SMALL); mRating.setSize(defaultFont->getHeight() * 5.0f, (float)defaultFont->getHeight()); mReleaseDate.setFont(defaultFont); mDeveloper.setFont(defaultFont); mPublisher.setFont(defaultFont); mGenre.setFont(defaultFont); mPlayers.setFont(defaultFont); mLastPlayed.setFont(defaultFont); mPlayCount.setFont(defaultFont); float bottom = 0.0f; const float colSize = (mSize.x() * 0.48f) / 2; for(unsigned int i = 0; i < labels.size(); i++) { const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2; values[i]->setPosition(labels[i]->getPosition() + Vector3f(labels[i]->getSize().x(), heightDiff, 0)); values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y()); float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); if(testBot > bottom) bottom = testBot; } mDescContainer.setPosition(mDescContainer.getPosition().x(), bottom + mSize.y() * 0.01f); mDescContainer.setSize(mDescContainer.getSize().x(), mSize.y() - mDescContainer.getPosition().y()); } void VideoGameListView::updateInfoPanel() { FileData* file = (mList.size() == 0 || mList.isScrolling()) ? NULL : mList.getSelected(); bool fadingOut; if(file == NULL) { mVideo.setVideo(""); mVideo.setImage(""); mVideoPlaying = false; //mMarquee.setImage(""); //mDescription.setText(""); fadingOut = true; }else{ std::string video_path; std::string marquee_path; std::string thumbnail_path; video_path = file->getVideoPath(); marquee_path = file->getMarqueePath(); thumbnail_path = file->getThumbnailPath(); if (!video_path.empty() && (video_path[0] == '~')) { video_path.erase(0, 1); video_path.insert(0, getHomePath()); } if (!marquee_path.empty() && (marquee_path[0] == '~')) { marquee_path.erase(0, 1); marquee_path.insert(0, getHomePath()); } if (!thumbnail_path.empty() && (thumbnail_path[0] == '~')) { thumbnail_path.erase(0, 1); thumbnail_path.insert(0, getHomePath()); } if (!mVideo.setVideo(video_path)) mVideo.setDefaultVideo(); mVideoPlaying = true; mVideo.setImage(thumbnail_path); mMarquee.setImage(marquee_path); mImage.setImage(thumbnail_path); mDescription.setText(file->metadata.get("desc")); mDescContainer.reset(); if(file->getType() == GAME) { mRating.setValue(file->metadata.get("rating")); mReleaseDate.setValue(file->metadata.get("releasedate")); mDeveloper.setValue(file->metadata.get("developer")); mPublisher.setValue(file->metadata.get("publisher")); mGenre.setValue(file->metadata.get("genre")); mPlayers.setValue(file->metadata.get("players")); mLastPlayed.setValue(file->metadata.get("lastplayed")); mPlayCount.setValue(file->metadata.get("playcount")); } fadingOut = false; } std::vector comps = getMDValues(); comps.push_back(&mMarquee); comps.push_back(&mVideo); comps.push_back(&mDescription); comps.push_back(&mImage); std::vector labels = getMDLabels(); comps.insert(comps.end(), labels.begin(), labels.end()); for(auto it = comps.begin(); it != comps.end(); it++) { GuiComponent* comp = *it; // an animation is playing // then animate if reverse != fadingOut // an animation is not playing // then animate if opacity != our target opacity if((comp->isAnimationPlaying(0) && comp->isAnimationReversed(0) != fadingOut) || (!comp->isAnimationPlaying(0) && comp->getOpacity() != (fadingOut ? 0 : 255))) { auto func = [comp](float t) { comp->setOpacity((unsigned char)(lerp(0.0f, 1.0f, t)*255)); }; comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut); } } } void VideoGameListView::launch(FileData* game) { Eigen::Vector3f target(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f, 0); if(mMarquee.hasImage()) target << mVideo.getCenter().x(), mVideo.getCenter().y(), 0; ViewController::get()->launch(game, target); } std::vector VideoGameListView::getMDLabels() { std::vector ret; ret.push_back(&mLblRating); ret.push_back(&mLblReleaseDate); ret.push_back(&mLblDeveloper); ret.push_back(&mLblPublisher); ret.push_back(&mLblGenre); ret.push_back(&mLblPlayers); ret.push_back(&mLblLastPlayed); ret.push_back(&mLblPlayCount); return ret; } std::vector VideoGameListView::getMDValues() { std::vector ret; ret.push_back(&mRating); ret.push_back(&mReleaseDate); ret.push_back(&mDeveloper); ret.push_back(&mPublisher); ret.push_back(&mGenre); ret.push_back(&mPlayers); ret.push_back(&mLastPlayed); ret.push_back(&mPlayCount); return ret; } void VideoGameListView::update(int deltaTime) { BasicGameListView::update(deltaTime); mVideo.update(deltaTime); } void VideoGameListView::onShow() { GuiComponent::onShow(); updateInfoPanel(); }