730 lines
28 KiB
C++
730 lines
28 KiB
C++
/***************************************************************************
|
|
|
|
file : raceresultsmenus.cpp
|
|
created : Fri Apr 14 22:36:36 CEST 2000
|
|
copyright : (C) 2000 by Eric Espie
|
|
email : torcs@free.fr
|
|
version : $Id$
|
|
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
/** @file
|
|
This is a set of tools useful for race managers to display results.
|
|
@ingroup racemantools
|
|
@author <a href=mailto:torcs@free.fr>Eric Espie</a>
|
|
@version $Id$
|
|
*/
|
|
|
|
#include <portability.h>
|
|
#include <tgfclient.h>
|
|
|
|
#include <drivers.h>
|
|
#include <tracks.h>
|
|
#include <race.h>
|
|
#include <racemanagers.h>
|
|
|
|
#include "legacymenu.h"
|
|
#include "racescreens.h"
|
|
|
|
|
|
static int rmSaveButtonId;
|
|
static int rmReplayButtonId;
|
|
static void *rmScrHdle = NULL;
|
|
|
|
static void rmPracticeResults(void *prevHdle, tRmInfo *info, int start);
|
|
static void rmRaceResults(void *prevHdle, tRmInfo *info, int start);
|
|
static void rmQualifResults(void *prevHdle, tRmInfo *info, const char*pszTitle, int start);
|
|
|
|
static const int DefaultSimuVersion = 1;
|
|
static const char *SimuVersionList[] =
|
|
{RM_VAL_MOD_SIMU_V2, RM_VAL_MOD_SIMU_V2_1, RM_VAL_MOD_SIMU_V3, RM_VAL_MOD_SIMU_V4, RM_VAL_MOD_SIMU_REPLAY};
|
|
static const int NbSimuVersions = sizeof(SimuVersionList) / sizeof(SimuVersionList[0]);
|
|
static int CurSimuVersion = DefaultSimuVersion;
|
|
|
|
typedef struct
|
|
{
|
|
void *prevHdle;
|
|
tRmInfo *info;
|
|
int start;
|
|
const char *title;
|
|
} tRaceCall;
|
|
|
|
tRaceCall RmNextRace;
|
|
tRaceCall RmPrevRace;
|
|
|
|
|
|
static void
|
|
rmReplayRace(void * /* dummy */)
|
|
{
|
|
const char *simuVersionName;
|
|
int i;
|
|
char buf[1024];
|
|
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
|
|
|
void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
|
|
|
// Temporarily overwrite Simulation Type
|
|
CurSimuVersion = DefaultSimuVersion;
|
|
simuVersionName = GfParmGetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[DefaultSimuVersion]);
|
|
for (i = 0; i < NbSimuVersions; i++) {
|
|
if (strcmp(simuVersionName, SimuVersionList[i]) == 0) {
|
|
CurSimuVersion = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[4]);
|
|
GfParmWriteFile(NULL, paramHandle, "raceengine");
|
|
|
|
LmRaceEngine().startNewRace();
|
|
|
|
// Restore original Simulation type
|
|
GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[CurSimuVersion]);
|
|
GfParmWriteFile(NULL, paramHandle, "raceengine");
|
|
GfParmReleaseHandle(paramHandle);
|
|
}
|
|
|
|
static void
|
|
rmSaveRes(void *vInfo)
|
|
{
|
|
tRmInfo *info = (tRmInfo *)vInfo;
|
|
|
|
GfParmWriteFile(0, info->results, "Results");
|
|
|
|
GfuiVisibilitySet(rmScrHdle, rmSaveButtonId, GFUI_INVISIBLE);
|
|
}
|
|
|
|
static void
|
|
rmChgPracticeScreen(void *vprc)
|
|
{
|
|
void *prevScr = rmScrHdle;
|
|
tRaceCall *prc = (tRaceCall*)vprc;
|
|
|
|
rmPracticeResults(prc->prevHdle, prc->info, prc->start);
|
|
GfuiScreenRelease(prevScr);
|
|
}
|
|
|
|
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;
|
|
void *paramHandle;
|
|
const char *replayRateSchemeName;
|
|
|
|
// 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);
|
|
|
|
// Add "Replay" button (if available)
|
|
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
|
paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
|
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, RM_VAL_REPLAY_OFF);
|
|
|
|
rmReplayButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ReplayButton", prevHdle, rmReplayRace);
|
|
if (strcmp(replayRateSchemeName, RM_VAL_REPLAY_OFF) == 0)
|
|
GfuiEnable(rmScrHdle, rmReplayButtonId, GFUI_DISABLE);
|
|
GfParmReleaseHandle(paramHandle);
|
|
|
|
//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);
|
|
}
|
|
|
|
|
|
static void
|
|
rmChgRaceScreen(void *vprc)
|
|
{
|
|
void *prevScr = rmScrHdle;
|
|
tRaceCall *prc = (tRaceCall*)vprc;
|
|
|
|
rmRaceResults(prc->prevHdle, prc->info, prc->start);
|
|
GfuiScreenRelease(prevScr);
|
|
}
|
|
|
|
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;
|
|
void *paramHandle;
|
|
const char *replayRateSchemeName;
|
|
|
|
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);
|
|
|
|
// Add "Replay" button (if available)
|
|
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
|
paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
|
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, RM_VAL_REPLAY_OFF);
|
|
|
|
rmReplayButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ReplayButton", prevHdle, rmReplayRace);
|
|
if (strcmp(replayRateSchemeName, RM_VAL_REPLAY_OFF) == 0)
|
|
GfuiEnable(rmScrHdle, rmReplayButtonId, GFUI_DISABLE);
|
|
GfParmReleaseHandle(paramHandle);
|
|
|
|
//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
|
|
|
|
|
|
static void
|
|
rmChgQualifScreen(void *vprc)
|
|
{
|
|
void *prevScr = rmScrHdle;
|
|
tRaceCall *prc = (tRaceCall*)vprc;
|
|
|
|
rmQualifResults(prc->prevHdle, prc->info, prc->title, prc->start);
|
|
GfuiScreenRelease(prevScr);
|
|
}
|
|
|
|
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
|
|
rmChgStandingScreen(void *vprc)
|
|
{
|
|
void *prevScr = rmScrHdle;
|
|
tRaceCall *prc = (tRaceCall*)vprc;
|
|
|
|
RmShowStandings(prc->prevHdle, prc->info, prc->start);
|
|
GfuiScreenRelease(prevScr);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
RmShowResults(void *prevHdle, tRmInfo *info)
|
|
{
|
|
switch (info->s->_raceType)
|
|
{
|
|
case RM_TYPE_PRACTICE:
|
|
{
|
|
char buffer[128];
|
|
snprintf(buffer, sizeof(buffer), "%s/%s", info->track->name, RE_SECT_DRIVERS);
|
|
int nCars = GfParmGetEltNb(info->results, buffer);
|
|
bool bQualif = (nCars != 1);
|
|
|
|
// Career special case : Practice results show multiple cars,
|
|
// but only 1 driver, so no 'rank' section.
|
|
// TODO: Rather fix the Career code ?
|
|
if (bQualif)
|
|
{
|
|
snprintf(buffer, sizeof(buffer), "%s/%s/%s/%s", info->track->name, RE_SECT_RESULTS, info->_reRaceName, RE_SECT_RANK);
|
|
nCars = (int)GfParmGetEltNb(info->results, buffer);
|
|
GfLogDebug("RmShowResults: %d elements in %s\n", nCars, buffer);
|
|
bQualif = bQualif && (nCars != 0);
|
|
}
|
|
|
|
if (bQualif)
|
|
rmQualifResults(prevHdle, info, "Practice", 0);
|
|
else
|
|
rmPracticeResults(prevHdle, info, 0);
|
|
break;
|
|
}
|
|
|
|
case RM_TYPE_RACE:
|
|
rmRaceResults(prevHdle, info, 0);
|
|
break;
|
|
|
|
case RM_TYPE_QUALIF:
|
|
rmQualifResults(prevHdle, info, "Qualification", 0);
|
|
break;
|
|
}//switch raceType
|
|
}//RmShowResults
|