// Generic function for creating and activating the menu. static void* rmStopRaceMenu(const tButtonDesc aButtons[], int nButtons, int nCancelIndex) { // Create screen, load menu XML descriptor and create static controls. void *hscreen = GfuiScreenCreate(NULL, NULL, NULL, NULL, NULL, 1); void *hmenu = GfuiMenuLoad("stopracemenu.xml"); GfuiMenuCreateStaticControls(hscreen, hmenu); // Create buttons from menu properties and button template. const int xpos = (int)GfuiMenuGetNumProperty(hmenu, "xButton", 270); const int dy = (int)GfuiMenuGetNumProperty(hmenu, "buttonShift", 30); int ypos = (int)GfuiMenuGetNumProperty(hmenu, "yTopButton", 380); char pszPropName[64]; const char* pszCancelTip = ""; for (int nButInd = 0; nButInd < nButtons; nButInd++) { // Get text and tip from button role and menu properties. sprintf(pszPropName, "%s.text", aButtons[nButInd].role); const char* pszText = GfuiMenuGetStrProperty(hmenu, pszPropName, ""); sprintf(pszPropName, "%s.tip", aButtons[nButInd].role); const char* pszTip = GfuiMenuGetStrProperty(hmenu, pszPropName, ""); if (nButInd == nCancelIndex) pszCancelTip = pszTip; // Create the button from the template. GfuiMenuCreateTextButtonControl(hscreen, hmenu, "button", aButtons[nButInd].screen, GfuiScreenActivate, 0, 0, 0, true, // From template. pszText, pszTip, xpos, ypos); // Next button if not last. ypos -= dy; } // Register keyboard shortcuts. GfuiMenuDefaultKeysAdd(hscreen); GfuiAddKey(hscreen, GFUIK_ESCAPE, pszCancelTip, aButtons[nCancelIndex].screen, GfuiScreenActivate, NULL); // Close menu XML descriptor. GfParmReleaseHandle(hmenu); // Activate the created screen. GfuiScreenActivate(hscreen); return hscreen; }
static void rmPracticeResults(void *prevHdle, tRmInfo *info, int start) { // Used across rmPracticeResults calls when multiple pages. static int NLastLapDamages = 0; void *results = info->results; const char *race = info->_reRaceName; int i; int y; static char buf[256]; static char path[1024]; char *str; int damages; // Create screen, load menu XML descriptor and create static controls. rmScrHdle = GfuiScreenCreate(); GfLogTrace("Entering Practice Results menu\n"); void *hmenu = GfuiMenuLoad("practiceresultsmenu.xml"); GfuiMenuCreateStaticControls(rmScrHdle, hmenu); // Create variable title labels. snprintf(buf, sizeof(buf), "%s at %s", race, info->track->name); const int titleId = GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Title"); GfuiLabelSetText(rmScrHdle, titleId, buf); snprintf(path, sizeof(path), "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race); snprintf(buf, sizeof(buf), "%s (%s)", GfParmGetStr(results, path, RM_ATTR_DRVNAME, NULL), GfParmGetStr(results, path, RM_ATTR_CAR, NULL)); 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); // Display the result table. y = yTopLine; snprintf(path, sizeof(path), "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race); const int totLaps = (int)GfParmGetEltNb(results, path); // Reset last damage value if top of the table. if (start == 0) NLastLapDamages = 0; else { snprintf(path, sizeof(path), "%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, start - 1); NLastLapDamages = (int)(GfParmGetNum(results, path, RE_ATTR_DAMMAGES, NULL, 0)); } for (i = 0 + start; i < MIN(start + nMaxLines, totLaps); i++) { snprintf(path, sizeof(path), "%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, i + 1); /* Lap */ snprintf(buf, sizeof(buf), "%d", i+1); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "LapNumber", true, // From template. buf, GFUI_TPL_X, y); /* Time */ str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0), " ", false, 3); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "LapTime", true, // From template. str, GFUI_TPL_X, y); free(str); /* Best Lap Time */ str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), " ", false, 3); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "BestTime", true, // From template. str, GFUI_TPL_X, y); free(str); /* Top Spd */ snprintf(buf, sizeof(buf), "%3.1f", (GfParmGetNum(results, path, RE_ATTR_TOP_SPEED, NULL, 0) * 3.6)); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "TopSpeed", true, // From template. buf, GFUI_TPL_X, y); /* Min Spd */ snprintf(buf, sizeof(buf), "%3.1f", (GfParmGetNum(results, path, RE_ATTR_BOT_SPEED, NULL, 0) * 3.6)); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "MinSpeed", true, // From template. buf, GFUI_TPL_X, y); /* Damages in current lap + (total so far) */ damages = (int)(GfParmGetNum(results, path, RE_ATTR_DAMMAGES, NULL, 0)); snprintf(buf, sizeof(buf), "%d (%d)", damages ? damages - NLastLapDamages : 0, damages); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Damages", true, // From template. buf, GFUI_TPL_X, y); NLastLapDamages = damages; y -= yLineShift; } if (start > 0) { RmPrevRace.prevHdle = prevHdle; RmPrevRace.info = info; RmPrevRace.start = start - nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "PreviousPageArrow", (void*)&RmPrevRace, rmChgPracticeScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEUP, "Previous Results", (void*)&RmPrevRace, rmChgPracticeScreen, NULL); } // Add "Continue" button GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace); //Create 'save' button in the bottom right //rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "SaveButton", info, rmSaveRes); if (i < totLaps) { RmNextRace.prevHdle = prevHdle; RmNextRace.info = info; RmNextRace.start = start + nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "NextPageArrow", (void*)&RmNextRace, rmChgPracticeScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEDOWN, "Next Results", (void*)&RmNextRace, rmChgPracticeScreen, NULL); } GfuiAddKey(rmScrHdle, GFUIK_ESCAPE, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_RETURN, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL); GfuiAddKey(rmScrHdle, GFUIK_F1, "Help", rmScrHdle, GfuiHelpScreen, NULL); GfuiScreenActivate(rmScrHdle); }
/** * 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
static void rmQualifResults(void *prevHdle, tRmInfo *info, const char* pszTitle, int start) { void *results = info->results; const char *race = info->_reRaceName; int i; static char buf[256]; static char path[512]; char *str; GfLogTrace("Entering %s Results menu\n", pszTitle); // Create screen, load menu XML descriptor and create static controls. rmScrHdle = GfuiScreenCreate(); void *hmenu = GfuiMenuLoad("qualifsresultsmenu.xml"); GfuiMenuCreateStaticControls(rmScrHdle, hmenu); // Create variable title label. const int titleId = GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Title"); snprintf(buf, sizeof(buf), "%s at %s", race, info->track->name); GfuiLabelSetText(rmScrHdle, titleId, 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); // Never used : remove ? //snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, 1); //tdble refTime = GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0); //snprintf(path, sizeof(path), "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race); //const int totLaps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0); snprintf(path, sizeof(path), "%s/%s/%s/%s", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK); const int nbCars = (int)GfParmGetEltNb(results, path); GfLogDebug("rmQualifResults: path=%s, file=%s\n", path, GfParmGetFileName(results)); GfLogDebug("rmQualifResults: start=%d, nbCars=%d, nMaxLines=%d\n", start, nbCars, nMaxLines); int y = yTopLine; for (i = start; i < MIN(start + nMaxLines, nbCars); i++) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); // Never used : remove ? //const int laps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0); //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); //Best lap str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), 0, false, 3); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "BestLapTime", true, // From template. str, GFUI_TPL_X, y); free(str); // Next line. y -= yLineShift; }//for i if (start > 0) { RmPrevRace.prevHdle = prevHdle; RmPrevRace.info = info; RmPrevRace.start = start - nMaxLines; RmPrevRace.title = pszTitle; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "PreviousPageArrow", (void*)&RmPrevRace, rmChgQualifScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEUP, "Previous Results", (void*)&RmPrevRace, rmChgQualifScreen, NULL); } // Add "Continue" button GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace); //Create 'save' button in the bottom right //rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "savebutton", info, rmSaveRes); if (i < nbCars) { RmNextRace.prevHdle = prevHdle; RmNextRace.info = info; RmNextRace.start = start + nMaxLines; RmNextRace.title = pszTitle; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "NextPageArrow", (void*)&RmNextRace, rmChgQualifScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEDOWN, "Next Results", (void*)&RmNextRace, rmChgQualifScreen, NULL); } GfuiAddKey(rmScrHdle, GFUIK_ESCAPE, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_RETURN, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL); GfuiAddKey(rmScrHdle, GFUIK_F1, "Help", rmScrHdle, GfuiHelpScreen, NULL); GfuiScreenActivate(rmScrHdle); }
static void rmRaceResults(void *prevHdle, tRmInfo *info, int start) { void *results = info->results; const char *race = info->_reRaceName; static char buf[256]; static char path[512]; char *str; GfLogTrace("Entering Race Results menu\n"); // Create screen, load menu XML descriptor and create static controls. rmScrHdle = GfuiScreenCreate(); void *hmenu = GfuiMenuLoad("raceresultsmenu.xml"); GfuiMenuCreateStaticControls(rmScrHdle, hmenu); // Create variable title label. snprintf(buf, sizeof(buf), "%s at %s", race, info->track->name); const int titleId = GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Title"); GfuiLabelSetText(rmScrHdle, titleId, 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); const GfuiColor cPlaceGain = GfuiColor::build(GfuiMenuGetStrProperty(hmenu, "colorGainedPlaces", "0x32CD32")); const float* acPlaceGain = cPlaceGain.toFloatRGBA(); const GfuiColor cPlaceLoss = GfuiColor::build(GfuiMenuGetStrProperty(hmenu, "colorLostPlaces", "0xF28500")); const float* acPlaceLoss = cPlaceLoss.toFloatRGBA(); // Never used : remove ? //Get total laps, winner time //snprintf(path, sizeof(path), "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race); //int totLaps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0); //snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, 1); //tdble refTime = GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0); //Get number of cars snprintf(path, sizeof(path), "%s/%s/%s/%s", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK); int nbCars = (int)GfParmGetEltNb(results, path); // Display the result table. int y = yTopLine; int i; for (i = start; i < MIN(start + nMaxLines, nbCars); i++) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1); int laps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0);//Laps covered //Rank snprintf(buf, sizeof(buf), "%d", i+1); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Rank", true, // From template. buf, GFUI_TPL_X, y); //Advance (The num.attrib 'index' holds the starting position) int advance = (int)(GfParmGetNum(results, path, RE_ATTR_INDEX, NULL, 0)) - i; snprintf(buf, sizeof(buf), "%d", advance); const float *aColor = advance > 0 ? acPlaceGain : (advance < 0 ? acPlaceLoss : GFUI_TPL_COLOR); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Advance", true, // From template. buf, GFUI_TPL_X, y, GFUI_TPL_FONTID, GFUI_TPL_WIDTH, GFUI_TPL_ALIGN, GFUI_TPL_MAXLEN, aColor); //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); //Total Time str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0), 0, false, 3); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "TotalTime", true, // From template. str, GFUI_TPL_X, y); free(str); //Best lap str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), 0, false, 3); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "BestLapTime", true, // From template. str, GFUI_TPL_X, y); free(str); //Laps covered snprintf(buf, sizeof(buf), "%d", laps); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Laps", true, // From template. buf, GFUI_TPL_X, y); //Top speed snprintf(buf, sizeof(buf), "%3.1f", (GfParmGetNum(results, path, RE_ATTR_TOP_SPEED, NULL, 0) * 3.6)); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "TopSpeed", true, // From template. buf, GFUI_TPL_X, y); //Damage snprintf(buf, sizeof(buf), "%d", (int)(GfParmGetNum(results, path, RE_ATTR_DAMMAGES, NULL, 0))); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Damages", true, // From template. buf, GFUI_TPL_X, y); //Pitstops snprintf(buf, sizeof(buf), "%d", (int)(GfParmGetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, 0))); GfuiMenuCreateLabelControl(rmScrHdle, hmenu, "Pits", true, // From template. buf, GFUI_TPL_X, y); y -= yLineShift; //Line feed }//for i //If it is not the first screen of the results, show a 'Prev' button if (start > 0) { RmPrevRace.prevHdle = prevHdle; RmPrevRace.info = info; RmPrevRace.start = start - nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "PreviousPageArrow", (void*)&RmPrevRace, rmChgRaceScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEUP, "Previous Results", (void*)&RmPrevRace, rmChgRaceScreen, NULL); }//if start // Add "Continue" button GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace); //Create 'save' button in the bottom right //rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "SaveButton", info, rmSaveRes); //If we did not display all the results yet, let's show a 'Next' button if (i < nbCars) { RmNextRace.prevHdle = prevHdle; RmNextRace.info = info; RmNextRace.start = start + nMaxLines; GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "NextPageArrow", (void*)&RmNextRace, rmChgRaceScreen); GfuiAddKey(rmScrHdle, GFUIK_PAGEDOWN, "Next Results", (void*)&RmNextRace, rmChgRaceScreen, NULL); }//if i //Link key handlers GfuiAddKey(rmScrHdle, GFUIK_ESCAPE, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_RETURN, "Continue", prevHdle, GfuiScreenReplace, NULL); GfuiAddKey(rmScrHdle, GFUIK_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL); GfuiAddKey(rmScrHdle, GFUIK_F1, "Help", rmScrHdle, GfuiHelpScreen, NULL); //Show! GfuiScreenActivate(rmScrHdle); }//rmRaceResults
/** Interactive track selection @param vs Pointer on a tRmTrackSelect structure (cast to void *) @warning The race manager's parameters are updated but not saved to the file. @ingroup racemantools */ void RmTrackSelect(void *vs) { MenuData = (tRmTrackSelect*)vs; // Get currently selected track for the current race type // (or the first usable one in the selected category). PCurTrack = MenuData->pRace->getTrack(); const std::string strReqTrackId = PCurTrack->getId(); const std::string strReqTrackCatId = PCurTrack->getCategoryId(); PCurTrack = GfTracks::self()->getFirstUsableTrack(PCurTrack->getCategoryId(), PCurTrack->getId()); if (PCurTrack && PCurTrack->getId() != strReqTrackId) GfLogWarning("Could not find / use selected track %s (%s) ; using %s (%s)\n", strReqTrackId.c_str(), strReqTrackCatId.c_str(), PCurTrack->getId().c_str(), PCurTrack->getCategoryId().c_str()); // If not usable, try and get the first usable track going ahead in categories if (!PCurTrack) { PCurTrack = GfTracks::self()->getFirstUsableTrack(strReqTrackCatId, +1, true); if (PCurTrack) GfLogWarning("Could not find / use selected track %s and category %s unusable" " ; using %s (%s)\n", strReqTrackId.c_str(), strReqTrackCatId.c_str(), PCurTrack->getId().c_str(), PCurTrack->getCategoryId().c_str()); } // If no usable category/track found, ... return if (!PCurTrack) { GfLogError("No available track for any category ; quitting Track Select menu\n"); return; // or exit(1) abruptly ? } // Create screen menu and controls. ScrHandle = GfuiScreenCreate((float*)NULL, NULL, rmtsActivate, NULL, (tfuiCallback)NULL, 1); void *hparmMenu = GfuiMenuLoad("trackselectmenu.xml"); GfuiMenuCreateStaticControls( ScrHandle, hparmMenu); PrevCategoryArrowId = GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "trackcatleftarrow",(void*)-1, rmtsTrackCatPrevNext); NextCategoryArrowId = GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "trackcatrightarrow",(void*)1, rmtsTrackCatPrevNext); CategoryEditId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "trackcatlabel"); PrevTrackArrowId = GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "trackleftarrow", (void*)-1, rmtsTrackPrevNext); NextTrackArrowId = GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "trackrightarrow", (void*)1, rmtsTrackPrevNext); NameEditId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "tracklabel"); OutlineImageId = GfuiMenuCreateStaticImageControl(ScrHandle, hparmMenu, "outlineimage"); GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "nextbutton", NULL, rmtsSelect); GfuiMenuCreateButtonControl(ScrHandle, hparmMenu, "backbutton", MenuData->prevScreen, rmtsDeactivate); DescLine1LabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "description1label"); DescLine2LabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "description2label"); LengthLabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "lengthlabel"); WidthLabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "widthlabel"); MaxPitsLabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "pitslabel"); AuthorsLabelId = GfuiMenuCreateLabelControl(ScrHandle, hparmMenu, "authorslabel"); // Load menu properties. DescLinesMaxLen = (unsigned)GfuiMenuGetNumProperty(hparmMenu, "nDescLinesMaxLen", 35); GfParmReleaseHandle(hparmMenu); // Keyboard shortcuts. rmtsAddKeys(); // Let's go ! GfuiScreenActivate(ScrHandle); }
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; }
/** @ingroup racemantools @param title Screen title. @param bgimg Optional background image (0 for no img). @return None. */ void RmLoadingScreenStart(const char *title, const char *bgimg) { if (HScreen && GfuiScreenIsActive(HScreen)) return; if (HScreen) RmLoadingScreenShutdown(); // Create screen, load menu XML descriptor and create static controls. HScreen = GfuiScreenCreate(BGColor, NULL, NULL, NULL, NULL, 0); void *hmenu = GfuiMenuLoad("loadingscreen.xml"); GfuiMenuCreateStaticControls(HScreen, hmenu); // Create variable title label. int titleId = GfuiMenuCreateLabelControl(HScreen, hmenu, "titlelabel"); GfuiLabelSetText(HScreen, titleId, title); // Get layout / coloring properties. NTextLines = (int)GfuiMenuGetNumProperty(hmenu, "nLines", 20); const int yTopLine = (int)GfuiMenuGetNumProperty(hmenu, "yTopLine", 400); const int yLineShift = (int)GfuiMenuGetNumProperty(hmenu, "yLineShift", 16); const float alpha0 = GfuiMenuGetNumProperty(hmenu, "alpha0", 0.2); const float alphaSlope = GfuiMenuGetNumProperty(hmenu, "alphaSlope", 0.0421); // Allocate line info arrays. FGColors = (float**)calloc(NTextLines, sizeof(float*)); TextLines = (char**)calloc(NTextLines, sizeof(char*)); TextLineIds = (int*)calloc(NTextLines, sizeof(int)); // Create one label for each text line int y = yTopLine; for (int i = 0; i < NTextLines; i++) { // Create and set the color for this line. FGColors[i] = (float*)calloc(4, sizeof(float)); FGColors[i][0] = FGColors[i][1] = FGColors[i][2] = 1.0; FGColors[i][3] = (float)i * alphaSlope + alpha0; // Create the control from the template. TextLineIds[i] = GfuiMenuCreateLabelControl(HScreen, hmenu, "line", true, // from template "", GFUI_TPL_X, y, GFUI_TPL_FONTID, GFUI_TPL_WIDTH, GFUI_TPL_ALIGN, GFUI_TPL_MAXLEN, FGColors[i]); // Next line if not last. y -= yLineShift; } CurTextLineIdx = 0; // Add background image. if (bgimg) GfuiScreenAddBgImg(HScreen, bgimg); // Close menu XML descriptor. GfParmReleaseHandle(hmenu); // Display screen. GfuiScreenActivate(HScreen); GfuiDisplay(); }
/** 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"); GfuiMenuCreateStaticControls(scrHandle, hmenu); // Get menu properties. const int nXLeftColumn = (int)GfuiMenuGetNumProperty(hmenu, "xLeftColumn", 30); const int nXRightColumn = (int)GfuiMenuGetNumProperty(hmenu, "xRightColumn", 330); const int nNameFieldWidth = (int)GfuiMenuGetNumProperty(hmenu, "nameFieldWidth", 80); const int nLineShift = (int)GfuiMenuGetNumProperty(hmenu, "lineShift", 12); const int nYTopLine = (int)GfuiMenuGetNumProperty(hmenu, "yTopLine", 380); // Create 2 columns table for the keyboard shortcuts explanations int ys = nYTopLine; int yn = nYTopLine; tGfuiScreen *pscrTgt = (tGfuiScreen*)targetScreen; tGfuiKey *curKey = pscrTgt->userKeys; while (curKey) { curKey = curKey->next; // Decide if this key goes on the left of right column. bool bLeft; switch(curKey->key) { case GFUIK_BACKSPACE: case GFUIK_F1: case GFUIK_F2: case GFUIK_F3: case GFUIK_F4: case GFUIK_F5: case GFUIK_F6: case GFUIK_F7: case GFUIK_F8: case GFUIK_F9: case GFUIK_F10: case GFUIK_F11: case GFUIK_F12: case GFUIK_LEFT: case GFUIK_UP: case GFUIK_RIGHT: case GFUIK_DOWN: case GFUIK_PAGEUP: case GFUIK_PAGEDOWN: case GFUIK_HOME: case GFUIK_END: case GFUIK_INSERT: case GFUIK_DELETE: case GFUIK_CLEAR: case GFUIK_PAUSE: bLeft = true; break; default: bLeft = curKey->modifier != GFUIM_NONE; break; } // 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; } // Create Back button. GfuiMenuCreateButtonControl(scrHandle, hmenu, "backbutton", targetScreen, GfuiScreenReplace); // Create version label. const int versionId = GfuiMenuCreateLabelControl(scrHandle, hmenu, "versionlabel"); GfuiLabelSetText(scrHandle, versionId, GfuiApp().version().c_str()); // Close menu XML descriptor. GfParmReleaseHandle(hmenu); // Add keyboard shortcuts. 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); GfuiAddKey(scrHandle, GFUIK_UP, "Select previous entry", NULL, gfuiSelectPrev, NULL); GfuiAddKey(scrHandle, GFUIK_DOWN, "Select next entry", NULL, gfuiSelectNext, NULL); GfuiScreenActivate(scrHandle); }