Text scrolling now stops when launching a game and when the screensaver starts.

Also did some additional code cleanup.
This commit is contained in:
Leon Styhre 2020-09-17 22:00:07 +02:00
parent 254029fed6
commit d4f5b2d20d
13 changed files with 147 additions and 83 deletions

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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; }

View file

@ -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;
} }

View file

@ -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;
}; };

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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 {

View file

@ -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();
} }