mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Improved transitions for SystemView.
This commit is contained in:
parent
a67ee27815
commit
0a6e1f280f
|
@ -625,10 +625,6 @@ The order in which to sort your gamelists. This can be overriden per game system
|
||||||
|
|
||||||
Animation to play when opening the main menu or the game options menu. Can be set to _scale-up_, _fade-in_ or _none_.
|
Animation to play when opening the main menu or the game options menu. Can be set to _scale-up_, _fade-in_ or _none_.
|
||||||
|
|
||||||
**Display carousel transitions**
|
|
||||||
|
|
||||||
Whether to perform an animation when transitioning between systems in the system view.
|
|
||||||
|
|
||||||
**Render scanlines for gamelist videos** _(OpenGL renderer only)_
|
**Render scanlines for gamelist videos** _(OpenGL renderer only)_
|
||||||
|
|
||||||
Whether to use a shader to render scanlines for videos in the gamelist view. The effect is usually pretty subtle as the video is normally renderered in a limited size in the GUI, and the scanlines are sized relative to the video window size.
|
Whether to use a shader to render scanlines for videos in the gamelist view. The effect is usually pretty subtle as the video is normally renderered in a limited size in the GUI, and the scanlines are sized relative to the video window size.
|
||||||
|
|
|
@ -258,22 +258,7 @@ void GuiMenu::openUISettings()
|
||||||
s->setNeedsSaving();
|
s->setNeedsSaving();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
|
|
||||||
// Carousel transitions.
|
|
||||||
auto carousel_transitions = std::make_shared<SwitchComponent>(mWindow);
|
|
||||||
carousel_transitions->setState(Settings::getInstance()->getBool("CarouselTransitions"));
|
|
||||||
s->addWithLabel("DISPLAY CAROUSEL TRANSITIONS", carousel_transitions);
|
|
||||||
s->addSaveFunc([carousel_transitions, s] {
|
|
||||||
if (carousel_transitions->getState() !=
|
|
||||||
Settings::getInstance()->getBool("CarouselTransitions")) {
|
|
||||||
Settings::getInstance()->setBool("CarouselTransitions",
|
|
||||||
carousel_transitions->getState());
|
|
||||||
s->setNeedsSaving();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#if defined(USE_OPENGL_21)
|
|
||||||
// Render scanlines for videos in the gamelists.
|
// Render scanlines for videos in the gamelists.
|
||||||
auto gamelist_video_scanlines = std::make_shared<SwitchComponent>(mWindow);
|
auto gamelist_video_scanlines = std::make_shared<SwitchComponent>(mWindow);
|
||||||
gamelist_video_scanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines"));
|
gamelist_video_scanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines"));
|
||||||
|
|
|
@ -31,6 +31,7 @@ SystemView::SystemView(
|
||||||
: IList<SystemViewData, SystemData*>
|
: IList<SystemViewData, SystemData*>
|
||||||
(window, LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP),
|
(window, LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP),
|
||||||
mPreviousScrollVelocity(0),
|
mPreviousScrollVelocity(0),
|
||||||
|
mUpdatedGameCount(false),
|
||||||
mViewNeedsReload(true),
|
mViewNeedsReload(true),
|
||||||
mSystemInfo(window, "SYSTEM INFO", Font::get(FONT_SIZE_SMALL), 0x33333300, ALIGN_CENTER)
|
mSystemInfo(window, "SYSTEM INFO", Font::get(FONT_SIZE_SMALL), 0x33333300, ALIGN_CENTER)
|
||||||
{
|
{
|
||||||
|
@ -152,9 +153,31 @@ void SystemView::populate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemView::updateGameCount()
|
||||||
|
{
|
||||||
|
std::pair<unsigned int, unsigned int> gameCount = getSelected()->getDisplayedGameCount();
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
if (!getSelected()->isGameSystem())
|
||||||
|
ss << "CONFIGURATION";
|
||||||
|
else if (getSelected()->isCollection() && (getSelected()->getName() == "favorites"))
|
||||||
|
ss << gameCount.first << " GAME" << (gameCount.first == 1 ? " " : "S");
|
||||||
|
// The 'recent' gamelist has probably been trimmed after sorting, so we'll cap it at
|
||||||
|
// its maximum limit of 50 games.
|
||||||
|
else if (getSelected()->isCollection() && (getSelected()->getName() == "recent"))
|
||||||
|
ss << (gameCount.first > 50 ? 50 : gameCount.first) << " GAME" <<
|
||||||
|
(gameCount.first == 1 ? " " : "S");
|
||||||
|
else
|
||||||
|
ss << gameCount.first << " GAME" << (gameCount.first == 1 ? " " : "S ") << "(" <<
|
||||||
|
gameCount.second << " FAVORITE" << (gameCount.second == 1 ? ")" : "S)");
|
||||||
|
|
||||||
|
mSystemInfo.setText(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
void SystemView::goToSystem(SystemData* system, bool animate)
|
void SystemView::goToSystem(SystemData* system, bool animate)
|
||||||
{
|
{
|
||||||
setCursor(system);
|
setCursor(system);
|
||||||
|
updateGameCount();
|
||||||
|
|
||||||
if (!animate)
|
if (!animate)
|
||||||
finishAnimation(0);
|
finishAnimation(0);
|
||||||
|
@ -273,70 +296,31 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
|
||||||
mPreviousScrollVelocity = 1;
|
mPreviousScrollVelocity = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animate mSystemInfo's opacity (fade out, wait, fade back in).
|
|
||||||
cancelAnimation(1);
|
|
||||||
cancelAnimation(2);
|
|
||||||
|
|
||||||
std::string transition_style = Settings::getInstance()->getString("TransitionStyle");
|
std::string transition_style = Settings::getInstance()->getString("TransitionStyle");
|
||||||
bool goFast = transition_style == "instant";
|
bool goFast = transition_style == "instant";
|
||||||
const float infoStartOpacity = mSystemInfo.getOpacity() / 255.f;
|
const float infoStartOpacity = mSystemInfo.getOpacity() / 255.f;
|
||||||
|
|
||||||
Animation* infoFadeOut = new LambdaAnimation(
|
|
||||||
[infoStartOpacity, this] (float t) {
|
|
||||||
mSystemInfo.setOpacity(static_cast<unsigned char>(
|
|
||||||
Math::lerp(infoStartOpacity, 0.f, t) * 255));
|
|
||||||
}, static_cast<int>(infoStartOpacity * (goFast ? 10 : 150)));
|
|
||||||
|
|
||||||
// To prevent ugly jumps with two systems when quickly repeating the same direction.
|
// To prevent ugly jumps with two systems when quickly repeating the same direction.
|
||||||
if (mPreviousScrollVelocity != 0 && posMax == 2 &&
|
if (mPreviousScrollVelocity != 0 && posMax == 2 &&
|
||||||
mScrollVelocity == mPreviousScrollVelocity ) {
|
mScrollVelocity == mPreviousScrollVelocity ) {
|
||||||
if (fabs(endPos - startPos) < 0.5 || fabs(endPos - startPos) > 1.5) {
|
if (fabs(endPos - startPos) < 0.5 || fabs(endPos - startPos) > 1.5) {
|
||||||
(mScrollVelocity < 0) ? endPos -= 1 : endPos += 1;
|
(mScrollVelocity < 0) ? endPos -= 1 : endPos += 1;
|
||||||
(mCursor == 0) ? mCursor = 1 : mCursor = 0;
|
(mCursor == 0) ? mCursor = 1 : mCursor = 0;
|
||||||
|
updateGameCount();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<unsigned int, unsigned int> gameCount = getSelected()->getDisplayedGameCount();
|
|
||||||
|
|
||||||
// Also change the text after we've fully faded out.
|
|
||||||
setAnimation(infoFadeOut, 0, [this, gameCount] {
|
|
||||||
std::stringstream ss;
|
|
||||||
|
|
||||||
if (!getSelected()->isGameSystem())
|
|
||||||
ss << "CONFIGURATION";
|
|
||||||
else if (getSelected()->isCollection() && (getSelected()->getName() == "favorites"))
|
|
||||||
ss << gameCount.first << " GAME" << (gameCount.first == 1 ? " " : "S");
|
|
||||||
// The 'recent' gamelist has probably been trimmed after sorting, so we'll cap it at
|
|
||||||
// its maximum limit of 50 games.
|
|
||||||
else if (getSelected()->isCollection() && (getSelected()->getName() == "recent"))
|
|
||||||
ss << (gameCount.first > 50 ? 50 : gameCount.first) << " GAME" <<
|
|
||||||
(gameCount.first == 1 ? " " : "S");
|
|
||||||
else
|
|
||||||
ss << gameCount.first << " GAME" << (gameCount.first == 1 ? " " : "S ") << "(" <<
|
|
||||||
gameCount.second << " FAVORITE" << (gameCount.second == 1 ? ")" : "S)");
|
|
||||||
|
|
||||||
mSystemInfo.setText(ss.str());
|
|
||||||
}, false, 1);
|
|
||||||
|
|
||||||
Animation* infoFadeIn = new LambdaAnimation(
|
|
||||||
[this](float t) {
|
|
||||||
mSystemInfo.setOpacity(static_cast<unsigned char>(Math::lerp(0.f, 1.f, t) * 255));
|
|
||||||
}, goFast ? 10 : 300);
|
|
||||||
|
|
||||||
// Wait 150ms to fade in.
|
|
||||||
setAnimation(infoFadeIn, goFast ? 0 : 500, nullptr, false, 2);
|
|
||||||
|
|
||||||
// No need to animate transition, we're not going anywhere (probably mEntries.size() == 1).
|
// No need to animate transition, we're not going anywhere (probably mEntries.size() == 1).
|
||||||
if (endPos == mCamOffset && endPos == mExtrasCamOffset)
|
if (endPos == mCamOffset && endPos == mExtrasCamOffset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Animation* anim;
|
Animation* anim;
|
||||||
bool carousel_transitions = Settings::getInstance()->getBool("CarouselTransitions");
|
|
||||||
if (transition_style == "fade") {
|
if (transition_style == "fade") {
|
||||||
float startExtrasFade = mExtrasFadeOpacity;
|
float startExtrasFade = mExtrasFadeOpacity;
|
||||||
anim = new LambdaAnimation(
|
anim = new LambdaAnimation(
|
||||||
[this, startExtrasFade, startPos, endPos, posMax, carousel_transitions](float t) {
|
[this, startExtrasFade, startPos, endPos, posMax](float t) {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
|
@ -344,7 +328,7 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
|
||||||
if (f >= posMax)
|
if (f >= posMax)
|
||||||
f -= posMax;
|
f -= posMax;
|
||||||
|
|
||||||
this->mCamOffset = carousel_transitions ? f : endPos;
|
this->mCamOffset = f;
|
||||||
|
|
||||||
t += 1;
|
t += 1;
|
||||||
if (t < 0.3f)
|
if (t < 0.3f)
|
||||||
|
@ -357,12 +341,15 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
|
||||||
if (t > 0.5f)
|
if (t > 0.5f)
|
||||||
this->mExtrasCamOffset = endPos;
|
this->mExtrasCamOffset = endPos;
|
||||||
|
|
||||||
|
// Update the game count when the entire animation has been completed.
|
||||||
|
if (mExtrasFadeOpacity == 1.0)
|
||||||
|
updateGameCount();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
else if (transition_style == "slide") {
|
else if (transition_style == "slide") {
|
||||||
// Slide.
|
mUpdatedGameCount = false;
|
||||||
anim = new LambdaAnimation(
|
anim = new LambdaAnimation(
|
||||||
[this, startPos, endPos, posMax, carousel_transitions](float t) {
|
[this, startPos, endPos, posMax](float t) {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
|
@ -370,14 +357,30 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
|
||||||
if (f >= posMax)
|
if (f >= posMax)
|
||||||
f -= posMax;
|
f -= posMax;
|
||||||
|
|
||||||
this->mCamOffset = carousel_transitions ? f : endPos;
|
this->mCamOffset = f;
|
||||||
this->mExtrasCamOffset = f;
|
this->mExtrasCamOffset = f;
|
||||||
|
|
||||||
|
// Hack to make the game count being updated in the middle of the animation.
|
||||||
|
bool update = false;
|
||||||
|
if (endPos == -1 && fabs(fabs(posMax) - fabs(mCamOffset)) > 0.5 && !mUpdatedGameCount)
|
||||||
|
update = true;
|
||||||
|
else if (endPos > posMax && fabs(endPos - posMax - fabs(mCamOffset)) <
|
||||||
|
0.5 && !mUpdatedGameCount)
|
||||||
|
update = true;
|
||||||
|
else if (fabs(fabs(endPos) - fabs(mCamOffset)) < 0.5 && !mUpdatedGameCount)
|
||||||
|
update = true;
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
mUpdatedGameCount = true;
|
||||||
|
updateGameCount();
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Instant.
|
// Instant.
|
||||||
|
updateGameCount();
|
||||||
anim = new LambdaAnimation(
|
anim = new LambdaAnimation(
|
||||||
[this, startPos, endPos, posMax, carousel_transitions ](float t) {
|
[this, startPos, endPos, posMax ](float t) {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
float f = Math::lerp(startPos, endPos, t*t*t + 1);
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
|
@ -385,9 +388,9 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
|
||||||
if (f >= posMax)
|
if (f >= posMax)
|
||||||
f -= posMax;
|
f -= posMax;
|
||||||
|
|
||||||
this->mCamOffset = carousel_transitions ? f : endPos;
|
this->mCamOffset = f;
|
||||||
this->mExtrasCamOffset = endPos;
|
this->mExtrasCamOffset = endPos;
|
||||||
}, carousel_transitions ? 500 : 1);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAnimation(anim, 0, nullptr, false, 0);
|
setAnimation(anim, 0, nullptr, false, 0);
|
||||||
|
@ -400,29 +403,16 @@ void SystemView::render(const Transform4x4f& parentTrans)
|
||||||
|
|
||||||
Transform4x4f trans = getTransform() * parentTrans;
|
Transform4x4f trans = getTransform() * parentTrans;
|
||||||
|
|
||||||
auto systemInfoZIndex = mSystemInfo.getZIndex();
|
renderExtras(trans, INT16_MIN, INT16_MAX);
|
||||||
auto minMax = std::minmax(mCarousel.zIndex, systemInfoZIndex);
|
|
||||||
|
|
||||||
renderExtras(trans, INT16_MIN, minMax.first);
|
// Fade the screen if we're using fade transitions and we're currently transitioning.
|
||||||
|
// This basically renders a black rectangle on top of the currently visible extras
|
||||||
|
// (and beneath the carousel and help prompts).
|
||||||
|
if (mExtrasFadeOpacity)
|
||||||
renderFade(trans);
|
renderFade(trans);
|
||||||
|
|
||||||
if (mCarousel.zIndex > mSystemInfo.getZIndex()) {
|
// Always render the carousel on top so that it's not faded.
|
||||||
renderInfoBar(trans);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
renderCarousel(trans);
|
renderCarousel(trans);
|
||||||
}
|
|
||||||
|
|
||||||
renderExtras(trans, minMax.first, minMax.second);
|
|
||||||
|
|
||||||
if (mCarousel.zIndex > mSystemInfo.getZIndex()) {
|
|
||||||
renderCarousel(trans);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
renderInfoBar(trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderExtras(trans, minMax.second, INT16_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> SystemView::getHelpPrompts()
|
std::vector<HelpPrompt> SystemView::getHelpPrompts()
|
||||||
|
@ -597,12 +587,6 @@ void SystemView::renderCarousel(const Transform4x4f& trans)
|
||||||
Renderer::popClipRect();
|
Renderer::popClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemView::renderInfoBar(const Transform4x4f& trans)
|
|
||||||
{
|
|
||||||
Renderer::setMatrix(trans);
|
|
||||||
mSystemInfo.render(trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw background extras.
|
// Draw background extras.
|
||||||
void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upper)
|
void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upper)
|
||||||
{
|
{
|
||||||
|
@ -637,10 +621,10 @@ void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upp
|
||||||
SystemViewData data = mEntries.at(index).data;
|
SystemViewData data = mEntries.at(index).data;
|
||||||
for (unsigned int j = 0; j < data.backgroundExtras.size(); j++) {
|
for (unsigned int j = 0; j < data.backgroundExtras.size(); j++) {
|
||||||
GuiComponent *extra = data.backgroundExtras[j];
|
GuiComponent *extra = data.backgroundExtras[j];
|
||||||
if (extra->getZIndex() >= lower && extra->getZIndex() < upper) {
|
if (extra->getZIndex() >= lower && extra->getZIndex() < upper)
|
||||||
extra->render(extrasTrans);
|
extra->render(extrasTrans);
|
||||||
}
|
}
|
||||||
}
|
mSystemInfo.render(extrasTrans);
|
||||||
Renderer::popClipRect();
|
Renderer::popClipRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,12 +633,9 @@ void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upp
|
||||||
|
|
||||||
void SystemView::renderFade(const Transform4x4f& trans)
|
void SystemView::renderFade(const Transform4x4f& trans)
|
||||||
{
|
{
|
||||||
// Fade extras if necessary.
|
|
||||||
if (mExtrasFadeOpacity) {
|
|
||||||
unsigned int fadeColor = 0x00000000 | static_cast<unsigned char>(mExtrasFadeOpacity * 255);
|
unsigned int fadeColor = 0x00000000 | static_cast<unsigned char>(mExtrasFadeOpacity * 255);
|
||||||
Renderer::setMatrix(trans);
|
Renderer::setMatrix(trans);
|
||||||
Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), fadeColor, fadeColor);
|
Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), fadeColor, fadeColor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the system carousel with the legacy values.
|
// Populate the system carousel with the legacy values.
|
||||||
|
|
|
@ -76,13 +76,13 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void populate();
|
void populate();
|
||||||
|
void updateGameCount();
|
||||||
void getViewElements(const std::shared_ptr<ThemeData>& theme);
|
void getViewElements(const std::shared_ptr<ThemeData>& theme);
|
||||||
void getDefaultElements(void);
|
void getDefaultElements(void);
|
||||||
void getCarouselFromTheme(const ThemeData::ThemeElement* elem);
|
void getCarouselFromTheme(const ThemeData::ThemeElement* elem);
|
||||||
|
|
||||||
void renderCarousel(const Transform4x4f& parentTrans);
|
void renderCarousel(const Transform4x4f& parentTrans);
|
||||||
void renderExtras(const Transform4x4f& parentTrans, float lower, float upper);
|
void renderExtras(const Transform4x4f& parentTrans, float lower, float upper);
|
||||||
void renderInfoBar(const Transform4x4f& trans);
|
|
||||||
void renderFade(const Transform4x4f& trans);
|
void renderFade(const Transform4x4f& trans);
|
||||||
|
|
||||||
SystemViewCarousel mCarousel;
|
SystemViewCarousel mCarousel;
|
||||||
|
@ -94,6 +94,7 @@ private:
|
||||||
float mExtrasFadeOpacity;
|
float mExtrasFadeOpacity;
|
||||||
|
|
||||||
int mPreviousScrollVelocity;
|
int mPreviousScrollVelocity;
|
||||||
|
bool mUpdatedGameCount;
|
||||||
bool mViewNeedsReload;
|
bool mViewNeedsReload;
|
||||||
bool mShowing;
|
bool mShowing;
|
||||||
};
|
};
|
||||||
|
|
|
@ -110,7 +110,6 @@ void Settings::setDefaults()
|
||||||
mStringMap["UIMode"] = "full";
|
mStringMap["UIMode"] = "full";
|
||||||
mStringMap["DefaultSortOrder"] = "filename, ascending";
|
mStringMap["DefaultSortOrder"] = "filename, ascending";
|
||||||
mStringMap["MenuOpeningEffect"] = "scale-up";
|
mStringMap["MenuOpeningEffect"] = "scale-up";
|
||||||
mBoolMap["CarouselTransitions"] = true;
|
|
||||||
mBoolMap["GamelistVideoScanlines"] = true;
|
mBoolMap["GamelistVideoScanlines"] = true;
|
||||||
mBoolMap["FoldersOnTop"] = true;
|
mBoolMap["FoldersOnTop"] = true;
|
||||||
mBoolMap["FavoritesFirst"] = true;
|
mBoolMap["FavoritesFirst"] = true;
|
||||||
|
|
Loading…
Reference in a new issue