diff --git a/src/libs/tgfclient/guihelp.cpp b/src/libs/tgfclient/guihelp.cpp index d375ea239..bad241ea2 100644 --- a/src/libs/tgfclient/guihelp.cpp +++ b/src/libs/tgfclient/guihelp.cpp @@ -49,15 +49,29 @@ onDeactivate(void* /* dummy */) /** Generate a help screen. @ingroup gui - @param prevScreen Previous screen to return to + @param targetScreen The screen to display help for and to return to when exiting @warning The help screen is activated. */ void -GfuiHelpScreen(void *prevScreen) +GfuiHelpScreen(void *targetScreen) { - tGfuiScreen *pscr = (tGfuiScreen*)prevScreen; + GfuiHelpScreen(targetScreen, 0); +} - // Create screen, load menu XML descriptor and create static controls. +/** Generate a help screen. + @ingroup gui + @param targetScreen The screen to display help for + @param returnScreen The screen to return to when exiting + @warning The help screen is activated. + */ +void +GfuiHelpScreen(void *targetScreen, void *returnScreen) +{ + // The return screen is the target screen if not specified (0). + if (!returnScreen) + returnScreen = targetScreen; + + // Create help screen, load menu XML descriptor and create static controls. void* scrHandle = GfuiScreenCreate(0, 0, onActivate, 0, onDeactivate); void *hmenu = GfuiMenuLoad("helpmenu.xml"); @@ -75,8 +89,12 @@ GfuiHelpScreen(void *prevScreen) int ys = nYTopLine; int yn = nYTopLine; - tGfuiKey *curKey = pscr->userKeys; + tGfuiScreen *pscrTgt = (tGfuiScreen*)targetScreen; + + tGfuiKey *curKey = pscrTgt->userKeys; do { + // Decide if this key goes on the left of right column. + bool bLeft; if (curKey) { curKey = curKey->next; switch(curKey->key) { @@ -105,31 +123,45 @@ GfuiHelpScreen(void *prevScreen) case GFUIK_DELETE: case GFUIK_CLEAR: case GFUIK_PAUSE: - GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyName", true, // from template - curKey->name, nXLeftColumn, ys); - GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyDesc", true, // from template - curKey->descr, nXLeftColumn + nNameFieldWidth, ys); - ys -= nLineShift; + bLeft = true; break; default: - GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyName", true, // from template - curKey->name, nXRightColumn, yn); - GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyDesc", true, // from template - curKey->descr, nXRightColumn + nNameFieldWidth, yn); - yn -= nLineShift; + bLeft = curKey->modifier != GFUIM_NONE; break; } } - - if (curKey == pscr->userKeys) + + // Determine control coordinates, whether left or right column. + int x, y; + if (bLeft) + { + x = nXLeftColumn; + y = ys; + ys -= nLineShift; + } + else + { + x = nXRightColumn; + y = yn; + yn -= nLineShift; + } + + // Create label controls. + GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyName", true, // from template + curKey->name, x, y); + GfuiMenuCreateLabelControl(scrHandle, hmenu, "keyDesc", true, // from template + curKey->descr, x + nNameFieldWidth, y); + + // Stop if no more keys to explain. + if (curKey == pscrTgt->userKeys) curKey = (tGfuiKey*)NULL; } while (curKey); // Create Back button. - GfuiMenuCreateButtonControl(scrHandle, hmenu, "backbutton", prevScreen, GfuiScreenReplace); + GfuiMenuCreateButtonControl(scrHandle, hmenu, "backbutton", targetScreen, GfuiScreenReplace); // Create version label. const int versionId = GfuiMenuCreateLabelControl(scrHandle, hmenu, "versionlabel"); @@ -139,8 +171,8 @@ GfuiHelpScreen(void *prevScreen) GfParmReleaseHandle(hmenu); // Add keyboard shortcuts. - GfuiAddKey(scrHandle, GFUIK_ESCAPE, "Back to the menu", prevScreen, GfuiScreenReplace, NULL); - GfuiAddKey(scrHandle, GFUIK_RETURN, "Back to the menu", prevScreen, GfuiScreenReplace, NULL); + GfuiAddKey(scrHandle, GFUIK_ESCAPE, "Back to the menu", returnScreen, GfuiScreenReplace, NULL); + GfuiAddKey(scrHandle, GFUIK_RETURN, "Back to the menu", returnScreen, GfuiScreenReplace, NULL); if (NRecursions == 0) GfuiAddKey(scrHandle, GFUIK_F1, "Help on Help menu", scrHandle, GfuiHelpScreen, NULL); GfuiAddKey(scrHandle, GFUIK_F12, "Screen-shot", NULL, GfuiScreenShot, NULL); diff --git a/src/libs/tgfclient/tgfclient.h b/src/libs/tgfclient/tgfclient.h index 7adafde2d..c7064f94f 100644 --- a/src/libs/tgfclient/tgfclient.h +++ b/src/libs/tgfclient/tgfclient.h @@ -276,7 +276,8 @@ TGFCLIENT_API void GfuiAddKey(void *scr, int key, int modifier, const char *desc TGFCLIENT_API void GfuiRegisterKey(int key, const char *descr, void *userData, tfuiCallback onKeyPressed, tfuiCallback onKeyReleased); TGFCLIENT_API void GfuiSetKeyAutoRepeat(void *scr, int on); -TGFCLIENT_API void GfuiHelpScreen(void *prevScreen); +TGFCLIENT_API void GfuiHelpScreen(void *targetScreen); +TGFCLIENT_API void GfuiHelpScreen(void *targetScreen, void *returnScreen); TGFCLIENT_API void GfuiScreenShot(void *notused); TGFCLIENT_API void GfuiScreenAddBgImg(void *scr, const char *filename); TGFCLIENT_API void GfuiKeyEventRegister(void *scr, tfuiKeyCallback onKeyAction); diff --git a/src/modules/userinterface/legacymenu/racescreens/racerunningmenus.cpp b/src/modules/userinterface/legacymenu/racescreens/racerunningmenus.cpp index fdccf2417..94c9914b0 100644 --- a/src/modules/userinterface/legacymenu/racescreens/racerunningmenus.cpp +++ b/src/modules/userinterface/legacymenu/racescreens/racerunningmenus.cpp @@ -71,9 +71,17 @@ const double RmProgressiveTimeModifier::_sfTimeLapse = 2; RmProgressiveTimeModifier rmProgressiveTimeModifier; RmProgressiveTimeModifier::RmProgressiveTimeModifier() -: _bExecRunning(false), _fExecStartTime(0), _fWholeTimeLapse(0), - _fOldTimeMultiplier(_sfTimeMultiplier), _fResetterTimeMultiplier(1) { + reset(); +} + +void RmProgressiveTimeModifier::reset() +{ + _bExecRunning = false; + _fExecStartTime = 0; + _fWholeTimeLapse = 0; + _fOldTimeMultiplier = _sfTimeMultiplier; + _fResetterTimeMultiplier = 1; } void RmProgressiveTimeModifier::start() @@ -140,8 +148,8 @@ void RmProgressiveTimeModifier::execute() void RmProgressiveTimeModifier::terminate() { - // Seems we have done our work. Lets be quiet untill next start() call. - _bExecRunning = false; + // Seems we have done our work. Lets keep quiet until next time start() is called. + reset(); } /***************************************************************************/ @@ -159,6 +167,16 @@ rmUpdateRaceEngine() static std::string rmStrCurMsg; static std::string rmStrCurBigMsg; +// Race pause flag +// There are 2 concepts of "Pause" here, and they can overlap each other : +// 1) the race engine : LmRaceEngine().outData()->s->_raceState & RM_RACE_PAUSED +// which matches with the in-game 'P' key shortcut to freeze the race screen, +// 2) the menu one : you can also pause the game through the 'Esc' key (=> Stop Race menu) +// and through the 'F1' key (=> help menu). +// This flag is for the 2nd one : +// when you unpause in the 2nd one meaning, you may stay paused in the 1st one meaning. +static bool rmRacePaused = false; + // Flag to know if the menu state has been changed (and thus needs a redraw+redisplay). static bool rmbMenuChanged = false; @@ -202,6 +220,7 @@ rmInitMovieCapture() strcmp(GfParmGetStr(hparmRaceEng, RM_SECT_MOVIE_CAPTURE, RM_ATT_CAPTURE_ENABLE, RM_VAL_NO), RM_VAL_NO) ? true : false; + rmMovieCapture.active = false; if (!rmMovieCapture.enabled) { rmMovieCapture.outputBase = 0; @@ -209,7 +228,6 @@ rmInitMovieCapture() } else { - rmMovieCapture.active = false; rmMovieCapture.frameRate = GfParmGetNum(hparmRaceEng, RM_SECT_MOVIE_CAPTURE, RM_ATT_CAPTURE_FPS, NULL, 25.0); rmMovieCapture.simuRate = 1.0 / RCM_MAX_DT_SIMU; @@ -339,6 +357,10 @@ rmRedisplay() GfuiApp().eventLoop().postRedisplay(); } +// Warning : This function is called when the race is actually starting in "non-blind" mode, +// but also when coming back from the Stop Race menu (the user chose "Resume") +// or from the Help menu. It must also consider that the race may be currently paused ! + static void rmScreenActivate(void * /* dummy */) { @@ -361,23 +383,21 @@ rmScreenActivate(void * /* dummy */) #endif - // Hide the on-screen pause indicator in case it is visible. - GfuiVisibilitySet(rmScreenHandle, rmPauseId, GFUI_INVISIBLE); - - // Reset normal sound volume in any case. - if (LegacyMenu::self().soundEngine()) - LegacyMenu::self().soundEngine()->mute(false); - - // Deactivate the movie capture mode in any case. - rmMovieCapture.active = false; - // Configure the event loop. GfuiApp().eventLoop().setRecomputeCB(rmUpdateRaceEngine); GfuiApp().eventLoop().setRedisplayCB(rmRedisplay); - // Resynchronize the race engine. - LmRaceEngine().start(); - + // If not paused ... + if (!rmRacePaused) + { + // Reset normal sound volume. + if (LegacyMenu::self().soundEngine()) + LegacyMenu::self().soundEngine()->mute(false); + + // Resynchronize the race engine. + LmRaceEngine().start(); + } + // Request a redisplay for the next event loop. GfuiApp().eventLoop().postRedisplay(); @@ -388,7 +408,7 @@ rmScreenActivate(void * /* dummy */) static void rmRacePause(void * /* vboard */) { - if (LmRaceEngine().outData()->s->_raceState & RM_RACE_PAUSED) + if (rmRacePaused) { if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(false); @@ -421,6 +441,9 @@ rmRacePause(void * /* vboard */) GfuiVisibilitySet(rmScreenHandle, rmMsgId, GFUI_INVISIBLE); } + // Toggle the race-paused flag. + rmRacePaused = !rmRacePaused; + // The menu changed. rmbMenuChanged = true; } @@ -509,10 +532,12 @@ rmApplyState(void *pvState) static void rmOpenHelpScreen(void * /* dummy */) { + LmRaceEngine().stop(); + if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(true); - GfuiHelpScreen(rmScreenHandle); + GfuiHelpScreen(rmScreenHandle, RmBackToRaceHookInit()); } static void @@ -540,9 +565,6 @@ rmAddKeys() void * RmScreenInit() { - // Initialize the movie capture system. - rmInitMovieCapture(); - // Release screen if was initialized. RmScreenShutdown(); @@ -562,9 +584,17 @@ RmScreenInit() // Register keyboard shortcuts. rmAddKeys(); - // Hide the Pause label for the moment. - GfuiVisibilitySet(rmScreenHandle, rmPauseId, 0); + // We are starting "unpaused". + GfuiVisibilitySet(rmScreenHandle, rmPauseId, GFUI_INVISIBLE); + rmRacePaused = false; + // Re-initialize the progressive time modifier, + // in case the race was exited while it was running. + rmProgressiveTimeModifier.reset(); + + // Initialize the movie capture system. + rmInitMovieCapture(); + return rmScreenHandle; } @@ -651,6 +681,9 @@ rmResScreenActivate(void * /* dummy */) GfuiApp().eventLoop().setRecomputeCB(rmUpdateRaceEngine); GfuiApp().eventLoop().setRedisplayCB(rmResRedisplay); + // Resynchronize the race engine. + LmRaceEngine().start(); + // Request a redisplay for the next event loop. GfuiApp().eventLoop().postRedisplay(); diff --git a/src/modules/userinterface/legacymenu/racescreens/racescreens.h b/src/modules/userinterface/legacymenu/racescreens/racescreens.h index f783dfa55..4b313a794 100644 --- a/src/modules/userinterface/legacymenu/racescreens/racescreens.h +++ b/src/modules/userinterface/legacymenu/racescreens/racescreens.h @@ -85,6 +85,7 @@ extern void RmGameScreen(); extern void RmShowResults(void * /* prevHdle */, tRmInfo * /* info */); +extern void* RmBackToRaceHookInit(); extern void RmStopRaceMenu(); extern void RmStopRaceMenuShutdown(); @@ -141,14 +142,25 @@ extern void *RmRaceSelectMenuHandle; class RmProgressiveTimeModifier { public: + + //! Constructor. RmProgressiveTimeModifier(); + + //! Reset state as if just born. + void reset(); + + //! Start the ramp up. void start(); + + //! Simulation step : aimed at being called at each display loop. void execute(); private: + + //! For when the ramp up is over. void terminate(); -private: + private: // Should we run the manager at next simu step ? bool _bExecRunning; @@ -165,12 +177,12 @@ private: // Log the integrated time acceleration change (needed when multiple start without terminate) double _fResetterTimeMultiplier; -private: + private: // Config: Set how much time will take to restore to normal speed (after the delay) static const double _sfTimeMultiplier; - // Config: Set how much we wait befor starting to apply the time acceleration + // Config: Set how much we wait before starting to apply the time acceleration static const double _sfDelay; // Config: Set how much the time will be initially changed (as a fraction of the current time) diff --git a/src/modules/userinterface/legacymenu/racescreens/racestopmenu.cpp b/src/modules/userinterface/legacymenu/racescreens/racestopmenu.cpp index 1b3fddf11..3a6966272 100644 --- a/src/modules/userinterface/legacymenu/racescreens/racestopmenu.cpp +++ b/src/modules/userinterface/legacymenu/racescreens/racestopmenu.cpp @@ -34,7 +34,7 @@ rmAbortRaceHookActivate(void * /* dummy */) static void *pvAbortRaceHookHandle = 0; static void * -rmAbortRaceHookInit(void) +rmAbortRaceHookInit() { if (!pvAbortRaceHookHandle) pvAbortRaceHookHandle = GfuiHookCreate(0, rmAbortRaceHookActivate); @@ -52,7 +52,7 @@ rmSkipSessionHookActivate(void * /* dummy */) static void *pvSkipSessionHookHandle = 0; static void * -rmSkipSessionHookInit(void) +rmSkipSessionHookInit() { if (!pvSkipSessionHookHandle) pvSkipSessionHookHandle = GfuiHookCreate(0, rmSkipSessionHookActivate); @@ -64,8 +64,14 @@ rmSkipSessionHookInit(void) static void rmBackToRaceHookActivate(void * /* dummy */) { - LmRaceEngine().start(); - + // Temporary hack for the Paused race case, in order + // the race does not get ended (as is is currently stopped) + // TODO: Activate the Stop Race menu directly, as for the Help menu (F1), + // and no more through changing the race engine state to STOP + // But beware of the other hooks ... + LmRaceEngine().inData()->_reState = RE_STATE_RACE; + + // Back to the race screen in next display loop. LegacyMenu::self().activateGameScreen(); // Launch the "slow resume race" manager if non-blind mode. @@ -75,8 +81,8 @@ rmBackToRaceHookActivate(void * /* dummy */) static void *pvBackToRaceHookHandle = 0; -static void * -rmBackToRaceHookInit(void) +void * +RmBackToRaceHookInit() { if (!pvBackToRaceHookHandle) pvBackToRaceHookHandle = GfuiHookCreate(0, rmBackToRaceHookActivate); @@ -94,7 +100,7 @@ rmRestartRaceHookActivate(void * /* dummy */) static void *pvRestartRaceHookHandle = 0; static void * -rmRestartRaceHookInit(void) +rmRestartRaceHookInit() { if (!pvRestartRaceHookHandle) pvRestartRaceHookHandle = GfuiHookCreate(0, rmRestartRaceHookActivate); @@ -115,7 +121,7 @@ rmQuitHookActivate(void * /* dummy */) static void *pvQuitHookHandle = 0; static void * -rmQuitHookInit(void) +rmQuitHookInit() { if (!pvQuitHookHandle) pvQuitHookHandle = GfuiHookCreate(0, rmQuitHookActivate); @@ -239,7 +245,7 @@ RmStopRaceMenu() { rmStopScrHandle = rmStopRaceMenu - ("resume", rmBackToRaceHookInit(), + ("resume", RmBackToRaceHookInit(), "skip", rmSkipSessionHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); @@ -248,7 +254,7 @@ RmStopRaceMenu() { rmStopScrHandle = rmStopRaceMenu - ("resume", rmBackToRaceHookInit(), + ("resume", RmBackToRaceHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); } @@ -259,7 +265,7 @@ RmStopRaceMenu() { rmStopScrHandle = rmStopRaceMenu - ("resume", rmBackToRaceHookInit(), + ("resume", RmBackToRaceHookInit(), "skip", rmSkipSessionHookInit(), "restart", rmRestartRaceHookInit(), "abort", rmAbortRaceHookInit(), @@ -269,7 +275,7 @@ RmStopRaceMenu() { rmStopScrHandle = rmStopRaceMenu - ("resume", rmBackToRaceHookInit(), + ("resume", RmBackToRaceHookInit(), "restart", rmRestartRaceHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit());