mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 21:55:38 +00:00
Text scrolling now stops when launching a game and when the screensaver starts.
Also did some additional code cleanup.
This commit is contained in:
parent
254029fed6
commit
d4f5b2d20d
2
NEWS.md
2
NEWS.md
|
@ -56,7 +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.
|
* 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
|
* 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
|
* 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)
|
* Decreased CPU usage dramatically by only rendering the currently visible view (previously all views 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)
|
* 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)
|
* 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
|
* License files included for all the libraries and resources that are bundled with the application
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// FileData.cpp
|
// FileData.cpp
|
||||||
//
|
//
|
||||||
// Provides game file data structures and functions to access and sort this information.
|
// Provides game file data structures and functions to access and sort this information.
|
||||||
|
@ -39,7 +41,7 @@ FileData::FileData(
|
||||||
mParent(nullptr),
|
mParent(nullptr),
|
||||||
mOnlyFolders(false),
|
mOnlyFolders(false),
|
||||||
mDeletionFlag(false),
|
mDeletionFlag(false),
|
||||||
// Metadata is REALLY set in the constructor!
|
// Metadata is set in the constructor.
|
||||||
metadata(type == GAME ? GAME_METADATA : FOLDER_METADATA)
|
metadata(type == GAME ? GAME_METADATA : FOLDER_METADATA)
|
||||||
{
|
{
|
||||||
// Metadata needs at least a name field (since that's what getName() will return).
|
// Metadata needs at least a name field (since that's what getName() will return).
|
||||||
|
@ -382,12 +384,10 @@ std::string FileData::getKey() {
|
||||||
const bool FileData::isArcadeAsset()
|
const bool FileData::isArcadeAsset()
|
||||||
{
|
{
|
||||||
const std::string stem = Utils::FileSystem::getStem(mPath);
|
const std::string stem = Utils::FileSystem::getStem(mPath);
|
||||||
return (
|
return ((mSystem && (mSystem->hasPlatformId(PlatformIds::ARCADE) ||
|
||||||
(mSystem && (mSystem->hasPlatformId(PlatformIds::ARCADE) ||
|
mSystem->hasPlatformId(PlatformIds::NEOGEO))) &&
|
||||||
mSystem->hasPlatformId(PlatformIds::NEOGEO))) &&
|
(MameNames::getInstance()->isBios(stem) ||
|
||||||
(MameNames::getInstance()->isBios(stem) ||
|
MameNames::getInstance()->isDevice(stem)));
|
||||||
MameNames::getInstance()->isDevice(stem))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileData* FileData::getSourceFileData()
|
FileData* FileData::getSourceFileData()
|
||||||
|
@ -756,6 +756,9 @@ void FileData::launchGame(Window* window)
|
||||||
|
|
||||||
Scripting::fireEvent("game-end", rom, getSourceFileData()->metadata.get("name"));
|
Scripting::fireEvent("game-end", rom, getSourceFileData()->metadata.get("name"));
|
||||||
|
|
||||||
|
// Re-enable the text scrolling that was disabled in ViewController on game launch.
|
||||||
|
window->setAllowTextScrolling(true);
|
||||||
|
|
||||||
// Update number of times the game has been launched.
|
// Update number of times the game has been launched.
|
||||||
FileData* gameToUpdate = getSourceFileData();
|
FileData* gameToUpdate = getSourceFileData();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// FileData.h
|
// FileData.h
|
||||||
//
|
//
|
||||||
// Provides game file data structures and functions to access and sort this information.
|
// Provides game file data structures and functions to access and sort this information.
|
||||||
|
@ -6,12 +8,12 @@
|
||||||
// (launching initiated in ViewController).
|
// (launching initiated in ViewController).
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef ES_APP_FILE_DATA_H
|
#ifndef ES_APP_FILE_DATA_H
|
||||||
#define ES_APP_FILE_DATA_H
|
#define ES_APP_FILE_DATA_H
|
||||||
|
|
||||||
#include "utils/FileSystemUtil.h"
|
#include "utils/FileSystemUtil.h"
|
||||||
#include "MetaData.h"
|
#include "MetaData.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class SystemData;
|
class SystemData;
|
||||||
|
@ -111,7 +113,8 @@ public:
|
||||||
bool ascending;
|
bool ascending;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
||||||
SortType(ComparisonFunction* sortFunction,
|
SortType(
|
||||||
|
ComparisonFunction* sortFunction,
|
||||||
bool sortAscending,
|
bool sortAscending,
|
||||||
const std::string& sortDescription)
|
const std::string& sortDescription)
|
||||||
: comparisonFunction(sortFunction),
|
: comparisonFunction(sortFunction),
|
||||||
|
@ -145,7 +148,6 @@ private:
|
||||||
bool mOnlyFolders;
|
bool mOnlyFolders;
|
||||||
// Used for flagging a game for deletion from its gamelist.xml file.
|
// Used for flagging a game for deletion from its gamelist.xml file.
|
||||||
bool mDeletionFlag;
|
bool mDeletionFlag;
|
||||||
|
|
||||||
const std::string FAVORITE_CHAR = "\uF005";
|
const std::string FAVORITE_CHAR = "\uF005";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,6 +160,7 @@ public:
|
||||||
void refreshMetadata();
|
void refreshMetadata();
|
||||||
FileData* getSourceFileData();
|
FileData* getSourceFileData();
|
||||||
std::string getKey();
|
std::string getKey();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Needs to be updated when metadata changes.
|
// Needs to be updated when metadata changes.
|
||||||
std::string mCollectionFileName;
|
std::string mCollectionFileName;
|
||||||
|
|
|
@ -53,7 +53,6 @@ private:
|
||||||
STATE_SCREENSAVER_ACTIVE
|
STATE_SCREENSAVER_ACTIVE
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
bool mVideosCounted;
|
bool mVideosCounted;
|
||||||
unsigned long mVideoCount;
|
unsigned long mVideoCount;
|
||||||
VideoComponent* mVideoScreensaver;
|
VideoComponent* mVideoScreensaver;
|
||||||
|
|
|
@ -306,6 +306,9 @@ void ViewController::launch(FileData* game, Vector3f center)
|
||||||
if (mCurrentView)
|
if (mCurrentView)
|
||||||
mCurrentView->onPauseVideo();
|
mCurrentView->onPauseVideo();
|
||||||
|
|
||||||
|
// Disable text scrolling. It will be enabled again in FileData upon returning from the game.
|
||||||
|
mWindow->setAllowTextScrolling(false);
|
||||||
|
|
||||||
stopAnimation(1); // Make sure the fade in isn't still playing.
|
stopAnimation(1); // Make sure the fade in isn't still playing.
|
||||||
mWindow->stopInfoPopup(); // Make sure we disable any existing info popup.
|
mWindow->stopInfoPopup(); // Make sure we disable any existing info popup.
|
||||||
mLockInput = true;
|
mLockInput = true;
|
||||||
|
|
|
@ -86,11 +86,14 @@ public:
|
||||||
ViewMode viewing;
|
ViewMode viewing;
|
||||||
|
|
||||||
inline SystemData* getSystem() const
|
inline SystemData* getSystem() const
|
||||||
{ assert(viewing == GAME_LIST || viewing == SYSTEM_SELECT); return system; }
|
{
|
||||||
|
assert(viewing == GAME_LIST || viewing == SYSTEM_SELECT);
|
||||||
|
return system;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend ViewController;
|
friend ViewController;
|
||||||
SystemData* system;
|
SystemData* system;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const State& getState() const { return mState; }
|
inline const State& getState() const { return mState; }
|
||||||
|
|
|
@ -20,17 +20,18 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
Window::Window()
|
Window::Window()
|
||||||
: mNormalizeNextUpdate(false),
|
: mScreenSaver(nullptr),
|
||||||
|
mInfoPopup(nullptr),
|
||||||
|
mNormalizeNextUpdate(false),
|
||||||
mFrameTimeElapsed(0),
|
mFrameTimeElapsed(0),
|
||||||
mFrameCountElapsed(0),
|
mFrameCountElapsed(0),
|
||||||
mAverageDeltaTime(10),
|
mAverageDeltaTime(10),
|
||||||
mAllowSleep(true),
|
mAllowSleep(true),
|
||||||
mSleeping(false),
|
mSleeping(false),
|
||||||
mTimeSinceLastInput(0),
|
mTimeSinceLastInput(0),
|
||||||
mScreenSaver(nullptr),
|
|
||||||
mRenderScreenSaver(false),
|
mRenderScreenSaver(false),
|
||||||
mGameLaunchedState(false),
|
mGameLaunchedState(false),
|
||||||
mInfoPopup(nullptr),
|
mAllowTextScrolling(true),
|
||||||
mCachedBackground(false),
|
mCachedBackground(false),
|
||||||
mSaturationAmount(1.0),
|
mSaturationAmount(1.0),
|
||||||
mTopOpacity(0),
|
mTopOpacity(0),
|
||||||
|
@ -106,8 +107,8 @@ bool Window::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
mBackgroundOverlay->setImage(":/graphics/scroll_gradient.png");
|
mBackgroundOverlay->setImage(":/graphics/scroll_gradient.png");
|
||||||
mBackgroundOverlay->setResize((float)Renderer::getScreenWidth(),
|
mBackgroundOverlay->setResize(static_cast<float>(Renderer::getScreenWidth()),
|
||||||
(float)Renderer::getScreenHeight());
|
static_cast<float>(Renderer::getScreenHeight()));
|
||||||
|
|
||||||
// Update our help because font sizes probably changed.
|
// Update our help because font sizes probably changed.
|
||||||
if (peekGui())
|
if (peekGui())
|
||||||
|
@ -222,6 +223,7 @@ void Window::update(int deltaTime)
|
||||||
{
|
{
|
||||||
if (mNormalizeNextUpdate) {
|
if (mNormalizeNextUpdate) {
|
||||||
mNormalizeNextUpdate = false;
|
mNormalizeNextUpdate = false;
|
||||||
|
mTimeSinceLastInput = 0;
|
||||||
if (deltaTime > mAverageDeltaTime)
|
if (deltaTime > mAverageDeltaTime)
|
||||||
deltaTime = mAverageDeltaTime;
|
deltaTime = mAverageDeltaTime;
|
||||||
}
|
}
|
||||||
|
@ -236,9 +238,11 @@ void Window::update(int deltaTime)
|
||||||
|
|
||||||
// FPS.
|
// FPS.
|
||||||
ss << std::fixed << std::setprecision(1) <<
|
ss << std::fixed << std::setprecision(1) <<
|
||||||
(1000.0f * (float)mFrameCountElapsed / (float)mFrameTimeElapsed) << " FPS (";
|
(1000.0f * static_cast<float>(mFrameCountElapsed) /
|
||||||
|
static_cast<float>(mFrameTimeElapsed)) << " FPS (";
|
||||||
ss << std::fixed << std::setprecision(2) <<
|
ss << std::fixed << std::setprecision(2) <<
|
||||||
((float)mFrameTimeElapsed / (float)mFrameCountElapsed) << " ms)";
|
(static_cast<float>(mFrameTimeElapsed) /
|
||||||
|
static_cast<float>(mFrameCountElapsed)) << " ms)";
|
||||||
|
|
||||||
// The following calculations are not accurate, and the font calculation is completely
|
// The following calculations are not accurate, and the font calculation is completely
|
||||||
// broken. For now, still report the figures as it's somehow useful to locate memory
|
// broken. For now, still report the figures as it's somehow useful to locate memory
|
||||||
|
@ -280,6 +284,11 @@ void Window::render()
|
||||||
auto& bottom = mGuiStack.front();
|
auto& bottom = mGuiStack.front();
|
||||||
auto& top = mGuiStack.back();
|
auto& top = mGuiStack.back();
|
||||||
|
|
||||||
|
if (mRenderScreenSaver) {
|
||||||
|
bottom->cancelAllAnimations();
|
||||||
|
bottom->stopAllAnimations();
|
||||||
|
}
|
||||||
|
|
||||||
bottom->render(transform);
|
bottom->render(transform);
|
||||||
if (bottom != top) {
|
if (bottom != top) {
|
||||||
#if defined(USE_OPENGL_21)
|
#if defined(USE_OPENGL_21)
|
||||||
|
@ -343,7 +352,8 @@ void Window::render()
|
||||||
if (!mRenderedHelpPrompts)
|
if (!mRenderedHelpPrompts)
|
||||||
mHelp->render(transform);
|
mHelp->render(transform);
|
||||||
|
|
||||||
unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime");
|
unsigned int screensaverTime =
|
||||||
|
static_cast<unsigned int>(Settings::getInstance()->getInt("ScreenSaverTime"));
|
||||||
// If a game has been launched, reset the screensaver timer when it's been reached as we
|
// If a game has been launched, reset the screensaver timer when it's been reached as we
|
||||||
// don't want to start the screensaver in the background when running a game.
|
// don't want to start the screensaver in the background when running a game.
|
||||||
if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) {
|
if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) {
|
||||||
|
@ -501,7 +511,7 @@ void Window::setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpSt
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No, it hasn't!
|
// No, it hasn't!
|
||||||
mappedToSeenMap.emplace(it->second, (int)addPrompts.size());
|
mappedToSeenMap.emplace(it->second, static_cast<int>(addPrompts.size()));
|
||||||
addPrompts.push_back(*it);
|
addPrompts.push_back(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,6 +588,7 @@ void Window::startScreenSaver()
|
||||||
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
|
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
|
||||||
(*it)->onScreenSaverActivate();
|
(*it)->onScreenSaverActivate();
|
||||||
|
|
||||||
|
stopInfoPopup();
|
||||||
mScreenSaver->startScreenSaver();
|
mScreenSaver->startScreenSaver();
|
||||||
mRenderScreenSaver = true;
|
mRenderScreenSaver = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
void pushGui(GuiComponent* gui);
|
void pushGui(GuiComponent* gui);
|
||||||
void removeGui(GuiComponent* gui);
|
void removeGui(GuiComponent* gui);
|
||||||
GuiComponent* peekGui();
|
GuiComponent* peekGui();
|
||||||
inline int getGuiStackSize() { return (int)mGuiStack.size(); }
|
inline int getGuiStackSize() { return static_cast<int>(mGuiStack.size()); }
|
||||||
|
|
||||||
void textInput(const char* text);
|
void textInput(const char* text);
|
||||||
void input(InputConfig* config, Input input);
|
void input(InputConfig* config, Input input);
|
||||||
|
@ -94,6 +94,8 @@ public:
|
||||||
void setLaunchedGame();
|
void setLaunchedGame();
|
||||||
void unsetLaunchedGame();
|
void unsetLaunchedGame();
|
||||||
bool getGameLaunchedState() { return mGameLaunchedState; };
|
bool getGameLaunchedState() { return mGameLaunchedState; };
|
||||||
|
void setAllowTextScrolling(bool setting) { mAllowTextScrolling = setting; };
|
||||||
|
bool getAllowTextScrolling() { return mAllowTextScrolling; };
|
||||||
|
|
||||||
void invalidateCachedBackground() { mCachedBackground = false; };
|
void invalidateCachedBackground() { mCachedBackground = false; };
|
||||||
|
|
||||||
|
@ -108,30 +110,27 @@ private:
|
||||||
ImageComponent* mBackgroundOverlay;
|
ImageComponent* mBackgroundOverlay;
|
||||||
ScreenSaver* mScreenSaver;
|
ScreenSaver* mScreenSaver;
|
||||||
InfoPopup* mInfoPopup;
|
InfoPopup* mInfoPopup;
|
||||||
bool mRenderScreenSaver;
|
|
||||||
bool mGameLaunchedState;
|
|
||||||
|
|
||||||
std::vector<GuiComponent*> mGuiStack;
|
std::vector<GuiComponent*> mGuiStack;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Font>> mDefaultFonts;
|
std::vector<std::shared_ptr<Font>> mDefaultFonts;
|
||||||
|
|
||||||
int mFrameTimeElapsed;
|
|
||||||
int mFrameCountElapsed;
|
|
||||||
int mAverageDeltaTime;
|
|
||||||
|
|
||||||
std::unique_ptr<TextCache> mFrameDataText;
|
std::unique_ptr<TextCache> mFrameDataText;
|
||||||
|
|
||||||
bool mNormalizeNextUpdate;
|
bool mNormalizeNextUpdate;
|
||||||
|
int mFrameTimeElapsed;
|
||||||
|
int mFrameCountElapsed;
|
||||||
|
int mAverageDeltaTime;
|
||||||
|
bool mAllowSleep;
|
||||||
|
bool mSleeping;
|
||||||
|
unsigned int mTimeSinceLastInput;
|
||||||
|
|
||||||
|
bool mRenderScreenSaver;
|
||||||
|
bool mGameLaunchedState;
|
||||||
|
bool mAllowTextScrolling;
|
||||||
|
bool mCachedBackground;
|
||||||
|
|
||||||
float mSaturationAmount;
|
float mSaturationAmount;
|
||||||
unsigned char mTopOpacity;
|
unsigned char mTopOpacity;
|
||||||
float mTopScale;
|
float mTopScale;
|
||||||
float mDimValue;
|
float mDimValue;
|
||||||
bool mCachedBackground;
|
|
||||||
bool mAllowSleep;
|
|
||||||
bool mSleeping;
|
|
||||||
unsigned int mTimeSinceLastInput;
|
|
||||||
|
|
||||||
bool mRenderedHelpPrompts;
|
bool mRenderedHelpPrompts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// IList.h
|
// IList.h
|
||||||
//
|
//
|
||||||
// Gamelist base class.
|
// Gamelist base class.
|
||||||
|
@ -10,6 +12,7 @@
|
||||||
#include "components/ImageComponent.h"
|
#include "components/ImageComponent.h"
|
||||||
#include "resources/Font.h"
|
#include "resources/Font.h"
|
||||||
#include "PowerSaver.h"
|
#include "PowerSaver.h"
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
enum CursorState {
|
enum CursorState {
|
||||||
CURSOR_STOPPED,
|
CURSOR_STOPPED,
|
||||||
|
@ -63,10 +66,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int mCursor;
|
int mCursor;
|
||||||
|
|
||||||
int mScrollTier;
|
int mScrollTier;
|
||||||
int mScrollVelocity;
|
int mScrollVelocity;
|
||||||
|
|
||||||
int mScrollTierAccumulator;
|
int mScrollTierAccumulator;
|
||||||
int mScrollCursorAccumulator;
|
int mScrollCursorAccumulator;
|
||||||
|
|
||||||
|
@ -79,6 +80,7 @@ protected:
|
||||||
const ListLoopType mLoopType;
|
const ListLoopType mLoopType;
|
||||||
|
|
||||||
std::vector<Entry> mEntries;
|
std::vector<Entry> mEntries;
|
||||||
|
Window* mWindow;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IList(
|
IList(
|
||||||
|
@ -88,7 +90,8 @@ public:
|
||||||
: GuiComponent(window),
|
: GuiComponent(window),
|
||||||
mGradient(window),
|
mGradient(window),
|
||||||
mTierList(tierList),
|
mTierList(tierList),
|
||||||
mLoopType(loopType)
|
mLoopType(loopType),
|
||||||
|
mWindow(window)
|
||||||
{
|
{
|
||||||
mCursor = 0;
|
mCursor = 0;
|
||||||
mScrollTier = 0;
|
mScrollTier = 0;
|
||||||
|
@ -98,7 +101,8 @@ public:
|
||||||
|
|
||||||
mTitleOverlayOpacity = 0x00;
|
mTitleOverlayOpacity = 0x00;
|
||||||
mTitleOverlayColor = 0xFFFFFF00;
|
mTitleOverlayColor = 0xFFFFFF00;
|
||||||
mGradient.setResize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
mGradient.setResize(static_cast<float>(Renderer::getScreenWidth()),
|
||||||
|
static_cast<float>(Renderer::getScreenHeight()));
|
||||||
mGradient.setImage(":/graphics/scroll_gradient.png");
|
mGradient.setImage(":/graphics/scroll_gradient.png");
|
||||||
mTitleOverlayFont = Font::get(FONT_SIZE_LARGE);
|
mTitleOverlayFont = Font::get(FONT_SIZE_LARGE);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +168,7 @@ public:
|
||||||
{
|
{
|
||||||
for (auto it = mEntries.cbegin(); it != mEntries.cend(); it++) {
|
for (auto it = mEntries.cbegin(); it != mEntries.cend(); it++) {
|
||||||
if ((*it).object == obj) {
|
if ((*it).object == obj) {
|
||||||
mCursor = (int)(it - mEntries.cbegin());
|
mCursor = static_cast<int>(it - mEntries.cbegin());
|
||||||
onCursorChanged(CURSOR_STOPPED);
|
onCursorChanged(CURSOR_STOPPED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +195,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int size() const { return (int)mEntries.size(); }
|
inline int size() const { return static_cast<int>(mEntries.size()); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void remove(typename std::vector<Entry>::const_iterator& it)
|
void remove(typename std::vector<Entry>::const_iterator& it)
|
||||||
|
@ -247,7 +251,7 @@ protected:
|
||||||
else if (op <= 0)
|
else if (op <= 0)
|
||||||
mTitleOverlayOpacity = 0;
|
mTitleOverlayOpacity = 0;
|
||||||
else
|
else
|
||||||
mTitleOverlayOpacity = (unsigned char)op;
|
mTitleOverlayOpacity = static_cast<unsigned char>(op);
|
||||||
|
|
||||||
if (mScrollVelocity == 0 || size() < 2)
|
if (mScrollVelocity == 0 || size() < 2)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// ScrollableContainer.cpp
|
// ScrollableContainer.cpp
|
||||||
//
|
//
|
||||||
// Area containing scrollable information, for example the game description
|
// Area containing scrollable information, for example the game description
|
||||||
|
@ -9,6 +11,7 @@
|
||||||
|
|
||||||
#include "math/Vector2i.h"
|
#include "math/Vector2i.h"
|
||||||
#include "renderers/Renderer.h"
|
#include "renderers/Renderer.h"
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
#define AUTO_SCROLL_RESET_DELAY 3000 // ms to reset to top after we reach the bottom.
|
#define AUTO_SCROLL_RESET_DELAY 3000 // ms to reset to top after we reach the bottom.
|
||||||
#define AUTO_SCROLL_DELAY 2000 // ms to wait before we start to scroll.
|
#define AUTO_SCROLL_DELAY 2000 // ms to wait before we start to scroll.
|
||||||
|
@ -33,11 +36,12 @@ void ScrollableContainer::render(const Transform4x4f& parentTrans)
|
||||||
|
|
||||||
Transform4x4f trans = parentTrans * getTransform();
|
Transform4x4f trans = parentTrans * getTransform();
|
||||||
|
|
||||||
Vector2i clipPos((int)trans.translation().x(), (int)trans.translation().y());
|
Vector2i clipPos(static_cast<int>(trans.translation().x()),
|
||||||
|
static_cast<int>(trans.translation().y()));
|
||||||
|
|
||||||
Vector3f dimScaled = trans * Vector3f(mSize.x(), mSize.y(), 0);
|
Vector3f dimScaled = trans * Vector3f(mSize.x(), mSize.y(), 0);
|
||||||
Vector2i clipDim((int)(dimScaled.x() - trans.translation().x()),
|
Vector2i clipDim(static_cast<int>((dimScaled.x()) - trans.translation().x()),
|
||||||
(int)(dimScaled.y() - trans.translation().y()));
|
static_cast<int>((dimScaled.y()) - trans.translation().y()));
|
||||||
|
|
||||||
Renderer::pushClipRect(clipPos, clipDim);
|
Renderer::pushClipRect(clipPos, clipDim);
|
||||||
|
|
||||||
|
@ -76,6 +80,13 @@ void ScrollableContainer::setScrollPos(const Vector2f& pos)
|
||||||
|
|
||||||
void ScrollableContainer::update(int deltaTime)
|
void ScrollableContainer::update(int deltaTime)
|
||||||
{
|
{
|
||||||
|
// Don't scroll if the screensaver is active or text scrolling is disabled;
|
||||||
|
if (mWindow->isScreenSaverActive() || !mWindow->getAllowTextScrolling()) {
|
||||||
|
if (mScrollPos != 0)
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mAutoScrollSpeed != 0) {
|
if (mAutoScrollSpeed != 0) {
|
||||||
mAutoScrollAccumulator += deltaTime;
|
mAutoScrollAccumulator += deltaTime;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// ScrollableContainer.h
|
// ScrollableContainer.h
|
||||||
//
|
//
|
||||||
// Area containing scrollable information, for example the game description
|
// Area containing scrollable information, for example the game description
|
||||||
// text container in the detailed, video and grid views.
|
// text container in the detailed, video and grid views.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef ES_CORE_COMPONENTS_SCROLLABLE_CONTAINER_H
|
#ifndef ES_CORE_COMPONENTS_SCROLLABLE_CONTAINER_H
|
||||||
#define ES_CORE_COMPONENTS_SCROLLABLE_CONTAINER_H
|
#define ES_CORE_COMPONENTS_SCROLLABLE_CONTAINER_H
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
//
|
//
|
||||||
|
// EmulationStation Desktop Edition
|
||||||
// TextListComponent.h
|
// TextListComponent.h
|
||||||
//
|
//
|
||||||
// Used for displaying and navigating the gamelists.
|
// Used for displaying and navigating the gamelists.
|
||||||
|
@ -12,6 +14,7 @@
|
||||||
#include "utils/StringUtil.h"
|
#include "utils/StringUtil.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class TextCache;
|
class TextCache;
|
||||||
|
@ -33,6 +36,7 @@ protected:
|
||||||
using IList<TextListData, T>::getTransform;
|
using IList<TextListData, T>::getTransform;
|
||||||
using IList<TextListData, T>::mSize;
|
using IList<TextListData, T>::mSize;
|
||||||
using IList<TextListData, T>::mCursor;
|
using IList<TextListData, T>::mCursor;
|
||||||
|
using IList<TextListData, T>::mWindow;
|
||||||
// The following change is required for compilation with Clang.
|
// The following change is required for compilation with Clang.
|
||||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2070
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2070
|
||||||
// using IList<TextListData, T>::Entry;
|
// using IList<TextListData, T>::Entry;
|
||||||
|
@ -90,7 +94,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onScroll() override {
|
virtual void onScroll() override {
|
||||||
NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND); }
|
NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND); }
|
||||||
virtual void onCursorChanged(const CursorState& state) override;
|
virtual void onCursorChanged(const CursorState& state) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -120,7 +124,7 @@ private:
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
TextListComponent<T>::TextListComponent(Window* window) :
|
TextListComponent<T>::TextListComponent(Window* window) :
|
||||||
IList<TextListData, T>(window), mSelectorImage(window)
|
IList<TextListData, T>(window), mSelectorImage(window)
|
||||||
{
|
{
|
||||||
mMarqueeOffset = 0;
|
mMarqueeOffset = 0;
|
||||||
mMarqueeOffset2 = 0;
|
mMarqueeOffset2 = 0;
|
||||||
|
@ -152,12 +156,13 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
if (size() == 0)
|
if (size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float entrySize = Math::max(font->getHeight(1.0), (float)font->getSize()) * mLineSpacing;
|
const float entrySize = Math::max(font->getHeight(1.0),
|
||||||
|
static_cast<float>(font->getSize())) * mLineSpacing;
|
||||||
|
|
||||||
int startEntry = 0;
|
int startEntry = 0;
|
||||||
|
|
||||||
// Number of entries that can fit on the screen simultaneously.
|
// Number of entries that can fit on the screen simultaneously.
|
||||||
int screenCount = (int)(mSize.y() / entrySize + 0.5f);
|
int screenCount = static_cast<int>(mSize.y() / entrySize + 0.5f);
|
||||||
|
|
||||||
if (size() >= screenCount) {
|
if (size() >= screenCount) {
|
||||||
startEntry = mCursor - screenCount/2;
|
startEntry = mCursor - screenCount/2;
|
||||||
|
@ -197,12 +202,12 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
// Clip to inside margins.
|
// Clip to inside margins.
|
||||||
Vector3f dim(mSize.x(), mSize.y(), 0);
|
Vector3f dim(mSize.x(), mSize.y(), 0);
|
||||||
dim = trans * dim - trans.translation();
|
dim = trans * dim - trans.translation();
|
||||||
Renderer::pushClipRect(Vector2i((int)(trans.translation().x() + mHorizontalMargin),
|
Renderer::pushClipRect(Vector2i(static_cast<int>(trans.translation().x() +
|
||||||
(int)trans.translation().y()), Vector2i((int)(dim.x() - mHorizontalMargin*2),
|
mHorizontalMargin), static_cast<int>(trans.translation().y())),
|
||||||
(int)dim.y()));
|
Vector2i(static_cast<int>(dim.x() - mHorizontalMargin*2), static_cast<int>(dim.y())));
|
||||||
|
|
||||||
for (int i = startEntry; i < listCutoff; i++) {
|
for (int i = startEntry; i < listCutoff; i++) {
|
||||||
typename IList<TextListData, T>::Entry& entry = mEntries.at((unsigned int)i);
|
typename IList<TextListData, T>::Entry& entry = mEntries.at(static_cast<unsigned int>(i));
|
||||||
|
|
||||||
unsigned int color;
|
unsigned int color;
|
||||||
if (mCursor == i && mSelectedColor)
|
if (mCursor == i && mSelectedColor)
|
||||||
|
@ -211,12 +216,12 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
color = mColors[entry.data.colorId];
|
color = mColors[entry.data.colorId];
|
||||||
|
|
||||||
if (!entry.data.textCache)
|
if (!entry.data.textCache)
|
||||||
entry.data.textCache = std::unique_ptr<TextCache>
|
entry.data.textCache = std::unique_ptr<TextCache>(
|
||||||
(font->buildTextCache(mUppercase ?
|
font->buildTextCache(mUppercase ?
|
||||||
Utils::String::toUpper(entry.name) : entry.name, 0, 0, 0x000000FF));
|
Utils::String::toUpper(entry.name) : entry.name, 0, 0, 0x000000FF));
|
||||||
|
|
||||||
// If a game is marked as hidden, lower the text opacity quite a lot.
|
// If a game is marked as hidden, lower the text opacity a lot.
|
||||||
// For games marked not to be counted, lower the opacity moderately.
|
// If a game is marked to not be counted, lower the opacity a moderate amount.
|
||||||
if (entry.object->getHidden())
|
if (entry.object->getHidden())
|
||||||
entry.data.textCache->setColor(color & 0xFFFFFF44);
|
entry.data.textCache->setColor(color & 0xFFFFFF44);
|
||||||
else if (!entry.object->getCountAsGame())
|
else if (!entry.object->getCountAsGame())
|
||||||
|
@ -231,7 +236,7 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
offset[0] = mHorizontalMargin;
|
offset[0] = mHorizontalMargin;
|
||||||
break;
|
break;
|
||||||
case ALIGN_CENTER:
|
case ALIGN_CENTER:
|
||||||
offset[0] = (int)((mSize.x() - entry.data.textCache->metrics.size.x()) / 2);
|
offset[0] = static_cast<int>((mSize.x() - entry.data.textCache->metrics.size.x()) / 2);
|
||||||
if (offset[0] < mHorizontalMargin)
|
if (offset[0] < mHorizontalMargin)
|
||||||
offset[0] = mHorizontalMargin;
|
offset[0] = mHorizontalMargin;
|
||||||
break;
|
break;
|
||||||
|
@ -248,7 +253,7 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
|
|
||||||
// Currently selected item text might be scrolling.
|
// Currently selected item text might be scrolling.
|
||||||
if ((mCursor == i) && (mMarqueeOffset > 0))
|
if ((mCursor == i) && (mMarqueeOffset > 0))
|
||||||
drawTrans.translate(offset - Vector3f((float)mMarqueeOffset, 0, 0));
|
drawTrans.translate(offset - Vector3f(static_cast<float>(mMarqueeOffset), 0, 0));
|
||||||
else
|
else
|
||||||
drawTrans.translate(offset);
|
drawTrans.translate(offset);
|
||||||
|
|
||||||
|
@ -259,11 +264,10 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
// scrolled far enough for it to repeat.
|
// scrolled far enough for it to repeat.
|
||||||
if ((mCursor == i) && (mMarqueeOffset2 < 0)) {
|
if ((mCursor == i) && (mMarqueeOffset2 < 0)) {
|
||||||
drawTrans = trans;
|
drawTrans = trans;
|
||||||
drawTrans.translate(offset - Vector3f((float)mMarqueeOffset2, 0, 0));
|
drawTrans.translate(offset - Vector3f(static_cast<float>(mMarqueeOffset2), 0, 0));
|
||||||
Renderer::setMatrix(drawTrans);
|
Renderer::setMatrix(drawTrans);
|
||||||
font->renderTextCache(entry.data.textCache.get());
|
font->renderTextCache(entry.data.textCache.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
y += entrySize;
|
y += entrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,35 +327,39 @@ void TextListComponent<T>::update(int deltaTime)
|
||||||
{
|
{
|
||||||
listUpdate(deltaTime);
|
listUpdate(deltaTime);
|
||||||
|
|
||||||
|
if (mWindow->isScreenSaverActive() || !mWindow->getAllowTextScrolling())
|
||||||
|
stopScrolling();
|
||||||
|
|
||||||
if (!isScrolling() && size() > 0) {
|
if (!isScrolling() && size() > 0) {
|
||||||
// Always reset the marquee offsets.
|
// Always reset the marquee offsets.
|
||||||
mMarqueeOffset = 0;
|
mMarqueeOffset = 0;
|
||||||
mMarqueeOffset2 = 0;
|
mMarqueeOffset2 = 0;
|
||||||
|
|
||||||
// If we're not scrolling and this object's text goes outside our size, marquee it!
|
// If we're not scrolling and this object's text goes outside our size, marquee it!
|
||||||
const float textLength = mFont->sizeText(mEntries.at((unsigned int)mCursor).name).x();
|
const float textLength = mFont->sizeText(
|
||||||
const float limit = mSize.x() - mHorizontalMargin * 2;
|
mEntries.at(static_cast<unsigned int>(mCursor)).name).x();
|
||||||
|
const float limit = mSize.x() - mHorizontalMargin * 2;
|
||||||
|
|
||||||
if (textLength > limit) {
|
if (textLength > limit) {
|
||||||
// Loop.
|
// Loop.
|
||||||
// Pixels per second (based on nes-mini font at 1920x1080 to produce a speed of 200).
|
// Pixels per second (based on nes-mini font at 1920x1080 to produce a speed of 200).
|
||||||
const float speed = mFont->sizeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ").x() * 0.247f;
|
const float speed = mFont->sizeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ").x() * 0.247f;
|
||||||
const float delay = 3000;
|
const float delay = 3000;
|
||||||
const float scrollLength = textLength;
|
const float scrollLength = textLength;
|
||||||
const float returnLength = speed * 1.5f;
|
const float returnLength = speed * 1.5f;
|
||||||
const float scrollTime = (scrollLength * 1000) / speed;
|
const float scrollTime = (scrollLength * 1000) / speed;
|
||||||
const float returnTime = (returnLength * 1000) / speed;
|
const float returnTime = (returnLength * 1000) / speed;
|
||||||
const int maxTime = (int)(delay + scrollTime + returnTime);
|
const int maxTime = static_cast<int>(delay + scrollTime + returnTime);
|
||||||
|
|
||||||
mMarqueeTime += deltaTime;
|
mMarqueeTime += deltaTime;
|
||||||
while (mMarqueeTime > maxTime)
|
while (mMarqueeTime > maxTime)
|
||||||
mMarqueeTime -= maxTime;
|
mMarqueeTime -= maxTime;
|
||||||
|
|
||||||
mMarqueeOffset = (int)(Math::Scroll::loop(delay, scrollTime + returnTime,
|
mMarqueeOffset = static_cast<int>(Math::Scroll::loop(delay, scrollTime + returnTime,
|
||||||
(float)mMarqueeTime, scrollLength + returnLength));
|
static_cast<float>(mMarqueeTime), scrollLength + returnLength));
|
||||||
|
|
||||||
if (mMarqueeOffset > (scrollLength - (limit - returnLength)))
|
if (mMarqueeOffset > (scrollLength - (limit - returnLength)))
|
||||||
mMarqueeOffset2 = (int)(mMarqueeOffset - (scrollLength + returnLength));
|
mMarqueeOffset2 = static_cast<int>(mMarqueeOffset - (scrollLength + returnLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +421,7 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
|
||||||
setFont(Font::getFromTheme(elem, properties, mFont));
|
setFont(Font::getFromTheme(elem, properties, mFont));
|
||||||
const float selectorHeight = Math::max(mFont->getHeight(1.0),
|
const float selectorHeight = Math::max(mFont->getHeight(1.0),
|
||||||
(float)mFont->getSize()) * mLineSpacing;
|
static_cast<float>(mFont->getSize())) * mLineSpacing;
|
||||||
setSelectorHeight(selectorHeight);
|
setSelectorHeight(selectorHeight);
|
||||||
|
|
||||||
if (properties & ALIGNMENT) {
|
if (properties & ALIGNMENT) {
|
||||||
|
@ -431,7 +439,7 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (elem->has("horizontalMargin")) {
|
if (elem->has("horizontalMargin")) {
|
||||||
mHorizontalMargin = elem->get<float>("horizontalMargin") *
|
mHorizontalMargin = elem->get<float>("horizontalMargin") *
|
||||||
(this->mParent ? this->mParent->getSize().x() :
|
(this->mParent ? this->mParent->getSize().x() :
|
||||||
(float)Renderer::getScreenWidth());
|
static_cast<float>(Renderer::getScreenWidth()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +452,8 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (elem->has("selectorHeight"))
|
if (elem->has("selectorHeight"))
|
||||||
setSelectorHeight(elem->get<float>("selectorHeight") * Renderer::getScreenHeight());
|
setSelectorHeight(elem->get<float>("selectorHeight") * Renderer::getScreenHeight());
|
||||||
if (elem->has("selectorOffsetY")) {
|
if (elem->has("selectorOffsetY")) {
|
||||||
float scale = this->mParent ? this->mParent->getSize().y() : (float)Renderer::getScreenHeight();
|
float scale = this->mParent ? this->mParent->getSize().y() :
|
||||||
|
static_cast<float>(Renderer::getScreenHeight());
|
||||||
setSelectorOffsetY(elem->get<float>("selectorOffsetY") * scale);
|
setSelectorOffsetY(elem->get<float>("selectorOffsetY") * scale);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -373,13 +373,20 @@ void VideoComponent::onPauseVideo()
|
||||||
|
|
||||||
void VideoComponent::onScreenSaverActivate()
|
void VideoComponent::onScreenSaverActivate()
|
||||||
{
|
{
|
||||||
mScreensaverActive = true;
|
mBlockPlayer = true;
|
||||||
|
mPause = true;
|
||||||
|
if (Settings::getInstance()->getString("ScreenSaverBehavior") == "dim")
|
||||||
|
stopVideo();
|
||||||
manageState();
|
manageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoComponent::onScreenSaverDeactivate()
|
void VideoComponent::onScreenSaverDeactivate()
|
||||||
{
|
{
|
||||||
mScreensaverActive = false;
|
mBlockPlayer = false;
|
||||||
|
// mPause = false;
|
||||||
|
// Stop video when deactivating the screensaver to force a reload of the
|
||||||
|
// static image (if the theme is configured as such).
|
||||||
|
stopVideo();
|
||||||
manageState();
|
manageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +405,17 @@ void VideoComponent::onGameLaunchedDeactivate()
|
||||||
|
|
||||||
void VideoComponent::topWindow(bool isTop)
|
void VideoComponent::topWindow(bool isTop)
|
||||||
{
|
{
|
||||||
mDisable = !isTop;
|
|
||||||
|
if (isTop) {
|
||||||
|
mBlockPlayer = false;
|
||||||
|
mPause = false;
|
||||||
|
// Stop video when closing the menu to force a reload of the
|
||||||
|
// static image (if the theme is configured as such).
|
||||||
|
stopVideo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mBlockPlayer = true;
|
||||||
|
mPause = true;
|
||||||
|
}
|
||||||
manageState();
|
manageState();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue