From f69be9f9f06da3a2b69b893bd9e8ef7358b6d679 Mon Sep 17 00:00:00 2001 From: Douglas Liu Date: Fri, 18 May 2018 18:05:46 +0800 Subject: [PATCH] STARK: Fix the busy-wait for clicking sound --- engines/stark/services/userinterface.cpp | 30 ++++++++++++++---------- engines/stark/services/userinterface.h | 15 +++++++++--- engines/stark/stark.cpp | 2 ++ engines/stark/ui/menu/diaryindex.cpp | 2 +- engines/stark/ui/menu/locationscreen.cpp | 8 +++++-- engines/stark/ui/menu/locationscreen.h | 3 +++ engines/stark/ui/menu/mainmenu.cpp | 24 +++++++++++++++---- engines/stark/ui/menu/mainmenu.h | 7 ++++++ engines/stark/ui/screen.h | 9 ++++++- 9 files changed, 76 insertions(+), 24 deletions(-) diff --git a/engines/stark/services/userinterface.cpp b/engines/stark/services/userinterface.cpp index 6588caf370..fdc783a222 100644 --- a/engines/stark/services/userinterface.cpp +++ b/engines/stark/services/userinterface.cpp @@ -55,7 +55,8 @@ UserInterface::UserInterface(Gfx::Driver *gfx) : _interactionAttemptDenied(false), _currentScreen(nullptr), _gameWindowThumbnail(nullptr), - _preScreenNameStack() { + _prevScreenNameStack(), + _nextScreenName(Screen::kScreenMainMenu) { } UserInterface::~UserInterface() { @@ -91,7 +92,10 @@ void UserInterface::update() { } void UserInterface::handleMouseMove(const Common::Point &pos) { - _cursor->setMousePosition(pos); + // Cursor should not move when there is request of changing the displayed screen + if (!hasChangeScreenRequest()) { + _cursor->setMousePosition(pos); + } } void UserInterface::handleClick() { @@ -134,24 +138,26 @@ void UserInterface::requestFMVPlayback(const Common::String &name) { } void UserInterface::onFMVStopped() { - backPreScreen(); + backPrevScreen(); } void UserInterface::changeScreen(Screen::Name screenName) { - if (screenName == _currentScreen->getName()) { - return; - } + _nextScreenName = screenName; +} - _preScreenNameStack.push(_currentScreen->getName()); - _currentScreen->close(); - _currentScreen = getScreenByName(screenName); - _currentScreen->open(); +void UserInterface::handleChangeScreen() { + if (hasChangeScreenRequest() && !(_currentScreen->hasRemainingSound())) { + _prevScreenNameStack.push(_currentScreen->getName()); + _currentScreen->close(); + _currentScreen = getScreenByName(_nextScreenName); + _currentScreen->open(); + } } -void UserInterface::backPreScreen() { +void UserInterface::backPrevScreen() { // No need to check the stack since at least there will be a MainMenuScreen in it // and MainMenuScreen will not request to go back - changeScreen(_preScreenNameStack.pop()); + changeScreen(_prevScreenNameStack.pop()); } Screen *UserInterface::getScreenByName(Screen::Name screenName) const { diff --git a/engines/stark/services/userinterface.h b/engines/stark/services/userinterface.h index 6cdcaa5b1d..343dc7fe28 100644 --- a/engines/stark/services/userinterface.h +++ b/engines/stark/services/userinterface.h @@ -82,11 +82,19 @@ class UserInterface { */ bool skipFMV(); - /** Set the currently displayed screen */ + /** Request to change the currently displayed screen */ void changeScreen(Screen::Name screenName); + /** Check whether there is request of changing screen */ + bool hasChangeScreenRequest() { + return _nextScreenName != _currentScreen->getName(); + } + + /** Handle the request of changing the currently displayed screen */ + void handleChangeScreen(); + /** Back to the previous displayed screen */ - void backPreScreen(); + void backPrevScreen(); /** Is the game screen currently displayed? */ bool isInGameScreen() const; @@ -146,7 +154,8 @@ class UserInterface { DiaryIndexScreen *_diaryIndexScreen; MainMenuScreen *_mainMenuScreen; Screen *_currentScreen; - Common::Stack _preScreenNameStack; + Common::Stack _prevScreenNameStack; + Screen::Name _nextScreenName; Gfx::Driver *_gfx; Cursor *_cursor; diff --git a/engines/stark/stark.cpp b/engines/stark/stark.cpp index a2248b0e02..57fc94b082 100644 --- a/engines/stark/stark.cpp +++ b/engines/stark/stark.cpp @@ -200,6 +200,8 @@ void StarkEngine::mainLoop() { break; } + _userInterface->handleChangeScreen(); + if (_resourceProvider->hasLocationChangeRequest()) { _global->setNormalSpeed(); _resourceProvider->performLocationChange(); diff --git a/engines/stark/ui/menu/diaryindex.cpp b/engines/stark/ui/menu/diaryindex.cpp index 2f53256ef4..a81888184f 100644 --- a/engines/stark/ui/menu/diaryindex.cpp +++ b/engines/stark/ui/menu/diaryindex.cpp @@ -110,7 +110,7 @@ void DiaryIndexScreen::widgetTextColorHandler(StaticLocationWidget &widget, cons } void DiaryIndexScreen::backHandler() { - StarkUserInterface->backPreScreen(); + StarkUserInterface->backPrevScreen(); } void DiaryIndexScreen::quitHandler() { diff --git a/engines/stark/ui/menu/locationscreen.cpp b/engines/stark/ui/menu/locationscreen.cpp index b6c352c6a6..32ef8632ba 100644 --- a/engines/stark/ui/menu/locationscreen.cpp +++ b/engines/stark/ui/menu/locationscreen.cpp @@ -108,6 +108,12 @@ void StaticLocationScreen::onClick(const Common::Point &pos) { for (uint i = 1; i < _widgets.size(); i++) { StaticLocationWidget *widget = _widgets[i]; if (widget->isVisible() && widget->isMouseInside(pos)) { + // The click sound needs to be tracked to ensure being played completely + Resources::Sound *clickSound = widget->getSoundMouseClick(); + if (clickSound) { + _prevTrackedSound = clickSound; + } + widget->onClick(); break; } @@ -178,8 +184,6 @@ void StaticLocationWidget::onClick() { if (_soundMouseClick) { _soundMouseClick->play(); - // Ensure the click sound is played completely - while (_soundMouseClick->isPlaying()) {}; } if (_onClick) { diff --git a/engines/stark/ui/menu/locationscreen.h b/engines/stark/ui/menu/locationscreen.h index 1d1dc9c3b0..20fa91fe33 100644 --- a/engines/stark/ui/menu/locationscreen.h +++ b/engines/stark/ui/menu/locationscreen.h @@ -88,6 +88,9 @@ class StaticLocationWidget { /** Lookup sounds in the static location for use when hovering / clicking the widget */ void setupSounds(int16 enterSound, int16 clickSound); + /** Get the mouse click sound */ + Resources::Sound *getSoundMouseClick() { return _soundMouseClick; } + /** * Override the text color * diff --git a/engines/stark/ui/menu/mainmenu.cpp b/engines/stark/ui/menu/mainmenu.cpp index b0687d1214..eb9df7ec79 100644 --- a/engines/stark/ui/menu/mainmenu.cpp +++ b/engines/stark/ui/menu/mainmenu.cpp @@ -24,10 +24,13 @@ #include "engines/stark/services/userinterface.h" #include "engines/stark/services/resourceprovider.h" +#define SET_CLOSE_ACTION(method) new Common::Functor0Mem(this, &MainMenuScreen::method); + namespace Stark { MainMenuScreen::MainMenuScreen(Gfx::Driver *gfx, Cursor *cursor) : - StaticLocationScreen(gfx, cursor, "MainMenuLocation", Screen::kScreenMainMenu) { + StaticLocationScreen(gfx, cursor, "MainMenuLocation", Screen::kScreenMainMenu), + _closeAction(nullptr) { } MainMenuScreen::~MainMenuScreen() { @@ -125,6 +128,14 @@ void MainMenuScreen::open() { nullptr)); } +void MainMenuScreen::close() { + StaticLocationScreen::close(); + + if (_closeAction) { + (*_closeAction)(); + } +} + template void MainMenuScreen::helpTextHandler(StaticLocationWidget &widget, const Common::Point &mousePos) { if (widget.isVisible()) { @@ -140,7 +151,14 @@ void MainMenuScreen::creditsHandler() { void MainMenuScreen::newGameHandler() { StarkUserInterface->changeScreen(kScreenGame); + _closeAction = SET_CLOSE_ACTION(newGameHandlerHelper); +} + +void MainMenuScreen::quitHandler() { + StarkUserInterface->notifyShouldExit(); +} +void MainMenuScreen::newGameHandlerHelper() { if (isDemo()) { StarkResourceProvider->requestLocationChange(0x4f, 0x00); } else { @@ -148,8 +166,4 @@ void MainMenuScreen::newGameHandler() { } } -void MainMenuScreen::quitHandler() { - StarkUserInterface->notifyShouldExit(); -} - } // End of namespace Stark \ No newline at end of file diff --git a/engines/stark/ui/menu/mainmenu.h b/engines/stark/ui/menu/mainmenu.h index fb13a55e90..11289166a1 100644 --- a/engines/stark/ui/menu/mainmenu.h +++ b/engines/stark/ui/menu/mainmenu.h @@ -39,8 +39,13 @@ class MainMenuScreen : public StaticLocationScreen { // StaticLocationScreen API void open() override; + void close() override; private: + typedef Common::Functor0Mem CloseActionFunctor; + + CloseActionFunctor *_closeAction; + template void helpTextHandler(StaticLocationWidget &widget, const Common::Point &mousePos); @@ -48,6 +53,8 @@ class MainMenuScreen : public StaticLocationScreen { void creditsHandler(); void quitHandler(); + void newGameHandlerHelper(); + bool isDemo() { return StarkGameDescription->flags & ADGF_DEMO; } diff --git a/engines/stark/ui/screen.h b/engines/stark/ui/screen.h index c61672cef4..100552918e 100644 --- a/engines/stark/ui/screen.h +++ b/engines/stark/ui/screen.h @@ -27,6 +27,7 @@ #include "common/rect.h" #include "engines/stark/ui/window.h" +#include "engines/stark/resources/sound.h" namespace Stark { @@ -42,7 +43,7 @@ class Screen { kScreenDiaryIndex }; - explicit Screen(Name name) : _name(name) {}; + explicit Screen(Name name) : _name(name), _prevTrackedSound(nullptr) {}; virtual ~Screen() {}; /** Obtain the name of the screen */ @@ -57,11 +58,17 @@ class Screen { /** Draw the screen */ virtual void render() = 0; + /** Check whether the tracked sound has done playing */ + bool hasRemainingSound() { return _prevTrackedSound && _prevTrackedSound->isPlaying(); } + virtual void handleMouseMove() = 0; virtual void handleClick() = 0; virtual void handleRightClick() = 0; virtual void handleDoubleClick() = 0; +protected: + Resources::Sound *_prevTrackedSound; + private: Name _name; };