Fixed an issue where game media would not get rendered during gamelist transitions.

This commit is contained in:
Leon Styhre 2020-11-18 22:26:58 +01:00
parent 8aac36c9d3
commit e30e636780
4 changed files with 75 additions and 30 deletions

View file

@ -87,6 +87,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Fixed a massive memory leak related to SVG images * Fixed a massive memory leak related to SVG images
* Toggling the screensaver didn't work as expected * Toggling the screensaver didn't work as expected
* Wrapping around the first and last game systems generated strange camera movements when using the slide transition style * Wrapping around the first and last game systems generated strange camera movements when using the slide transition style
* Game media was not rendered when moving between gamelists using the slide transition style
* The setting to enable or disable audio for the video screensaver only worked on Raspberry Pi * The setting to enable or disable audio for the video screensaver only worked on Raspberry Pi
* The screensaver random function did not consider the previously selected game and could potentially show the same image or video over and over again * The screensaver random function did not consider the previously selected game and could potentially show the same image or video over and over again
* The random system selection did not consider the currently selected system * The random system selection did not consider the currently selected system

View file

@ -51,10 +51,11 @@ ViewController::ViewController(
: GuiComponent(window), : GuiComponent(window),
mCurrentView(nullptr), mCurrentView(nullptr),
mPreviousView(nullptr), mPreviousView(nullptr),
mSkipView(nullptr),
mCamera(Transform4x4f::Identity()), mCamera(Transform4x4f::Identity()),
mWrappedViews(false), mWrappedViews(false),
mFadeOpacity(0), mFadeOpacity(0),
mCancelledAnimation(false), mCancelledTransition(false),
mLockInput(false), mLockInput(false),
mGameToLaunch(nullptr) mGameToLaunch(nullptr)
{ {
@ -129,15 +130,24 @@ bool ViewController::isCameraMoving()
void ViewController::cancelViewTransitions() void ViewController::cancelViewTransitions()
{ {
if (Settings::getInstance()->getString("TransitionStyle") == "slide" && isCameraMoving()) { if (Settings::getInstance()->getString("TransitionStyle") == "slide") {
if (isCameraMoving()) {
mCamera.r3().x() = -mCurrentView->getPosition().x(); mCamera.r3().x() = -mCurrentView->getPosition().x();
mCamera.r3().y() = -mCurrentView->getPosition().y(); mCamera.r3().y() = -mCurrentView->getPosition().y();
stopAllAnimations(); stopAllAnimations();
} }
// mSkipView is used when skipping through the gamelists in quick succession.
// Without this, the game video (or static image) would not get rendered during
// the slide transition animation.
else if (mSkipView) {
mSkipView.reset();
mSkipView = nullptr;
}
}
else if (Settings::getInstance()->getString("TransitionStyle") == "fade") { else if (Settings::getInstance()->getString("TransitionStyle") == "fade") {
if (isAnimationPlaying(0)) { if (isAnimationPlaying(0)) {
finishAnimation(0); finishAnimation(0);
mCancelledAnimation = true; mCancelledTransition = true;
mFadeOpacity = 0; mFadeOpacity = 0;
mWindow->invalidateCachedBackground(); mWindow->invalidateCachedBackground();
} }
@ -166,8 +176,6 @@ void ViewController::restoreViewPosition()
restorePosition.x() = mWrapPreviousPositionX; restorePosition.x() = mWrapPreviousPositionX;
mPreviousView->setPosition(restorePosition); mPreviousView->setPosition(restorePosition);
mWrapPreviousPositionX = 0; mWrapPreviousPositionX = 0;
mPreviousView.reset();
mPreviousView = nullptr;
mWrappedViews = false; mWrappedViews = false;
} }
} }
@ -183,9 +191,18 @@ void ViewController::goToSystemView(SystemData* system, bool playTransition)
if (mWrappedViews) if (mWrappedViews)
restoreViewPosition(); restoreViewPosition();
// Tell any current view it's about to be hidden and stop its rendering. if (mPreviousView) {
mPreviousView.reset();
mPreviousView = nullptr;
}
mPreviousView = mCurrentView;
// Pause the video and flag the view to not be rendered. The onHide() will take place
// later in the transition animation lambda function. For views without videos this has
// no effect (and no adverse effect either).
if (mCurrentView) { if (mCurrentView) {
mCurrentView->onHide(); mCurrentView->onPauseVideo();
mCurrentView->setRenderView(false); mCurrentView->setRenderView(false);
} }
@ -265,6 +282,19 @@ void ViewController::goToGameList(SystemData* system)
if (mWrappedViews) if (mWrappedViews)
restoreViewPosition(); restoreViewPosition();
if (mPreviousView && Settings::getInstance()->getString("TransitionStyle") == "fade" &&
isAnimationPlaying(0))
mPreviousView->onHide();
if (mPreviousView) {
mSkipView = mPreviousView;
mPreviousView.reset();
mPreviousView = nullptr;
}
if (mState.viewing != SYSTEM_SELECT)
mPreviousView = mCurrentView;
// Find if we're wrapping around the first and last systems, which requires the gamelist // Find if we're wrapping around the first and last systems, which requires the gamelist
// to be moved in order to avoid weird camera movements. This is only needed for the // to be moved in order to avoid weird camera movements. This is only needed for the
// slide transition style though. // slide transition style though.
@ -293,14 +323,16 @@ void ViewController::goToGameList(SystemData* system)
if (getSystemListView()->getRenderView()) { if (getSystemListView()->getRenderView()) {
getSystemListView()->setRenderView(false); getSystemListView()->setRenderView(false);
} }
// If switching between gamelists, disable rendering of the current view. // Pause the video and flag the view to not be rendered. The onHide() will take place
// later in the transition animation lambda function. For views without videos this has
// no effect (and no adverse effect either).
else if (mCurrentView) { else if (mCurrentView) {
mCurrentView->onHide(); mCurrentView->onPauseVideo();
mCurrentView->setRenderView(false); mCurrentView->setRenderView(false);
} }
if (mState.viewing == SYSTEM_SELECT) { if (mState.viewing == SYSTEM_SELECT) {
// Move system list. // Move the system list.
auto sysList = getSystemListView(); auto sysList = getSystemListView();
float offsetX = sysList->getPosition().x(); float offsetX = sysList->getPosition().x();
int sysId = getSystemId(system); int sysId = getSystemId(system);
@ -323,7 +355,6 @@ void ViewController::goToGameList(SystemData* system)
currentPosition.x() = offsetX; currentPosition.x() = offsetX;
mCurrentView->setPosition(currentPosition); mCurrentView->setPosition(currentPosition);
mCamera.translation().x() -= offsetX; mCamera.translation().x() -= offsetX;
mPreviousView = mCurrentView;
mWrappedViews = true; mWrappedViews = true;
} }
else if (wrapLastToFirst) { else if (wrapLastToFirst) {
@ -334,7 +365,6 @@ void ViewController::goToGameList(SystemData* system)
currentPosition.x() = offsetX; currentPosition.x() = offsetX;
mCurrentView->setPosition(currentPosition); mCurrentView->setPosition(currentPosition);
mCamera.translation().x() = -offsetX; mCamera.translation().x() = -offsetX;
mPreviousView = mCurrentView;
mWrappedViews = true; mWrappedViews = true;
} }
@ -358,9 +388,6 @@ void ViewController::goToGameList(SystemData* system)
mState.viewing = GAME_LIST; mState.viewing = GAME_LIST;
mState.system = system; mState.system = system;
if (mCurrentView)
mCurrentView->onHide();
if (mCurrentView) { if (mCurrentView) {
mCurrentView->onShow(); mCurrentView->onShow();
mCurrentView->setRenderView(true); mCurrentView->setRenderView(true);
@ -370,7 +397,7 @@ void ViewController::goToGameList(SystemData* system)
void ViewController::playViewTransition(bool instant) void ViewController::playViewTransition(bool instant)
{ {
mCancelledAnimation = false; mCancelledTransition = false;
Vector3f target(Vector3f::Zero()); Vector3f target(Vector3f::Zero());
if (mCurrentView) if (mCurrentView)
@ -385,7 +412,10 @@ void ViewController::playViewTransition(bool instant)
if (instant || transition_style == "instant") { if (instant || transition_style == "instant") {
setAnimation(new LambdaAnimation([this, target](float /*t*/) { setAnimation(new LambdaAnimation([this, target](float /*t*/) {
this->mCamera.translation() = -target; }, 1)); this->mCamera.translation() = -target;
if (mPreviousView)
mPreviousView->onHide();
}, 1));
updateHelpPrompts(); updateHelpPrompts();
} }
else if (transition_style == "fade") { else if (transition_style == "fade") {
@ -393,20 +423,27 @@ void ViewController::playViewTransition(bool instant)
cancelAnimation(0); cancelAnimation(0);
auto fadeFunc = [this](float t) { auto fadeFunc = [this](float t) {
// The flag mCancelledAnimation is required only when cancelViewTransitions() // The flag mCancelledTransition is required only when cancelViewTransitions()
// cancels the animation, and it's only needed for the Fade transitions. // cancels the animation, and it's only needed for the Fade transitions.
// Without this, a (much shorter) fade transition would still play as // Without this, a (much shorter) fade transition would still play as
// finishedCallback is calling this function. // finishedCallback is calling this function.
if (!mCancelledAnimation) if (!mCancelledTransition)
mFadeOpacity = Math::lerp(0, 1, t); mFadeOpacity = Math::lerp(0, 1, t);
}; };
auto fadeCallback = [this]() {
if (mPreviousView)
mPreviousView->onHide();
};
const static int FADE_DURATION = 120; // Fade in/out time. const static int FADE_DURATION = 120; // Fade in/out time.
const static int FADE_WAIT = 200; // Time to wait between in/out. const static int FADE_WAIT = 200; // Time to wait between in/out.
setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), 0, [this, fadeFunc, target] { setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), 0,
[this, fadeFunc, fadeCallback, target] {
this->mCamera.translation() = -target; this->mCamera.translation() = -target;
updateHelpPrompts(); updateHelpPrompts();
setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), FADE_WAIT, nullptr, true); setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION),
FADE_WAIT, fadeCallback, true);
}); });
// Fast-forward animation if we're partway faded. // Fast-forward animation if we're partway faded.
@ -421,8 +458,17 @@ void ViewController::playViewTransition(bool instant)
} }
} }
else if (transition_style == "slide") { else if (transition_style == "slide") {
// Slide or simple slide. auto slideCallback = [this]() {
setAnimation(new MoveCameraAnimation(mCamera, target)); if (mSkipView) {
mSkipView->onHide();
mSkipView.reset();
mSkipView = nullptr;
}
else if (mPreviousView) {
mPreviousView->onHide();
}
};
setAnimation(new MoveCameraAnimation(mCamera, target), 0, slideCallback);
updateHelpPrompts(); // Update help prompts immediately. updateHelpPrompts(); // Update help prompts immediately.
} }
} }

View file

@ -117,6 +117,7 @@ private:
std::shared_ptr<GuiComponent> mCurrentView; std::shared_ptr<GuiComponent> mCurrentView;
std::shared_ptr<GuiComponent> mPreviousView; std::shared_ptr<GuiComponent> mPreviousView;
std::shared_ptr<GuiComponent> mSkipView;
std::map<SystemData*, std::shared_ptr<IGameListView>> mGameListViews; std::map<SystemData*, std::shared_ptr<IGameListView>> mGameListViews;
std::shared_ptr<SystemView> mSystemListView; std::shared_ptr<SystemView> mSystemListView;
@ -124,7 +125,7 @@ private:
bool mWrappedViews; bool mWrappedViews;
float mWrapPreviousPositionX; float mWrapPreviousPositionX;
float mFadeOpacity; float mFadeOpacity;
bool mCancelledAnimation; // Needed only for the Fade transition style. bool mCancelledTransition; // Needed only for the Fade transition style.
bool mLockInput; bool mLockInput;
FileData* mGameToLaunch; FileData* mGameToLaunch;

View file

@ -182,9 +182,6 @@ void VideoVlcComponent::resize()
void VideoVlcComponent::render(const Transform4x4f& parentTrans) void VideoVlcComponent::render(const Transform4x4f& parentTrans)
{ {
if (!isVisible())
return;
VideoComponent::render(parentTrans); VideoComponent::render(parentTrans);
Transform4x4f trans = parentTrans * getTransform(); Transform4x4f trans = parentTrans * getTransform();
GuiComponent::renderChildren(trans); GuiComponent::renderChildren(trans);