Example #1
0
// 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
Example #6
0
/** 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();
}
Example #9
0
/** 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);
}