static void rmCarSettingsMenu(void *pMenu) { int nDriverIdx = NetGetNetwork()->GetDriverIdx(); if (nDriverIdx > -1) { NetDriver driver; // char newName[64]; Never used char dname[256]; // check for car change GfLogInfo("Car %d changed \n", nDriverIdx); tRmInfo* reInfo = LmRaceEngine().inData(); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); sprintf(dname, "%s/%d", RM_SECT_DRIVERS, nDriverIdx); int idx = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, "",0); // Garage menu to change clients car GfDriver* PCurrentDriver = GfDrivers::self()->getDriver(NETWORKROBOT, idx); GarageMenu.setPreviousMenuHandle(racemanMenuHdle); GarageMenu.runMenu(LmRaceEngine().race(), PCurrentDriver); bGarage = true; } }
static void rmUpdateRaceMessages() { if (!rmScreenHandle) return; // Set the new text for the "message" label if it changed. const char *pszMsg = LmRaceEngine().outData()->_reMessage; if ((pszMsg && rmStrCurMsg != pszMsg) || (!pszMsg && !rmStrCurMsg.empty())) { rmStrCurMsg = pszMsg ? pszMsg : ""; GfuiLabelSetText(rmScreenHandle, rmMsgId, rmStrCurMsg.c_str()); // The menu changed. rmbMenuChanged = true; } // Set the new text for the "big message" label if it changed. const char *pszBigMsg = LmRaceEngine().outData()->_reBigMessage; if ((pszBigMsg && rmStrCurBigMsg != pszBigMsg) || (!pszBigMsg && !rmStrCurBigMsg.empty())) { rmStrCurBigMsg = pszBigMsg ? pszBigMsg : ""; GfuiLabelSetText(rmScreenHandle, rmBigMsgId, rmStrCurBigMsg.c_str()); // The menu changed. rmbMenuChanged = true; } }
bool LegacyMenu::startRace() { // Get the race to start. std::string strRaceToStart; if (!GfApp().hasOption("startrace", strRaceToStart)) return false; // And run it if there's such a race manager. GfRaceManager* pSelRaceMan = GfRaceManagers::self()->getRaceManager(strRaceToStart); if (pSelRaceMan) // Should never happen (checked in activate). { // Initialize the race engine. LmRaceEngine().reset(); // Give the selected race manager to the race engine. LmRaceEngine().selectRaceman(pSelRaceMan); // Configure the new race (but don't enter the config. menu tree). LmRaceEngine().configureRace(/* bInteractive */ false); // Start the race engine state automaton LmRaceEngine().startNewRace(); } else { GfLogError("No such race type '%s'\n", strRaceToStart.c_str()); return false; } return true; }
void RmStopRaceMenu() { void* params = LmRaceEngine().outData()->params; const char* pszRaceName = LmRaceEngine().outData()->_reRaceName; // Mute sound. if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(); if (!strcmp(GfParmGetStr(params, pszRaceName, RM_ATTR_ALLOW_RESTART, RM_VAL_NO), RM_VAL_NO)) { if (strcmp(GfParmGetStr(params, pszRaceName, RM_ATTR_MUST_COMPLETE, RM_VAL_YES), RM_VAL_YES)) { rmStopScrHandle = rmStopRaceMenu ("resume", RmBackToRaceHookInit(), "skip", rmSkipSessionHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); } else { rmStopScrHandle = rmStopRaceMenu ("resume", RmBackToRaceHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); } } else { if (strcmp(GfParmGetStr(params, pszRaceName, RM_ATTR_MUST_COMPLETE, RM_VAL_YES), RM_VAL_YES)) { rmStopScrHandle = rmStopRaceMenu ("resume", RmBackToRaceHookInit(), "skip", rmSkipSessionHookInit(), "restart", rmRestartRaceHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); } else { rmStopScrHandle = rmStopRaceMenu ("resume", RmBackToRaceHookInit(), "restart", rmRestartRaceHookInit(), "abort", rmAbortRaceHookInit(), "quit", rmQuitHookInit()); } } }
static void ClientIdle(void) { GfuiIdle(); if (NetIsClient()) { if (!NetGetClient()->TimeSynced()) { NetGetClient()->SendServerTimeRequest(); } if (NetGetClient()->GetRefreshDisplay()) { //Update the screen UpdateNetworkPlayers(); GfuiApp().eventLoop().postRedisplay(); } if (NetGetClient()->PrepareToRace()) { NetGetClient()->SetLocalDrivers(); LmRaceEngine().startNewRace(); } if (!NetGetClient()->IsConnected()) { rmNetworkClientDisconnect(NULL); } GfuiApp().eventLoop().postRedisplay(); } /* Let CPU take breath (and fans stay at low and quiet speed) */ GfSleep(0.001); }
static void onHostPlayerReady(tCheckBoxInfo* pInfo) { tRmInfo* reInfo = LmRaceEngine().inData(); char dname[256]; int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS); NetServerMutexData *pSData = NetGetServer()->LockServerData(); for (int i=1; i <= nCars; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); GfLogInfo("Setting driver %d to %d\n", i, pInfo->bChecked); if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) { // Human drive, check if local int index = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, NULL, 1.0) - 1; GfLogInfo("Index %d\n", index); if (pSData->m_vecNetworkPlayers[index].client == false) NetGetServer()->OverrideDriverReady(i, pInfo->bChecked); } else { // Robot driver, all are local NetGetServer()->OverrideDriverReady(i, pInfo->bChecked); } bRobotsReady = pInfo->bChecked; } NetGetServer()->UnlockServerData(); EnableMenuHostButtons(pInfo->bChecked); GfLogInfo("menu ready\n"); }
static void RmReadyToRace(void * /* dummy */) { if (GfuiRemoveKey(rmScreenHandle,GFUIK_RETURN,"Ready")) { GfLogInfo("<Enter> key for Ready' removed \n"); } else { GfLogInfo("FAILED to remove <Enter> to Start key \n"); } // The menu changed. rmbMenuChanged = true; rmPreRacePause = false; // Enable the sound if (LegacyMenu::self().soundEngine()) { LegacyMenu::self().soundEngine()->mute(false); } LmRaceEngine().stopPreracePause(); }
// Back to race hook *************************************************** static void rmBackToRaceHookActivate(void * /* dummy */) { // 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. if (LmRaceEngine().outData()->_displayMode == RM_DISP_MODE_NORMAL) rmProgressiveTimeModifier.start(); }
// Pit menu return callback. static void rmOnBackFromPitMenu(void *pvcar) { const tCarElt* car = (tCarElt*)pvcar; LmRaceEngine().setPitCommand(car->index, &car->pitcmd); LegacyMenu::self().activateGameScreen(); }
static void rmTimeMod (void *pvCmd) { double fMultFactor = 0.0; // The mult. factor for resetting "real time" simulation step. if ((long)pvCmd > 0) fMultFactor = 0.5; // Accelerate time means reduce the simulation time step. else if ((long)pvCmd < 0) fMultFactor = 2.0; // Slow-down time means increase the simulation time step. LmRaceEngine().accelerateTime(fMultFactor); }
void RmProgressiveTimeModifier::start() { // First, reset to the initial time multiplier if already running. if (_bExecRunning) LmRaceEngine().accelerateTime(1 / _fResetterTimeMultiplier); // Initially apply the whole simulation-time change. LmRaceEngine().accelerateTime(_sfTimeMultiplier); // Log the activation time. _fExecStartTime = GfTimeClock(); // Initialize manager state. _fWholeTimeLapse = _sfDelay + _sfTimeLapse; _fOldTimeMultiplier = _fResetterTimeMultiplier = _sfTimeMultiplier; // Enable the manager. _bExecRunning = true; }
static void rmOpenHelpScreen(void * /* dummy */) { LmRaceEngine().stop(); if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(true); GfuiHelpScreen(rmScreenHandle, RmBackToRaceHookInit()); }
static void ServerPrepareStartNetworkRace(void * /* dummy */) { NetGetServer()->SetLocalDrivers(); //Tell all clients to prepare to race and wait for response from all clients NetGetServer()->SendPrepareToRacePacket(); //restore the idle function GfuiApp().eventLoop().setRecomputeCB(GfuiIdle); LmRaceEngine().startNewRace(); }
static void rmToggleMovieCapture(void * /* dummy */) { if (!rmMovieCapture.enabled) { GfLogWarning("Movie capture is not enabled : command ignored\n"); return; } if (!(LmRaceEngine().outData()->_displayMode & RM_DISP_MODE_NORMAL)) { GfLogWarning("Movie capture is available only in normal display mode : command ignored\n"); return; } rmMovieCapture.active = !rmMovieCapture.active; if (rmMovieCapture.active) { // Try and change the race engine scheduling scheme for movie capture. if (LmRaceEngine().setSchedulingSpecs(rmMovieCapture.simuRate, rmMovieCapture.frameRate)) { rmMovieCapture.currentFrame = 0; rmMovieCapture.currentCapture++; GfLogInfo("Starting movie capture\n"); } else { // Not supported (multi-threaded mode). rmMovieCapture.active = false; GfLogWarning("Movie capture not supported in multi-threaded mode : command ignored\n"); } } else { GfLogInfo("Stopping movie capture\n"); LmRaceEngine().setSchedulingSpecs(1.0 / RCM_MAX_DT_SIMU); LmRaceEngine().start(); // Resynchronize the race engine. } }
bool RmCheckPitRequest() { // If one (human) driver is in pit, switch the display loop to the pit menu. if (LmRaceEngine().outData()->_rePitRequester) { // Mute sound. if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(true); // TODO pit music?? // First, stop the race engine. LmRaceEngine().stop(); // Then open the pit menu (will return in ReCarsUpdateCarPitCmd). RmPitMenuStart(LmRaceEngine().outData()->_rePitRequester, LmRaceEngine().outData()->s, rmOnBackFromPitMenu); return true; } return false; }
static void OnActivateNetworkClient(void *) { int nDriverIdx = NetGetNetwork()->GetDriverIdx(); if(NetGetNetwork()->IsConnected() && nDriverIdx > -1) { // Menu reactivated after garage menu is done NetDriver driver; char newName[64]; char dname[256]; // check for car change if (bGarage == true ) { bGarage = false; tRmInfo* reInfo = LmRaceEngine().inData(); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); sprintf(dname, "%s/%d", RM_SECT_DRIVERS, nDriverIdx); int idx = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, "",0); GfDriver* PCurrentDriver = GfDrivers::self()->getDriver(NETWORKROBOT, idx); strncpy(newName, PCurrentDriver->getCar()->getId().c_str(), sizeof(newName)); GfLogInfo("Client: Index %d changed to %s\n", idx, newName); NetGetNetwork()->SetCarInfo(newName); } else { // Ensure menu system knows about all cars GfDrivers::self()->reload(); // tRmInfo* reInfo = LmRaceEngine().inData(); // Never used LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true); } } GfuiApp().eventLoop().setRecomputeCB(ClientIdle); bGarage = false; }
static void rmScreenActivate(void * /* dummy */) { // Configure the FPS limiter if active. #ifdef UseFPSLimiter // Get the max. refresh rate from the screen config params file. std::ostringstream ossConfFile; ossConfFile << GfLocalDir() << GFSCR_CONF_FILE; void* hparmScrConf = GfParmReadFile(ossConfFile.str().c_str(), GFPARM_RMODE_STD); FPSLimLastTime = 0.0; FPSLimMaxRate = GfParmGetNum(hparmScrConf, GFSCR_SECT_VALIDPROPS, GFSCR_ATT_MAXREFRESH, NULL, 0.0); if (FPSLimMaxRate) GfLogInfo("FPS limiter is on (%.1f Hz).\n", FPSLimMaxRate); else GfLogInfo("FPS limiter is off.\n"); GfParmReleaseHandle(hparmScrConf); #endif // Configure the event loop. GfuiApp().eventLoop().setRecomputeCB(rmUpdateRaceEngine); GfuiApp().eventLoop().setRedisplayCB(rmRedisplay); // If not paused ... #ifdef STARTPAUSED if ((!rmRacePaused)&&(!rmPreRacePause)) #else if (!rmRacePaused) #endif { // 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(); // The menu changed. rmbMenuChanged = true; }
static void rmResScreenActivate(void * /* dummy */) { GfLogInfo("Entering Result menu ...\n"); // Configure the event loop. 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(); // The menu changed. rmbResMenuChanged = true; }
bool LegacyMenu::backLoad() { GfLogTrace("Pre-loading menu and game data ...\n"); bool SupportsHumanDrivers = LmRaceEngine().supportsHumanDrivers(); // Pre-load the main and race select menus // (to be able to get back to them, even when directly starting a given race). if (!RmRaceSelectInit(MainMenuInit(SupportsHumanDrivers))) return false; // Pre-load race managers, drivers, tracks, cars stuff. if (!GfRaceManagers::self()) return false; GfLogTrace("Pre-loading menu and game data completed.\n"); return true; }
void RmNetworkMenu(void *) { GfLogTrace("Entering Network menu.\n"); tRmInfo* reInfo = LmRaceEngine().inData(); void *params = reInfo->params; if (NetGetNetwork()) { NetGetNetwork()->ResetNetwork(); } racemanMenuHdle = GfuiScreenCreate(NULL, NULL, (tfuiCallback)NULL, NULL, (tfuiCallback)NULL, 1); void *mparam = GfuiMenuLoad("networkmenu.xml"); GfuiMenuCreateStaticControls(racemanMenuHdle, mparam); const int nTitleLabelId = GfuiMenuCreateLabelControl(racemanMenuHdle, mparam, "TitleLabel"); const char* pszTitle = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, 0); if (pszTitle) GfuiLabelSetText(racemanMenuHdle, nTitleLabelId, pszTitle); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "HostButton", 0, RmNetworkHostMenu); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "JoinButton", 0, NetworkClientConnectMenu); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "BackButton", RmRaceSelectMenuHandle, GfuiScreenActivate); GfuiMenuDefaultKeysAdd(racemanMenuHdle); GfuiAddKey(racemanMenuHdle, GFUIK_ESCAPE, "Back to previous menu", RmRaceSelectMenuHandle, 0, GfuiScreenActivate); GfParmReleaseHandle(mparam); GfuiScreenActivate(racemanMenuHdle); }
void RmProgressiveTimeModifier::execute() { if (_bExecRunning) { // Get current time. const double fExecCurrentTime = GfTimeClock(); // Calculate the difference from start time to current time : // how long have run the manger until now ? double fExecTimeDifference = fExecCurrentTime - _fExecStartTime; // We wait until we reached the delay time. if (fExecTimeDifference > _sfDelay) { // We should be sure that we dont set a speed higher than the 1.0 one ; // this can happen if the execTimeDifference is higther that the timeLapse. if (fExecTimeDifference > _fWholeTimeLapse) fExecTimeDifference = _fWholeTimeLapse; // Factor to restore normal game speed. const double fResetter = 1 / _fOldTimeMultiplier; // Factor to apply the new acceleration. const double fNewMult = 1 + _sfTimeMultiplier * ((_fWholeTimeLapse - fExecTimeDifference) / _fWholeTimeLapse); // Apply the simulation-time changes. LmRaceEngine().accelerateTime(fResetter * fNewMult); // Remember the integrated-since-start applied acceleration. _fResetterTimeMultiplier *= fResetter * fNewMult; // Remember the new applied acceleration. _fOldTimeMultiplier = fNewMult; } // if the timeLapse is reached we should not run next time. if (fExecTimeDifference >= _fWholeTimeLapse) terminate(); } }
static void OnActivateNetworkHost(void *) { tRmInfo* reInfo = LmRaceEngine().inData(); // Set everyone to the 'not-ready' state bRobotsReady = 0; NetMutexData *pNData = NetGetNetwork()->LockNetworkData(); for (unsigned int i=0;i<pNData->m_vecReadyStatus.size();i++) pNData->m_vecReadyStatus[i] = false; NetGetNetwork()->UnlockNetworkData(); NetGetServer()->SetRaceInfoChanged(true); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); assert(reInfo->params); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); GfuiApp().eventLoop().setRecomputeCB(HostServerIdle); NetGetServer()->SetRefreshDisplay(true); }
static void rmRacePause(void * /* vboard */) { #ifdef STARTPAUSED // Pause is disabled during Pre Race Pause // as the simulation is already Paused if (!rmPreRacePause) { if (rmRacePaused) { if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(false); #else if (rmRacePaused) { if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(false); #endif LmRaceEngine().start(); // Hide the "Pause" label. GfuiVisibilitySet(rmScreenHandle, rmPauseId, GFUI_INVISIBLE); // Show again the hidden message label. GfuiVisibilitySet(rmScreenHandle, rmMsgId, GFUI_VISIBLE); // Launch the "slow resume race" manager if non-blind mode. if (LmRaceEngine().outData()->_displayMode == RM_DISP_MODE_NORMAL) rmProgressiveTimeModifier.start(); } else { if (LegacyMenu::self().soundEngine()) LegacyMenu::self().soundEngine()->mute(true); LmRaceEngine().stop(); // Show the "Pause" label. GfuiVisibilitySet(rmScreenHandle, rmPauseId, GFUI_VISIBLE); // Hide the message label (no need to bother the user with the time mult. factor // when it is changing, whihc occurs when the user hits P when a slow start // is in-process). GfuiVisibilitySet(rmScreenHandle, rmMsgId, GFUI_INVISIBLE); } // Toggle the race-paused flag. rmRacePaused = !rmRacePaused; // The menu changed. rmbMenuChanged = true; #ifdef STARTPAUSED } #endif } static void rmSkipPreStart(void * /* dummy */) { // TODO: move this to a new LmRaceEngine().skipRacePreStart() ... tRmInfo* reInfo = LmRaceEngine().inData(); if (reInfo->s->currentTime < -1.0) { reInfo->s->currentTime = -1.0; reInfo->_reLastRobTime = -1.0; } }
/** * RmShowStandings * * Shows a results page, with optional prev/next results page buttons * * @param prevHdle handle for previous results page * @param info race results information * @param start page number */ void RmShowStandings(void *prevHdle, tRmInfo *info, int start) { int i; static char buf[256]; static char path[512]; void *results = info->results; GfLogTrace("Entering Standings menu\n"); // Create screen, load menu XML descriptor and create static controls. rmScrHdle = GfuiScreenCreate(); void *hmenu = GfuiMenuLoad("standingsmenu.xml"); GfuiMenuCreateStaticControls(rmScrHdle, hmenu); // Create variable title label (with group info for the Career mode). const int titleId = GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Title"); GfRaceManager* pRaceMan = LmRaceEngine().race()->getManager(); if (pRaceMan->hasSubFiles()) { const char* pszGroup = GfParmGetStr(info->params, RM_SECT_HEADER, RM_ATTR_NAME, "<no group>"); snprintf(buf, sizeof(buf), "%s - %s", info->_reName, pszGroup); } else snprintf(buf, sizeof(buf), "%s", info->_reName); GfuiLabelSetText(rmScrHdle, titleId, buf); // Create variable subtitle label. const char* pszSessionName; const char* pszTrackName; if (pRaceMan->hasSubFiles()) { // Career mode : Can't rely on GfRaceManager/GfRace, they don't support Career mode yet. pszSessionName = info->_reRaceName; const int curTrackIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) - 1; snprintf(path, sizeof(path), "%s/%d", RM_SECT_TRACKS, curTrackIdx); pszTrackName = GfParmGetStr(info->params, path, RM_ATTR_NAME, "<unkown track>"); } else { // Non-Career mode : The session is the _last_ one ; the track is the _previous_ one. const unsigned nCurrEventIndex = (unsigned)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1); pszSessionName = pRaceMan->getSessionName(pRaceMan->getSessionCount() - 1).c_str(); pszTrackName = pRaceMan->getPreviousEventTrack(nCurrEventIndex - 1)->getName().c_str(); } snprintf(buf, sizeof(buf), "%s at %s", pszSessionName, pszTrackName); const int subTitleId = GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "SubTitle"); GfuiLabelSetText(rmScrHdle, subTitleId, buf); // Get layout properties. const int nMaxLines = (int)GfuiMenuGetNumProperty(hmenu, "nMaxResultLines", 15); const int yTopLine = (int)GfuiMenuGetNumProperty(hmenu, "yTopLine", 400); const int yLineShift = (int)GfuiMenuGetNumProperty(hmenu, "yLineShift", 20); // List results line by line, paginated int y = yTopLine; const int nbCars = (int)GfParmGetEltNb(results, RE_SECT_STANDINGS); for (i = start; i < MIN(start + nMaxLines, nbCars); i++) { snprintf(path, sizeof(path), "%s/%d", RE_SECT_STANDINGS, i + 1); //Rank snprintf(buf, sizeof(buf), "%d", i+1); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Rank", true, // From template. buf, GFUI_TPL_X, y); //Driver short name GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "DriverName", true, // From template. GfParmGetStr(results, path, RE_ATTR_SNAME, ""), GFUI_TPL_X, y); //Driver type const std::string strModName = GfParmGetStr(results, path, RE_ATTR_MODULE, ""); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "DriverType", true, // From template. GfDriver::getType(strModName).c_str(), GFUI_TPL_X, y); //Car GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "CarModel", true, // From template. GfParmGetStr(results, path, RE_ATTR_CAR, ""), GFUI_TPL_X, y); //Points snprintf(buf, sizeof(buf), "%d", (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0)); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Points", true, // From template. buf, GFUI_TPL_X, y); // Next line. y -= yLineShift; //Next line }//for i // If not on first page, show 'previous results' button on the bottom left if (start > 0) { RmPrevRace.prevHdle = prevHdle; RmPrevRace.info = info; RmPrevRace.start = start - nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "PreviousPageArrow", (void*)&RmPrevRace, rmChgStandingScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEUP, "Previous Results", (void*)&RmPrevRace, rmChgStandingScreen, NULL); }//if start // Add "Continue" button in the bottom left GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace); // Add "save" button in the bottom right, but disable it when Career mode. rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "SaveButton", info, rmSaveRes); if (LmRaceEngine().race()->getManager()->hasSubFiles()) GfuiEnable(rmScrHdle, rmSaveButtonId, GFUI_DISABLE); // If there is a next page, show 'next results' button on the bottom extreme right if (i < nbCars) { RmNextRace.prevHdle = prevHdle; RmNextRace.info = info; RmNextRace.start = start + nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "NextPageArrow", (void*)&RmNextRace, rmChgStandingScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEDOWN, "Next Results", (void*)&RmNextRace, rmChgStandingScreen, NULL); }//if i GfuiAddKey(rmScrHdle, GFUIK_ESCAPE, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_RETURN, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_F1, "Help", rmScrHdle, GfuiHelpScreen, NULL); GfuiAddKey(rmScrHdle, GFUIK_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL); GfuiScreenActivate(rmScrHdle); }//RmShowStandings
void RmNextEventMenu(void) { char buf[128]; tRmInfo* reInfo = LmRaceEngine().inData(); void *params = reInfo->params; void *results = reInfo->results; int raceNumber; int xx; if (rmScrHandle) { GfuiScreenRelease(rmScrHandle); } GfLogTrace("Entering Next Event menu\n"); // Create screen, load menu XML descriptor and create static controls. rmScrHandle = GfuiScreenCreate(NULL, NULL, (tfuiCallback)NULL, NULL, (tfuiCallback)NULL, 1); void *menuXMLDescHdle = GfuiMenuLoad("racenexteventmenu.xml"); GfuiMenuCreateStaticControls(rmScrHandle, menuXMLDescHdle); // Create background image from race params. const char* pszBGImg = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_BGIMG, 0); if (pszBGImg) { GfuiScreenAddBgImg(rmScrHandle, pszBGImg); } // Create variable title label from race params. int titleId = GfuiMenuCreateLabelControl(rmScrHandle, menuXMLDescHdle, "TitleLabel"); char pszTitle[128]; if (LmRaceEngine().race()->getManager()->hasSubFiles()) { const char* pszGroup = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, "<no group>"); snprintf(pszTitle, sizeof(pszTitle), "%s - %s", reInfo->_reName, pszGroup); } else snprintf(pszTitle, sizeof(pszTitle), "%s", reInfo->_reName); GfuiLabelSetText(rmScrHandle, titleId, pszTitle); // Calculate which race of the series this is raceNumber = 1; for (xx = 1; xx < (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1); ++xx) { snprintf(buf, sizeof(buf), "%s/%d", RM_SECT_TRACKS, xx); if (!strcmp( GfParmGetStr(reInfo->params, buf, RM_ATTR_NAME, "free"), "free") == 0) ++raceNumber; } // Create variable subtitle label from race params. snprintf(buf, sizeof(buf), "Race Day #%d/%d at %s", raceNumber, (int)GfParmGetNum(params, RM_SECT_TRACKS, RM_ATTR_NUMBER, NULL, -1 ) >= 0 ? (int)GfParmGetNum(params, RM_SECT_TRACKS, RM_ATTR_NUMBER, NULL, -1 ) : GfParmGetEltNb(params, RM_SECT_TRACKS), reInfo->track->name); int subTitleId = GfuiMenuCreateLabelControl(rmScrHandle, menuXMLDescHdle, "SubTitleLabel"); GfuiLabelSetText(rmScrHandle, subTitleId, buf); // Create Start and Abandon buttons. GfuiMenuCreateButtonControl(rmScrHandle, menuXMLDescHdle, "StartButton", NULL, rmStateManage); GfuiMenuCreateButtonControl(rmScrHandle, menuXMLDescHdle, "AbandonButton", RmRaceSelectMenuHandle, GfuiScreenActivate); // Close menu XML descriptor. GfParmReleaseHandle(menuXMLDescHdle); // Register keyboard shortcuts. GfuiMenuDefaultKeysAdd(rmScrHandle); GfuiAddKey(rmScrHandle, GFUIK_RETURN, "Start Event", NULL, rmStateManage, NULL); GfuiAddKey(rmScrHandle, GFUIK_ESCAPE, "Abandon", RmRaceSelectMenuHandle, GfuiScreenActivate, NULL); // Activate screen. GfuiScreenActivate(rmScrHandle); }
static void rmUpdateRaceEngine() { LmRaceEngine().updateState(); }
void* RmResScreenInit() { if (rmResScreenHdle) GfuiScreenRelease(rmResScreenHdle); tRmInfo* reInfo = LmRaceEngine().inData(); // Create screen, load menu XML descriptor and create static controls. rmResScreenHdle = GfuiScreenCreate(black, 0, rmResScreenActivate, 0, rmResScreenDeactivate, 0); void *hmenu = GfuiMenuLoad("raceblindscreen.xml"); GfuiMenuCreateStaticControls(rmResScreenHdle, hmenu); // Create variable main title (race session) label. rmResTitleId = GfuiMenuCreateLabelControl(rmResScreenHdle, hmenu, "Title"); // Create background image if any specified. const char* img = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_RUNIMG, 0); if (img) GfuiScreenAddBgImg(rmResScreenHdle, img); // Create variable subtitle (driver and race name, lap number) label. rmResSubTitleId = GfuiMenuCreateLabelControl(rmResScreenHdle, hmenu, "SubTitle"); // Create table header label. rmResHeaderId = GfuiMenuCreateLabelControl(rmResScreenHdle, hmenu, "Header"); // Get layout properties, except for nMaxResultRows (see below). const int yTopRow = (int)GfuiMenuGetNumProperty(hmenu, "yTopRow", 400); const int yRowShift = (int)GfuiMenuGetNumProperty(hmenu, "yRowShift", 20); // Allocate row info arrays, if not already done. if (!rmResRowLabelId) { // Load nMaxResultRows/colors only the first time (ignore any later change, // otherwize, we'd have to realloc the row info arrays). rmNMaxResRows = (int)GfuiMenuGetNumProperty(hmenu, "nMaxResultRows", 20); const GfuiColor cNormal = GfuiColor::build(GfuiMenuGetStrProperty(hmenu, "rowColorNormal", "0x0000FF")); const GfuiColor cHighlighted = GfuiColor::build(GfuiMenuGetStrProperty(hmenu, "rowColorHighlighted", "0x00FF00")); memcpy(rmColors[0], cNormal.toFloatRGBA(), sizeof(rmColors[0])); memcpy(rmColors[1], cHighlighted.toFloatRGBA(), sizeof(rmColors[1])); rmResRowLabelId = (int*)calloc(rmNMaxResRows, sizeof(int)); rmResRowText = (char**)calloc(rmNMaxResRows, sizeof(char*)); rmResRowColor = (float**)calloc(rmNMaxResRows, sizeof(float*)); } // Create result rows (1 label for each). int y = yTopRow; for (int i = 0; i < rmNMaxResRows; i++) { freez(rmResRowText[i]); rmResRowColor[i] = rmColors[0]; rmResRowLabelId[i] = GfuiMenuCreateLabelControl(rmResScreenHdle, hmenu, "Row", true, // from template "", GFUI_TPL_X, y, GFUI_TPL_FONTID, GFUI_TPL_WIDTH, GFUI_TPL_ALIGN, GFUI_TPL_MAXLEN, rmResRowColor[i]); y -= yRowShift; } // Close menu XML descriptor. GfParmReleaseHandle(hmenu); // Register keyboard shortcuts. GfuiAddKey(rmResScreenHdle, GFUIK_F1, "Help", rmResScreenHdle, GfuiHelpScreen, NULL); GfuiAddKey(rmResScreenHdle, GFUIK_F12, "Screen shot", NULL, GfuiScreenShot, NULL); GfuiAddKey(rmResScreenHdle, GFUIK_ESCAPE, "Stop current race", (void*)RE_STATE_RACE_STOP, rmApplyState, NULL); GfuiAddKey(rmResScreenHdle, 'q', GFUIM_ALT, "Quit game now, save nothing", (void*)RE_STATE_EXIT, rmApplyState, NULL); // Initialize current result row. rmCurRowIndex = 0; return rmResScreenHdle; }
static void rmRedisplay() { // Process any pending (human) pit request. const bool bPitRequested = RmCheckPitRequest(); #ifdef UseFPSLimiter // Auto FPS limitation if specified and if not capturing frames. if (FPSLimMaxRate > 0 && !rmMovieCapture.active) { // If too early to refresh graphics, do nothing more than wait a little. const double dCurrentTime = GfTimeClock(); if (dCurrentTime < FPSLimLastTime + 1.0 / FPSLimMaxRate) { // Wait a little, to let the CPU take breath. // Note : Theorical resolution is 1ms, but actual one is from far more // (10-15ms under Windows, even worse under Linux ?) // which explains a lower than expected actual FPS mean. GfSleep(0.001); // Only giving back control to the scheduler gives good results // as for the actual mean FPS, but keeps the CPU 100 % (not very cool). //GfSleep(0.0); // Request an update in the next event loop though. GfuiApp().eventLoop().postRedisplay(); return; } // Otherwise, last update time is now : go on with graphics update. FPSLimLastTime = dCurrentTime; } #endif // Exec the "slow resume race" manager, if needed. #ifdef STARTPAUSED if (!rmPreRacePause) { rmProgressiveTimeModifier.execute(); } #else rmProgressiveTimeModifier.execute(); #endif // Redraw the graphics part of the GUI if requested. const bool bUpdateGraphics = LmRaceEngine().outData()->_displayMode == RM_DISP_MODE_NORMAL && !bPitRequested && LegacyMenu::self().graphicsEngine(); if (bUpdateGraphics) { //GfSchedBeginEvent("raceupdate", "graphics"); LegacyMenu::self().redrawGraphicsView(LmRaceEngine().outData()->s); //GfSchedEndEvent("raceupdate", "graphics"); } // Synchronize the menu with the race messages if any changed. rmUpdateRaceMessages(); // Redraw the menu part of the GUI // (always necessary if the graphics were redrawn first). if (bUpdateGraphics || rmbMenuChanged) GfuiRedraw(); // Really do the display work. if (bUpdateGraphics || rmbMenuChanged) GfuiSwapBuffers(); // The menu changes has now been taken into account. rmbMenuChanged = false; //只要改成任何时候都输出每一帧的RGB信息到PNG,即可输出PNG格式的图片 Add by gaoyu 2015-7-15 // Capture the newly displayed frame if movie capture mode. if (rmMovieCapture.active) rmCaptureScreen();//会自动获取屏幕像素,并保存为png文件 Add by gaoyu 2015-7-15 //rmCaptureScreen(); // Request an redisplay in the next event loop. GfuiApp().eventLoop().postRedisplay(); }
static void RmResultShow(void * /* dummy */) { LmRaceEngine().stopCooldown(); }
static void rmApplyState(void *pvState) { LmRaceEngine().applyState((int)(long)pvState); }