Decreased CPU usage dramatically and fixed multiple UI navigation glitches.

Also did some code cleanup.
This commit is contained in:
Leon Styhre 2020-09-15 22:57:54 +02:00
parent a6430ff0ff
commit ae7c9dabb8
18 changed files with 261 additions and 168 deletions

View file

@ -56,6 +56,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Refactoring, cleanup and documentation of the source code, removal of deprecated files etc.
* All required fonts bundled with the application, no dependencies on the OS to provide them any longer
* Made pugixml an external dependency instead of bundling it
* Decreased CPU usage dramatically by only rendering the currently visible view (previously every view were always rendered)
* Updated the CMake/CPack install and package build script to work as expected (it can now generate .deb, .rpm, .dmg and NSIS installation packages)
* Added support for Clang/LLVM, made the application build with no errors or warnings using this compiler (Unix and macOS only)
* License files included for all the libraries and resources that are bundled with the application
@ -79,6 +80,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
* The random game selection traversed folders, i.e. a game could be selected inside a subdirectory and vice versa
* Deleting a game from the metadata editor did not delete the game media files or the entry in the gamelist.xml file
* SystemView didn't properly loop the systems if only two systems were available
* When changing to the video view style from inside a gamelist, the view was not initialized
* Hidden files still showed up if they had a gamelist.xml entry
* Fixed an annoying gamelist issue that caused the game images and data to be updated and rendered up to six times every time the list was scrolled
* VRAM statistics overlay was somewhat broken and incorrectly displayed numbers in megabytes instead of mebibytes

View file

@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// MoveCameraAnimation.h
//
// Animation to play when moving the camera, used by the slide transition style
// (when moving between gamelists using quick system select).
// Animation to play when moving the camera, used by the slide transition style.
//
#pragma once
#ifndef ES_APP_ANIMATIONS_MOVE_CAMERA_ANIMATION_H
#define ES_APP_ANIMATIONS_MOVE_CAMERA_ANIMATION_H

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiGamelistOptions.cpp
//
// Gamelist options menu for the 'Jump to...' quick selector,
@ -19,8 +21,8 @@
#include "FileFilterIndex.h"
#include "FileSorts.h"
#include "GuiMetaDataEd.h"
#include "SystemData.h"
#include "Sound.h"
#include "SystemData.h"
GuiGamelistOptions::GuiGamelistOptions(
Window* window,
@ -177,6 +179,11 @@ GuiGamelistOptions::GuiGamelistOptions(
GuiGamelistOptions::~GuiGamelistOptions()
{
// This is required for the situation where scrolling started just before the menu
// was openened. Without this, the scrolling would run until manually stopped after
// the menu has been closed.
ViewController::get()->stopScrolling();
if (mCancelled)
return;

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiGamelistOptions.h
//
// Gamelist options menu for the 'Jump to...' quick selector,
@ -8,15 +10,14 @@
// metadata edit interface is covered by GuiMetaDataEd.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H
#define ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H
#include "components/MenuComponent.h"
#include "components/OptionListComponent.h"
#include "utils/StringUtil.h"
#include "FileData.h"
#include "GuiComponent.h"
#include "utils/StringUtil.h"
class IGameListView;
class SystemData;

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiMenu.cpp
//
// Main menu.
@ -17,9 +19,9 @@
#include "guis/GuiMsgBox.h"
#include "guis/GuiScraperMenu.h"
#include "guis/GuiSettings.h"
#include "views/gamelist/IGameListView.h"
#include "views/UIModeController.h"
#include "views/ViewController.h"
#include "views/gamelist/IGameListView.h"
#include "CollectionSystemManager.h"
#include "EmulationStation.h"
#include "FileSorts.h"
@ -63,6 +65,14 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window),
Renderer::getScreenHeight() * 0.15f);
}
GuiMenu::~GuiMenu()
{
// This is required for the situation where scrolling started just before the menu
// was openened. Without this, the scrolling would run until manually stopped after
// the menu has been closed.
ViewController::get()->stopScrolling();
}
void GuiMenu::openScraperSettings()
{
// Open the scrape menu.

View file

@ -1,11 +1,12 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiMenu.h
//
// Main menu.
// Some submenus are covered in separate source files.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_MENU_H
#define ES_APP_GUIS_GUI_MENU_H
@ -16,6 +17,7 @@ class GuiMenu : public GuiComponent
{
public:
GuiMenu(Window* window);
~GuiMenu();
bool input(InputConfig* config, Input input) override;
void onSizeChanged() override;

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// SystemView.cpp
//
// Main system view.
@ -177,10 +179,12 @@ bool SystemView::input(InputConfig* config, Input input)
case VERTICAL:
case VERTICAL_WHEEL:
if (config->isMappedLike("up", input)) {
ViewController::get()->resetMovingCamera();
listInput(-1);
return true;
}
if (config->isMappedLike("down", input)) {
ViewController::get()->resetMovingCamera();
listInput(1);
return true;
}
@ -189,10 +193,12 @@ bool SystemView::input(InputConfig* config, Input input)
case HORIZONTAL_WHEEL:
default:
if (config->isMappedLike("left", input)) {
ViewController::get()->resetMovingCamera();
listInput(-1);
return true;
}
if (config->isMappedLike("right", input)) {
ViewController::get()->resetMovingCamera();
listInput(1);
return true;
}

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// SystemView.h
//
// Main system view.
//
#pragma once
#ifndef ES_APP_VIEWS_SYSTEM_VIEW_H
#define ES_APP_VIEWS_SYSTEM_VIEW_H

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// ViewController.cpp
//
// Handles overall system navigation including animations and transitions.
@ -11,14 +13,13 @@
#include "animations/Animation.h"
#include "animations/LambdaAnimation.h"
#include "animations/LaunchAnimation.h"
#include "animations/MoveCameraAnimation.h"
#include "guis/GuiInfoPopup.h"
#include "guis/GuiMenu.h"
#include "guis/GuiMsgBox.h"
#include "views/gamelist/DetailedGameListView.h"
#include "views/gamelist/IGameListView.h"
#include "views/gamelist/GridGameListView.h"
#include "views/gamelist/IGameListView.h"
#include "views/gamelist/VideoGameListView.h"
#include "views/SystemView.h"
#include "views/UIModeController.h"
@ -111,28 +112,59 @@ void ViewController::ReloadAndGoToStart()
ViewController::get()->goToStart();
}
bool ViewController::isCameraMoving()
{
if (mCurrentView) {
if (mCamera.r3().x() != -mCurrentView->getPosition().x() ||
mCamera.r3().y() != -mCurrentView->getPosition().y())
return true;
}
return false;
}
void ViewController::resetMovingCamera()
{
if (isCameraMoving()) {
mCamera.r3().x() = -mCurrentView->getPosition().x();
mCamera.r3().y() = -mCurrentView->getPosition().y();
stopAllAnimations();
}
}
void ViewController::stopScrolling()
{
mSystemListView->stopScrolling();
mCurrentView->stopListScrolling();
if (mSystemListView->isAnimationPlaying(0))
mSystemListView->finishAnimation(0);
}
int ViewController::getSystemId(SystemData* system)
{
std::vector<SystemData*>& sysVec = SystemData::sSystemVector;
return (int)(std::find(sysVec.cbegin(), sysVec.cend(), system) - sysVec.cbegin());
return static_cast<int>(std::find(sysVec.cbegin(), sysVec.cend(), system) - sysVec.cbegin());
}
void ViewController::goToSystemView(SystemData* system)
{
// Tell any current view it's about to be hidden.
if (mCurrentView)
// Tell any current view it's about to be hidden and stop its rendering.
if (mCurrentView) {
mCurrentView->onHide();
mCurrentView->setRenderView(false);
}
mState.viewing = SYSTEM_SELECT;
mState.system = system;
auto systemList = getSystemListView();
systemList->setPosition(getSystemId(system) * (float)Renderer::getScreenWidth(),
systemList->setPosition(getSystemId(system) * static_cast<float>(Renderer::getScreenWidth()),
systemList->getPosition().y());
systemList->goToSystem(system, false);
mCurrentView = systemList;
mCurrentView->onShow();
mCurrentView->setRenderView(true);
PowerSaver::setState(true);
playViewTransition();
@ -158,13 +190,29 @@ void ViewController::goToPrevGameList()
void ViewController::goToGameList(SystemData* system)
{
// Stop any scrolling, animations and camera movements.
if (mSystemListView) {
mSystemListView->stopScrolling();
if (mSystemListView->isAnimationPlaying(0))
mSystemListView->finishAnimation(0);
}
resetMovingCamera();
// Disable rendering of the system view.
if (getSystemListView()->getRenderView())
getSystemListView()->setRenderView(false);
// If switching between gamelists, disable rendering of the current view.
if (mCurrentView)
mCurrentView->setRenderView(false);
if (mState.viewing == SYSTEM_SELECT) {
// Move system list.
auto sysList = getSystemListView();
float offX = sysList->getPosition().x();
int sysId = getSystemId(system);
sysList->setPosition(sysId * (float)Renderer::getScreenWidth(),
sysList->setPosition(sysId * static_cast<float>(Renderer::getScreenWidth()),
sysList->getPosition().y());
offX = sysList->getPosition().x() - offX;
mCamera.translation().x() -= offX;
@ -178,8 +226,10 @@ void ViewController::goToGameList(SystemData* system)
mCurrentView = getGameListView(system);
if (mCurrentView)
if (mCurrentView) {
mCurrentView->onShow();
mCurrentView->setRenderView(true);
}
playViewTransition();
}
@ -218,10 +268,10 @@ void ViewController::playViewTransition()
// Not changing screens, so cancel the first half entirely.
advanceAnimation(0, FADE_DURATION);
advanceAnimation(0, FADE_WAIT);
advanceAnimation(0, FADE_DURATION - (int)(mFadeOpacity * FADE_DURATION));
advanceAnimation(0, FADE_DURATION - static_cast<int>(mFadeOpacity * FADE_DURATION));
}
else {
advanceAnimation(0, (int)(mFadeOpacity * FADE_DURATION));
advanceAnimation(0, static_cast<int>(mFadeOpacity * FADE_DURATION));
}
}
else if (transition_style == "slide") {
@ -247,90 +297,43 @@ void ViewController::onFileChanged(FileData* file, FileChangeType change)
void ViewController::launch(FileData* game, Vector3f center)
{
if (game->getType() != GAME) {
LOG(LogError) << "tried to launch something that isn't a game";
LOG(LogError) << "tried to launch something that isn't a game.";
return;
}
// Hide the current view.
// If the video view style is used, pause the video currently playing or block the
// video from starting to play if the static image is still shown.
if (mCurrentView)
mCurrentView->onHide();
mCurrentView->onPauseVideo();
Transform4x4f origCamera = mCamera;
origCamera.translation() = -mCurrentView->getPosition();
center += mCurrentView->getPosition();
stopAnimation(1); // Make sure the fade in isn't still playing.
mWindow->stopInfoPopup(); // Make sure we disable any existing info popup.
mLockInput = true;
// TEMPORARY - Until a proper game launch screen is implemented, at least this
// will let the user know that something is actually happening (in addition
// to the launch sound, if navigation sounds are enabled).
// Until a proper game launch screen is implemented, at least this will let the
// user know that something is actually happening (in addition to the launch sound,
// if navigation sounds are enabled).
GuiInfoPopup* s = new GuiInfoPopup(mWindow, "LAUNCHING GAME '" +
Utils::String::toUpper(game->metadata.get("name") + "'"), 10000);
mWindow->setInfoPopup(s);
std::string transition_style = Settings::getInstance()->getString("TransitionStyle");
NavigationSounds::getInstance()->playThemeNavigationSound(LAUNCHSOUND);
// Let launch sound play to the end before launching game.
while (NavigationSounds::getInstance()->isPlayingThemeNavigationSound(LAUNCHSOUND));
// TEMPORARY - disabled the launch animations as they don't work properly and more
// work is needed to fix them. This has been done in LaunchAnimation.h instead of here,
// as not calling the animation leads to input not being properly consumed. This also
// needs to be fixed later on.
setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 1500), 0,
[this, origCamera, center, game] {
// This is just a dummy animation in order for the launch notification popup to be
// displayed briefly, and for the navigation sound playing to be able to complete.
// During this time period, all user input is blocked.
setAnimation(new LambdaAnimation([](float t){}, 1700), 0, [this, game] {
while (NavigationSounds::getInstance()->isPlayingThemeNavigationSound(LAUNCHSOUND));
game->launchGame(mWindow);
mCamera = origCamera;
setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 600), 0, [this] {
mLockInput = false; }, true);
this->onFileChanged(game, FILE_METADATA_CHANGED);
onFileChanged(game, FILE_METADATA_CHANGED);
if (mCurrentView)
mCurrentView->onShow();
// This is a workaround so that any key or button presses used for exiting the emulator
// are not captured upon returning to ES.
setAnimation(new LambdaAnimation([](float t){}, 1), 0, [this] {
mLockInput = false;
});
});
// if (transition_style == "fade") {
// // Fade out, launch game, fade back in.
// auto fadeFunc = [this](float t) {
// mFadeOpacity = Math::lerp(0.0f, 1.0f, t);
// };
// setAnimation(new LambdaAnimation(fadeFunc, 800), 0, [this, game, fadeFunc] {
// game->launchGame(mWindow);
// setAnimation(new LambdaAnimation(fadeFunc, 800), 0, [this] {
// mLockInput = false; }, true);
// this->onFileChanged(game, FILE_METADATA_CHANGED);
// if (mCurrentView)
// mCurrentView->onShow();
// });
// }
// else if (transition_style == "slide") {
// // Move camera to zoom in on center + fade out, launch game, come back in.
// setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 1500), 0,
// [this, origCamera, center, game] {
// game->launchGame(mWindow);
// mCamera = origCamera;
// setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 600), 0, [this] {
// mLockInput = false; }, true);
// this->onFileChanged(game, FILE_METADATA_CHANGED);
// if (mCurrentView)
// mCurrentView->onShow();
// });
// }
// // Instant
// else {
// setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 10), 0,
// [this, origCamera, center, game] {
// game->launchGame(mWindow);
// mCamera = origCamera;
// setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 10), 0,
// [this] { mLockInput = false; }, true);
// this->onFileChanged(game, FILE_METADATA_CHANGED);
// if (mCurrentView)
// mCurrentView->onShow();
// });
// }
}
void ViewController::removeGameListView(SystemData* system)
@ -344,46 +347,46 @@ void ViewController::removeGameListView(SystemData* system)
std::shared_ptr<IGameListView> ViewController::getGameListView(SystemData* system)
{
// If we already made one, return that one.
// If we have already created an entry for this system, then return that one.
auto exists = mGameListViews.find(system);
if (exists != mGameListViews.cend())
return exists->second;
system->getIndex()->setUIModeFilters();
// If we didn't, make it, remember it, and return it.
// If there's no entry, then create it and return it.
std::shared_ptr<IGameListView> view;
bool themeHasVideoView = system->getTheme()->hasView("video");
// Decide type.
GameListViewType selectedViewType = AUTOMATIC;
// Decide which view style to use.
GameListViewType selectedViewStyle = AUTOMATIC;
std::string viewPreference = Settings::getInstance()->getString("GamelistViewStyle");
if (viewPreference.compare("basic") == 0)
selectedViewType = BASIC;
selectedViewStyle = BASIC;
if (viewPreference.compare("detailed") == 0)
selectedViewType = DETAILED;
selectedViewStyle = DETAILED;
if (viewPreference.compare("grid") == 0)
selectedViewType = GRID;
selectedViewStyle = GRID;
if (viewPreference.compare("video") == 0)
selectedViewType = VIDEO;
selectedViewStyle = VIDEO;
if (selectedViewType == AUTOMATIC) {
if (selectedViewStyle == AUTOMATIC) {
std::vector<FileData*> files = system->getRootFolder()->getFilesRecursive(GAME | FOLDER);
for (auto it = files.cbegin(); it != files.cend(); it++) {
if (themeHasVideoView && !(*it)->getVideoPath().empty()) {
selectedViewType = VIDEO;
selectedViewStyle = VIDEO;
break;
}
else if (!(*it)->getImagePath().empty()) {
selectedViewType = DETAILED;
selectedViewStyle = DETAILED;
// Don't break out in case any subsequent files have videos.
}
}
}
// Create the view.
switch (selectedViewType)
switch (selectedViewStyle)
{
case VIDEO:
view = std::shared_ptr<IGameListView>(
@ -407,9 +410,10 @@ std::shared_ptr<IGameListView> ViewController::getGameListView(SystemData* syste
view->setTheme(system->getTheme());
std::vector<SystemData*>& sysVec = SystemData::sSystemVector;
int id = (int)(std::find(sysVec.cbegin(), sysVec.cend(), system) - sysVec.cbegin());
view->setPosition(id * (float)Renderer::getScreenWidth(),
(float)Renderer::getScreenHeight() * 2);
int id = static_cast<int>(
std::find(sysVec.cbegin(), sysVec.cend(), system) - sysVec.cbegin());
view->setPosition(id * static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight() * 2));
addChild(view.get());
@ -419,13 +423,13 @@ std::shared_ptr<IGameListView> ViewController::getGameListView(SystemData* syste
std::shared_ptr<SystemView> ViewController::getSystemListView()
{
// If we already made one, return that one.
// If we have already created a system view entry, then return it.
if (mSystemListView)
return mSystemListView;
mSystemListView = std::shared_ptr<SystemView>(new SystemView(mWindow));
addChild(mSystemListView.get());
mSystemListView->setPosition(0, (float)Renderer::getScreenHeight());
mSystemListView->setPosition(0, static_cast<float>(Renderer::getScreenHeight()));
return mSystemListView;
}
@ -447,7 +451,7 @@ bool ViewController::input(InputConfig* config, Input input)
}
#endif
// Open menu.
// Open the main menu.
if (!(UIModeController::getInstance()->isUIModeKid() &&
!Settings::getInstance()->getBool("ShowKidStartMenu")) &&
config->isMappedTo("start", input) && input.value != 0) {
@ -461,8 +465,9 @@ bool ViewController::input(InputConfig* config, Input input)
mSystemListView->finishAnimation(0);
// Stop the gamelist scrolling as well as it would otherwise
// also continue to run after closing the menu.
if (mCurrentView->isListScrolling())
mCurrentView->stopListScrolling();
mCurrentView->stopListScrolling();
// Finally, if the camera is currently moving, reset its position.
resetMovingCamera();
mWindow->pushGui(new GuiMenu(mWindow));
return true;
@ -494,25 +499,32 @@ void ViewController::render(const Transform4x4f& parentTrans)
// Camera position, position + size.
Vector3f viewStart = transInverse.translation();
Vector3f viewEnd = transInverse * Vector3f((float)Renderer::getScreenWidth(),
(float)Renderer::getScreenHeight(), 0);
Vector3f viewEnd = transInverse * Vector3f(static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight(), 0));
// Keep track of UI mode changes.
UIModeController::getInstance()->monitorUIMode();
// Draw system view.
getSystemListView()->render(trans);
// Draw the system view if it's flagged to be rendered.
// If the camera is moving, we're transitioning and in that case render it regardless
// of whether it's flagged for rendering or not. (Otherwise there will be a black portion
// shown on the screen during the animation).
if (getSystemListView()->getRenderView() || isCameraMoving())
getSystemListView()->render(trans);
// Draw gamelists.
// Draw the gamelists.
for (auto it = mGameListViews.cbegin(); it != mGameListViews.cend(); it++) {
// Clipping.
Vector3f guiStart = it->second->getPosition();
Vector3f guiEnd = it->second->getPosition() + Vector3f(it->second->getSize().x(),
it->second->getSize().y(), 0);
// Same thing as for the system view, limit the rendering only to what needs to be drawn.
if (it->second->getRenderView() || isCameraMoving()) {
// Clipping.
Vector3f guiStart = it->second->getPosition();
Vector3f guiEnd = it->second->getPosition() + Vector3f(it->second->getSize().x(),
it->second->getSize().y(), 0);
if (guiEnd.x() >= viewStart.x() && guiEnd.y() >= viewStart.y() &&
guiStart.x() <= viewEnd.x() && guiStart.y() <= viewEnd.y())
it->second->render(trans);
if (guiEnd.x() >= viewStart.x() && guiEnd.y() >= viewStart.y() &&
guiStart.x() <= viewEnd.x() && guiStart.y() <= viewEnd.y())
it->second->render(trans);
}
}
if (mWindow->peekGui() == this)
@ -520,7 +532,7 @@ void ViewController::render(const Transform4x4f& parentTrans)
// Fade out.
if (mFadeOpacity) {
unsigned int fadeColor = 0x00000000 | (unsigned char)(mFadeOpacity * 255);
unsigned int fadeColor = 0x00000000 | static_cast<unsigned char>(mFadeOpacity * 255);
Renderer::setMatrix(parentTrans);
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(),
Renderer::getScreenHeight(), fadeColor, fadeColor);
@ -529,23 +541,21 @@ void ViewController::render(const Transform4x4f& parentTrans)
void ViewController::preload()
{
uint32_t i = 0;
for (auto it = SystemData::sSystemVector.cbegin();
it != SystemData::sSystemVector.cend(); it++) {
if (Settings::getInstance()->getBool("SplashScreen") &&
Settings::getInstance()->getBool("SplashScreenProgress")) {
i++;
char buffer[100];
sprintf (buffer, "Loading '%s' (%d/%d)",
(*it)->getFullName().c_str(), i, (int)SystemData::sSystemVector.size());
mWindow->renderLoadingScreen(std::string(buffer));
}
unsigned int systemCount = SystemData::sSystemVector.size();
for (auto it = SystemData::sSystemVector.cbegin();
it != SystemData::sSystemVector.cend(); it ++) {
if (Settings::getInstance()->getBool("SplashScreen") &&
Settings::getInstance()->getBool("SplashScreenProgress")) {
mWindow->renderLoadingScreen("Loading '" + (*it)->getFullName() + "' (" +
std::to_string(std::distance(SystemData::sSystemVector.cbegin(), it)+1) +
"/" + std::to_string(systemCount) + ")");
}
(*it)->getIndex()->resetFilters();
getGameListView(*it);
}
// Load navigation sounds, but only if at least one system exists.
if (SystemData::sSystemVector.size() > 0)
if (systemCount > 0)
NavigationSounds::getInstance()->loadThemeNavigationSounds(
SystemData::sSystemVector.front()->getTheme());
}
@ -587,8 +597,10 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
#endif
// Redisplay the current view.
if (mCurrentView)
if (mCurrentView) {
mCurrentView->onShow();
mCurrentView->setRenderView(true);
}
}
void ViewController::reloadAll()
@ -630,6 +642,8 @@ void ViewController::reloadAll()
NavigationSounds::getInstance()->loadThemeNavigationSounds(
SystemData::sSystemVector.front()->getTheme());
mCurrentView->onShow();
mCurrentView->setRenderView(true);
updateHelpPrompts();
}

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// ViewController.h
//
// Handles overall system navigation including animations and transitions.
@ -7,13 +9,13 @@
// Initiates the launching of games, calling FileData to do the actual launch.
//
#pragma once
#ifndef ES_APP_VIEWS_VIEW_CONTROLLER_H
#define ES_APP_VIEWS_VIEW_CONTROLLER_H
#include "renderers/Renderer.h"
#include "FileData.h"
#include "GuiComponent.h"
#include <vector>
class IGameListView;
@ -51,10 +53,13 @@ public:
void goToStart();
void ReloadAndGoToStart();
// Functions to make the GUI behave properly.
bool isCameraMoving();
void resetMovingCamera();
void stopScrolling();
void onFileChanged(FileData* file, FileChangeType change);
// Plays a nice launch effect and launches the game at the end of it.
// Once the game terminates, plays a return effect.
void launch(FileData* game, Vector3f centerCameraOn =
Vector3f(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f, 0));

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// IGameListView.cpp
//
// Interface that defines the minimum for a GameListView.
@ -17,8 +19,8 @@ bool IGameListView::input(InputConfig* config, Input input)
// Select button opens GuiGamelistOptions.
if (!UIModeController::getInstance()->isUIModeKid() &&
config->isMappedTo("select", input) && input.value) {
if (isListScrolling())
stopListScrolling();
ViewController::get()->resetMovingCamera();
stopListScrolling();
mWindow->pushGui(new GuiGamelistOptions(mWindow, this->mRoot->getSystem()));
return true;
}
@ -56,10 +58,10 @@ void IGameListView::render(const Transform4x4f& parentTrans)
float scaleX = trans.r0().x();
float scaleY = trans.r1().y();
Vector2i pos((int)Math::round(trans.translation()[0]),
(int)Math::round(trans.translation()[1]));
Vector2i size((int)Math::round(mSize.x() * scaleX),
(int)Math::round(mSize.y() * scaleY));
Vector2i pos(static_cast<int>(Math::round(trans.translation()[0])),
static_cast<int>(Math::round(trans.translation()[1])));
Vector2i size(static_cast<int>(Math::round(mSize.x() * scaleX)),
static_cast<int>(Math::round(mSize.y() * scaleY)));
Renderer::pushClipRect(pos, size);
renderChildren(trans);

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// IGameListView.h
//
// Interface that defines the minimum for a GameListView.
//
#pragma once
#ifndef ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H
#define ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H
@ -24,15 +25,15 @@ public:
FileData* root)
: GuiComponent(window),
mRoot(root)
{ setSize((float)Renderer::getScreenWidth(),
(float)Renderer::getScreenHeight()); }
{ setSize(static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight())); }
virtual ~IGameListView() {}
// Called when a new file is added, a file is removed, a file's metadata changes,
// or a file's children are sorted.
// NOTE: FILE_SORTED is only reported for the topmost FileData, where the sort started.
// Since sorts are recursive, that FileData's children probably changed too.
// Note: FILE_SORTED is only reported for the topmost FileData, where the sort started.
// Since sorts are recursive, FileData's children probably changed too.
virtual void onFileChanged(FileData* file, FileChangeType change) = 0;
// Called whenever the theme changes.

View file

@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// ISimpleGameListView.cpp
//
// Interface that defines a simple GameListView.
// Interface that defines a simple gamelist view.
//
#include "views/gamelist/ISimpleGameListView.h"
@ -101,13 +103,14 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
if (config->isMappedTo("a", input)) {
FileData* cursor = getCursor();
if (cursor->getType() == GAME) {
if (isListScrolling())
stopListScrolling();
ViewController::get()->resetMovingCamera();
stopListScrolling();
launch(cursor);
}
else {
// It's a folder.
if (cursor->getChildren().size() > 0) {
ViewController::get()->resetMovingCamera();
NavigationSounds::getInstance()->playThemeNavigationSound(SELECTSOUND);
mCursorStack.push(cursor);
populateList(cursor->getChildrenListToDisplay());
@ -119,6 +122,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
return true;
}
else if (config->isMappedTo("b", input)) {
ViewController::get()->resetMovingCamera();
if (mCursorStack.size()) {
NavigationSounds::getInstance()->playThemeNavigationSound(BACKSOUND);
populateList(mCursorStack.top()->getParent()->getChildren());
@ -128,8 +132,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
else {
NavigationSounds::getInstance()->playThemeNavigationSound(BACKSOUND);
onFocusLost();
if (isListScrolling())
stopListScrolling();
stopListScrolling();
SystemData* systemToView = getCursor()->getSystem();
if (systemToView->isCollection())
systemToView = CollectionSystemManager::get()->getSystemToView(systemToView);
@ -142,8 +145,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
else if (config->isMappedLike(getQuickSystemSelectRightButton(), input)) {
if (Settings::getInstance()->getBool("QuickSystemSelect")) {
onFocusLost();
if (isListScrolling())
stopListScrolling();
stopListScrolling();
ViewController::get()->goToNextGameList();
return true;
}
@ -151,16 +153,14 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
else if (config->isMappedLike(getQuickSystemSelectLeftButton(), input)) {
if (Settings::getInstance()->getBool("QuickSystemSelect")) {
onFocusLost();
if (isListScrolling())
stopListScrolling();
stopListScrolling();
ViewController::get()->goToPrevGameList();
return true;
}
}
else if (config->isMappedTo("x", input)) {
if (mRoot->getSystem()->isGameSystem() && getCursor()->getType() != PLACEHOLDER) {
if (isListScrolling())
stopListScrolling();
stopListScrolling();
// Go to random system game.
NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND);
FileData* randomGame = getCursor()->getSystem()->getRandomGame(getCursor());
@ -182,7 +182,6 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
if (mRoot->getSystem()->isGameSystem()) {
if (getCursor()->getType() == GAME || getCursor()->getType() == FOLDER)
NavigationSounds::getInstance()->playThemeNavigationSound(FAVORITESOUND);
// Marking folders as favorites is only cosmetic as they're not sorted
// differently and they're not part of any collections. So it makes more
// sense to do it here than to add the function to CollectionSystemManager.

View file

@ -1,16 +1,18 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// ISimpleGameListView.h
//
// Interface that defines a simple GameListView.
// Interface that defines a simple gamelist view.
//
#pragma once
#ifndef ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H
#define ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H
#include "components/ImageComponent.h"
#include "components/TextComponent.h"
#include "views/gamelist/IGameListView.h"
#include <stack>
class ISimpleGameListView : public IGameListView
@ -21,8 +23,8 @@ public:
// Called when a new file is added, a file is removed, a file's metadata changes,
// or a file's children are sorted.
// NOTE: FILE_SORTED is only reported for the topmost FileData, where the sort started.
// Since sorts are recursive, that FileData's children probably changed too.
// Note: FILE_SORTED is only reported for the topmost FileData, where the sort started.
// Since sorts are recursive, FileData's children probably changed too.
virtual void onFileChanged(FileData* file, FileChangeType change) override;
// Called whenever the theme changes.

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiComponent.cpp
//
// Basic GUI component handling such as placement, rotation, Z-order, rendering and animation.
@ -12,6 +14,7 @@
#include "Log.h"
#include "ThemeData.h"
#include "Window.h"
#include <algorithm>
GuiComponent::GuiComponent(Window* window)
@ -26,7 +29,8 @@ GuiComponent::GuiComponent(Window* window)
mTransform(Transform4x4f::Identity()),
mIsProcessing(false),
mVisible(true),
mEnabled(true)
mEnabled(true),
mRenderView(false)
{
for (unsigned char i = 0; i < MAX_ANIMATIONS; i++)
mAnimationMap[i] = nullptr;
@ -230,7 +234,7 @@ void GuiComponent::sortChildren()
unsigned int GuiComponent::getChildCount() const
{
return (int)mChildren.size();
return static_cast<int>(mChildren.size());
}
GuiComponent* GuiComponent::getChild(unsigned int i) const
@ -437,7 +441,8 @@ void GuiComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
const std::string& view, const std::string& element, unsigned int properties)
{
Vector2f scale = getParent() ? getParent()->getSize()
: Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
: Vector2f(static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight()));
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "");
if (!elem)
@ -511,6 +516,12 @@ void GuiComponent::onHide()
getChild(i)->onHide();
}
void GuiComponent::onPauseVideo()
{
for (unsigned int i = 0; i < getChildCount(); i++)
getChild(i)->onPauseVideo();
}
void GuiComponent::onScreenSaverActivate()
{
for (unsigned int i = 0; i < getChildCount(); i++)

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GuiComponent.h
//
// Basic GUI component handling such as placement, rotation, Z-order, rendering and animation.
@ -91,7 +93,8 @@ public:
float getRotation() const;
void setRotation(float rotation);
inline void setRotationDegrees(float rotation) { setRotation((float)ES_DEG_TO_RAD(rotation)); }
inline void setRotationDegrees(float rotation) {
setRotation(static_cast<float>(ES_DEG_TO_RAD(rotation))); }
float getScale() const;
void setScale(float scale);
@ -163,6 +166,9 @@ public:
virtual void onShow();
virtual void onHide();
virtual void onPauseVideo();
virtual void setRenderView(bool status) { mRenderView = status; }
virtual bool getRenderView() { return mRenderView; };
virtual void onScreenSaverActivate();
virtual void onScreenSaverDeactivate();
@ -221,6 +227,7 @@ protected:
bool mIsProcessing;
bool mVisible;
bool mEnabled;
bool mRenderView;
private:
// Don't access this directly! Use getTransform()!

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// VideoComponent.cpp
//
// Base class for playing videos.
@ -67,10 +69,11 @@ VideoComponent::VideoComponent(
mIsPlaying(false),
mPause(false),
mShowing(false),
mScreensaverActive(false),
mGameLaunched(false),
mDisable(false),
mScreensaverActive(false),
mScreensaverMode(false),
mGameLaunched(false),
mBlockPlayer(false),
mTargetIsMax(false),
mTargetSize(0, 0)
{
@ -236,6 +239,9 @@ std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
void VideoComponent::handleStartDelay()
{
if (mBlockPlayer)
return;
// Only play if any delay has timed out.
if (mStartDelayed) {
// If the setting to override the theme-supplied video delay setting has been enabled,
@ -284,6 +290,11 @@ void VideoComponent::startVideoWithDelay()
void VideoComponent::update(int deltaTime)
{
if (mBlockPlayer) {
setImage(mStaticImagePath);
return;
}
manageState();
// If the video start is delayed and there is less than the fade time, then set
@ -340,6 +351,8 @@ void VideoComponent::manageState()
void VideoComponent::onShow()
{
mBlockPlayer = false;
mPause = false;
mShowing = true;
manageState();
}
@ -350,6 +363,13 @@ void VideoComponent::onHide()
manageState();
}
void VideoComponent::onPauseVideo()
{
mBlockPlayer = true;
mPause = true;
manageState();
}
void VideoComponent::onScreenSaverActivate()
{
mScreensaverActive = true;

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// VideoComponent.h
//
// Base class for playing videos.
//
#pragma once
#ifndef ES_CORE_COMPONENTS_VIDEO_COMPONENT_H
#define ES_CORE_COMPONENTS_VIDEO_COMPONENT_H
@ -46,6 +47,7 @@ public:
virtual void onShow() override;
virtual void onHide() override;
virtual void onPauseVideo() override;
virtual void onScreenSaverActivate() override;
virtual void onScreenSaverDeactivate() override;
virtual void onGameLaunchedActivate() override;
@ -110,8 +112,8 @@ protected:
std::string mVideoPath;
std::string mPlayingVideoPath;
bool mStartDelayed;
unsigned mStartTime;
bool mStartDelayed;
bool mIsPlaying;
bool mPause;
bool mShowing;
@ -119,6 +121,7 @@ protected:
bool mScreensaverActive;
bool mScreensaverMode;
bool mGameLaunched;
bool mBlockPlayer;
bool mTargetIsMax;
Configuration mConfig;