mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Rewrote the gamelist logic for the new theme engine.
Also split out all legacy mode (backward compatibility) functions to a separate header file.
This commit is contained in:
parent
a147c87cea
commit
62d5c1e656
|
@ -50,6 +50,7 @@ set(ES_HEADERS
|
||||||
|
|
||||||
# Views
|
# Views
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GamelistBase.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GamelistBase.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GamelistLegacy.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GamelistView.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GamelistView.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemView.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemView.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/ViewController.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/views/ViewController.h
|
||||||
|
|
|
@ -660,7 +660,7 @@ void GamelistBase::generateGamelistInfo(FileData* cursor, FileData* firstEntry)
|
||||||
|
|
||||||
void GamelistBase::remove(FileData* game, bool deleteFile)
|
void GamelistBase::remove(FileData* game, bool deleteFile)
|
||||||
{
|
{
|
||||||
// Delete the game file on the filesystem.
|
// Optionally delete the game file on the filesystem.
|
||||||
if (deleteFile)
|
if (deleteFile)
|
||||||
Utils::FileSystem::removeFile(game->getPath());
|
Utils::FileSystem::removeFile(game->getPath());
|
||||||
|
|
||||||
|
|
768
es-app/src/views/GamelistLegacy.h
Normal file
768
es-app/src/views/GamelistLegacy.h
Normal file
|
@ -0,0 +1,768 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
|
// GamelistLegacy.h
|
||||||
|
//
|
||||||
|
// Specific gamelist functions for backward compatibility (legacy mode).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ES_APP_VIEWS_GAMELIST_LEGACY_H
|
||||||
|
#define ES_APP_VIEWS_GAMELIST_LEGACY_H
|
||||||
|
|
||||||
|
#include "CollectionSystemsManager.h"
|
||||||
|
#include "animations/LambdaAnimation.h"
|
||||||
|
|
||||||
|
#define FADE_IN_START_OPACITY 0.5f
|
||||||
|
#define FADE_IN_TIME 325
|
||||||
|
|
||||||
|
void GamelistView::legacyPopulateFields()
|
||||||
|
{
|
||||||
|
const float padding {0.01f};
|
||||||
|
|
||||||
|
// Logo text (fallback if no logo image exists).
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText(mRoot->getSystem()->getFullName(), false);
|
||||||
|
mTextComponents.back()->setSize(mSize.x, 0.0f);
|
||||||
|
mTextComponents.back()->setPosition(0.0f, 0.0f);
|
||||||
|
mTextComponents.back()->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
|
mTextComponents.back()->setColor(0xFFFFFFFF);
|
||||||
|
mTextComponents.back()->setDefaultZIndex(50.0f);
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
// Logo.
|
||||||
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setResize(0.0f, mSize.y * 0.185f);
|
||||||
|
mImageComponents.back()->setOrigin(0.5f, 0.0f);
|
||||||
|
mImageComponents.back()->setPosition(mSize.x / 2.0f, 0.0f);
|
||||||
|
mImageComponents.back()->setDefaultZIndex(50.0f);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
|
||||||
|
// Background.
|
||||||
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setResize(mSize.x, mSize.y);
|
||||||
|
mImageComponents.back()->setDefaultZIndex(0.0f);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
|
||||||
|
// Thumbnails.
|
||||||
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setMetadataField("md_thumbnail");
|
||||||
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mImageComponents.back()->setVisible(false);
|
||||||
|
mImageComponents.back()->setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f);
|
||||||
|
mImageComponents.back()->setDefaultZIndex(25.0f);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
|
||||||
|
// Marquee.
|
||||||
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setMetadataField("md_marquee");
|
||||||
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mImageComponents.back()->setVisible(false);
|
||||||
|
mImageComponents.back()->setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f);
|
||||||
|
mImageComponents.back()->setDefaultZIndex(35.0f);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
|
||||||
|
// Image.
|
||||||
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setMetadataField("md_image");
|
||||||
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mImageComponents.back()->setPosition(mSize.x * 0.25f,
|
||||||
|
mList.getPosition().y + mSize.y * 0.2125f);
|
||||||
|
mImageComponents.back()->setMaxSize(mSize.x * (0.50f - 2.0f * padding), mSize.y * 0.4f);
|
||||||
|
mImageComponents.back()->setDefaultZIndex(30.0f);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
|
||||||
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
// Video.
|
||||||
|
mVideoComponents.push_back(std::make_unique<VideoFFmpegComponent>());
|
||||||
|
mVideoComponents.back()->setMetadataField("md_video");
|
||||||
|
mVideoComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mVideoComponents.back()->setPosition(mSize.x * 0.25f, mSize.y * 0.4f);
|
||||||
|
mVideoComponents.back()->setSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.4f);
|
||||||
|
mVideoComponents.back()->setDefaultZIndex(30.0f);
|
||||||
|
addChild(mVideoComponents.back().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
|
||||||
|
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);
|
||||||
|
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
||||||
|
mList.setCursorChangedCallback([&](const CursorState& /*state*/) { legacyUpdateInfoPanel(); });
|
||||||
|
|
||||||
|
// Metadata labels + values.
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Rating: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_rating");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Released: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_releasedate");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Developer: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_developer");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Publisher: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_publisher");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Genre: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_genre");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Players: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_players");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Last played: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_lastplayed");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setText("Times played: ", false);
|
||||||
|
mTextComponents.back()->setMetadataField("md_lbl_playcount");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mRatingComponents.push_back(std::make_unique<RatingComponent>());
|
||||||
|
mRatingComponents.back()->setMetadataField("md_rating");
|
||||||
|
mRatingComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
addChild(mRatingComponents.back().get());
|
||||||
|
|
||||||
|
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
||||||
|
mDateTimeComponents.back()->setMetadataField("md_releasedate");
|
||||||
|
addChild(mDateTimeComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_developer");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_publisher");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_genre");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_players");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
||||||
|
mDateTimeComponents.back()->setMetadataField("md_lastplayed");
|
||||||
|
addChild(mDateTimeComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_playcount");
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setMetadataField("md_name");
|
||||||
|
mTextComponents.back()->setPosition(mSize.x, mSize.y);
|
||||||
|
mTextComponents.back()->setFont(Font::get(FONT_SIZE_MEDIUM));
|
||||||
|
mTextComponents.back()->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
|
mTextComponents.back()->setColor(0xAAAAAAFF);
|
||||||
|
mTextComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
// Badges.
|
||||||
|
mBadgeComponents.push_back(std::make_unique<BadgeComponent>());
|
||||||
|
mBadgeComponents.back()->setMetadataField("md_badges");
|
||||||
|
mBadgeComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mBadgeComponents.back()->setPosition(mSize.x * 0.8f, mSize.y * 0.7f);
|
||||||
|
mBadgeComponents.back()->setSize(mSize.x * 0.15f, mSize.y * 0.2f);
|
||||||
|
mBadgeComponents.back()->setDefaultZIndex(50.0f);
|
||||||
|
addChild(mBadgeComponents.back().get());
|
||||||
|
|
||||||
|
// Scrollable container (game description).
|
||||||
|
mScrollableContainerComponents.push_back(std::make_unique<ScrollableContainer>());
|
||||||
|
mScrollableContainerComponents.back()->setMetadataField("md_description");
|
||||||
|
mScrollableContainerComponents.back()->setSize(
|
||||||
|
mSize.x * (0.50f - 2.0f * padding),
|
||||||
|
mSize.y - mScrollableContainerComponents.back()->getPosition().y);
|
||||||
|
mScrollableContainerComponents.back()->setAutoScroll(true);
|
||||||
|
mScrollableContainerComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
addChild(mScrollableContainerComponents.back().get());
|
||||||
|
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
|
mTextComponents.back()->setSize(mScrollableContainerComponents.back()->getSize().x, 0.0f);
|
||||||
|
mScrollableContainerComponents.back()->addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
|
mGamelistInfoComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mGamelistInfoComponents.back()->setMetadataField("gamelistInfo");
|
||||||
|
mGamelistInfoComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
|
mGamelistInfoComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
|
mGamelistInfoComponents.back()->setDefaultZIndex(50.0f);
|
||||||
|
mGamelistInfoComponents.back()->setVisible(true);
|
||||||
|
addChild(mGamelistInfoComponents.back().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
|
{
|
||||||
|
legacyPopulateFields();
|
||||||
|
|
||||||
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
|
mTextComponents[LOGOTEXT]->applyTheme(theme, getName(), "logoText", ALL);
|
||||||
|
mImageComponents[LOGO]->applyTheme(theme, getName(), "logo", ALL);
|
||||||
|
mImageComponents[BACKGROUND]->applyTheme(theme, getName(), "background", ALL);
|
||||||
|
|
||||||
|
// Remove old theme extras.
|
||||||
|
for (auto extra : mThemeExtras) {
|
||||||
|
removeChild(extra);
|
||||||
|
delete extra;
|
||||||
|
}
|
||||||
|
mThemeExtras.clear();
|
||||||
|
|
||||||
|
// Add new theme extras.
|
||||||
|
mThemeExtras = ThemeData::makeExtras(theme, getName());
|
||||||
|
for (auto extra : mThemeExtras)
|
||||||
|
addChild(extra);
|
||||||
|
|
||||||
|
mList.applyTheme(theme, getName(), "gamelist", ALL);
|
||||||
|
|
||||||
|
mImageComponents[LegacyImage::MD_THUMBNAIL]->applyTheme(
|
||||||
|
theme, getName(), mImageComponents[LegacyImage::MD_THUMBNAIL]->getMetadataField(), ALL);
|
||||||
|
mImageComponents[LegacyImage::MD_MARQUEE]->applyTheme(
|
||||||
|
theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
||||||
|
|
||||||
|
if (mViewStyle == ViewController::DETAILED) {
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->applyTheme(
|
||||||
|
theme, getName(), mImageComponents[LegacyImage::MD_IMAGE]->getMetadataField(),
|
||||||
|
POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
||||||
|
}
|
||||||
|
else if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
mVideoComponents.front()->applyTheme(
|
||||||
|
theme, getName(), mVideoComponents.front()->getMetadataField(),
|
||||||
|
POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX | ROTATION | VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
legacyInitMDLabels();
|
||||||
|
legacyInitMDValues();
|
||||||
|
|
||||||
|
mTextComponents[LegacyText::MD_NAME]->applyTheme(
|
||||||
|
theme, getName(), mTextComponents[LegacyText::MD_NAME]->getMetadataField(), ALL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mBadgeComponents.size(); ++i)
|
||||||
|
mBadgeComponents[i]->applyTheme(theme, getName(), mBadgeComponents[i]->getMetadataField(),
|
||||||
|
ALL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mRatingComponents.size(); ++i)
|
||||||
|
mRatingComponents[i]->applyTheme(theme, getName(), mRatingComponents[i]->getMetadataField(),
|
||||||
|
ALL);
|
||||||
|
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->applyTheme(
|
||||||
|
theme, getName(), mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->getMetadataField(),
|
||||||
|
ALL);
|
||||||
|
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->applyTheme(
|
||||||
|
theme, getName(), mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->getMetadataField(),
|
||||||
|
ALL);
|
||||||
|
|
||||||
|
if (mLegacyMode) {
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_NAME; ++i)
|
||||||
|
mTextComponents[i]->applyTheme(theme, getName(), mTextComponents[i]->getMetadataField(),
|
||||||
|
ALL ^ ThemeFlags::TEXT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_NAME; ++i)
|
||||||
|
mTextComponents[i]->applyTheme(theme, getName(), mTextComponents[i]->getMetadataField(),
|
||||||
|
ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& container : mScrollableContainerComponents) {
|
||||||
|
container->applyTheme(theme, getName(), container->getMetadataField(),
|
||||||
|
POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextComponents[LegacyText::MD_DESCRIPTION]->setSize(
|
||||||
|
mScrollableContainerComponents.front()->getSize().x, 0.0f);
|
||||||
|
mTextComponents[LegacyText::MD_DESCRIPTION]->applyTheme(
|
||||||
|
theme, getName(), "md_description",
|
||||||
|
ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION));
|
||||||
|
|
||||||
|
for (auto& gamelistInfo : mGamelistInfoComponents)
|
||||||
|
gamelistInfo->applyTheme(theme, getName(), gamelistInfo->getMetadataField(),
|
||||||
|
ALL ^ ThemeFlags::TEXT);
|
||||||
|
|
||||||
|
// If there is no position defined in the theme for gamelistInfo, then hide it.
|
||||||
|
if (mGamelistInfoComponents.front()->getPosition() == glm::vec3 {})
|
||||||
|
mGamelistInfoComponents.front()->setVisible(false);
|
||||||
|
else
|
||||||
|
mGamelistInfoComponents.front()->setVisible(true);
|
||||||
|
|
||||||
|
// Hide some components if we're in Basic mode.
|
||||||
|
if (mViewStyle == ViewController::BASIC) {
|
||||||
|
if (mTheme->getElement(getName(), "logoText", "text") == nullptr)
|
||||||
|
mTextComponents[LegacyText::LOGOTEXT]->setVisible(false);
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setVisible(false);
|
||||||
|
for (auto& container : mScrollableContainerComponents)
|
||||||
|
container->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
sortChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamelistView::legacyUpdateInfoPanel()
|
||||||
|
{
|
||||||
|
FileData* file {(mList.size() == 0 || mList.isScrolling()) ? nullptr : mList.getSelected()};
|
||||||
|
|
||||||
|
// If the game data has already been rendered to the info panel, then skip it this time.
|
||||||
|
if (file == mLastUpdated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mList.isScrolling())
|
||||||
|
mLastUpdated = file;
|
||||||
|
|
||||||
|
bool hideMetaDataFields {false};
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
// Always hide the metadata fields if browsing grouped custom collections.
|
||||||
|
if (file->getSystem()->isCustomCollection() &&
|
||||||
|
file->getPath() == file->getSystem()->getName())
|
||||||
|
hideMetaDataFields = true;
|
||||||
|
else
|
||||||
|
hideMetaDataFields = (file->metadata.get("hidemetadata") == "true");
|
||||||
|
|
||||||
|
// Always hide the metadata fields for placeholders as well.
|
||||||
|
if (file->getType() == PLACEHOLDER) {
|
||||||
|
hideMetaDataFields = true;
|
||||||
|
mLastUpdated = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're scrolling, hide the metadata fields if the last game had this options set,
|
||||||
|
// or if we're in the grouped custom collection view.
|
||||||
|
if (mList.isScrolling())
|
||||||
|
if ((mLastUpdated && mLastUpdated->metadata.get("hidemetadata") == "true") ||
|
||||||
|
(mLastUpdated->getSystem()->isCustomCollection() &&
|
||||||
|
mLastUpdated->getPath() == mLastUpdated->getSystem()->getName()))
|
||||||
|
hideMetaDataFields = true;
|
||||||
|
|
||||||
|
if (hideMetaDataFields || mViewStyle == ViewController::BASIC) {
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DESCRIPTION; ++i)
|
||||||
|
mTextComponents[i]->setVisible(false);
|
||||||
|
for (auto& date : mDateTimeComponents)
|
||||||
|
date->setVisible(false);
|
||||||
|
for (auto& badge : mBadgeComponents)
|
||||||
|
badge->setVisible(false);
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setVisible(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DESCRIPTION; ++i)
|
||||||
|
mTextComponents[i]->setVisible(true);
|
||||||
|
for (auto& date : mDateTimeComponents)
|
||||||
|
date->setVisible(true);
|
||||||
|
for (auto& badge : mBadgeComponents)
|
||||||
|
badge->setVisible(true);
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fadingOut = false;
|
||||||
|
if (file == nullptr) {
|
||||||
|
mVideoPlaying = false;
|
||||||
|
fadingOut = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If we're browsing a grouped custom collection, then update the folder metadata
|
||||||
|
// which will generate a description of three random games and return a pointer to
|
||||||
|
// the first of these so that we can display its game media.
|
||||||
|
if (file->getSystem()->isCustomCollection() &&
|
||||||
|
file->getPath() == file->getSystem()->getName()) {
|
||||||
|
mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata(
|
||||||
|
file->getSystem());
|
||||||
|
if (mRandomGame) {
|
||||||
|
mImageComponents[LegacyImage::MD_THUMBNAIL]->setImage(
|
||||||
|
mRandomGame->getThumbnailPath());
|
||||||
|
mImageComponents[LegacyImage::MD_MARQUEE]->setImage(mRandomGame->getMarqueePath(),
|
||||||
|
false, true);
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setImage(mRandomGame->getImagePath());
|
||||||
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
mVideoComponents.front()->setImage(mRandomGame->getImagePath());
|
||||||
|
// Always stop the video before setting a new video as it will otherwise
|
||||||
|
// continue to play if it has the same path (i.e. it is the same physical
|
||||||
|
// video file) as the previously set video. That may happen when entering a
|
||||||
|
// folder with the same name as the first game file inside, or as in this
|
||||||
|
// case, when entering a custom collection.
|
||||||
|
mVideoComponents.front()->onHide();
|
||||||
|
|
||||||
|
if (!mVideoComponents.front()->setVideo(mRandomGame->getVideoPath()))
|
||||||
|
mVideoComponents.front()->setDefaultVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mImageComponents[LegacyImage::MD_THUMBNAIL]->setImage("");
|
||||||
|
mImageComponents[LegacyImage::MD_MARQUEE]->setImage("");
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setImage("");
|
||||||
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
mVideoComponents.front()->setImage("");
|
||||||
|
mVideoComponents.front()->setVideo("");
|
||||||
|
mVideoComponents.front()->setDefaultVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mImageComponents[LegacyImage::MD_THUMBNAIL]->setImage(file->getThumbnailPath());
|
||||||
|
mImageComponents[LegacyImage::MD_MARQUEE]->setImage(file->getMarqueePath(), false,
|
||||||
|
true);
|
||||||
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
mVideoComponents.front()->setImage(file->getImagePath());
|
||||||
|
mVideoComponents.front()->onHide();
|
||||||
|
|
||||||
|
if (!mVideoComponents.front()->setVideo(file->getVideoPath()))
|
||||||
|
mVideoComponents.front()->setDefaultVideo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setImage(file->getImagePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mVideoPlaying = true;
|
||||||
|
|
||||||
|
// Populate the gamelistInfo field which shows an icon if a folder has been entered
|
||||||
|
// as well as the game count for the entire system (total and favorites separately).
|
||||||
|
// If a filter has been applied, then the number of filtered and total games replaces
|
||||||
|
// the game counter.
|
||||||
|
for (auto& gamelistInfo : mGamelistInfoComponents) {
|
||||||
|
std::string gamelistInfoString;
|
||||||
|
Alignment infoAlign = gamelistInfo->getHorizontalAlignment();
|
||||||
|
|
||||||
|
if (mIsFolder && infoAlign == ALIGN_RIGHT)
|
||||||
|
gamelistInfoString = ViewController::FOLDER_CHAR + " ";
|
||||||
|
|
||||||
|
if (mIsFiltered) {
|
||||||
|
if (mFilteredGameCountAll == mFilteredGameCount)
|
||||||
|
gamelistInfoString += ViewController::FILTER_CHAR + " " +
|
||||||
|
std::to_string(mFilteredGameCount) + " / " +
|
||||||
|
std::to_string(mGameCount);
|
||||||
|
else
|
||||||
|
gamelistInfoString +=
|
||||||
|
ViewController::FILTER_CHAR + " " + std::to_string(mFilteredGameCount) +
|
||||||
|
" + " + std::to_string(mFilteredGameCountAll - mFilteredGameCount) + " / " +
|
||||||
|
std::to_string(mGameCount);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gamelistInfoString +=
|
||||||
|
ViewController::CONTROLLER_CHAR + " " + std::to_string(mGameCount);
|
||||||
|
if (!(file->getSystem()->isCollection() &&
|
||||||
|
file->getSystem()->getFullName() == "favorites"))
|
||||||
|
gamelistInfoString += " " + ViewController::FAVORITE_CHAR + " " +
|
||||||
|
std::to_string(mFavoritesGameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsFolder && infoAlign != ALIGN_RIGHT)
|
||||||
|
gamelistInfoString += " " + ViewController::FOLDER_CHAR;
|
||||||
|
|
||||||
|
gamelistInfo->setValue(gamelistInfoString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mViewStyle == ViewController::DETAILED) {
|
||||||
|
// Fade in the game image.
|
||||||
|
auto func = [this](float t) {
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setOpacity(static_cast<unsigned char>(
|
||||||
|
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->setAnimation(
|
||||||
|
new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false);
|
||||||
|
}
|
||||||
|
else if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
// Fade in the static image.
|
||||||
|
auto func = [this](float t) {
|
||||||
|
mVideoComponents.front()->setOpacity(static_cast<unsigned char>(
|
||||||
|
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
mVideoComponents.front()->setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0,
|
||||||
|
nullptr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextComponents[LegacyText::MD_DESCRIPTION]->setText(file->metadata.get("desc"));
|
||||||
|
for (auto& container : mScrollableContainerComponents)
|
||||||
|
container->reset();
|
||||||
|
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setValue(file->metadata.get("rating"));
|
||||||
|
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->setValue(
|
||||||
|
file->metadata.get("releasedate"));
|
||||||
|
mTextComponents[LegacyText::MD_DEVELOPER]->setValue(file->metadata.get("developer"));
|
||||||
|
mTextComponents[LegacyText::MD_PUBLISHER]->setValue(file->metadata.get("publisher"));
|
||||||
|
mTextComponents[LegacyText::MD_GENRE]->setValue(file->metadata.get("genre"));
|
||||||
|
mTextComponents[LegacyText::MD_PLAYERS]->setValue(file->metadata.get("players"));
|
||||||
|
|
||||||
|
// Populate the badge slots based on game metadata.
|
||||||
|
std::vector<BadgeComponent::BadgeInfo> badgeSlots;
|
||||||
|
for (auto& badgeComponent : mBadgeComponents) {
|
||||||
|
for (auto& badge : badgeComponent->getBadgeTypes()) {
|
||||||
|
BadgeComponent::BadgeInfo badgeInfo;
|
||||||
|
badgeInfo.badgeType = badge;
|
||||||
|
if (badge == "controller") {
|
||||||
|
if (file->metadata.get("controller").compare("") != 0) {
|
||||||
|
badgeInfo.gameController = file->metadata.get("controller");
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (badge == "altemulator") {
|
||||||
|
if (file->metadata.get(badge).compare("") != 0)
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (file->metadata.get(badge).compare("true") == 0)
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
badgeComponent->setBadges(badgeSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextComponents[LegacyText::MD_NAME]->setValue(file->metadata.get("name"));
|
||||||
|
|
||||||
|
if (file->getType() == GAME) {
|
||||||
|
if (!hideMetaDataFields) {
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->setValue(
|
||||||
|
file->metadata.get("lastplayed"));
|
||||||
|
mTextComponents[LegacyText::MD_PLAYCOUNT]->setValue(
|
||||||
|
file->metadata.get("playcount"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (file->getType() == FOLDER) {
|
||||||
|
if (!hideMetaDataFields) {
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->setValue(
|
||||||
|
file->metadata.get("lastplayed"));
|
||||||
|
mTextComponents[LegacyText::MD_LBL_PLAYCOUNT]->setVisible(false);
|
||||||
|
mTextComponents[LegacyText::MD_PLAYCOUNT]->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getValue() != "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string metadata = text->getMetadataField();
|
||||||
|
if (metadata == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (metadata == "md_controller") {
|
||||||
|
std::string controller =
|
||||||
|
BadgeComponent::getDisplayName(file->metadata.get("controller"));
|
||||||
|
text->setValue(controller == "unknown" ? "" : controller);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadata == "md_name")
|
||||||
|
text->setValue(file->metadata.get("name"));
|
||||||
|
else if (metadata == "md_rating")
|
||||||
|
text->setValue(mRatingComponents.front()->getRatingValue());
|
||||||
|
else if (metadata == "md_developer")
|
||||||
|
text->setValue(file->metadata.get("developer"));
|
||||||
|
else if (metadata == "md_publisher")
|
||||||
|
text->setValue(file->metadata.get("publisher"));
|
||||||
|
else if (metadata == "md_genre")
|
||||||
|
text->setValue(file->metadata.get("genre"));
|
||||||
|
else if (metadata == "md_players")
|
||||||
|
text->setValue(file->metadata.get("players"));
|
||||||
|
else if (metadata == "md_favorite")
|
||||||
|
text->setValue(file->metadata.get("favorite") == "true" ? "yes" : "no");
|
||||||
|
else if (metadata == "md_completed")
|
||||||
|
text->setValue(file->metadata.get("completed") == "true" ? "yes" : "no");
|
||||||
|
else if (metadata == "md_kidgame")
|
||||||
|
text->setValue(file->metadata.get("kidgame") == "true" ? "yes" : "no");
|
||||||
|
else if (metadata == "md_broken")
|
||||||
|
text->setValue(file->metadata.get("broken") == "true" ? "yes" : "no");
|
||||||
|
else if (metadata == "md_playcount")
|
||||||
|
text->setValue(file->metadata.get("playcount"));
|
||||||
|
else if (metadata == "md_altemulator")
|
||||||
|
text->setValue(file->metadata.get("altemulator"));
|
||||||
|
else
|
||||||
|
text->setValue(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
std::string metadata = date->getMetadataField();
|
||||||
|
if (metadata == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (metadata == "md_releasedate") {
|
||||||
|
date->setValue(file->metadata.get("releasedate"));
|
||||||
|
}
|
||||||
|
else if (metadata == "md_lastplayed") {
|
||||||
|
date->setValue(file->metadata.get("lastplayed"));
|
||||||
|
date->setDisplayRelative(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
date->setValue("19700101T000000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fadingOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GuiComponent*> comps;
|
||||||
|
|
||||||
|
if (!mLegacyMode) {
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getScrollHide())
|
||||||
|
comps.emplace_back(text.get());
|
||||||
|
}
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
if (date->getScrollHide())
|
||||||
|
comps.emplace_back(date.get());
|
||||||
|
}
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getScrollHide())
|
||||||
|
comps.emplace_back(image.get());
|
||||||
|
}
|
||||||
|
for (auto& badge : mBadgeComponents) {
|
||||||
|
if (badge->getScrollHide())
|
||||||
|
comps.emplace_back(badge.get());
|
||||||
|
}
|
||||||
|
for (auto& rating : mRatingComponents) {
|
||||||
|
if (rating->getScrollHide())
|
||||||
|
comps.emplace_back(rating.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mLegacyMode) {
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::END; ++i)
|
||||||
|
comps.emplace_back(mTextComponents[i].get());
|
||||||
|
comps.emplace_back(mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE].get());
|
||||||
|
comps.emplace_back(mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED].get());
|
||||||
|
comps.emplace_back(mTextComponents[LegacyText::MD_NAME].get());
|
||||||
|
comps.emplace_back(mImageComponents[LegacyImage::MD_THUMBNAIL].get());
|
||||||
|
comps.emplace_back(mImageComponents[LegacyImage::MD_MARQUEE].get());
|
||||||
|
comps.emplace_back(mImageComponents[LegacyImage::MD_IMAGE].get());
|
||||||
|
comps.push_back(mBadgeComponents.front().get());
|
||||||
|
comps.push_back(mRatingComponents.front().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = comps.cbegin(); it != comps.cend(); ++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(static_cast<unsigned char>(glm::mix(0.0f, 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamelistView::legacyUpdate(int deltaTime)
|
||||||
|
{
|
||||||
|
if (ViewController::getInstance()->getGameLaunchTriggered() &&
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->isAnimationPlaying(0))
|
||||||
|
mImageComponents[LegacyImage::MD_IMAGE]->finishAnimation(0);
|
||||||
|
|
||||||
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
|
if (!mVideoPlaying)
|
||||||
|
mVideoComponents.front()->onHide();
|
||||||
|
else if (mVideoPlaying && !mVideoComponents.front()->isVideoPaused() &&
|
||||||
|
!mWindow->isScreensaverActive())
|
||||||
|
mVideoComponents.front()->onShow();
|
||||||
|
|
||||||
|
if (ViewController::getInstance()->getGameLaunchTriggered() &&
|
||||||
|
mVideoComponents.front()->isAnimationPlaying(0))
|
||||||
|
mVideoComponents.front()->finishAnimation(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChildren(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamelistView::legacyInitMDLabels()
|
||||||
|
{
|
||||||
|
std::vector<TextComponent*> components;
|
||||||
|
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DEVELOPER; ++i)
|
||||||
|
components.emplace_back(&*mTextComponents[i]);
|
||||||
|
|
||||||
|
const unsigned int colCount {2};
|
||||||
|
const unsigned int rowCount {static_cast<unsigned int>(components.size() / 2)};
|
||||||
|
|
||||||
|
glm::vec3 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;
|
||||||
|
glm::vec3 pos {};
|
||||||
|
if (row == 0) {
|
||||||
|
pos = start + glm::vec3 {colSize * (i / rowCount), 0.0f, 0.0f};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Work from the last component.
|
||||||
|
GuiComponent* lc {components[i - 1]};
|
||||||
|
pos = lc->getPosition() + glm::vec3 {0.0f, lc->getSize().y + rowPadding, 0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
components[i]->setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
|
components[i]->setPosition(pos);
|
||||||
|
// components[i]->setColor(0xFFFFFFFF);
|
||||||
|
components[i]->setDefaultZIndex(40.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamelistView::legacyInitMDValues()
|
||||||
|
{
|
||||||
|
std::vector<TextComponent*> labels;
|
||||||
|
std::vector<GuiComponent*> values;
|
||||||
|
|
||||||
|
std::shared_ptr<Font> defaultFont {Font::get(FONT_SIZE_SMALL)};
|
||||||
|
|
||||||
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DEVELOPER; ++i) {
|
||||||
|
labels.emplace_back(&*mTextComponents[i]);
|
||||||
|
mTextComponents[i]->setFont(defaultFont);
|
||||||
|
// mTextComponents[i]->setColor(0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->setFont(defaultFont);
|
||||||
|
// mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->setColor(0xFFFFFFFF);
|
||||||
|
mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->setFont(defaultFont);
|
||||||
|
// mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->setColor(0xFFFFFFFF);
|
||||||
|
|
||||||
|
values.emplace_back(mRatingComponents.front().get());
|
||||||
|
values.emplace_back(mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE].get());
|
||||||
|
values.emplace_back(mTextComponents[LegacyText::MD_DEVELOPER].get());
|
||||||
|
values.emplace_back(mTextComponents[LegacyText::MD_PUBLISHER].get());
|
||||||
|
values.emplace_back(mTextComponents[LegacyText::MD_GENRE].get());
|
||||||
|
values.emplace_back(mTextComponents[LegacyText::MD_PLAYERS].get());
|
||||||
|
values.emplace_back(mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED].get());
|
||||||
|
values.emplace_back(mTextComponents[LegacyText::MD_PLAYCOUNT].get());
|
||||||
|
|
||||||
|
float bottom {0.0f};
|
||||||
|
const float colSize {(mSize.x * 0.48f) / 2.0f};
|
||||||
|
for (unsigned int i = 0; i < labels.size(); ++i) {
|
||||||
|
const float heightDiff = (labels[i]->getSize().y - values[i]->getSize().y) / 2.0f;
|
||||||
|
values[i]->setPosition(labels[i]->getPosition() +
|
||||||
|
glm::vec3 {labels[i]->getSize().x, heightDiff, 0.0f});
|
||||||
|
values[i]->setSize(colSize - labels[i]->getSize().x, values[i]->getSize().y);
|
||||||
|
values[i]->setDefaultZIndex(40.0f);
|
||||||
|
|
||||||
|
float testBot = values[i]->getPosition().y + values[i]->getSize().y;
|
||||||
|
|
||||||
|
if (testBot > bottom)
|
||||||
|
bottom = testBot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to off the screen for the following components.
|
||||||
|
mRatingComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
||||||
|
Renderer::getScreenHeight() * 2.0f);
|
||||||
|
|
||||||
|
mScrollableContainerComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
||||||
|
Renderer::getScreenHeight() * 2.0f);
|
||||||
|
|
||||||
|
for (auto& container : mScrollableContainerComponents) {
|
||||||
|
container->setPosition(container->getPosition().x, bottom + mSize.y * 0.01f);
|
||||||
|
container->setSize(container->getSize().x, mSize.y - container->getPosition().y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ES_APP_VIEWS_GAMELIST_LEGACY_H
|
|
@ -7,145 +7,34 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "views/GamelistView.h"
|
#include "views/GamelistView.h"
|
||||||
|
#include "views/GamelistLegacy.h"
|
||||||
|
|
||||||
#include "CollectionSystemsManager.h"
|
#include "CollectionSystemsManager.h"
|
||||||
#include "UIModeController.h"
|
#include "UIModeController.h"
|
||||||
#include "animations/LambdaAnimation.h"
|
#include "animations/LambdaAnimation.h"
|
||||||
|
|
||||||
#define FADE_IN_START_OPACITY 0.5f
|
// #define FADE_IN_START_OPACITY 0.5f
|
||||||
#define FADE_IN_TIME 325
|
// #define FADE_IN_TIME 325
|
||||||
|
|
||||||
GamelistView::GamelistView(FileData* root)
|
GamelistView::GamelistView(FileData* root, bool legacyMode)
|
||||||
: GamelistBase {root}
|
: GamelistBase {root}
|
||||||
|
, mLegacyMode {legacyMode}
|
||||||
, mViewStyle {ViewController::BASIC}
|
, mViewStyle {ViewController::BASIC}
|
||||||
, mVideo {nullptr}
|
|
||||||
{
|
{
|
||||||
|
// TEMPORARY
|
||||||
|
mLegacyMode = true;
|
||||||
|
|
||||||
mViewStyle = ViewController::getInstance()->getState().viewstyle;
|
mViewStyle = ViewController::getInstance()->getState().viewstyle;
|
||||||
|
|
||||||
mHeaderText.setText("Logo Text", false);
|
if (mLegacyMode)
|
||||||
mHeaderText.setSize(mSize.x, 0.0f);
|
return;
|
||||||
mHeaderText.setPosition(0.0f, 0.0f);
|
|
||||||
mHeaderText.setHorizontalAlignment(ALIGN_CENTER);
|
|
||||||
mHeaderText.setDefaultZIndex(50.0f);
|
|
||||||
|
|
||||||
mHeaderText.setText(mRoot->getSystem()->getFullName());
|
const float padding {0.01f};
|
||||||
|
|
||||||
mHeaderImage.setResize(0.0f, mSize.y * 0.185f);
|
|
||||||
mHeaderImage.setOrigin(0.5f, 0.0f);
|
|
||||||
mHeaderImage.setPosition(mSize.x / 2.0f, 0.0f);
|
|
||||||
mHeaderImage.setDefaultZIndex(50.0f);
|
|
||||||
|
|
||||||
mBackground.setResize(mSize.x, mSize.y);
|
|
||||||
mBackground.setDefaultZIndex(0.0f);
|
|
||||||
|
|
||||||
addChild(&mHeaderText);
|
|
||||||
addChild(&mBackground);
|
|
||||||
|
|
||||||
const float padding = 0.01f;
|
|
||||||
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
// Create the video window.
|
|
||||||
mVideo = new VideoFFmpegComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
|
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
|
||||||
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);
|
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);
|
||||||
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
||||||
mList.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); });
|
mList.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); });
|
||||||
|
|
||||||
// Thumbnail.
|
|
||||||
mThumbnail.setOrigin(0.5f, 0.5f);
|
|
||||||
mThumbnail.setPosition(2.0f, 2.0f);
|
|
||||||
mThumbnail.setVisible(false);
|
|
||||||
mThumbnail.setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f);
|
|
||||||
mThumbnail.setDefaultZIndex(25.0f);
|
|
||||||
addChild(&mThumbnail);
|
|
||||||
|
|
||||||
// Marquee.
|
|
||||||
mMarquee.setOrigin(0.5f, 0.5f);
|
|
||||||
// Default to off the screen.
|
|
||||||
mMarquee.setPosition(2.0f, 2.0f);
|
|
||||||
mMarquee.setVisible(false);
|
|
||||||
mMarquee.setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f);
|
|
||||||
mMarquee.setDefaultZIndex(35.0f);
|
|
||||||
addChild(&mMarquee);
|
|
||||||
|
|
||||||
// Image.
|
|
||||||
mImage.setOrigin(0.5f, 0.5f);
|
|
||||||
mImage.setPosition(mSize.x * 0.25f, mList.getPosition().y + mSize.y * 0.2125f);
|
|
||||||
mImage.setMaxSize(mSize.x * (0.50f - 2.0f * padding), mSize.y * 0.4f);
|
|
||||||
mImage.setDefaultZIndex(30.0f);
|
|
||||||
addChild(&mImage);
|
|
||||||
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
// Video.
|
|
||||||
mVideo->setOrigin(0.5f, 0.5f);
|
|
||||||
mVideo->setPosition(mSize.x * 0.25f, mSize.y * 0.4f);
|
|
||||||
mVideo->setSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.4f);
|
|
||||||
mVideo->setDefaultZIndex(30.0f);
|
|
||||||
addChild(mVideo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metadata labels + values.
|
|
||||||
mLblRating.setText("Rating: ", false);
|
|
||||||
addChild(&mLblRating);
|
|
||||||
addChild(&mRating);
|
|
||||||
mLblReleaseDate.setText("Released: ", false);
|
|
||||||
addChild(&mLblReleaseDate);
|
|
||||||
addChild(&mReleaseDate);
|
|
||||||
mLblDeveloper.setText("Developer: ", false);
|
|
||||||
addChild(&mLblDeveloper);
|
|
||||||
addChild(&mDeveloper);
|
|
||||||
mLblPublisher.setText("Publisher: ", false);
|
|
||||||
addChild(&mLblPublisher);
|
|
||||||
addChild(&mPublisher);
|
|
||||||
mLblGenre.setText("Genre: ", false);
|
|
||||||
addChild(&mLblGenre);
|
|
||||||
addChild(&mGenre);
|
|
||||||
mLblPlayers.setText("Players: ", false);
|
|
||||||
addChild(&mLblPlayers);
|
|
||||||
addChild(&mPlayers);
|
|
||||||
mLblLastPlayed.setText("Last played: ", false);
|
|
||||||
addChild(&mLblLastPlayed);
|
|
||||||
mLastPlayed.setDisplayRelative(true);
|
|
||||||
addChild(&mLastPlayed);
|
|
||||||
mLblPlayCount.setText("Times played: ", false);
|
|
||||||
addChild(&mLblPlayCount);
|
|
||||||
addChild(&mPlayCount);
|
|
||||||
|
|
||||||
// Badges.
|
|
||||||
addChild(&mBadges);
|
|
||||||
mBadges.setOrigin(0.5f, 0.5f);
|
|
||||||
mBadges.setPosition(mSize.x * 0.8f, mSize.y * 0.7f);
|
|
||||||
mBadges.setSize(mSize.x * 0.15f, mSize.y * 0.2f);
|
|
||||||
mBadges.setDefaultZIndex(50.0f);
|
|
||||||
|
|
||||||
mName.setPosition(mSize.x, mSize.y);
|
|
||||||
mName.setDefaultZIndex(40.0f);
|
|
||||||
mName.setColor(0xAAAAAAFF);
|
|
||||||
mName.setFont(Font::get(FONT_SIZE_MEDIUM));
|
|
||||||
mName.setHorizontalAlignment(ALIGN_CENTER);
|
|
||||||
addChild(&mName);
|
|
||||||
|
|
||||||
mDescContainer.setPosition(mSize.x * padding, mSize.y * 0.65f);
|
|
||||||
mDescContainer.setSize(mSize.x * (0.50f - 2.0f * padding),
|
|
||||||
mSize.y - mDescContainer.getPosition().y);
|
|
||||||
mDescContainer.setAutoScroll(true);
|
|
||||||
mDescContainer.setDefaultZIndex(40.0f);
|
|
||||||
addChild(&mDescContainer);
|
|
||||||
|
|
||||||
mDescription.setFont(Font::get(FONT_SIZE_SMALL));
|
|
||||||
mDescription.setSize(mDescContainer.getSize().x, 0.0f);
|
|
||||||
mDescContainer.addChild(&mDescription);
|
|
||||||
|
|
||||||
mGamelistInfo.setOrigin(0.5f, 0.5f);
|
|
||||||
mGamelistInfo.setFont(Font::get(FONT_SIZE_SMALL));
|
|
||||||
mGamelistInfo.setDefaultZIndex(50.0f);
|
|
||||||
mGamelistInfo.setVisible(true);
|
|
||||||
addChild(&mGamelistInfo);
|
|
||||||
|
|
||||||
initMDLabels();
|
|
||||||
initMDValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GamelistView::~GamelistView()
|
GamelistView::~GamelistView()
|
||||||
|
@ -156,9 +45,6 @@ GamelistView::~GamelistView()
|
||||||
delete extra;
|
delete extra;
|
||||||
}
|
}
|
||||||
mThemeExtras.clear();
|
mThemeExtras.clear();
|
||||||
|
|
||||||
if (mViewStyle == ViewController::VIDEO && mVideo != nullptr)
|
|
||||||
delete mVideo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamelistView::onFileChanged(FileData* file, bool reloadGamelist)
|
void GamelistView::onFileChanged(FileData* file, bool reloadGamelist)
|
||||||
|
@ -190,15 +76,20 @@ void GamelistView::onShow()
|
||||||
|
|
||||||
mLastUpdated = nullptr;
|
mLastUpdated = nullptr;
|
||||||
GuiComponent::onShow();
|
GuiComponent::onShow();
|
||||||
updateInfoPanel();
|
if (mLegacyMode)
|
||||||
|
legacyUpdateInfoPanel();
|
||||||
|
else
|
||||||
|
updateInfoPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
{
|
{
|
||||||
|
if (mLegacyMode) {
|
||||||
|
legacyOnThemeChanged(theme);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
mBackground.applyTheme(theme, getName(), "background", ALL);
|
|
||||||
mHeaderImage.applyTheme(theme, getName(), "logo", ALL);
|
|
||||||
mHeaderText.applyTheme(theme, getName(), "logoText", ALL);
|
|
||||||
|
|
||||||
// Remove old theme extras.
|
// Remove old theme extras.
|
||||||
for (auto extra : mThemeExtras) {
|
for (auto extra : mThemeExtras) {
|
||||||
|
@ -212,83 +103,18 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
for (auto extra : mThemeExtras)
|
for (auto extra : mThemeExtras)
|
||||||
addChild(extra);
|
addChild(extra);
|
||||||
|
|
||||||
if (mHeaderImage.hasImage()) {
|
|
||||||
removeChild(&mHeaderText);
|
|
||||||
addChild(&mHeaderImage);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addChild(&mHeaderText);
|
|
||||||
removeChild(&mHeaderImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
mList.applyTheme(theme, getName(), "gamelist", ALL);
|
mList.applyTheme(theme, getName(), "gamelist", ALL);
|
||||||
|
|
||||||
mThumbnail.applyTheme(theme, getName(), "md_thumbnail",
|
// TODO: Implement logic to populate component vectors.
|
||||||
POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
|
||||||
mMarquee.applyTheme(theme, getName(), "md_marquee",
|
|
||||||
POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
|
||||||
mImage.applyTheme(theme, getName(), "md_image",
|
|
||||||
POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
|
||||||
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
mVideo->applyTheme(theme, getName(), "md_video",
|
|
||||||
POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX | ROTATION |
|
|
||||||
VISIBLE);
|
|
||||||
}
|
|
||||||
mName.applyTheme(theme, getName(), "md_name", ALL);
|
|
||||||
mBadges.applyTheme(theme, getName(), "md_badges", ALL);
|
|
||||||
|
|
||||||
initMDLabels();
|
|
||||||
std::vector<TextComponent*> labels {getMDLabels()};
|
|
||||||
assert(labels.size() == 8);
|
|
||||||
std::vector<std::string> lblElements = {
|
|
||||||
"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<GuiComponent*> values {getMDValues()};
|
|
||||||
assert(values.size() == 8);
|
|
||||||
std::vector<std::string> valElements = {"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 | Z_INDEX | VISIBLE);
|
|
||||||
mDescription.setSize(mDescContainer.getSize().x, 0.0f);
|
|
||||||
mDescription.applyTheme(
|
|
||||||
theme, getName(), "md_description",
|
|
||||||
ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION));
|
|
||||||
|
|
||||||
mGamelistInfo.applyTheme(theme, getName(), "gamelistInfo", ALL ^ ThemeFlags::TEXT);
|
|
||||||
// If there is no position defined in the theme for gamelistInfo, then hide it.
|
|
||||||
if (mGamelistInfo.getPosition() == glm::vec3 {})
|
|
||||||
mGamelistInfo.setVisible(false);
|
|
||||||
else
|
|
||||||
mGamelistInfo.setVisible(true);
|
|
||||||
|
|
||||||
sortChildren();
|
sortChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GamelistView::update(int deltaTime)
|
void GamelistView::update(int deltaTime)
|
||||||
{
|
{
|
||||||
if (ViewController::getInstance()->getGameLaunchTriggered() && mImage.isAnimationPlaying(0))
|
if (mLegacyMode) {
|
||||||
mImage.finishAnimation(0);
|
legacyUpdate(deltaTime);
|
||||||
|
return;
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
if (!mVideoPlaying)
|
|
||||||
mVideo->onHide();
|
|
||||||
else if (mVideoPlaying && !mVideo->isVideoPaused() && !mWindow->isScreensaverActive())
|
|
||||||
mVideo->onShow();
|
|
||||||
|
|
||||||
if (ViewController::getInstance()->getGameLaunchTriggered() &&
|
|
||||||
mVideo->isAnimationPlaying(0))
|
|
||||||
mVideo->finishAnimation(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChildren(deltaTime);
|
updateChildren(deltaTime);
|
||||||
|
@ -393,325 +219,5 @@ void GamelistView::updateInfoPanel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're scrolling, hide the metadata fields if the last game had this options set,
|
// TODO: Implement gamelist logic.
|
||||||
// or if we're in the grouped custom collection view.
|
|
||||||
if (mList.isScrolling())
|
|
||||||
if ((mLastUpdated && mLastUpdated->metadata.get("hidemetadata") == "true") ||
|
|
||||||
(mLastUpdated->getSystem()->isCustomCollection() &&
|
|
||||||
mLastUpdated->getPath() == mLastUpdated->getSystem()->getName()))
|
|
||||||
hideMetaDataFields = true;
|
|
||||||
|
|
||||||
if (hideMetaDataFields || mViewStyle == ViewController::BASIC) {
|
|
||||||
mLblRating.setVisible(false);
|
|
||||||
mRating.setVisible(false);
|
|
||||||
mLblReleaseDate.setVisible(false);
|
|
||||||
mReleaseDate.setVisible(false);
|
|
||||||
mLblDeveloper.setVisible(false);
|
|
||||||
mDeveloper.setVisible(false);
|
|
||||||
mLblPublisher.setVisible(false);
|
|
||||||
mPublisher.setVisible(false);
|
|
||||||
mLblGenre.setVisible(false);
|
|
||||||
mGenre.setVisible(false);
|
|
||||||
mLblPlayers.setVisible(false);
|
|
||||||
mPlayers.setVisible(false);
|
|
||||||
mLblLastPlayed.setVisible(false);
|
|
||||||
mLastPlayed.setVisible(false);
|
|
||||||
mLblPlayCount.setVisible(false);
|
|
||||||
mPlayCount.setVisible(false);
|
|
||||||
mBadges.setVisible(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mLblRating.setVisible(true);
|
|
||||||
mRating.setVisible(true);
|
|
||||||
mLblReleaseDate.setVisible(true);
|
|
||||||
mReleaseDate.setVisible(true);
|
|
||||||
mLblDeveloper.setVisible(true);
|
|
||||||
mDeveloper.setVisible(true);
|
|
||||||
mLblPublisher.setVisible(true);
|
|
||||||
mPublisher.setVisible(true);
|
|
||||||
mLblGenre.setVisible(true);
|
|
||||||
mGenre.setVisible(true);
|
|
||||||
mLblPlayers.setVisible(true);
|
|
||||||
mPlayers.setVisible(true);
|
|
||||||
mLblLastPlayed.setVisible(true);
|
|
||||||
mLastPlayed.setVisible(true);
|
|
||||||
mLblPlayCount.setVisible(true);
|
|
||||||
mPlayCount.setVisible(true);
|
|
||||||
mBadges.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fadingOut = false;
|
|
||||||
if (file == nullptr) {
|
|
||||||
mVideoPlaying = false;
|
|
||||||
fadingOut = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If we're browsing a grouped custom collection, then update the folder metadata
|
|
||||||
// which will generate a description of three random games and return a pointer to
|
|
||||||
// the first of these so that we can display its game media.
|
|
||||||
if (file->getSystem()->isCustomCollection() &&
|
|
||||||
file->getPath() == file->getSystem()->getName()) {
|
|
||||||
mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata(
|
|
||||||
file->getSystem());
|
|
||||||
if (mRandomGame) {
|
|
||||||
mThumbnail.setImage(mRandomGame->getThumbnailPath());
|
|
||||||
mMarquee.setImage(mRandomGame->getMarqueePath(), false, true);
|
|
||||||
mImage.setImage(mRandomGame->getImagePath());
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
mVideo->setImage(mRandomGame->getImagePath());
|
|
||||||
// Always stop the video before setting a new video as it will otherwise
|
|
||||||
// continue to play if it has the same path (i.e. it is the same physical video
|
|
||||||
// file) as the previously set video. That may happen when entering a folder
|
|
||||||
// with the same name as the first game file inside, or as in this case, when
|
|
||||||
// entering a custom collection.
|
|
||||||
mVideo->onHide();
|
|
||||||
|
|
||||||
if (!mVideo->setVideo(mRandomGame->getVideoPath()))
|
|
||||||
mVideo->setDefaultVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mThumbnail.setImage("");
|
|
||||||
mMarquee.setImage("");
|
|
||||||
mImage.setImage("");
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
mVideo->setImage("");
|
|
||||||
mVideo->setVideo("");
|
|
||||||
mVideo->setDefaultVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mThumbnail.setImage(file->getThumbnailPath());
|
|
||||||
mMarquee.setImage(file->getMarqueePath(), false, true);
|
|
||||||
mImage.setImage(file->getImagePath());
|
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
mVideo->setImage(file->getImagePath());
|
|
||||||
mVideo->onHide();
|
|
||||||
|
|
||||||
if (!mVideo->setVideo(file->getVideoPath()))
|
|
||||||
mVideo->setDefaultVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mVideoPlaying = true;
|
|
||||||
|
|
||||||
// Populate the gamelistInfo field which shows an icon if a folder has been entered
|
|
||||||
// as well as the game count for the entire system (total and favorites separately).
|
|
||||||
// If a filter has been applied, then the number of filtered and total games replaces
|
|
||||||
// the game counter.
|
|
||||||
std::string gamelistInfoString;
|
|
||||||
Alignment infoAlign = mGamelistInfo.getHorizontalAlignment();
|
|
||||||
|
|
||||||
if (mIsFolder && infoAlign == ALIGN_RIGHT)
|
|
||||||
gamelistInfoString = ViewController::FOLDER_CHAR + " ";
|
|
||||||
|
|
||||||
if (mIsFiltered) {
|
|
||||||
if (mFilteredGameCountAll == mFilteredGameCount)
|
|
||||||
gamelistInfoString += ViewController::FILTER_CHAR + " " +
|
|
||||||
std::to_string(mFilteredGameCount) + " / " +
|
|
||||||
std::to_string(mGameCount);
|
|
||||||
else
|
|
||||||
gamelistInfoString += ViewController::FILTER_CHAR + " " +
|
|
||||||
std::to_string(mFilteredGameCount) + " + " +
|
|
||||||
std::to_string(mFilteredGameCountAll - mFilteredGameCount) +
|
|
||||||
" / " + std::to_string(mGameCount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gamelistInfoString +=
|
|
||||||
ViewController::CONTROLLER_CHAR + " " + std::to_string(mGameCount);
|
|
||||||
if (!(file->getSystem()->isCollection() &&
|
|
||||||
file->getSystem()->getFullName() == "favorites"))
|
|
||||||
gamelistInfoString += " " + ViewController::FAVORITE_CHAR + " " +
|
|
||||||
std::to_string(mFavoritesGameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsFolder && infoAlign != ALIGN_RIGHT)
|
|
||||||
gamelistInfoString += " " + ViewController::FOLDER_CHAR;
|
|
||||||
|
|
||||||
mGamelistInfo.setValue(gamelistInfoString);
|
|
||||||
|
|
||||||
if (mViewStyle == ViewController::DETAILED) {
|
|
||||||
// Fade in the game image.
|
|
||||||
auto func = [this](float t) {
|
|
||||||
mImage.setOpacity(static_cast<unsigned char>(
|
|
||||||
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
|
||||||
};
|
|
||||||
mImage.setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false);
|
|
||||||
}
|
|
||||||
else if (mViewStyle == ViewController::VIDEO) {
|
|
||||||
// Fade in the static image.
|
|
||||||
auto func = [this](float t) {
|
|
||||||
mVideo->setOpacity(static_cast<unsigned char>(
|
|
||||||
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
|
||||||
};
|
|
||||||
mVideo->setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mDescription.setText(file->metadata.get("desc"));
|
|
||||||
mDescContainer.reset();
|
|
||||||
|
|
||||||
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"));
|
|
||||||
|
|
||||||
// Populate the badge slots based on game metadata.
|
|
||||||
std::vector<BadgeComponent::BadgeInfo> badgeSlots;
|
|
||||||
for (auto badge : mBadges.getBadgeTypes()) {
|
|
||||||
BadgeComponent::BadgeInfo badgeInfo;
|
|
||||||
badgeInfo.badgeType = badge;
|
|
||||||
if (badge == "controller") {
|
|
||||||
if (file->metadata.get("controller").compare("") != 0) {
|
|
||||||
badgeInfo.gameController = file->metadata.get("controller");
|
|
||||||
badgeSlots.push_back(badgeInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (badge == "altemulator") {
|
|
||||||
if (file->metadata.get(badge).compare("") != 0)
|
|
||||||
badgeSlots.push_back(badgeInfo);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (file->metadata.get(badge).compare("true") == 0)
|
|
||||||
badgeSlots.push_back(badgeInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mBadges.setBadges(badgeSlots);
|
|
||||||
|
|
||||||
mName.setValue(file->metadata.get("name"));
|
|
||||||
|
|
||||||
if (file->getType() == GAME) {
|
|
||||||
if (!hideMetaDataFields) {
|
|
||||||
mLastPlayed.setValue(file->metadata.get("lastplayed"));
|
|
||||||
mPlayCount.setValue(file->metadata.get("playcount"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (file->getType() == FOLDER) {
|
|
||||||
if (!hideMetaDataFields) {
|
|
||||||
mLastPlayed.setValue(file->metadata.get("lastplayed"));
|
|
||||||
mLblPlayCount.setVisible(false);
|
|
||||||
mPlayCount.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fadingOut = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GuiComponent*> comps = getMDValues();
|
|
||||||
comps.push_back(&mThumbnail);
|
|
||||||
comps.push_back(&mMarquee);
|
|
||||||
comps.push_back(&mImage);
|
|
||||||
comps.push_back(&mDescription);
|
|
||||||
comps.push_back(&mName);
|
|
||||||
comps.push_back(&mBadges);
|
|
||||||
std::vector<TextComponent*> labels = getMDLabels();
|
|
||||||
comps.insert(comps.cend(), labels.cbegin(), labels.cend());
|
|
||||||
|
|
||||||
for (auto it = comps.cbegin(); it != comps.cend(); ++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(static_cast<unsigned char>(glm::mix(0.0f, 1.0f, t) * 255));
|
|
||||||
};
|
|
||||||
comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GamelistView::initMDLabels()
|
|
||||||
{
|
|
||||||
std::vector<TextComponent*> components {getMDLabels()};
|
|
||||||
|
|
||||||
const unsigned int colCount {2};
|
|
||||||
const unsigned int rowCount {static_cast<unsigned int>(components.size() / 2)};
|
|
||||||
|
|
||||||
glm::vec3 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;
|
|
||||||
glm::vec3 pos {};
|
|
||||||
if (row == 0) {
|
|
||||||
pos = start + glm::vec3 {colSize * (i / rowCount), 0.0f, 0.0f};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Work from the last component.
|
|
||||||
GuiComponent* lc {components[i - 1]};
|
|
||||||
pos = lc->getPosition() + glm::vec3 {0.0f, lc->getSize().y + rowPadding, 0.0f};
|
|
||||||
}
|
|
||||||
|
|
||||||
components[i]->setFont(Font::get(FONT_SIZE_SMALL));
|
|
||||||
components[i]->setPosition(pos);
|
|
||||||
components[i]->setDefaultZIndex(40.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GamelistView::initMDValues()
|
|
||||||
{
|
|
||||||
std::vector<TextComponent*> labels {getMDLabels()};
|
|
||||||
std::vector<GuiComponent*> values {getMDValues()};
|
|
||||||
|
|
||||||
std::shared_ptr<Font> defaultFont {Font::get(FONT_SIZE_SMALL)};
|
|
||||||
mRating.setSize(defaultFont->getHeight() * 5.0f, static_cast<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.0f};
|
|
||||||
for (unsigned int i = 0; i < labels.size(); ++i) {
|
|
||||||
const float heightDiff = (labels[i]->getSize().y - values[i]->getSize().y) / 2.0f;
|
|
||||||
values[i]->setPosition(labels[i]->getPosition() +
|
|
||||||
glm::vec3 {labels[i]->getSize().x, heightDiff, 0.0f});
|
|
||||||
values[i]->setSize(colSize - labels[i]->getSize().x, values[i]->getSize().y);
|
|
||||||
values[i]->setDefaultZIndex(40.0f);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TextComponent*> GamelistView::getMDLabels()
|
|
||||||
{
|
|
||||||
std::vector<TextComponent*> 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<GuiComponent*> GamelistView::getMDValues()
|
|
||||||
{
|
|
||||||
std::vector<GuiComponent*> 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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
class GamelistView : public GamelistBase
|
class GamelistView : public GamelistBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GamelistView(FileData* root);
|
GamelistView(FileData* root, bool legacyMode = false);
|
||||||
~GamelistView();
|
~GamelistView();
|
||||||
|
|
||||||
// Called when a FileData* is added, has its metadata changed, or is removed.
|
// Called when a FileData* is added, has its metadata changed, or is removed.
|
||||||
|
@ -36,7 +36,6 @@ public:
|
||||||
case ViewController::DETAILED:
|
case ViewController::DETAILED:
|
||||||
return "detailed";
|
return "detailed";
|
||||||
case ViewController::BASIC:
|
case ViewController::BASIC:
|
||||||
return "basic";
|
|
||||||
default:
|
default:
|
||||||
return "basic";
|
return "basic";
|
||||||
}
|
}
|
||||||
|
@ -59,49 +58,61 @@ public:
|
||||||
private:
|
private:
|
||||||
void updateInfoPanel();
|
void updateInfoPanel();
|
||||||
|
|
||||||
void initMDLabels();
|
// Legacy (backward compatibility) functions.
|
||||||
void initMDValues();
|
void legacyPopulateFields();
|
||||||
|
void legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme);
|
||||||
|
void legacyUpdateInfoPanel();
|
||||||
|
void legacyUpdate(int deltaTime);
|
||||||
|
void legacyInitMDLabels();
|
||||||
|
void legacyInitMDValues();
|
||||||
|
|
||||||
|
bool mLegacyMode;
|
||||||
ViewController::GamelistViewStyle mViewStyle;
|
ViewController::GamelistViewStyle mViewStyle;
|
||||||
|
|
||||||
std::vector<TextComponent*> getMDLabels();
|
|
||||||
std::vector<GuiComponent*> getMDValues();
|
|
||||||
|
|
||||||
std::shared_ptr<ThemeData> mTheme;
|
std::shared_ptr<ThemeData> mTheme;
|
||||||
std::vector<GuiComponent*> mThemeExtras;
|
std::vector<GuiComponent*> mThemeExtras;
|
||||||
|
|
||||||
TextComponent mHeaderText;
|
std::vector<std::unique_ptr<TextComponent>> mTextComponents;
|
||||||
ImageComponent mHeaderImage;
|
std::vector<std::unique_ptr<DateTimeComponent>> mDateTimeComponents;
|
||||||
ImageComponent mBackground;
|
std::vector<std::unique_ptr<ImageComponent>> mImageComponents;
|
||||||
|
std::vector<std::unique_ptr<VideoFFmpegComponent>> mVideoComponents;
|
||||||
|
std::vector<std::unique_ptr<BadgeComponent>> mBadgeComponents;
|
||||||
|
std::vector<std::unique_ptr<RatingComponent>> mRatingComponents;
|
||||||
|
std::vector<std::unique_ptr<ScrollableContainer>> mScrollableContainerComponents;
|
||||||
|
std::vector<std::unique_ptr<TextComponent>> mGamelistInfoComponents;
|
||||||
|
|
||||||
ImageComponent mThumbnail;
|
enum LegacyText {
|
||||||
ImageComponent mMarquee;
|
LOGOTEXT = 0,
|
||||||
ImageComponent mImage;
|
MD_LBL_RATING = 1,
|
||||||
VideoComponent* mVideo;
|
MD_LBL_RELEASEDATE = 2,
|
||||||
|
MD_LBL_DEVELOPER = 3,
|
||||||
|
MD_LBL_PUBLISHER = 4,
|
||||||
|
MD_LBL_GENRE = 5,
|
||||||
|
MD_LBL_PLAYERS = 6,
|
||||||
|
MD_LBL_LASTPLAYED = 7,
|
||||||
|
MD_LBL_PLAYCOUNT = 8,
|
||||||
|
MD_DEVELOPER = 9,
|
||||||
|
MD_PUBLISHER = 10,
|
||||||
|
MD_GENRE = 11,
|
||||||
|
MD_PLAYERS = 12,
|
||||||
|
MD_PLAYCOUNT = 13,
|
||||||
|
MD_NAME = 14,
|
||||||
|
MD_DESCRIPTION = 15,
|
||||||
|
END
|
||||||
|
};
|
||||||
|
|
||||||
TextComponent mLblRating;
|
enum LegacyDateTime {
|
||||||
TextComponent mLblReleaseDate;
|
MD_RELEASEDATE = 0, //
|
||||||
TextComponent mLblDeveloper;
|
MD_LASTPLAYED = 1
|
||||||
TextComponent mLblPublisher;
|
};
|
||||||
TextComponent mLblGenre;
|
|
||||||
TextComponent mLblPlayers;
|
|
||||||
TextComponent mLblLastPlayed;
|
|
||||||
TextComponent mLblPlayCount;
|
|
||||||
|
|
||||||
RatingComponent mRating;
|
enum LegacyImage {
|
||||||
DateTimeComponent mReleaseDate;
|
LOGO = 0, //
|
||||||
TextComponent mDeveloper;
|
BACKGROUND = 1,
|
||||||
TextComponent mPublisher;
|
MD_THUMBNAIL = 2,
|
||||||
TextComponent mGenre;
|
MD_MARQUEE = 3,
|
||||||
TextComponent mPlayers;
|
MD_IMAGE = 4
|
||||||
DateTimeComponent mLastPlayed;
|
};
|
||||||
TextComponent mPlayCount;
|
|
||||||
TextComponent mName;
|
|
||||||
BadgeComponent mBadges;
|
|
||||||
|
|
||||||
ScrollableContainer mDescContainer;
|
|
||||||
TextComponent mDescription;
|
|
||||||
TextComponent mGamelistInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_APP_VIEWS_GAMELIST_VIEW_H
|
#endif // ES_APP_VIEWS_GAMELIST_VIEW_H
|
||||||
|
|
Loading…
Reference in a new issue