Re #329 Enhanced tgfdata library + Moved the whole code of the race configuration menu system to using it in place of GfParmXXX functions and ReInfo pointer

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3301 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: e23bd748ca59a2220ba9d20609a6e40e7c16f011
Former-commit-id: 0911ffa5f671a76ec05b4c4f3c6ff694161f6801
This commit is contained in:
pouillot 2011-02-02 14:34:30 +00:00
parent 80caa830df
commit 854364e933
27 changed files with 1168 additions and 747 deletions

View file

@ -6,13 +6,16 @@ SET(RACEENGINECLIENT_SOURCES racecareer.cpp raceupdate.cpp racenetwork.cpp racec
racemessage.cpp racegl.cpp raceinit.cpp racemain.cpp
racetrack.cpp raceresults.cpp racesimusimu.cpp
racestate.cpp racesituation.cpp
raceutil.cpp
racemanmenu.cpp raceselectmenu.cpp networkingmenu.cpp
racenexteventmenu.cpp raceconfigstate.cpp
raceengineclient.h raceenginemenus.h
racecareer.h raceupdate.h racenetwork.h racecars.h
racemessage.h racegl.h raceinit.h
racetrack.h raceresults.h racesimusimu.h
racestate.h racesituation.h raceselectmenu.h networkingmenu.h)
racestate.h racesituation.h
raceutil.h
raceselectmenu.h networkingmenu.h)
ADD_SD_DEFINITIONS()

View file

@ -33,10 +33,10 @@
#include <racescreens.h>
#include <race.h>
#include "racesituation.h"
//#include "racemain.h"
//#include "raceinit.h"
//#include "racestate.h"
#include "raceinit.h"
#include "raceenginemenus.h"
@ -104,7 +104,7 @@ reConfigBackHookInit(void)
}
void
ReConfigRunState(void)
ReConfigRunState(bool bStart)
{
char path[256];
int i;
@ -114,23 +114,35 @@ ReConfigRunState(void)
const char *opt;
void *params = ReInfo->params;
// TODO: Replace any read/write to params to get/set from/to race/raceman instances ?
// Reset config automaton to the "start" state if specified.
if (bStart)
GfParmSetNum(params, RM_SECT_CONF, RM_ATTR_CUR_CONF, NULL, 1);
// If configuration finished, save race config to disk and go back to the raceman menu.
curConf = (int)GfParmGetNum(params, RM_SECT_CONF, RM_ATTR_CUR_CONF, NULL, 1);
if (curConf > GfParmGetEltNb(params, RM_SECT_CONF)) {
GfLogInfo("%s configuration finished.\n", ReInfo->_reName);
GfParmWriteFile(NULL, ReInfo->params, ReInfo->_reName);
GfuiScreenActivate(ReGetRacemanMenuHandle()); /* Back to the race manager menu */
ReGetRace()->save(); // Save race data to params.
GfParmWriteFile(NULL, params, ReInfo->_reName); // Save params to disk.
GfuiScreenActivate(ReGetRacemanMenuHandle()); // Back to the race manager menu
return;
}
// If wrong configuration data, back to the raceman menu.
snprintf(path, sizeof(path), "%s/%d", RM_SECT_CONF, curConf);
conf = GfParmGetStr(params, path, RM_ATTR_TYPE, 0);
if (!conf) {
GfLogError("No %s here (%s) !\n", RM_ATTR_TYPE, path);
GfLogError("No '%s' field in '%s' section of %s\n",
RM_ATTR_TYPE, path, GfParmGetFileName(params));
GfuiScreenActivate(ReGetRacemanMenuHandle()); /* Back to the race manager menu */
return;
}
// Normal configuration steps :
GfLogInfo("%s configuration now in '%s' stage.\n", ReInfo->_reName, conf);
if (!strcmp(conf, RM_VAL_TRACKSEL)) {
/* Track Select Menu */
@ -140,7 +152,7 @@ ReConfigRunState(void)
} else {
ts.prevScreen = reConfigBackHookInit();
}
ts.param = ReInfo->params;
ts.pRace = ReGetRace();
ts.trackItf = ReInfo->_reTrackItf;
RmTrackSelect(&ts);
@ -153,7 +165,7 @@ ReConfigRunState(void)
} else {
ds.prevScreen = reConfigBackHookInit();
}
ds.param = ReInfo->params;
ds.pRace = ReGetRace();
RmDriversSelect(&ds);
} else if (!strcmp(conf, RM_VAL_RACECONF)) {
@ -165,8 +177,7 @@ ReConfigRunState(void)
} else {
rp.prevScreen = reConfigBackHookInit();
}
rp.param = ReInfo->params;
rp.title = GfParmGetStr(params, path, RM_ATTR_RACE, "Race");
rp.pRace = ReGetRace();
/* Select options to configure */
rp.confMask = 0;

View file

@ -29,14 +29,14 @@
#include "raceengineclient.h"
RACEENGINECLIENT_API int ReRacemanMenu(void);
RACEENGINECLIENT_API int ReRacemanMenu();
RACEENGINECLIENT_API int ReNextEventMenu(void);
RACEENGINECLIENT_API void ReConfigureRace(void * /* dummy */);
RACEENGINECLIENT_API void ReSetRacemanMenuHandle(void * handle);
extern void* ReGetRacemanMenuHandle();
extern void ReConfigRunState(void);
extern void ReConfigRunState(bool bStart = false);
#endif /* _RACEENGINEMENU_H_ */

View file

@ -36,6 +36,7 @@
#include <teammanager.h>
#include <robottools.h>
#include <racemanagers.h>
#include <race.h>
#include <racescreens.h>
@ -49,12 +50,22 @@
#include "raceinit.h"
static const char *level_str[] = { ROB_VAL_ROOKIE, ROB_VAL_AMATEUR, ROB_VAL_SEMI_PRO, ROB_VAL_PRO };
static const char *level_str[] =
{ ROB_VAL_ROOKIE, ROB_VAL_AMATEUR, ROB_VAL_SEMI_PRO, ROB_VAL_PRO };
static tModList *reEventModList = 0;
// Modules ... ?
tModList *ReRaceModList = 0;
// The race (temporary partially duplicates ReInfo, as long as not merged).
static GfRace* PReRace = 0;
GfRace* ReGetRace()
{
return PReRace;
}
/* Race Engine Initialization */
void
@ -156,24 +167,60 @@ ReStartNewRace(void * /* dummy */)
}
// Select the given manager for the race.
void
ReRaceSelectRaceman(GfRaceManager* pRaceMan)
{
// Trace the chosen raceman full type.
std::string strFullType(pRaceMan->getType());
if (!pRaceMan->getSubType().empty())
{
strFullType += " / ";
strFullType += pRaceMan->getSubType();
}
GfLogTrace("'%s' race type selected\n", strFullType.c_str());
// Re-init. race engine info about the race.
ReInfo->mainParams = ReInfo->params = pRaceMan->getDescriptorHandle();
ReInfo->_reName = pRaceMan->getName().c_str();
ReInfo->_reFilename = pRaceMan->getId().c_str();
GfParmRemoveVariable (ReInfo->params, "/", "humanInGroup");
GfParmSetVariable (ReInfo->params, "/", "humanInGroup", ReHumanInGroup() ? 1 : 0);
}
// Start configuring a race for the given manager
void
ReRaceConfigure(GfRaceManager* pRaceman)
ReRaceConfigure(GfRaceManager* pRaceMan)
{
ReInfo->mainParams = ReInfo->params = pRaceman->getDescriptorHandle();
ReInfo->_reName = pRaceman->getName().c_str();
ReInfo->_reFilename = pRaceman->getId().c_str();
// Select the given race manager for the race.
ReRaceSelectRaceman(pRaceMan);
// If not already done, instanciate the race.
if (!PReRace)
PReRace = new GfRace();
// (Re-)initialize it from the selected race manager.
PReRace->load(pRaceMan);
// Enter CONFIG state.
ReStateApply(RE_STATE_CONFIG);
}
std::string strFullType(pRaceman->getType());
if (!pRaceman->getSubType().empty())
{
strFullType += " / ";
strFullType += pRaceman->getSubType();
}
GfLogTrace("%s selected\n", strFullType.c_str());
// Enter CONFIG state.
ReStateApply(RE_STATE_CONFIG);
// Restore the race from the given result file
void
ReRaceRestore(GfRaceManager* pRaceMan, const char *pszResultFileName)
{
// Select the given race manager for the race.
ReRaceSelectRaceman(pRaceMan);
// Update race engine info.
ReInfo->mainResults = GfParmReadFile(pszResultFileName, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
ReInfo->results = ReInfo->mainResults;
ReInfo->_reRaceName = ReInfo->_reName;
// Fire standings screen.
RmShowStandings(ReInfo->_reGameScreen, ReInfo);
}
/*

View file

@ -29,6 +29,7 @@
#include "raceengineclient.h"
class GfRaceManager;
class GfRace;
RACEENGINECLIENT_API void ReStartNewRace(void * /* dummy */);
@ -36,7 +37,9 @@ RACEENGINECLIENT_API void ReStartNewRace(void * /* dummy */);
extern void ReInit(void);
extern void ReShutdown(void);
extern void ReRaceConfigure(GfRaceManager* pRaceman);
extern void ReRaceSelectRaceman(GfRaceManager* pRaceMan);
extern void ReRaceRestore(GfRaceManager* pRaceMan, const char *pszResultFileName);
extern void ReRaceConfigure(GfRaceManager* pRaceMan);
extern int ReInitCars(void);
@ -51,6 +54,9 @@ extern char *ReGetPrevRaceName(void);
extern tModList *ReRaceModList;
// The race (temporarily partly duplicates ReInfo, as long as not merged together).
extern GfRace* ReGetRace();
#endif /* _RACEINIT_H_ */

View file

@ -28,6 +28,7 @@
#include <racescreens.h>
#include <network.h>
#include "raceutil.h" // RmGetFeaturesList
#include "racesituation.h"
#include "racecareer.h"
#include "raceinit.h"

View file

@ -23,14 +23,15 @@
@version $Id$
*/
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <sstream>
#include <portability.h>
#include <tgfclient.h>
#include <raceman.h>
#include <tgfclient.h>
#include <racemanagers.h>
#include <race.h>
#include <tracks.h>
@ -79,41 +80,37 @@ void* ReGetRacemanMenuHandle()
void
ReConfigureRace(void * /* dummy */)
{
void *params = ReInfo->params;
/* Reset configuration automaton */
GfParmSetNum(params, RM_SECT_CONF, RM_ATTR_CUR_CONF, NULL, 1);
ReConfigRunState();
ReConfigRunState(/*bStart=*/true);
}
static char*
reGetLoadFileDir(char* pszDirPath, int nMaxLen)
// TODO: ossPathDirPath ...
static std::string
reGetLoadFileDir()
{
void *params = ReInfo->params;
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
// For race types with more than 1 event (= 1 race on 1 track), load a race result file,
// as the previous race standings has an influence on the next race starting grid.
if (GfParmGetEltNb(params, RM_SECT_TRACKS) > 1)
snprintf(pszDirPath, nMaxLen, "%sresults/%s", GfLocalDir(), ReInfo->_reFilename);
std::string strDirPath(GfLocalDir());
if (pRaceMan->getEventCount() > 1)
strDirPath += "results/";
// But for race types with only 1 event (= 1 race on 1 track), load a race config file.
else
snprintf(pszDirPath, nMaxLen, "%sconfig/raceman/%s", GfLocalDir(), ReInfo->_reFilename);
strDirPath += "config/raceman/";
strDirPath += pRaceMan->getId();
return pszDirPath;
return strDirPath;
}
static bool
reCanLoadRace()
{
void *params = ReInfo->params;
// Determine the source folder.
char pszDirPath[256];
reGetLoadFileDir(pszDirPath, sizeof(pszDirPath));
// Get the list of files in the target folder.
tFList *pFileList = GfDirGetListFiltered(pszDirPath, "", PARAMEXT);
std::string strDirPath = reGetLoadFileDir();
tFList *pFileList = GfDirGetListFiltered(strDirPath.c_str(), "", PARAMEXT);
// Now we know what to answer.
const bool bAnswer = (pFileList != 0);
@ -128,25 +125,24 @@ reCanLoadRace()
static bool
reCanSaveRace()
{
void *params = ReInfo->params;
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
// Multi-events race types are automatically saved in config/raceman/results
return GfParmGetEltNb(params, RM_SECT_TRACKS) == 1;
return pRaceMan->getEventCount() == 1;
}
static void
reOnRaceDataChanged()
{
char buf[128];
void *params = ReInfo->params;
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
// Retrieve track infos.
const char* pszTrackId = GfParmGetStr(ReInfo->params, "Tracks/1", RM_ATTR_NAME, "");
const GfTrack* pTrack = GfTracks::self()->getTrack(pszTrackId);
// Get the current track.
const GfTrack* pTrack = ReGetRace()->getTrack();
// Set title (race type + track name).
snprintf(buf, sizeof(buf), "%s at %s", ReInfo->_reName, pTrack->getName().c_str());
GfuiLabelSetText(ScrHandle, TitleLabelId, buf);
std::ostringstream ossText;
ossText << pRaceMan->getName() << " at " << pTrack->getName();
GfuiLabelSetText(ScrHandle, TitleLabelId, ossText.str().c_str());
// Display track name, outline image and preview image
GfuiScreenAddBgImg(ScrHandle, pTrack->getPreviewFile().c_str());
@ -158,86 +154,64 @@ reOnRaceDataChanged()
GfuiEnable(ScrHandle, SaveRaceButtonId,
reCanSaveRace() ? GFUI_ENABLE : GFUI_DISABLE);
// Re-load competitors scroll list from the race file.
// Re-load competitors scroll list from the race.
GfuiScrollListClear(ScrHandle, CompetitorsScrollListId);
VecCompetitorsInfo.clear();
const int nCompetitors = GfParmGetEltNb(ReInfo->params, RM_SECT_DRIVERS);
for (int nCompIndex = 1; nCompIndex <= nCompetitors; nCompIndex++)
const std::vector<GfDriver*>& vecCompetitors = ReGetRace()->getCompetitors();
for (int nCompIndex = 0; nCompIndex < (int)vecCompetitors.size(); nCompIndex++)
{
snprintf(buf, sizeof(buf), "%s/%d", RM_SECT_DRIVERS, nCompIndex);
const char* pszCompModuleName = GfParmGetStr(ReInfo->params, buf, RM_ATTR_MODULE, "");
int nCompItfIdx = (int)GfParmGetNum(ReInfo->params, buf, RM_ATTR_IDX, (char*)NULL, 0);
const GfDriver* pComp =
GfDrivers::self()->getDriver(pszCompModuleName, nCompItfIdx);
if (pComp)
{
snprintf(buf, sizeof(buf), "%s (%s)", pComp->getName().c_str(), pComp->getCar()->getName().c_str());
VecCompetitorsInfo.push_back(buf);
GfuiScrollListInsertElement(ScrHandle, CompetitorsScrollListId,
VecCompetitorsInfo.back().c_str(), nCompIndex, (void*)pComp);
GfLogDebug("Added competitor %s (%s#%d)\n", buf, pszCompModuleName, nCompItfIdx);
}
else
GfLogWarning("Ignoring competitor %s#%d (no such driver available)\n",
pszCompModuleName, nCompItfIdx);
const GfDriver* pComp = vecCompetitors[nCompIndex];
ossText.str("");
ossText << pComp->getName() << " (" << pComp->getCar()->getName() << ')';
VecCompetitorsInfo.push_back(ossText.str());
GfuiScrollListInsertElement(ScrHandle, CompetitorsScrollListId,
VecCompetitorsInfo.back().c_str(), nCompIndex+1, (void*)pComp);
GfLogDebug("Added competitor %s (%s#%d)\n", ossText.str().c_str(),
pComp->getModuleName().c_str(), pComp->getInterfaceIndex());
}
}
static void
reLoadRaceFromResultsFile(const char *filename)
{
char pszFileName[256];
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
snprintf(pszFileName, sizeof(pszFileName), "%sresults/%s/%s", GfLocalDir(), ReInfo->_reFilename, filename);
GfLogInfo("Loading saved race from %s ...\n", pszFileName);
// Determine the full path-name of the result file.
std::ostringstream ossResFileName;
ossResFileName << GfLocalDir() << "results/" << pRaceMan->getId() << '/' << filename;
// Update race data.
ReInfo->mainResults = GfParmReadFile(pszFileName, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
ReInfo->results = ReInfo->mainResults;
ReInfo->_reRaceName = ReInfo->_reName;
GfParmRemoveVariable (ReInfo->params, "/", "humanInGroup");
GfParmSetVariable (ReInfo->params, "/", "humanInGroup", ReHumanInGroup() ? 1 : 0);
GfLogInfo("Restoring race from results %s ...\n", ossResFileName.str().c_str());
// Fire standings screen.
RmShowStandings(ReInfo->_reGameScreen, ReInfo);
// Restore the race from the result file.
ReRaceRestore(ReGetRace()->getManager(), ossResFileName.str().c_str());
}
static void
reLoadRaceFromConfigFile(const char *filename)
{
char pszSelFilePathName[256];
snprintf(pszSelFilePathName, sizeof(pszSelFilePathName), "%sconfig/raceman/%s/%s",
GfLocalDir(), ReInfo->_reFilename, filename);
GfLogInfo("Loading saved race from %s ...\n", pszSelFilePathName);
GfRaceManager* pRaceMan = ReGetRace()->getManager();
// Replace the main race file by the selected one.
char pszMainFilePathName[256];
snprintf(pszMainFilePathName, sizeof(pszMainFilePathName), "%sconfig/raceman/%s%s",
GfLocalDir(), ReInfo->_reFilename, PARAMEXT);
if (!GfFileCopy(pszSelFilePathName, pszMainFilePathName))
// Determine the full path-name of the selected race config file.
std::ostringstream ossSelFileName;
ossSelFileName << GfLocalDir() << "config/raceman/" << pRaceMan->getId() << '/' << filename;
GfLogInfo("Loading saved race from config %s ...\n", ossSelFileName.str().c_str());
// Replace the main race config file by the selected one.
const std::string strMainFileName = pRaceMan->getDescriptorFileName();
if (!GfFileCopy(ossSelFileName.str().c_str(), strMainFileName.c_str()))
{
GfLogError("Failed to load selected race file %s", pszSelFilePathName);
GfLogError("Failed to load selected race config file %s", strMainFileName.c_str());
return;
}
// Update race data.
GfParmReleaseHandle(ReInfo->params);
ReInfo->mainParams = ReInfo->params = GfParmReadFile(pszMainFilePathName, GFPARM_RMODE_STD);
ReInfo->_reName = GfParmGetStr(ReInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, "");
ReInfo->_reRaceName = ReInfo->_reName;
// Update the race manager.
void* hparmRaceMan = GfParmReadFile(strMainFileName.c_str(), GFPARM_RMODE_STD);
pRaceMan->reset(hparmRaceMan, /* bClosePrevHdle= */ true);
// Notify the race engine of the changes.
ReRaceSelectRaceman(pRaceMan);
GfParmRemoveVariable (ReInfo->params, "/", "humanInGroup");
GfParmSetVariable (ReInfo->params, "/", "humanInGroup", ReHumanInGroup() ? 1 : 0);
// Update the race manager (the params handle changed).
GfRaceManager* pRaceMan = GfRaceManagers::self()->getRaceManager(ReInfo->_reFilename);
if (pRaceMan)
pRaceMan->setDescriptorHandle(ReInfo->params);
else
GfLogError("No such race manager (id=%s)\n", ReInfo->_reFilename);
// Update GUI.
reOnRaceDataChanged();
}
@ -246,22 +220,19 @@ static void
reSaveRaceToConfigFile(const char *filename)
{
// Note: No need to write the main file here, already done at the end of race configuration.
char pszMainFilePathName[256];
snprintf(pszMainFilePathName, sizeof(pszMainFilePathName), "%sconfig/raceman/%s%s",
GfLocalDir(), ReInfo->_reFilename, PARAMEXT);
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
// Add .xml extension if not there.
char pszSelFilePathName[256];
snprintf(pszSelFilePathName, sizeof(pszSelFilePathName), "%sconfig/raceman/%s/%s",
GfLocalDir(), ReInfo->_reFilename, filename);
const char* pszFileExt = strrchr(pszSelFilePathName, '.');
if (!pszFileExt || strcmp(pszFileExt, PARAMEXT))
strcat(pszSelFilePathName, PARAMEXT);
// Determine the full path-name of the target race config file (add .xml ext. if not there).
std::ostringstream ossTgtFileName;
ossTgtFileName << GfLocalDir() << "config/raceman/" << pRaceMan->getId() << '/' << filename;
if (ossTgtFileName.str().rfind(PARAMEXT) != ossTgtFileName.str().length() - strlen(PARAMEXT))
ossTgtFileName << PARAMEXT;
// Copy the main file to the selected one (overwrite if already there).
GfLogInfo("Saving race config to %s ...\n", pszSelFilePathName);
if (!GfFileCopy(pszMainFilePathName, pszSelFilePathName))
GfLogError("Failed to save race to selected config file %s", pszSelFilePathName);
const std::string strMainFileName = pRaceMan->getDescriptorFileName();
GfLogInfo("Saving race config to %s ...\n", strMainFileName.c_str());
if (!GfFileCopy(strMainFileName.c_str(), ossTgtFileName.str().c_str()))
GfLogError("Failed to save race to selected config file %s", ossTgtFileName.str().c_str());
}
static void
@ -287,18 +258,18 @@ reOnPlayerConfig(void * /* dummy */)
static void
reOnLoadRaceFromFile(void *pPrevMenu)
{
void *params = ReInfo->params;
fs.title = ReInfo->_reName;
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
fs.title = pRaceMan->getName();
fs.prevScreen = pPrevMenu;
fs.mode = RmFSModeLoad;
char pszDirPath[256];
fs.path = reGetLoadFileDir(pszDirPath, 256);
std::string strDirPath = reGetLoadFileDir();
fs.path = strDirPath;
// For race types with more than 1 event (= 1 race on 1 track), load a race result file,
// as the previous race standings has an influence on the next race starting grid.
if (GfParmGetEltNb(params, RM_SECT_TRACKS) > 1)
if (pRaceMan->getEventCount() > 1)
fs.select = reLoadRaceFromResultsFile;
// But for race types with only 1 event (= 1 race on 1 track), load a race config file.
@ -312,17 +283,16 @@ reOnLoadRaceFromFile(void *pPrevMenu)
static void
reOnSaveRaceToFile(void *pPrevMenu)
{
void *params = ReInfo->params;
const GfRaceManager* pRaceMan = ReGetRace()->getManager();
// Fill-in file selection descriptor
fs.title = ReInfo->_reName;
fs.title = pRaceMan->getName();
fs.prevScreen = pPrevMenu;
fs.mode = RmFSModeSave;
char pszDirPath[256];
snprintf(pszDirPath, sizeof(pszDirPath), "%sconfig/raceman/%s",
GfLocalDir(), ReInfo->_reFilename);
fs.path = pszDirPath;
fs.path = GfLocalDir();
fs.path += "config/raceman/";
fs.path += pRaceMan->getId();
fs.select = reSaveRaceToConfigFile;
@ -341,10 +311,8 @@ reOnActivate(void * /* dummy */)
}
int
ReRacemanMenu(void)
ReRacemanMenu()
{
void *params = ReInfo->params;
// Special case of the online race.
if (!strcmp(ReInfo->_reName, "Online Race"))
{

View file

@ -23,8 +23,6 @@
@version $Id$
*/
#include <cstdlib>
#include <cstdio>
#include <map>
#include <algorithm>
@ -46,7 +44,7 @@ static std::map<std::string, int> reMapSubTypeComboIds;
/* Called when the menu is activated */
static void
reOnRaceSelectMenuActivate(void * /* dummy */)
reOnActivate(void * /* dummy */)
{
/* Race engine init */
ReInit();
@ -88,6 +86,7 @@ reOnSelectRaceMan(void *pvRaceManTypeIndex)
}
}
}
// If only 1, no choice.
else if (vecRaceMans.size() == 1)
{
@ -114,7 +113,7 @@ ReRaceSelectInit(void *prevMenu)
// Create screen, load menu XML descriptor and create static controls.
reRaceSelectHandle = GfuiScreenCreateEx((float*)NULL,
NULL, reOnRaceSelectMenuActivate,
NULL, reOnActivate,
NULL, (tfuiCallback)NULL,
1);
void *hMenuXMLDesc = LoadMenuXML("raceselectmenu.xml");

View file

@ -27,7 +27,9 @@
#include <cstdio>
#include <tgfclient.h>
#include <raceman.h>
#include <racescreens.h>
#include "racesituation.h"

View file

@ -322,7 +322,7 @@ reTrackInitWeather(void)
else
rain = TR_RAIN_HEAVY;
// Whatever rain level, heavy clouds.
// Whatever rain level (except for none), heavy clouds.
clouds = TR_CLOUDS_FULL;
}
else
@ -336,6 +336,12 @@ reTrackInitWeather(void)
pszWeatherSelect = "randomly selected";
}
else
{
if (rain != TR_RAIN_NONE)
// Whatever rain level (except for none), heavy clouds.
clouds = TR_CLOUDS_FULL;
}
// Ground water = rain for the moment (might change in the future).
const int water = rain;

View file

@ -1,15 +1,37 @@
/**
* This file contains function which can also be used by raceengineclient.
* This function is needed in both modules
*
* Copyright (C) 2006, Mart Kelder <mart@kelder31.nl>
*/
/**************************************************************************
#include <tgfclient.h>
#include "racescreens.h"
file : racemain.cpp
created : Sat Nov 16 12:13:31 CET 2006
copyright : (C) 2006 Mart Kelder
email : mart@kelder31.nl
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
Useful functions for race engine
@author <a href=mailto:mart@kelder31.nl>Mart Kelder</a>
@version $Id$
*/
#include <tgf.h>
#include "raceutil.h"
#include <robot.h>
// TODO: When the race engine will have been moved to using tgfdata (it is not at present),
// remove RmGetFeaturesList (use GfRace::getSupportedFeatures).
static const int nMaxFeatureNameLength = 30;
typedef struct Feature

View file

@ -0,0 +1,34 @@
/***************************************************************************
file : racestate.h
created : Sat Nov 16 14:05:06 CET 2006
copyright : (C) 2006 Mart Kelder
email : mart@kelder31.nl
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
Useful functions for race engine
@author <a href=mailto:mart@kelder31.nl>Mart Kelder</a>
@version $Id$
*/
#ifndef _RACEUTIL_H_
#define _RACEUTIL_H_
extern int RmGetFeaturesList(void* param);
#endif /* _RACEUTIL_H_ */

View file

@ -5,7 +5,6 @@ INCLUDE(../../../cmake/macros.cmake)
SET(RACESCREENS_SOURCES carselect.cpp driverselect.cpp fileselect.cpp
loadingscreen.cpp miscscreens.cpp
pitmenu.cpp raceparamsmenu.cpp results.cpp trackselect.cpp
util.cpp
racescreens.h)
ADD_INTERFACE_INCLUDEDIR()

View file

@ -25,9 +25,6 @@
*/
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <tgfclient.h>
@ -90,16 +87,13 @@ static size_t CurDriverTypeIndex = 0;
static std::vector<GfDriverSkin> VecCurDriverPossSkins;
static size_t CurSkinIndex = 0;
// The current race.
GfRace TheRace;
// The current driver
// (the last one the user clicked on, shown as highligthed in one of the scroll-lists).
GfDriver* PCurrentDriver;
// Local functions.
static void rmdsFilterCandidatesScrollList(const std::string& strCarCatId,
const std::string& strType);
const std::string& strType);
static void rmdsClickOnDriver(void * /* dummy */);
@ -157,12 +151,12 @@ rmdsReloadCompetitorsScrollList()
GfuiScrollListClear(ScrHandle, CompetitorsScrollListId);
// For each competitor in the race :
std::vector<GfDriver*> vecCompetitors = TheRace.getCompetitors();
std::vector<GfDriver*> vecCompetitors = MenuData->pRace->getCompetitors();
std::vector<GfDriver*>::iterator itComp;
for (itComp = vecCompetitors.begin(); itComp != vecCompetitors.end(); itComp++)
// Add its name to the Competitors scroll list.
GfuiScrollListInsertElement(ScrHandle, CompetitorsScrollListId, (*itComp)->getName().c_str(),
TheRace.getCompetitorsCount(), (void*)(*itComp));
MenuData->pRace->getCompetitorsCount(), (void*)(*itComp));
}
// Screen activation call-back.
@ -199,8 +193,6 @@ rmdsCleanup(void)
VecCarCategoryNames.clear();
VecDriverTypes.clear();
VecCurDriverPossSkins.clear();
TheRace.clear();
}
// Screen de-activation call-back.
@ -294,7 +286,7 @@ static void
rmdsNextMenu(void * /* dummy */)
{
// Save the race data to its params file
TheRace.save();
MenuData->pRace->save();
// Finally, go back to the caller menu.
rmdsDeactivate(MenuData->nextScreen);
@ -326,7 +318,7 @@ rmdsMoveCompetitor(void *vd)
GfuiScrollListMoveSelectedElement(ScrHandle, CompetitorsScrollListId, (int)(long)vd);
// Move the competitor in the race.
TheRace.moveCompetitor(PCurrentDriver, (int)(long)vd);
MenuData->pRace->moveCompetitor(PCurrentDriver, (int)(long)vd);
}
}
@ -402,21 +394,21 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
const char* name;
int src, dst;
GfDriver *pDriver;
int sel;
bool bSelect;
// If the selected driver is in the Candidate scroll-list,
// and if the max number of selected drivers has not been reached,
// remove the driver from the Candidate scroll-list,
// and add him to the Competitors scroll-list and to the race competitors.
sel = 0;
bSelect = false;
name = 0;
if (TheRace.acceptsMoreCompetitors()) {
if (MenuData->pRace->acceptsMoreCompetitors()) {
src = CandidatesScrollListId;
name = GfuiScrollListExtractSelectedElement(ScrHandle, src, (void**)&pDriver);
if (name) {
dst = CompetitorsScrollListId;
GfuiScrollListInsertElement(ScrHandle, dst, name, GfDrivers::self()->getCount(), (void*)pDriver);
TheRace.appendCompetitor(pDriver); // Now selected.
MenuData->pRace->appendCompetitor(pDriver); // Now selected.
}
}
@ -425,7 +417,7 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
// and add him to the Candidate scroll-list
// (if it matches the Candidate scroll-list filtering criteria)
if (!name) {
sel = 1;
bSelect = true;
src = CompetitorsScrollListId;
name = GfuiScrollListExtractSelectedElement(ScrHandle, src, (void**)&pDriver);
if (name) {
@ -440,39 +432,33 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
GfuiScrollListInsertElement(ScrHandle, dst, name,
pDriver->isHuman() ? 0 : GfDrivers::self()->getCount(), (void*)pDriver);
}
TheRace.removeCompetitor(pDriver); // No more selected.
MenuData->pRace->removeCompetitor(pDriver); // No more selected.
} else {
return;
}
}
// Focused driver management (inhibited for the moment : what is it useful for ?)
const char *modName = GfParmGetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
int robotIdx = (int)GfParmGetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
if (sel) {
modName = GfParmGetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
robotIdx = (int)GfParmGetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
if (pDriver->getInterfaceIndex() == robotIdx && pDriver->getModuleName() == modName) {
const GfDriver* pFocDriver = MenuData->pRace->getFocusedCompetitor();
if (bSelect) {
if (MenuData->pRace->isCompetitorFocused(pDriver)) {
/* the focused element was deselected : select a new one */
name = GfuiScrollListGetElement(ScrHandle, CompetitorsScrollListId, 0, (void**)&pDriver);
if (name) {
GfParmSetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, pDriver->getModuleName().c_str());
GfParmSetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, pDriver->getInterfaceIndex());
MenuData->pRace->setFocusedCompetitor(pDriver);
#ifdef FOCUS
GfuiLabelSetText(ScrHandle, FocusedDriverLabelId, pDriver->getName.c_str());
#endif
} else {
GfParmSetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
GfParmSetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
MenuData->pRace->setFocusedCompetitor(0);
#ifdef FOCUS
GfuiLabelSetText(ScrHandle, FocusedDriverLabelId, "");
#endif
}
}
} else {
if (strlen(modName) == 0 || pDriver->isHuman()) {
GfParmSetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, pDriver->getModuleName().c_str());
GfParmSetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, pDriver->getInterfaceIndex());
if (!pFocDriver || pDriver->isHuman()) {
MenuData->pRace->setFocusedCompetitor(pDriver);
#ifdef FOCUS
GfuiLabelSetText(ScrHandle, FocusedDriverLabelId, pDriver->getName().c_str());
#endif
@ -483,7 +469,7 @@ rmdsSelectDeselectDriver(void * /* dummy */ )
rmdsClickOnDriver(0);
// Don't allow user to Accept 0 drivers, this would cause a crash.
GfuiEnable(ScrHandle, NextButtonId, TheRace.getCompetitorsCount() > 0 ? GFUI_ENABLE : GFUI_DISABLE);
GfuiEnable(ScrHandle, NextButtonId, MenuData->pRace->getCompetitorsCount() > 0 ? GFUI_ENABLE : GFUI_DISABLE);
// For a smart display refresh, when automatically called multiple time.
GfuiDisplay();
@ -520,7 +506,7 @@ rmdsSelectRandomCandidates(void * /* dummy */ )
unsigned nCount = 1;
int nCandidates;
while (nCount <= nRandomCompetitors
&& TheRace.acceptsMoreCompetitors()
&& MenuData->pRace->acceptsMoreCompetitors()
&& (nCandidates = GfuiScrollListGetNumberOfElements(ScrHandle, CandidatesScrollListId)) > 0)
{
// Pick-up a random candidate from the candidate scroll-list.
@ -541,7 +527,7 @@ static void
rmdsShuffleCompetitors(void * /* dummy */ )
{
// Shuffle the race competitor list and reload the scroll-list.
TheRace.shuffleCompetitors();
MenuData->pRace->shuffleCompetitors();
rmdsReloadCompetitorsScrollList();
// Re-highlight the previously highlighted driver if any
@ -646,15 +632,12 @@ RmDriversSelect(void *vs)
GfuiMenuDefaultKeysAdd(ScrHandle);
rmdsAddKeys();
// Load the race data from the params file.
TheRace.load(MenuData->param);
// Fill-in the competitors scroll-list.
rmdsReloadCompetitorsScrollList();
// Initialize the currently highlighted driver.
PCurrentDriver = 0;
std::vector<GfDriver*> vecCompetitors = TheRace.getCompetitors();
std::vector<GfDriver*> vecCompetitors = MenuData->pRace->getCompetitors();
std::vector<GfDriver*>::iterator itComp;
for (itComp = vecCompetitors.begin(); itComp != vecCompetitors.end(); itComp++)
// Initialize the current driver (the last human driver, or else of the last driver).
@ -675,7 +658,7 @@ rmdsFilterCandidatesScrollList(const std::string& strCarCatId, const std::string
GfuiEnable(ScrHandle, SelectButtonId, GFUI_DISABLE);
// Fill it with drivers that match the filter criteria and are not among competitors.
const std::vector<GfDriver*>& vecCompetitors = TheRace.getCompetitors();
const std::vector<GfDriver*>& vecCompetitors = MenuData->pRace->getCompetitors();
const std::string strCarCatIdFilter = (strCarCatId == AnyCarCategory ? "" : strCarCatId);
const std::string strTypeFilter = (strType == AnyDriverType ? "" : strType);
const std::vector<GfDriver*> vecCandidates =

View file

@ -46,7 +46,7 @@ rmOnActivate(void * /* dummy */ )
// Fill-in the Scroll List with the names of the files in the specified folder.
GfuiScrollListClear(ScrHandle, FilesScrollListId);
FileList = GfDirGetList(RmFs->path);
FileList = GfDirGetList(RmFs->path.c_str());
if (FileList)
{
tFList *fileCur;
@ -135,7 +135,7 @@ RmFileSelect(void *pFileSelect)
// Create variable title label.
const int titleId = CreateLabelControl(ScrHandle, menuXMLDescHdle, "TitleLabel");
GfuiLabelSetText(ScrHandle, titleId, RmFs->title);
GfuiLabelSetText(ScrHandle, titleId, RmFs->title.c_str());
// Create the Scroll List containing the File list
FilesScrollListId = CreateScrollListControl(ScrHandle, menuXMLDescHdle, "FilesScrollList",

View file

@ -33,30 +33,28 @@
#include <portability.h>
#include <tgfclient.h>
#include <track.h>
#include <car.h>
#include <raceman.h>
#include <robot.h>
#include <graphic.h>
#include <race.h>
#include "racescreens.h"
// Constants.
static const char *DispModeValues[] = { RM_VAL_VISIBLE, RM_VAL_INVISIBLE};
static const char *TimeOfDayValues[] = RM_VALS_TIME;
static const int NTimeOfDayValues = sizeof( TimeOfDayValues ) / sizeof( const char* );
static const char* CloudsValues[] = RM_VALS_CLOUDS;
static const int NCloudsValues = sizeof( CloudsValues ) / sizeof( const char* );
static const char *RainValues[] = RM_VALS_RAIN;
static const int NRainValues = sizeof( RainValues ) / sizeof( const char* );
static const char *DispModeValues[GfRace::nDisplayModeNumber] =
{ RM_VAL_VISIBLE, RM_VAL_INVISIBLE};
static const char *TimeOfDayValues[GfRace::nTimeSpecNumber] = RM_VALS_TIME;
static const char* CloudsValues[GfRace::nCloudsSpecNumber] = RM_VALS_CLOUDS;
static const char *RainValues[GfRace::nRainSpecNumber] = RM_VALS_RAIN;
// Global variables.
static void *scrHandle;
static tRmRaceParam *rp;
static void *ScrHandle;
static tRmRaceParam *MenuData;
// Menu control ids
static int rmrpDistEditId;
@ -71,10 +69,10 @@ static int rmrpRainEditId;
static int rmrpDistance;
static int rmrpLaps;
static int rmrpSessionTime;
static int rmrpDispMode;
static int rmrpClouds;
static int rmrpTimeOfDay;
static int rmrpRain;
static GfRace::EDisplayMode rmrpDispMode;
static GfRace::ECloudsSpec rmrpClouds;
static GfRace::ETimeOfDaySpec rmrpTimeOfDay;
static GfRace::ERainSpec rmrpRain;
static int rmrpFeatures;
static bool rmrpIsSkyDomeEnabled;
@ -83,7 +81,7 @@ static bool rmrpIsSkyDomeEnabled;
static void
rmrpDeactivate(void *screen)
{
GfuiScreenRelease(scrHandle);
GfuiScreenRelease(ScrHandle);
if (screen) {
GfuiScreenActivate(screen);
@ -96,16 +94,16 @@ rmrpUpdDist(void * /* dummy */)
char buf[32];
char *val;
val = GfuiEditboxGetString(scrHandle, rmrpDistEditId);
val = GfuiEditboxGetString(ScrHandle, rmrpDistEditId);
rmrpDistance = strtol(val, (char **)NULL, 0);
if (rmrpDistance == 0) {
strcpy(buf, "---");
} else {
sprintf(buf, "%d", rmrpDistance);
rmrpLaps = 0;
GfuiEditboxSetString(scrHandle, rmrpLapsEditId, "---");
GfuiEditboxSetString(ScrHandle, rmrpLapsEditId, "---");
}
GfuiEditboxSetString(scrHandle, rmrpDistEditId, buf);
GfuiEditboxSetString(ScrHandle, rmrpDistEditId, buf);
}
static void
@ -114,16 +112,16 @@ rmrpUpdLaps(void * /* dummy */)
char buf[32];
char *val;
val = GfuiEditboxGetString(scrHandle, rmrpLapsEditId);
val = GfuiEditboxGetString(ScrHandle, rmrpLapsEditId);
rmrpLaps = strtol(val, (char **)NULL, 0);
if (rmrpLaps == 0) {
strcpy(buf, "---");
} else {
sprintf(buf, "%d", rmrpLaps);
rmrpDistance = 0;
GfuiEditboxSetString(scrHandle, rmrpDistEditId, "---");
GfuiEditboxSetString(ScrHandle, rmrpDistEditId, "---");
}
GfuiEditboxSetString(scrHandle, rmrpLapsEditId, buf);
GfuiEditboxSetString(ScrHandle, rmrpLapsEditId, buf);
}
static void
@ -138,7 +136,7 @@ rmrpUpdSessionTime(void * /*dummy*/)
if ((rmrpFeatures & RM_FEATURE_TIMEDSESSION) == 0)
return; /* No timed session feature => nothing to do here */
val = GfuiEditboxGetString(scrHandle, rmrpSessionTimeEditId);
val = GfuiEditboxGetString(ScrHandle, rmrpSessionTimeEditId);
while( true )
{
@ -186,22 +184,27 @@ rmrpUpdSessionTime(void * /*dummy*/)
strcpy( buf, "---");
else
sprintf(buf, "%d:%02d:%02d", (int)floor( (float)rmrpSessionTime / 3600.0f ), (int)floor( (float)rmrpSessionTime / 60.0f ) % 60, (int)floor( (float)rmrpSessionTime ) % 60 );
GfuiEditboxSetString(scrHandle, rmrpSessionTimeEditId, buf);
GfuiEditboxSetString(ScrHandle, rmrpSessionTimeEditId, buf);
}
static void
rmChangeDisplayMode(void * /* dummy */)
rmChangeDisplayMode(void *vp)
{
rmrpDispMode = 1 - rmrpDispMode;
GfuiLabelSetText(scrHandle, rmrpDispModeEditId, DispModeValues[rmrpDispMode]);
const long delta = (int)(long)vp;
rmrpDispMode =
(GfRace::EDisplayMode)
((rmrpDispMode + GfRace::nDisplayModeNumber + delta) % GfRace::nDisplayModeNumber);
GfuiLabelSetText(ScrHandle, rmrpDispModeEditId, DispModeValues[rmrpDispMode]);
}
static void
rmChangeTimeOfDay(void *vp)
{
const long delta = (long)vp;
rmrpTimeOfDay = (rmrpTimeOfDay + NTimeOfDayValues + delta) % NTimeOfDayValues;
GfuiLabelSetText(scrHandle, rmrpTimeOfDayEditId, TimeOfDayValues[rmrpTimeOfDay]);
const long delta = (int)(long)vp;
rmrpTimeOfDay =
(GfRace::ETimeOfDaySpec)
((rmrpTimeOfDay + GfRace::nTimeSpecNumber + delta) % GfRace::nTimeSpecNumber);
GfuiLabelSetText(ScrHandle, rmrpTimeOfDayEditId, TimeOfDayValues[rmrpTimeOfDay]);
}
static void rmChangeRain(void *vp);
@ -209,17 +212,19 @@ static void rmChangeRain(void *vp);
static void
rmChangeClouds(void *vp)
{
const long delta = (long)vp;
rmrpClouds = (rmrpClouds + NCloudsValues + delta) % NCloudsValues;
GfuiLabelSetText(scrHandle, rmrpCloudsEditId, CloudsValues[rmrpClouds]);
const long delta = (int)(long)vp;
rmrpClouds =
(GfRace::ECloudsSpec)
((rmrpClouds + GfRace::nCloudsSpecNumber + delta) % GfRace::nCloudsSpecNumber);
GfuiLabelSetText(ScrHandle, rmrpCloudsEditId, CloudsValues[rmrpClouds]);
if ((rp->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
if ((MenuData->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
{
// Make rain level compatible if needed.
if (rmrpClouds < NCloudsValues - 1) // No heavy clouds => no rain
if (rmrpClouds != GfRace::eCloudsFull) // No heavy clouds => no rain
{
rmrpRain = TR_RAIN_NONE;
GfuiLabelSetText(scrHandle, rmrpRainEditId, RainValues[rmrpRain]);
rmrpRain = GfRace::eRainNone;
GfuiLabelSetText(ScrHandle, rmrpRainEditId, RainValues[rmrpRain]);
}
}
}
@ -227,32 +232,34 @@ rmChangeClouds(void *vp)
static void
rmChangeRain(void *vp)
{
const long delta = (long)vp;
rmrpRain = (rmrpRain + NRainValues + delta) % NRainValues;
GfuiLabelSetText(scrHandle, rmrpRainEditId, RainValues[rmrpRain]);
const long delta = (int)(long)vp;
rmrpRain =
(GfRace::ERainSpec)
((rmrpRain + GfRace::nRainSpecNumber + delta) % GfRace::nRainSpecNumber);
GfuiLabelSetText(ScrHandle, rmrpRainEditId, RainValues[rmrpRain]);
if ((rp->confMask & RM_CONF_CLOUD_COVER) && rmrpIsSkyDomeEnabled)
if ((MenuData->confMask & RM_CONF_CLOUD_COVER) && rmrpIsSkyDomeEnabled)
{
// Make clouds state compatible if needed.
int cloudsComboVisibility;
if (rmrpRain == TR_RAIN_RANDOM) // Random rain => Random clouds.
if (rmrpRain == GfRace::eRainRandom) // Random rain => Random clouds.
{
cloudsComboVisibility = GFUI_INVISIBLE;
GfuiLabelSetText(scrHandle, rmrpCloudsEditId, "random");
GfuiLabelSetText(ScrHandle, rmrpCloudsEditId, "random");
}
else
{
cloudsComboVisibility = GFUI_VISIBLE;
if (rmrpRain == TR_RAIN_NONE)
rmrpClouds = 0; // No rain => no clouds by default.
if (rmrpRain == GfRace::eRainNone)
rmrpClouds = GfRace::eCloudsNone; // No rain => no clouds by default.
else
rmrpClouds = NCloudsValues - 1; // Rain => Heavy clouds.
GfuiLabelSetText(scrHandle, rmrpCloudsEditId, CloudsValues[rmrpClouds]);
rmrpClouds = GfRace::eCloudsFull; // Rain => Heavy clouds.
GfuiLabelSetText(ScrHandle, rmrpCloudsEditId, CloudsValues[rmrpClouds]);
}
// Show / hide clouds combo arrow buttons (random rain => no sky choice).
GfuiVisibilitySet(scrHandle, rmrpCloudsLeftArrowId, cloudsComboVisibility);
GfuiVisibilitySet(scrHandle, rmrpCloudsRightArrowId, cloudsComboVisibility);
GfuiVisibilitySet(ScrHandle, rmrpCloudsLeftArrowId, cloudsComboVisibility);
GfuiVisibilitySet(ScrHandle, rmrpCloudsRightArrowId, cloudsComboVisibility);
}
}
@ -262,43 +269,45 @@ rmrpValidate(void * /* dummy */)
// Force current edit to loose focus (if one has it) and update associated variable.
GfuiUnSelectCurrent();
if (rp->confMask & RM_CONF_RACE_LEN)
GfRace::Parameters* pRaceParams = MenuData->pRace->getParameters();
if (MenuData->confMask & RM_CONF_RACE_LEN)
{
GfParmSetNum(rp->param, rp->title, RM_ATTR_DISTANCE, "km", rmrpDistance);
GfParmSetNum(rp->param, rp->title, RM_ATTR_LAPS, (char*)NULL, rmrpLaps);
GfParmSetNum(rp->param, rp->title, RM_ATTR_SESSIONTIME, "s", (tdble)rmrpSessionTime);
pRaceParams->nDistance = rmrpDistance;
pRaceParams->nLaps = rmrpLaps;
pRaceParams->nDuration = rmrpSessionTime;
}
if (rp->confMask & RM_CONF_TIME_OF_DAY)
if (MenuData->confMask & RM_CONF_TIME_OF_DAY)
{
GfParmSetStr(rp->param, rp->title, RM_ATTR_TIME_OF_DAY, TimeOfDayValues[rmrpTimeOfDay]);
pRaceParams->eTimeOfDaySpec = (GfRace::ETimeOfDaySpec)rmrpTimeOfDay;
}
if (rp->confMask & RM_CONF_CLOUD_COVER)
if (MenuData->confMask & RM_CONF_CLOUD_COVER)
{
GfParmSetStr(rp->param, rp->title, RM_ATTR_CLOUDS, CloudsValues[rmrpClouds]);
pRaceParams->eCloudsSpec = (GfRace::ECloudsSpec)rmrpClouds;
}
if ((rp->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
if ((MenuData->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
{
GfParmSetStr(rp->param, rp->title, RM_ATTR_RAIN, RainValues[rmrpRain]);
pRaceParams->eRainSpec = (GfRace::ERainSpec)rmrpRain;
}
if (rp->confMask & RM_CONF_DISP_MODE)
if (MenuData->confMask & RM_CONF_DISP_MODE)
{
GfParmSetStr(rp->param, rp->title, RM_ATTR_DISPMODE, DispModeValues[rmrpDispMode]);
pRaceParams->eDisplayMode = (GfRace::EDisplayMode)rmrpDispMode;
}
rmrpDeactivate(rp->nextScreen);
rmrpDeactivate(MenuData->nextScreen);
}
static void
rmrpAddKeys(void)
{
GfuiAddKey(scrHandle, GFUIK_RETURN, "Accept", NULL, rmrpValidate, NULL);
GfuiAddKey(scrHandle, GFUIK_ESCAPE, "Cancel", rp->prevScreen, rmrpDeactivate, NULL);
GfuiAddKey(scrHandle, GFUIK_F1, "Help", scrHandle, GfuiHelpScreen, NULL);
GfuiAddKey(scrHandle, GFUIK_F12, "Screen-Shot", NULL, GfuiScreenShot, NULL);
GfuiAddKey(ScrHandle, GFUIK_RETURN, "Accept", NULL, rmrpValidate, NULL);
GfuiAddKey(ScrHandle, GFUIK_ESCAPE, "Cancel", MenuData->prevScreen, rmrpDeactivate, NULL);
GfuiAddKey(ScrHandle, GFUIK_F1, "Help", ScrHandle, GfuiHelpScreen, NULL);
GfuiAddKey(ScrHandle, GFUIK_F12, "Screen-Shot", NULL, GfuiScreenShot, NULL);
}
void
@ -308,10 +317,14 @@ RmRaceParamsMenu(void *vrp)
GfLogTrace("Entering Race Params menu\n");
rp = (tRmRaceParam*)vrp;
MenuData = (tRmRaceParam*)vrp;
GfRace::Parameters* pRaceParams = MenuData->pRace->getParameters();
if (!pRaceParams)
return;
// Get race features.
rmrpFeatures = RmGetFeaturesList(rp->param);
rmrpFeatures = MenuData->pRace->getSupportedFeatures();
// Check if SkyDome is enabled
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), GR_PARAM_FILE);
@ -321,29 +334,29 @@ RmRaceParamsMenu(void *vrp)
GfParmReleaseHandle(grHandle);
// Create screen, load menu XML descriptor and create static controls.
scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, NULL, NULL, (tfuiCallback)NULL, 1);
ScrHandle = GfuiScreenCreateEx((float*)NULL, NULL, NULL, NULL, (tfuiCallback)NULL, 1);
void *menuXMLDescHdle = LoadMenuXML("raceparamsmenu.xml");
CreateStaticControls(menuXMLDescHdle,scrHandle);
CreateStaticControls(menuXMLDescHdle,ScrHandle);
// Create variable title label.
int titleId = CreateLabelControl(scrHandle,menuXMLDescHdle,"title");
sprintf(buf, "%s Options", rp->title);
GfuiLabelSetText(scrHandle,titleId,buf);
int titleId = CreateLabelControl(ScrHandle,menuXMLDescHdle,"title");
sprintf(buf, "%s Options", MenuData->pRace->getSessionName().c_str());
GfuiLabelSetText(ScrHandle,titleId,buf);
if (rp->confMask & RM_CONF_RACE_LEN)
if (MenuData->confMask & RM_CONF_RACE_LEN)
{
// Create Race distance label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"racedistancelabel");
rmrpDistance = (int)GfParmGetNum(rp->param, rp->title, RM_ATTR_DISTANCE, "km", 0);
CreateLabelControl(ScrHandle,menuXMLDescHdle,"racedistancelabel");
rmrpDistance = pRaceParams->nDistance;
// Create and initialize Race distance edit.
rmrpSessionTime = (int)GfParmGetNum(rp->param, rp->title, RM_ATTR_SESSIONTIME, NULL, 0);
rmrpSessionTime = pRaceParams->nDuration;
if (rmrpSessionTime > 0 && ( rmrpFeatures & RM_FEATURE_TIMEDSESSION ) == 0 )
rmrpDistance += rmrpSessionTime / 30;
if (rmrpDistance == 0)
{
strcpy(buf, "---");
rmrpLaps = (int)GfParmGetNum(rp->param, rp->title, RM_ATTR_LAPS, NULL, 25);
rmrpLaps = pRaceParams->nLaps;
if (rmrpSessionTime > 0 && ( rmrpFeatures & RM_FEATURE_TIMEDSESSION ) == 0 )
rmrpLaps += (int)floor( (tdble)rmrpSessionTime / 1.5f + 0.5f );
}
@ -353,11 +366,12 @@ RmRaceParamsMenu(void *vrp)
rmrpLaps = 0;
}
rmrpDistEditId = CreateEditControl(scrHandle,menuXMLDescHdle,"racedistanceedit",NULL,NULL,rmrpUpdDist);
GfuiEditboxSetString(scrHandle,rmrpDistEditId,buf);
rmrpDistEditId = CreateEditControl(ScrHandle, menuXMLDescHdle, "racedistanceedit",
NULL, NULL, rmrpUpdDist);
GfuiEditboxSetString(ScrHandle,rmrpDistEditId,buf);
// Create Laps label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"lapslabel");
CreateLabelControl(ScrHandle,menuXMLDescHdle,"lapslabel");
// Create and initialize Laps edit.
if (rmrpLaps == 0)
@ -369,13 +383,14 @@ RmRaceParamsMenu(void *vrp)
sprintf(buf, "%d", rmrpLaps);
}
rmrpLapsEditId = CreateEditControl(scrHandle,menuXMLDescHdle,"lapsedit",NULL,NULL,rmrpUpdLaps);
GfuiEditboxSetString(scrHandle,rmrpLapsEditId,buf);
rmrpLapsEditId = CreateEditControl(ScrHandle, menuXMLDescHdle, "lapsedit",
NULL, NULL, rmrpUpdLaps);
GfuiEditboxSetString(ScrHandle,rmrpLapsEditId,buf);
if (rmrpFeatures & RM_FEATURE_TIMEDSESSION)
{
// Create Session time label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"sessiontimelabel");
CreateLabelControl(ScrHandle,menuXMLDescHdle,"sessiontimelabel");
// Create and initialize Session time edit.
if (rmrpSessionTime <= 0)
@ -390,8 +405,9 @@ RmRaceParamsMenu(void *vrp)
}
rmrpSessionTimeEditId =
CreateEditControl(scrHandle,menuXMLDescHdle,"sessiontimeedit",NULL,NULL,rmrpUpdSessionTime);
GfuiEditboxSetString(scrHandle,rmrpSessionTimeEditId,buf);
CreateEditControl(ScrHandle, menuXMLDescHdle, "sessiontimeedit",
NULL, NULL, rmrpUpdSessionTime);
GfuiEditboxSetString(ScrHandle,rmrpSessionTimeEditId,buf);
}
else
{
@ -400,115 +416,97 @@ RmRaceParamsMenu(void *vrp)
}
// Create and initialize Time of day combo box (2 arrow buttons and a variable label).
if (rp->confMask & RM_CONF_TIME_OF_DAY)
if (MenuData->confMask & RM_CONF_TIME_OF_DAY)
{
if (rmrpIsSkyDomeEnabled)
{
rmrpTimeOfDay = 0;
const char* pszTimeOfDay =
GfParmGetStr(rp->param, rp->title, RM_ATTR_TIME_OF_DAY, RM_VAL_TIME_AFTERNOON);
for (int i = 0; i < NTimeOfDayValues; i++)
if (!strcmp(pszTimeOfDay, TimeOfDayValues[i]))
{
rmrpTimeOfDay = i;
break;
}
rmrpTimeOfDay = pRaceParams->eTimeOfDaySpec;
// Create Time of day label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"timeofdaylabel");
CreateLabelControl(ScrHandle,menuXMLDescHdle,"timeofdaylabel");
// Create and initialize Time of day combo-box-like control.
CreateButtonControl(scrHandle,menuXMLDescHdle,"timeofdayleftarrow",(void*)-1, rmChangeTimeOfDay);
CreateButtonControl(scrHandle,menuXMLDescHdle,"timeofdayrightarrow",(void*)1, rmChangeTimeOfDay);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "timeofdayleftarrow",
(void*)-1, rmChangeTimeOfDay);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "timeofdayrightarrow",
(void*)1, rmChangeTimeOfDay);
rmrpTimeOfDayEditId = CreateLabelControl(scrHandle,menuXMLDescHdle,"timeofdayedit");
GfuiLabelSetText(scrHandle,rmrpTimeOfDayEditId,TimeOfDayValues[rmrpTimeOfDay]);
rmrpTimeOfDayEditId = CreateLabelControl(ScrHandle,menuXMLDescHdle,"timeofdayedit");
GfuiLabelSetText(ScrHandle, rmrpTimeOfDayEditId, TimeOfDayValues[rmrpTimeOfDay]);
}
else
{
rmrpTimeOfDay = 3; // Afternoon (but normally not taken into account).
rmrpTimeOfDay = GfRace::eTimeAfternoon; // Normally not taken into account.
}
}
if (rp->confMask & RM_CONF_CLOUD_COVER)
if (MenuData->confMask & RM_CONF_CLOUD_COVER)
{
if (rmrpIsSkyDomeEnabled)
{
// Create and initialize Clouds combo box (2 arrow buttons and a variable label).
rmrpClouds = 0;
const char* pszClouds =
GfParmGetStr(rp->param, rp->title, RM_ATTR_CLOUDS, RM_VAL_CLOUDS_NONE);
for (int i = 0; i < NCloudsValues; i++)
if (!strcmp(pszClouds, CloudsValues[i]))
{
rmrpClouds = i;
break;
}
rmrpClouds = pRaceParams->eCloudsSpec;
// Create Cloud cover label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"cloudslabel");
CreateLabelControl(ScrHandle,menuXMLDescHdle,"cloudslabel");
// Create and initialize Cloud cover combo-box-like control.
rmrpCloudsLeftArrowId =
CreateButtonControl(scrHandle,menuXMLDescHdle,"cloudsleftarrow",(void*)-1, rmChangeClouds);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "cloudsleftarrow",
(void*)-1, rmChangeClouds);
rmrpCloudsRightArrowId =
CreateButtonControl(scrHandle,menuXMLDescHdle,"cloudsrightarrow",(void*)1, rmChangeClouds);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "cloudsrightarrow",
(void*)+1, rmChangeClouds);
rmrpCloudsEditId = CreateLabelControl(scrHandle,menuXMLDescHdle,"cloudsedit");
GfuiLabelSetText(scrHandle,rmrpCloudsEditId,CloudsValues[rmrpClouds]);
rmrpCloudsEditId = CreateLabelControl(ScrHandle,menuXMLDescHdle,"cloudsedit");
GfuiLabelSetText(ScrHandle,rmrpCloudsEditId,CloudsValues[rmrpClouds]);
}
else
{
rmrpClouds = 0;
rmrpClouds = GfRace::eCloudsNone;
}
}
if ((rp->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
if ((MenuData->confMask & RM_CONF_RAIN_FALL) && (rmrpFeatures & RM_FEATURE_WETTRACK))
{
// Create and initialize Rain combo box (2 arrow buttons and a variable label).
rmrpRain = 0;
const char* pszRain =
GfParmGetStr(rp->param, rp->title, RM_ATTR_RAIN, RM_VAL_RAIN_NONE);
for (int i = 0; i < NRainValues; i++)
if (!strcmp(pszRain, RainValues[i]))
{
rmrpRain = i;
break;
}
rmrpRain = pRaceParams->eRainSpec;
// Create Rain label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"rainlabel");
CreateLabelControl(ScrHandle,menuXMLDescHdle,"rainlabel");
// Create and initialize Rain combo-box-like control.
CreateButtonControl(scrHandle,menuXMLDescHdle,"rainleftarrow",(void*)-1, rmChangeRain);
CreateButtonControl(scrHandle,menuXMLDescHdle,"rainrightarrow",(void*)1, rmChangeRain);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "rainleftarrow",
(void*)-1, rmChangeRain);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "rainrightarrow",
(void*)1, rmChangeRain);
rmrpRainEditId = CreateLabelControl(scrHandle,menuXMLDescHdle,"rainedit");
GfuiLabelSetText(scrHandle,rmrpRainEditId,RainValues[rmrpRain]);
rmrpRainEditId = CreateLabelControl(ScrHandle,menuXMLDescHdle,"rainedit");
GfuiLabelSetText(ScrHandle,rmrpRainEditId,RainValues[rmrpRain]);
rmChangeRain(0); // Make cloud cover settings compatible if needed.
}
if (rp->confMask & RM_CONF_DISP_MODE)
if (MenuData->confMask & RM_CONF_DISP_MODE)
{
if (!strcmp(GfParmGetStr(rp->param, rp->title, RM_ATTR_DISPMODE, RM_VAL_VISIBLE), RM_VAL_INVISIBLE))
rmrpDispMode = 1;
else
rmrpDispMode = 0;
rmrpDispMode = pRaceParams->eDisplayMode;
// Create Display mode label.
CreateLabelControl(scrHandle,menuXMLDescHdle,"displaylabel");
CreateLabelControl(ScrHandle, menuXMLDescHdle, "displaylabel");
// Create and initialize Display mode combo-box-like control.
CreateButtonControl(scrHandle,menuXMLDescHdle,"displayleftarrow",(void*)0, rmChangeDisplayMode);
CreateButtonControl(scrHandle,menuXMLDescHdle,"displayrightarrow",(void*)1, rmChangeDisplayMode);
rmrpDispModeEditId = CreateLabelControl(scrHandle,menuXMLDescHdle,"displayedit");
GfuiLabelSetText(scrHandle,rmrpDispModeEditId,DispModeValues[rmrpDispMode]);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "displayleftarrow",
(void*)-1, rmChangeDisplayMode);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "displayrightarrow",
(void*)+1, rmChangeDisplayMode);
rmrpDispModeEditId = CreateLabelControl(ScrHandle, menuXMLDescHdle, "displayedit");
GfuiLabelSetText(ScrHandle, rmrpDispModeEditId, DispModeValues[rmrpDispMode]);
}
// Create Accept and Cancel buttons
CreateButtonControl(scrHandle,menuXMLDescHdle,"nextbutton",NULL,rmrpValidate);
CreateButtonControl(scrHandle,menuXMLDescHdle,"previousbutton",rp->prevScreen,rmrpDeactivate);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "nextbutton", NULL, rmrpValidate);
CreateButtonControl(ScrHandle, menuXMLDescHdle, "previousbutton",
MenuData->prevScreen, rmrpDeactivate);
// Close menu XML descriptor.
GfParmReleaseHandle(menuXMLDescHdle);
@ -516,5 +514,5 @@ RmRaceParamsMenu(void *vrp)
// Register keyboard shortcuts.
rmrpAddKeys();
GfuiScreenActivate(scrHandle);
GfuiScreenActivate(ScrHandle);
}

View file

@ -29,6 +29,8 @@
#include <tgfclient.h> // tfuiCalback
class GfRace;
// DLL exported symbols declarator for Windows.
#ifdef WIN32
@ -44,7 +46,7 @@
typedef struct RmTrackSelect
{
void *param; /* Race manager parameters where to set the selected track */
GfRace *pRace; /* The race to update */
void *prevScreen; /* Race manager screen to go back */
void *nextScreen; /* Race manager screen to go after select */
tTrackItf trackItf; /* Track module interface */
@ -52,17 +54,16 @@ typedef struct RmTrackSelect
typedef struct RmDriverSelect
{
void *param;
GfRace *pRace; /* The race to update */
void *prevScreen; /* Race manager screen to go back */
void *nextScreen; /* Race manager screen to go after select */
} tRmDriverSelect;
typedef struct RmRaceParam
{
void *param;
GfRace *pRace; /* The race to update */
void *prevScreen;
void *nextScreen; /* Race manager screen to go after select */
const char *title;
unsigned int confMask; /* Tell what to configure */
#define RM_CONF_RACE_LEN 0x00000001
#define RM_CONF_DISP_MODE 0x00000002
@ -77,8 +78,8 @@ enum RmFileSelectMode { RmFSModeLoad, RmFSModeSave };
typedef struct RmFileSelect
{
const char *title;
const char *path;
std::string title;
std::string path;
void *prevScreen;
tfSelectFile select;
RmFileSelectMode mode;
@ -128,7 +129,5 @@ RACESCREENS_API void RmShowStandings(void *prevHdle, tRmInfo *info);
RACESCREENS_API void* RmFileSelect(void *vs);
RACESCREENS_API int RmGetFeaturesList( void* param );
#endif /* __RACESCREENS_H__ */

View file

@ -22,16 +22,16 @@
@version $Id$
*/
#include <sstream>
#include <iterator>
#include <algorithm>
#include <iomanip>
#include <raceman.h>
#include <tgfclient.h>
#include <portability.h>
#include <race.h>
#include <tracks.h>
#include "racescreens.h"
@ -40,8 +40,8 @@
// Screen handle.
static void *ScrHandle;
//
static tRmTrackSelect *TrackSelect;
// Track select menu data.
static tRmTrackSelect *MenuData;
// The currently selected track.
GfTrack* PCurTrack;
@ -84,130 +84,18 @@ rmtsWordWrap(const std::string str, std::string &str1, std::string &str2, unsign
it++;
}//while
if(str.size() >= length) //If input string was longer than required,
if (str.size() >= length) //If input string was longer than required,
str2 = str.substr(str1.size()); //put the rest in str2.
}//rmtsWordWrap
/**
* rmtsGetFirstUsableTrack
*
* Retrieve the first usable track in the given category, searching in the given direction
* and skipping the first found if specified
*
* @param strCatId Id of the category to search inside of.
* @param strFromTrackId Id of the track from which to start the search.
* @param nSearchDir <0 = previous, >0 = next.
* @param bSkipFrom If true, skip the first found track.
*/
static GfTrack*
rmtsGetFirstUsableTrack(const std::string& strCatId, const std::string& strFromTrackId = "",
int nSearchDir = +1, bool bSkipFrom = false)
{
//GfLogDebug("rmtsGetFirstUsableTrack(c=%s, ft=%s, %d)\n",
// strCatId.c_str(), strFromTrackId.c_str(), nSearchDir);
GfTrack* pTrack = 0;
if (nSearchDir == 0)
nSearchDir = +1;
// Check category.
const std::vector<std::string>& vecCatIds = GfTracks::self()->getCategoryIds();
if (std::find(vecCatIds.begin(), vecCatIds.end(), strCatId) == vecCatIds.end())
return 0;
// Retrieve tracks in this category.
const std::vector<GfTrack*> vecTracksInCat =
GfTracks::self()->getTracksInCategory(strCatId);
if (vecTracksInCat.size() == 0)
return 0;
// Retrieve the index of the specified track to start from, if any.
int nCurTrackInd = 0;
if (!strFromTrackId.empty())
{
std::vector<GfTrack*>::const_iterator itTrack = vecTracksInCat.begin();
while (itTrack != vecTracksInCat.end())
{
if ((*itTrack)->getId() == strFromTrackId)
{
nCurTrackInd = itTrack - vecTracksInCat.begin();
break;
}
itTrack++;
}
}
int nTrackInd = nCurTrackInd;
if (bSkipFrom || !vecTracksInCat[nTrackInd]->isUsable())
{
const int nPrevTrackInd = nCurTrackInd;
do
{
nTrackInd =
(nTrackInd + nSearchDir + vecTracksInCat.size()) % vecTracksInCat.size();
//GfLogDebug("xxx nTrackInd=%d\n", nTrackInd);
}
while (nTrackInd != nPrevTrackInd && !vecTracksInCat[nTrackInd]->isUsable());
}
if (vecTracksInCat[nTrackInd]->isUsable())
pTrack = vecTracksInCat[nTrackInd];
return pTrack;
}
/**
* rmtsGetFirstUsableTrack
*
* Retrieve the first usable track among all categories, searching in the given direction
* from the given category, but skipping it if specified
*
* @param strFromCatId Id of the category to search inside of.
* @param nSearchDir <0 = previous, >0 = next.
* @param bSkipFrom If true, skip the first found track.
*/
static GfTrack*
rmtsGetFirstUsableTrack(const std::string& strFromCatId, int nSearchDir, bool bSkipFrom = false)
{
//GfLogDebug("rmtsGetFirstUsableTrack(fc=%s, %d)\n", strFromCatId.c_str(), nSearchDir);
GfTrack* pTrack = 0;
if (nSearchDir == 0)
nSearchDir = +1;
// Retrieve and check category.
const std::vector<std::string>& vecCatIds = GfTracks::self()->getCategoryIds();
std::vector<std::string>::const_iterator itFromCat =
std::find(vecCatIds.begin(), vecCatIds.end(), strFromCatId);
if (itFromCat == vecCatIds.end())
return 0;
int nCatInd = itFromCat - vecCatIds.begin();
if (bSkipFrom || !(pTrack = rmtsGetFirstUsableTrack(vecCatIds[nCatInd])))
{
const int nPrevCatInd = nCatInd;
//GfLogDebug("xxx nPrevCatInd=%d\n", nPrevCatInd);
do
{
nCatInd =
(nCatInd + nSearchDir + vecCatIds.size()) % vecCatIds.size();
pTrack = rmtsGetFirstUsableTrack(vecCatIds[nCatInd]);
//GfLogDebug("xxx cat[%d]=%s, p=%p\n", nCatInd, vecCatIds[nCatInd].c_str(), pTrack);
}
while (nCatInd != nPrevCatInd && !pTrack);
}
return pTrack;
}
static void
rmtsUpdateTrackInfo(void)
{
static const int nMaxLinesLength = 30; //Line length for track description (chars)
if (!PCurTrack)
return;
// Update GUI with track info.
// 0) Track category and name.
GfuiLabelSetText(ScrHandle, CategoryEditId, PCurTrack->getCategoryName().c_str());
@ -270,17 +158,14 @@ rmtsActivate(void * /* dummy */)
static void
rmtsTrackPrevNext(void *vsel)
{
const int nSearchDir = vsel ? (int)(long)vsel : +1;
const int nSearchDir = (long)vsel > 0 ? +1 : -1;
PCurTrack =
rmtsGetFirstUsableTrack(PCurTrack->getCategoryId(), PCurTrack->getId(), nSearchDir, true);
// Select next usable track in the current catergory in the requested direction.
PCurTrack = GfTracks::self()->getFirstUsableTrack(PCurTrack->getCategoryId(),
PCurTrack->getId(), nSearchDir, true);
// If any next/previous usable track in the current category, select it.
if (PCurTrack)
{
// Update GUI
rmtsUpdateTrackInfo();
}
// Update GUI
rmtsUpdateTrackInfo();
}
@ -288,106 +173,25 @@ rmtsTrackPrevNext(void *vsel)
static void
rmtsTrackCatPrevNext(void *vsel)
{
const int nSearchDir = vsel ? (int)(long)vsel : +1;
const int nSearchDir = (long)vsel > 0 ? +1 : -1;
//
PCurTrack = rmtsGetFirstUsableTrack(PCurTrack->getCategoryId(), nSearchDir, true);
// Select first usable track in the next catergory in the requested direction.
PCurTrack = GfTracks::self()->getFirstUsableTrack(PCurTrack->getCategoryId(),
nSearchDir, true);
// If any next/previous usable category, select it.
if (PCurTrack)
{
// Update GUI
rmtsUpdateTrackInfo();
}
// /* Get next/previous usable track category
// Note: Here, we assume there's at least one,
// which is guaranteed by CategoryList initialization in RmTrackSelect */
// const int nDeltaInd = (int)(long)(vsel ? vsel : 1);
// const std::string& strCurCat = GfTracks::self()->getCategoryIds()[NCurCatIndex];
// const std::vector<GfTrack*> vecTracksInCat =
// GfTracks::self()->getTracksInCategory(strCurCat);
// const int nPrevTrackIndex = NCurTrackCatIndex;
// do
// {
// NCurTrackInCatIndex =
// (NCurTrackInCatIndex + nDeltaInd + GfTracks::self()->getCategoryIds())
// % GfTracks::self()->getCategoryIds();
// }
// while (nPrevTrackIndex != NCurTrackInCatIndex
// && vecTracksInCat[NCurTrackCatIndex]->isUsable());
// tFList *curCat = CategoryList;
// do {
// /* Next/previous category */
// curCat = vsel ? curCat->next : curCat->prev;
// /* Try and get the category display name if not already done */
// if (curCat->userData && !curCat->dispName) {
// curCat->dispName = rmtsGetCategoryName(curCat->name);
// if (!curCat->dispName || strlen(curCat->dispName) == 0) {
// GfError("rmtsTrackCatPrevNext: No definition for track category %s\n", curCat->name);
// }
// }
// /* If the category is loadable and not empty : */
// if (curCat->dispName && curCat->userData) {
// /* Select the first usable track in the category */
// tFList *curTr = (tFList*)(curCat->userData);
// do {
// /* Try and get the track display name if not already done */
// if (!curTr->dispName) {
// curTr->dispName = rmtsGetTrackName(curCat->name, curTr->name);
// if (!curTr->dispName || strlen(curTr->dispName) == 0) {
// GfError("rmtsTrackCatPrevNext: No definition for track %s\n", curTr->name);
// }
// }
// /* That's all if the track is usable*/
// if (curTr->dispName)
// break;
// /* Next track */
// curTr = curTr->next;
// } while (curTr != (tFList*)(curCat->userData));
// curCat->userData = (void*)curTr;
// }
// } while ((!curCat->dispName || !curCat->userData || !((tFList*)(curCat->userData))->dispName)
// && curCat != CategoryList);
// CategoryList = curCat;
// /* Update GUI */
// GfuiLabelSetText(ScrHandle, CategoryEditId, CategoryList->dispName);
// GfuiLabelSetText(ScrHandle, NameEditId, ((tFList*)curCat->userData)->dispName);
// GfuiStaticImageSet(ScrHandle, OutlineImageLabelId, rmtsGetOutlineFileName(PathBuf, MaxPathSize));
// GfuiScreenAddBgImg(ScrHandle, rmtsGetPreviewFileName(PathBuf, MaxPathSize));
// rmtsUpdateTrackInfo();
// Update GUI
rmtsUpdateTrackInfo();
}
static void
rmtsSelect(void * /* dummy */)
{
// Save currently slected track category and LabelId to the race params file.
const int nCurTrackInd =
(int)GfParmGetNum(TrackSelect->param, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1);
std::ostringstream ossParamPath;
ossParamPath << RM_SECT_TRACKS << '/' << nCurTrackInd;
GfParmSetStr(TrackSelect->param, ossParamPath.str().c_str(), RM_ATTR_CATEGORY,
PCurTrack->getCategoryId().c_str());
GfParmSetStr(TrackSelect->param, ossParamPath.str().c_str(), RM_ATTR_NAME,
PCurTrack->getId().c_str());
GfParmSetStr(TrackSelect->param, ossParamPath.str().c_str(), RM_ATTR_FULLNAME,
PCurTrack->getId().c_str());
// Save currently selected track into the race.
MenuData->pRace->setTrack(PCurTrack);
rmtsDeactivate(TrackSelect->nextScreen);
// Next screen.
rmtsDeactivate(MenuData->nextScreen);
}
@ -395,7 +199,7 @@ static void
rmtsAddKeys(void)
{
GfuiAddKey(ScrHandle, GFUIK_RETURN, "Select Track", NULL, rmtsSelect, NULL);
GfuiAddKey(ScrHandle, GFUIK_ESCAPE, "Cancel Selection", TrackSelect->prevScreen, rmtsDeactivate, NULL);
GfuiAddKey(ScrHandle, GFUIK_ESCAPE, "Cancel Selection", MenuData->prevScreen, rmtsDeactivate, NULL);
GfuiAddKey(ScrHandle, GFUIK_LEFT, "Previous Track", (void*)-1, rmtsTrackPrevNext, NULL);
GfuiAddKey(ScrHandle, GFUIK_RIGHT, "Next Track", (void*)+1, rmtsTrackPrevNext, NULL);
GfuiAddKey(ScrHandle, GFUIK_F1, "Help", ScrHandle, GfuiHelpScreen, NULL);
@ -413,33 +217,28 @@ rmtsAddKeys(void)
void
RmTrackSelect(void *vs)
{
TrackSelect = (tRmTrackSelect*)vs;
MenuData = (tRmTrackSelect*)vs;
// Get currently selected track for the current race type
// (or the first usable one in the selected category).
const int nCurTrackInd =
(int)GfParmGetNum(TrackSelect->param, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1);
std::ostringstream ossSectionPath;
ossSectionPath << RM_SECT_TRACKS << '/' << nCurTrackInd;
const char* pszCurTrackId =
GfParmGetStr(TrackSelect->param, ossSectionPath.str().c_str(), RM_ATTR_NAME, 0);
const char* pszCurTrackCatId =
GfParmGetStr(TrackSelect->param, ossSectionPath.str().c_str(), RM_ATTR_CATEGORY, 0);
PCurTrack = rmtsGetFirstUsableTrack(pszCurTrackCatId, pszCurTrackId);
if (PCurTrack && PCurTrack->getId() != pszCurTrackId)
GfLogWarning("Could not find selected track %s (%s) ; using %s (%s)\n",
pszCurTrackId, pszCurTrackCatId,
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 = rmtsGetFirstUsableTrack(pszCurTrackCatId, +1, true);
PCurTrack = GfTracks::self()->getFirstUsableTrack(strReqTrackCatId, +1, true);
if (PCurTrack)
GfLogWarning("Could not find selected track %s and category %s unusable"
GfLogWarning("Could not find / use selected track %s and category %s unusable"
" ; using %s (%s)\n",
pszCurTrackId, pszCurTrackCatId,
strReqTrackId.c_str(), strReqTrackCatId.c_str(),
PCurTrack->getId().c_str(), PCurTrack->getCategoryId().c_str());
}
@ -468,7 +267,7 @@ RmTrackSelect(void *vs)
OutlineImageId = CreateStaticImageControl(ScrHandle, hparmMenu, "outlineimage");
CreateButtonControl(ScrHandle, hparmMenu, "nextbutton", NULL, rmtsSelect);
CreateButtonControl(ScrHandle, hparmMenu, "previousbutton", TrackSelect->prevScreen, rmtsDeactivate);
CreateButtonControl(ScrHandle, hparmMenu, "previousbutton", MenuData->prevScreen, rmtsDeactivate);
DescLine1LabelId = CreateLabelControl(ScrHandle, hparmMenu, "descriptionlabel");
DescLine2LabelId = CreateLabelControl(ScrHandle, hparmMenu, "descriptionlabel2");

View file

@ -124,26 +124,14 @@ GfDrivers::GfDrivers()
continue;
}
// Read driver info from the XML file.
std::ostringstream ossDriverListPath;
ossDriverListPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX
<< '/' << pCurModule->modInfo[nItfInd].index;
const char* pszCarId = GfParmGetStr(hparmRobot, ossDriverListPath.str().c_str(), ROB_ATTR_CAR, "");
const bool bIsHuman = strcmp(GfParmGetStr(hparmRobot, ossDriverListPath.str().c_str(), ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT) != 0;
// Create the driver and load info from the XML file.
GfDriver* pDriver = new GfDriver(strModName, pCurModule->modInfo[nItfInd].index,
pCurModule->modInfo[nItfInd].name, hparmRobot);
// Compute/retrieve other information.
const GfCar* pCar = GfCars::self()->getCar(pszCarId);
if (pCar)
// Keep the driver only if its car exists and is usable.
if (pDriver->getCar())
{
// Store it in the GfDriver structure.
GfDriver* pDriver = new GfDriver;
pDriver->setName(pCurModule->modInfo[nItfInd].name);
pDriver->setModuleName(strModName);
pDriver->setInterfaceIndex(pCurModule->modInfo[nItfInd].index);
pDriver->setIsHuman(bIsHuman);
pDriver->setCar(pCar);
// Update the GfCars singleton.
// Update the GfDrivers singleton.
_pPrivate->vecDrivers.push_back(pDriver);
const std::pair<std::string, int> driverKey(pDriver->getModuleName(),
pDriver->getInterfaceIndex());
@ -152,13 +140,21 @@ GfDrivers::GfDrivers()
pDriver->getType()) == _pPrivate->vecTypes.end())
_pPrivate->vecTypes.push_back(pDriver->getType());
if (std::find(_pPrivate->vecCarCategoryIds.begin(), _pPrivate->vecCarCategoryIds.end(),
pCar->getCategoryId()) == _pPrivate->vecCarCategoryIds.end())
_pPrivate->vecCarCategoryIds.push_back(pCar->getCategoryId());
pDriver->getCar()->getCategoryId()) == _pPrivate->vecCarCategoryIds.end())
_pPrivate->vecCarCategoryIds.push_back(pDriver->getCar()->getCategoryId());
}
else
{
delete pDriver;
std::ostringstream ossDrvSecPath;
ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/'
<< pCurModule->modInfo[nItfInd].index;
const char* pszCarId =
GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, "");
GfLogWarning("Ignoring '%s' driver '%s' (#%d) (default car %s not available)\n",
strModName.c_str(), pCurModule->modInfo[nItfInd].name, nItfInd, pszCarId);
strModName.c_str(), pCurModule->modInfo[nItfInd].name,
pCurModule->modInfo[nItfInd].index, pszCarId);
}
}
@ -233,8 +229,10 @@ void GfDrivers::print() const
GfLogTrace(" '%s' car category :\n", itCarCatId->c_str());
std::vector<GfDriver*>::const_iterator itDriver;
for (itDriver = vecDrivers.begin(); itDriver != vecDrivers.end(); itDriver++)
GfLogTrace(" %-24s : %s\n", (*itDriver)->getName().c_str(),
(*itDriver)->getCar()->getName().c_str());
GfLogTrace(" %-24s : %s, %02X-featured\n",
(*itDriver)->getName().c_str(),
(*itDriver)->getCar()->getName().c_str(),
(*itDriver)->getSupportedFeatures());
}
}
}
@ -282,8 +280,95 @@ void GfDriverSkin::setCarPreviewFileName(const std::string& strFileName)
// GfDriver class -------------------------------------------------------------------
GfDriver::GfDriver() : _nItfIndex(-1), _bIsHuman(false), _pCar(0)
// Skill level related constants.
static const char *ASkillLevelStrings[] =
{ ROB_VAL_ROOKIE, ROB_VAL_AMATEUR, ROB_VAL_SEMI_PRO, ROB_VAL_PRO };
static const int NbSkillLevels = sizeof(ASkillLevelStrings) / sizeof(ASkillLevelStrings[0]);
static const double ASkillLevelValues[NbSkillLevels] = { 10.0, 7.0, 3.0, 0.0 };
// Robot drivers features related constants.
struct RobotFeature
{
const char *pszName;
int nValue;
};
static RobotFeature RobotFeatures[] =
{
{ ROB_VAL_FEATURE_PENALTIES, RM_FEATURE_PENALTIES },
{ ROB_VAL_FEATURE_TIMEDSESSION, RM_FEATURE_TIMEDSESSION },
{ ROB_VAL_FEATURE_WETTRACK, RM_FEATURE_WETTRACK },
/* Career mode features not yet resurrected (robots need work to support them).
{ ROB_VAL_FEATURE_SC, RM_FEATURE_SC | RM_FEATURE_YELLOW | RM_FEATURE_PENALTIES },
{ ROB_VAL_FEATURE_YELLOW, RM_FEATURE_YELLOW | RM_FEATURE_PENALTIES },
{ ROB_VAL_FEATURE_RED, RM_FEATURE_RED },
{ ROB_VAL_FEATURE_BLUE, RM_FEATURE_BLUE },
{ ROB_VAL_FEATURE_PITEXIT, RM_FEATURE_PITEXIT | RM_FEATURE_PENALTIES },
{ ROB_VAL_FEATURE_TIMEDSESSION, RM_FEATURE_TIMEDSESSION },
{ ROB_VAL_FEATURE_PENALTIES, RM_FEATURE_PENALTIES }
*/
};
static const int NRobotFeatures = sizeof(RobotFeatures) / sizeof(RobotFeatures[0]);
GfDriver::GfDriver(const std::string& strModName, int nItfIndex,
const std::string& strName, void* hparmRobot)
: _strModName(strModName), _strName(strName), _nItfIndex(nItfIndex), _bIsHuman(false), _pCar(0)
{
load(hparmRobot);
}
void GfDriver::load(void* hparmRobot)
{
std::ostringstream ossDrvSecPath;
ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/' << _nItfIndex;
// Humanity.
_bIsHuman =
strcmp(GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_TYPE, ROB_VAL_ROBOT),
ROB_VAL_ROBOT) != 0;
// Skill level.
const char* pszKillLevel =
GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO);
for(int nLevelInd = 0; nLevelInd < NbSkillLevels; nLevelInd++)
{
if (!strcmp(ASkillLevelStrings[nLevelInd], pszKillLevel))
{
_fSkillLevel = ASkillLevelValues[nLevelInd];
break;
}
}
// Supported features.
if (_bIsHuman)
{
_nFeatures = RM_FEATURE_TIMEDSESSION | RM_FEATURE_WETTRACK;
if (_fSkillLevel <= ASkillLevelValues[3]) // Pro (TODO: Create enum fro that !)
_nFeatures |= RM_FEATURE_PENALTIES;
}
else
{
_nFeatures = 0;
char* pszDrvFeatures =
strdup(GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_FEATURES, ""));
for (char* pszFeature = strtok(pszDrvFeatures, ";");
pszFeature != 0; pszFeature = strtok(NULL, ";"))
{
for (int nFeatInd = 0; nFeatInd < NRobotFeatures; nFeatInd++)
if (!strcmp(pszFeature, RobotFeatures[nFeatInd].pszName))
{
_nFeatures |= RobotFeatures[nFeatInd].nValue;
break;
}
}
free(pszDrvFeatures);
}
// Driven car.
const char* pszCarId = GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, "");
_pCar = GfCars::self()->getCar(pszCarId);
}
const std::string& GfDriver::getName() const
@ -345,25 +430,35 @@ bool GfDriver::matchesTypeAndCategory(const std::string& strType,
&& (strCarCatId.empty() || getCar()->getCategoryId() == strCarCatId);
}
void GfDriver::setName(const std::string& strName)
double GfDriver::getSkillLevel() const
{
_strName = strName;
return _fSkillLevel;
}
void GfDriver::setModuleName(const std::string& strModName)
int GfDriver::getSupportedFeatures() const
{
_strModName = strModName;
return _nFeatures;
}
void GfDriver::setInterfaceIndex(int nItfIndex)
{
_nItfIndex = nItfIndex;
}
// void GfDriver::setName(const std::string& strName)
// {
// _strName = strName;
// }
void GfDriver::setIsHuman(bool bIsHuman)
{
_bIsHuman = bIsHuman;
}
// void GfDriver::setModuleName(const std::string& strModName)
// {
// _strModName = strModName;
// }
// void GfDriver::setInterfaceIndex(int nItfIndex)
// {
// _nItfIndex = nItfIndex;
// }
// void GfDriver::setIsHuman(bool bIsHuman)
// {
// _bIsHuman = bIsHuman;
// }
void GfDriver::setCar(const GfCar* pCar)
{

View file

@ -61,10 +61,11 @@ class TGFDATA_API GfDriver
{
public:
GfDriver();
public:
GfDriver(const std::string& strModuleName, int nItfIndex,
const std::string& strName, void* hparmRobot);
void load(void* hparmRobot);
const std::string& getName() const;
const std::string& getModuleName() const;
int getInterfaceIndex() const;
@ -76,10 +77,14 @@ public:
bool matchesTypeAndCategory(const std::string& strType = "",
const std::string& strCarCatId = "") const;
void setName(const std::string& strName);
void setModuleName(const std::string& strModName);
void setInterfaceIndex(int nItfIndex);
void setIsHuman(bool bIsHuman);
int getSupportedFeatures() const;
double getSkillLevel() const;
// void setName(const std::string& strName);
// void setModuleName(const std::string& strModName);
// void setInterfaceIndex(int nItfIndex);
// void setIsHuman(bool bIsHuman);
void setCar(const GfCar* pCar);
void setSkin(const GfDriverSkin& skin);
@ -107,6 +112,9 @@ protected:
GfDriverSkin _skin; // Skin
mutable std::string _strType; // Type ~ module type (ex: "simplix", "usr")
double _fSkillLevel; // From 0 (pro) to 10 (rookie).
int _nFeatures; // Bit mask built with RM_FEATURE_*
};
class TGFDATA_API GfDrivers

View file

@ -22,80 +22,173 @@
#include <map>
#include <algorithm>
#include <raceman.h>
#include <robot.h>
#include <car.h>
#include "cars.h"
#include "drivers.h"
#include "tracks.h"
#include "racemanagers.h"
#include "race.h"
// Constants.
static const char *DispModeNames[GfRace::nDisplayModeNumber] =
{ RM_VAL_VISIBLE, RM_VAL_INVISIBLE};
static const char *TimeOfDaySpecNames[GfRace::nTimeSpecNumber] = RM_VALS_TIME;
static const char* CloudsSpecNames[GfRace::nCloudsSpecNumber] = RM_VALS_CLOUDS;
static const char *RainSpecNames[GfRace::nRainSpecNumber] = RM_VALS_RAIN;
// Private data for GfRace
class GfRace::Private
{
public:
Private() : hparmRace(0), nMaxCompetitors(0) {};
Private() : pRaceMan(0), pParameters(0), nMaxCompetitors(0), nFocusedItfIndex(-1) {};
public:
// The race params handle.
void* hparmRace;
// The "parent" race manager.
GfRaceManager* pRaceMan;
// Session type (like Qualification 1/2/3 ... Race ...)
std::string strSessionName;
// Race parameters.
Parameters* pParameters;
// Max authorized number of competitors.
unsigned nMaxCompetitors;
// One GfDriver pointer for each competitor (order = race starting grid).
std::vector<GfDriver*> vecCompetitors;
// TODO: Is this usefull ?
// Map for quick access to GfDriver by { module name, interface index }
typedef std::map<std::pair<std::string, int>, GfDriver*> TMapCompetitorsByKey;
TMapCompetitorsByKey mapCompetitorsByKey;
// Focused competitor (what for ?).
std::string strFocusedModuleName;
int nFocusedItfIndex;
};
GfRace::GfRace(void* hparmRace)
GfRace::GfRace()
{
_pPrivate = new GfRace::Private;
load(hparmRace);
}
void GfRace::clear()
{
_pPrivate->hparmRace = 0;
_pPrivate->pRaceMan = 0;
_pPrivate->nMaxCompetitors = 0;
_pPrivate->mapCompetitorsByKey.clear();
_pPrivate->vecCompetitors.clear();
}
void GfRace::load(void* hparmRace)
void GfRace::load(GfRaceManager* pRaceMan)
{
// Clear the race.
clear();
_pPrivate->hparmRace = hparmRace;
// Save the new race manager.
_pPrivate->pRaceMan = pRaceMan;
if (!_pPrivate->hparmRace)
// Check if usable, and exit if not.
if (!_pPrivate->pRaceMan)
return;
// Load data from the race params.
void* hparmRaceMan = pRaceMan->getDescriptorHandle();
if (!hparmRaceMan)
return;
// Load race parameters (from the "race config" configuration, if any).
// a) Search for the "race config" configuration.
std::ostringstream ossConfSecPath;
const char* pszSessionName = 0;
const int nbConfs = GfParmGetEltNb(hparmRaceMan, RM_SECT_CONF);
int nConfInd = 1;
while (nConfInd <= nbConfs)
{
ossConfSecPath.str("");
ossConfSecPath << RM_SECT_CONF << '/' << nConfInd;
const char* pszConfType =
GfParmGetStr(hparmRaceMan, ossConfSecPath.str().c_str(), RM_ATTR_TYPE, 0);
if (pszConfType && !strcmp(pszConfType, RM_VAL_RACECONF))
{
pszSessionName =
GfParmGetStr(hparmRaceMan, ossConfSecPath.str().c_str(), RM_ATTR_RACE, "Race");
break;
}
nConfInd++;
}
// b) If found, load the race parameters from it.
if (pszSessionName)
{
_pPrivate->pParameters = new Parameters;
_pPrivate->strSessionName = pszSessionName;
_pPrivate->pParameters->nLaps =
(int)GfParmGetNum(hparmRaceMan, pszSessionName, RM_ATTR_LAPS, NULL, 25);
_pPrivate->pParameters->nDistance =
(int)GfParmGetNum(hparmRaceMan, pszSessionName, RM_ATTR_DISTANCE, "km", 0);
_pPrivate->pParameters->nDuration =
(int)GfParmGetNum(hparmRaceMan, pszSessionName, RM_ATTR_SESSIONTIME, "s", 0);
_pPrivate->pParameters->eDisplayMode =
strcmp(GfParmGetStr(hparmRaceMan, pszSessionName, RM_ATTR_DISPMODE, RM_VAL_VISIBLE),
RM_VAL_INVISIBLE) ? eDisplayNormal : eDisplayResultsOnly;
const char* pszTimeOfDaySpec =
GfParmGetStr(hparmRaceMan, pszSessionName, RM_ATTR_TIME_OF_DAY, RM_VAL_TIME_AFTERNOON);
for (int i = 0; i < nTimeSpecNumber; i++)
if (!strcmp(pszTimeOfDaySpec, TimeOfDaySpecNames[i]))
{
_pPrivate->pParameters->eTimeOfDaySpec = (ETimeOfDaySpec)i;
break;
}
const char* pszCloudsSpec =
GfParmGetStr(hparmRaceMan, pszSessionName, RM_ATTR_CLOUDS, RM_VAL_CLOUDS_NONE);
for (int i = 0; i < nCloudsSpecNumber; i++)
if (!strcmp(pszCloudsSpec, CloudsSpecNames[i]))
{
_pPrivate->pParameters->eCloudsSpec = (ECloudsSpec)i;
break;
}
const char* pszRainSpec =
GfParmGetStr(hparmRaceMan, pszSessionName, RM_ATTR_RAIN, RM_VAL_RAIN_NONE);
for (int i = 0; i < nRainSpecNumber; i++)
if (!strcmp(pszRainSpec, RainSpecNames[i]))
{
_pPrivate->pParameters->eRainSpec = (ERainSpec)i;
break;
}
}
// Load competitors data from the raceman params.
_pPrivate->vecCompetitors.clear();
_pPrivate->mapCompetitorsByKey.clear();
_pPrivate->nMaxCompetitors =
(unsigned)GfParmGetNum(_pPrivate->hparmRace, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0);
const int nCompetitors = GfParmGetEltNb(_pPrivate->hparmRace, RM_SECT_DRIVERS);
GfLogDebug("Competitors : n=%d (max=%d)\n", nCompetitors, _pPrivate->nMaxCompetitors);
(unsigned)GfParmGetNum(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0);
const int nCompetitors = GfParmGetEltNb(hparmRaceMan, RM_SECT_DRIVERS);
std::ostringstream ossDrvSecPath;
for (int nCompIndex = 1; nCompIndex < nCompetitors+1; nCompIndex++)
{
// Get driver infos from the the starting grid in the race params file
std::ostringstream ossSectionPath;
ossSectionPath << RM_SECT_DRIVERS << '/' << nCompIndex;
// Get driver infos from the the starting grid in the race params file.
ossDrvSecPath.str("");
ossDrvSecPath << RM_SECT_DRIVERS << '/' << nCompIndex;
const char* pszModName =
GfParmGetStr(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_MODULE, "");
GfParmGetStr(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_MODULE, "");
const int nItfIndex =
(int)GfParmGetNum(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_IDX, NULL, 0);
(int)GfParmGetNum(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_IDX, NULL, 0);
GfLogDebug("Competitor #%d : %s#%d\n", nCompIndex, pszModName, nItfIndex);
//GfLogDebug("Competitor #%d : %s#%d\n", nCompIndex, pszModName, nItfIndex);
// Try and retrieve this driver among all the available drivers
GfDriver* pCompetitor = GfDrivers::self()->getDriver(pszModName, nItfIndex);
@ -111,26 +204,22 @@ void GfRace::load(void* hparmRace)
if (acceptsMoreCompetitors())
{
const char* pszSkinName =
GfParmGetStr(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_SKINNAME, "");
GfParmGetStr(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_SKINNAME, "");
const int nSkinTargets =
(int)GfParmGetNum(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_SKINTARGETS, NULL, 0);
(int)GfParmGetNum(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_SKINTARGETS, NULL, 0);
const bool bExtended =
GfParmGetNum(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_EXTENDED, NULL, 0)
GfParmGetNum(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_EXTENDED, NULL, 0)
? true : false;
GfLogDebug(" Name = %s, ext=%d\n",
pCompetitor->getName().c_str(), bExtended ? 1 : 0);
// Get the chosen car for the race if any specified (human only).
const GfCar* pCar = 0;
if (pCompetitor->isHuman() && bExtended)
{
ossSectionPath.str("");
ossSectionPath << RM_SECT_DRIVERINFO << '/' << pszModName
ossDrvSecPath.str("");
ossDrvSecPath << RM_SECT_DRIVERINFO << '/' << pszModName
<< '/' << (bExtended ? 1 : 0) << '/' << nItfIndex;
const char* pszCarId =
GfParmGetStr(hparmRace, ossSectionPath.str().c_str(), RM_ATTR_CARNAME, 0);
GfLogDebug(" Extended && Human, %s : %s\n", ossSectionPath.str().c_str(), pszCarId);
GfParmGetStr(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_CARNAME, 0);
pCar = GfCars::self()->getCar(pszCarId);
if (!pCar)
GfLogError("Falling back to default car '%s' "
@ -156,12 +245,50 @@ void GfRace::load(void* hparmRace)
break;
}
}
// Load focused competitor data from the raceman params.
_pPrivate->strFocusedModuleName =
GfParmGetStr(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
_pPrivate->nFocusedItfIndex =
(int)GfParmGetNum(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0);
}
void GfRace::save()
{
if (!_pPrivate->pRaceMan)
return;
void* hparmRaceMan = _pPrivate->pRaceMan->getDescriptorHandle();
if (!hparmRaceMan)
return;
// Save race manager level data.
_pPrivate->pRaceMan->save();
// Save race session and associated parameters.
if (_pPrivate->pParameters)
{
const Parameters* pParams = _pPrivate->pParameters;
const char* pszSessionName = _pPrivate->strSessionName.c_str();
GfParmSetNum(hparmRaceMan, pszSessionName, RM_ATTR_LAPS,
(char*)NULL, (tdble)pParams->nLaps);
GfParmSetNum(hparmRaceMan, pszSessionName, RM_ATTR_DISTANCE,
"km", (tdble)pParams->nDistance);
GfParmSetNum(hparmRaceMan, pszSessionName, RM_ATTR_SESSIONTIME,
"s", (tdble)pParams->nDuration);
GfParmSetStr(hparmRaceMan, pszSessionName, RM_ATTR_DISPMODE,
DispModeNames[pParams->eDisplayMode]);
GfParmSetStr(hparmRaceMan, pszSessionName, RM_ATTR_TIME_OF_DAY,
TimeOfDaySpecNames[pParams->eTimeOfDaySpec]);
GfParmSetStr(hparmRaceMan, pszSessionName, RM_ATTR_CLOUDS,
CloudsSpecNames[pParams->eCloudsSpec]);
GfParmSetStr(hparmRaceMan, pszSessionName, RM_ATTR_RAIN,
RainSpecNames[pParams->eRainSpec]);
}
// Clear the race starting grid.
GfParmListClean(_pPrivate->hparmRace, RM_SECT_DRIVERS);
GfParmListClean(hparmRaceMan, RM_SECT_DRIVERS);
// And then rebuild it from the current Competitors list state
// (for each competitor, module name, interface index, car name if human,
@ -170,39 +297,39 @@ void GfRace::save()
for (itComp = _pPrivate->vecCompetitors.begin();
itComp != _pPrivate->vecCompetitors.end(); itComp++)
{
std::ostringstream ossSectionPath;
ossSectionPath << RM_SECT_DRIVERS
std::ostringstream ossDrvSecPath;
ossDrvSecPath << RM_SECT_DRIVERS
<< '/' << (unsigned)(itComp - _pPrivate->vecCompetitors.begin() + 1);
const std::string strDrvSec(ossSectionPath.str());
const std::string strDrvSec(ossDrvSecPath.str());
GfParmSetNum(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_IDX, (char*)NULL,
GfParmSetNum(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_IDX, (char*)NULL,
(tdble)(*itComp)->getInterfaceIndex());
GfParmSetStr(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_MODULE,
GfParmSetStr(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_MODULE,
(*itComp)->getModuleName().c_str());
const GfCar* pCar = (*itComp)->getCar();
if (pCar && (*itComp)->isHuman())
{
/* Set extended */
GfParmSetNum(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_EXTENDED, NULL, 1);
GfParmSetNum(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_EXTENDED, NULL, 1);
ossSectionPath.str("");
ossSectionPath << RM_SECT_DRIVERINFO << '/' << (*itComp)->getModuleName()
ossDrvSecPath.str("");
ossDrvSecPath << RM_SECT_DRIVERINFO << '/' << (*itComp)->getModuleName()
<< '/' << 1 /*extended*/ << '/' << (*itComp)->getInterfaceIndex();
GfParmSetStr(_pPrivate->hparmRace, ossSectionPath.str().c_str(), RM_ATTR_CARNAME,
GfParmSetStr(hparmRaceMan, ossDrvSecPath.str().c_str(), RM_ATTR_CARNAME,
pCar->getId().c_str());
// Save also the chosen car as the default one for this human driver
// (may be needed later for races where it is not specified in <race>.xml)
std::ostringstream ossFilePath;
ossFilePath << GfLocalDir() << "drivers/" << (*itComp)->getModuleName()
ossFilePath << GetLocalDir() << "drivers/" << (*itComp)->getModuleName()
<< '/' << (*itComp)->getModuleName() << PARAMEXT;
void* hparmRobot = GfParmReadFile(ossFilePath.str().c_str(), GFPARM_RMODE_STD);
ossSectionPath.str("");
ossSectionPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX
ossDrvSecPath.str("");
ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX
<< '/' << (*itComp)->getInterfaceIndex();
GfParmSetStr(hparmRobot, ossSectionPath.str().c_str(), ROB_ATTR_CAR,
GfParmSetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR,
pCar->getId().c_str());
GfParmWriteFile(NULL, hparmRobot, (*itComp)->getModuleName().c_str());
GfParmReleaseHandle(hparmRobot);
@ -210,18 +337,57 @@ void GfRace::save()
else
{
/* Not extended for robots yet in driverconfig */
GfParmSetNum(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_EXTENDED, NULL, 0);
GfParmSetNum(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_EXTENDED, NULL, 0);
}
// Skin and skin targets.
const GfDriverSkin& skin = (*itComp)->getSkin();
GfParmSetNum(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_SKINTARGETS, (char*)NULL,
GfParmSetNum(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_SKINTARGETS, NULL,
(tdble)skin.getTargets());
if ((!skin.getName().empty())
|| GfParmGetStr(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_SKINNAME, 0))
GfParmSetStr(_pPrivate->hparmRace, strDrvSec.c_str(), RM_ATTR_SKINNAME,
|| GfParmGetStr(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_SKINNAME, 0))
GfParmSetStr(hparmRaceMan, strDrvSec.c_str(), RM_ATTR_SKINNAME,
skin.getName().c_str());
}
// Save focused competitor data to the raceman params.
const GfDriver* pFocComp = getFocusedCompetitor();
GfParmSetStr(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSED,
_pPrivate->strFocusedModuleName.c_str());
GfParmSetNum(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL,
(tdble)_pPrivate->nFocusedItfIndex);
}
GfRaceManager* GfRace::getManager() const
{
return _pPrivate->pRaceMan;
}
const std::string& GfRace::getSessionName() const
{
return _pPrivate->strSessionName;
}
GfRace::Parameters* GfRace::getParameters()
{
return _pPrivate->pParameters;
}
int GfRace::getSupportedFeatures() const
{
int nFeatures = 0;
std::vector<GfDriver*>::const_iterator itComp;
for (itComp = _pPrivate->vecCompetitors.begin();
itComp != _pPrivate->vecCompetitors.end(); itComp++)
{
if (itComp == _pPrivate->vecCompetitors.begin())
nFeatures = (*itComp)->getSupportedFeatures();
else
nFeatures &= (*itComp)->getSupportedFeatures();
}
return nFeatures;
}
const std::vector<GfDriver*>& GfRace::getCompetitors() const
@ -242,7 +408,7 @@ bool GfRace::acceptsMoreCompetitors() const
GfDriver* GfRace::getCompetitor(const std::string& strModName, int nItfIndex) const
{
const std::pair<std::string, int> compKey(strModName, nItfIndex);
Private::TMapCompetitorsByKey::iterator itComp;
Private::TMapCompetitorsByKey::iterator itComp =
_pPrivate->mapCompetitorsByKey.find(compKey);
if (itComp != _pPrivate->mapCompetitorsByKey.end())
return itComp->second;
@ -250,6 +416,23 @@ GfDriver* GfRace::getCompetitor(const std::string& strModName, int nItfIndex) co
return 0;
}
bool GfRace::isCompetitorFocused(const GfDriver* pComp) const
{
return _pPrivate->strFocusedModuleName == pComp->getModuleName()
&& _pPrivate->nFocusedItfIndex == pComp->getInterfaceIndex();
}
GfDriver* GfRace::getFocusedCompetitor() const
{
return getCompetitor(_pPrivate->strFocusedModuleName, _pPrivate->nFocusedItfIndex);
}
void GfRace::setFocusedCompetitor(const GfDriver* pComp)
{
_pPrivate->strFocusedModuleName = pComp ? pComp->getModuleName() : "";
_pPrivate->nFocusedItfIndex = pComp ? pComp->getInterfaceIndex() : -1;
}
bool GfRace::appendCompetitor(GfDriver* pComp)
{
const bool bAppended = acceptsMoreCompetitors();
@ -358,3 +541,20 @@ bool GfRace::shuffleCompetitors()
return true;
}
GfTrack* GfRace::getTrack() const
{
return _pPrivate->pRaceMan ? _pPrivate->pRaceMan->getCurrentEventTrack() : 0;
}
void GfRace::setTrack(GfTrack* pTrack)
{
if (_pPrivate->pRaceMan && pTrack)
_pPrivate->pRaceMan->setCurrentEventTrack(pTrack);
}
void GfRace::print() const
{
// TODO.
GfLogWarning("GfTrack::print() not yet implemented\n");
}

View file

@ -32,23 +32,55 @@
#include "tgfdata.h"
class GfRaceManager;
class GfDriver;
class GfTrack;
class TGFDATA_API GfRace
{
public:
GfRace(void* hparmRace = 0);
//! Constructor.
GfRace();
//! Load from the race params.
void load(void* hparmRace);
//! Load from the given race manager params file.
void load(GfRaceManager* pRaceMan);
//! Clear the race.
void clear();
//! Save to the race params.
//! Save to the race manager params file.
void save();
GfRaceManager* getManager() const;
const std::string& getSessionName() const;
enum EDisplayMode { eDisplayNormal, eDisplayResultsOnly,
nDisplayModeNumber };
enum ETimeOfDaySpec { eTimeDawn, eTimeMorning, eTimeNoon, eTimeAfternoon,
eTimeDusk, eTimeNight, eTimeNow, eTimeFromTrack,
nTimeSpecNumber };
enum ECloudsSpec { eCloudsNone, eCloudsFew, eCloudsScarce, eCloudsMany, eCloudsFull,
nCloudsSpecNumber};
enum ERainSpec { eRainNone, eRainLittle, eRainMedium, eRainHeavy, eRainRandom,
nRainSpecNumber };
class Parameters
{
public:
int nLaps;
int nDistance; // km
int nDuration; // s
EDisplayMode eDisplayMode;
ETimeOfDaySpec eTimeOfDaySpec;
ECloudsSpec eCloudsSpec;
ERainSpec eRainSpec;
};
Parameters* getParameters();
int getSupportedFeatures() const;
unsigned getCompetitorsCount() const;
const std::vector<GfDriver*>& getCompetitors() const;
@ -60,14 +92,15 @@ public:
bool shuffleCompetitors();
GfDriver* getCompetitor(const std::string& strModName, int nItfIndex) const;
// GfDriver* getCompetitorWithName(const std::string& strName) const;
// const std::string& getCompetitorName(const std::string& strId) const;
// std::vector<GfDriver*> getCompetitorsInCategory(const std::string& strCatId = "") const;
// std::vector<std::string> getCompetitorIdsInCategory(const std::string& strCatId = "") const;
// std::vector<std::string> getCompetitorIdsInCategory(const std::string& strCatId = "") const;
bool isCompetitorFocused(const GfDriver* pComp) const;
GfDriver* getFocusedCompetitor() const;
void setFocusedCompetitor(const GfDriver* pComp);
GfTrack* getTrack() const;
void setTrack(GfTrack* pTrack);
// void print() const;
void print() const;
protected:

View file

@ -23,6 +23,7 @@
#include <raceman.h>
#include "tracks.h"
#include "racemanagers.h"
@ -99,7 +100,6 @@ GfRaceManagers::GfRaceManagers()
}
}
//const std::string strRaceManId(pFile->name, strlen(pFile->name) - strlen(PARAMEXT));
std::string strRaceManId(pFile->name);
strRaceManId.erase(strlen(pFile->name) - strlen(PARAMEXT));
if (!hparmRaceMan)
@ -109,14 +109,8 @@ GfRaceManagers::GfRaceManagers()
continue;
}
// Read race manager info and store it in the GfRaceManager structure.
GfRaceManager* pRaceMan = new GfRaceManager;
pRaceMan->setId(strRaceManId);
pRaceMan->setName(GfParmGetStr(hparmRaceMan, RM_SECT_HEADER, RM_ATTR_NAME, "<unknown>"));
pRaceMan->setType(GfParmGetStr(hparmRaceMan, RM_SECT_HEADER, RM_ATTR_TYPE, "<unknown>"));
pRaceMan->setSubType(GfParmGetStr(hparmRaceMan, RM_SECT_HEADER, RM_ATTR_SUBTYPE, ""));
pRaceMan->setPriority((int)GfParmGetNum(hparmRaceMan, RM_SECT_HEADER, RM_ATTR_PRIO, NULL, 10000));
pRaceMan->setDescriptorHandle(hparmRaceMan);
// Create the race manager and load it from the params file.
GfRaceManager* pRaceMan = new GfRaceManager(strRaceManId, hparmRaceMan);
// Update the GfRaceManagers singleton.
_pPrivate->vecRaceMans.push_back(pRaceMan);
@ -132,6 +126,7 @@ GfRaceManagers::GfRaceManagers()
// Sort the race manager vector by priority.
std::sort(_pPrivate->vecRaceMans.begin(), _pPrivate->vecRaceMans.end(), hasHigherPriority);
// And log what we've got now.
print();
}
@ -161,7 +156,7 @@ GfRaceManager* GfRaceManagers::getRaceManagerWithName(const std::string& strName
return 0;
}
const std::vector<GfRaceManager*> GfRaceManagers::getRaceManagersWithType(const std::string& strType) const
std::vector<GfRaceManager*> GfRaceManagers::getRaceManagersWithType(const std::string& strType) const
{
std::vector<GfRaceManager*> vecRaceMans;
@ -193,15 +188,94 @@ void GfRaceManagers::print() const
// GfRaceManager class ---------------------------------------------------------------
GfRaceManager::GfRaceManager() : _nPriority(-1), _hparmHandle(0)
GfRaceManager::GfRaceManager(const std::string& strId, void* hparmHandle)
{
_strId = strId;
// Load constant properties (never changed afterwards).
_strName = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_NAME, "<unknown>");
_strType = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_TYPE, "<unknown>");
_strSubType = GfParmGetStr(hparmHandle, RM_SECT_HEADER, RM_ATTR_SUBTYPE, "");
_nPriority = (int)GfParmGetNum(hparmHandle, RM_SECT_HEADER, RM_ATTR_PRIO, NULL, 10000);
// Load other "mutable" properties.
reset(hparmHandle, false);
}
void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
{
if (bClosePrevHdle && _hparmHandle)
GfParmReleaseHandle(_hparmHandle);
_hparmHandle = hparmHandle;
// Get current event in the schedule.
_nCurrentEventInd =
(int)GfParmGetNum(_hparmHandle, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL, 1) - 1;
// Load track id for each event in the schedule.
std::ostringstream ossSectionPath;
int nEventNum = 1;
const char* pszTrackId;
do
{
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventNum;
pszTrackId = GfParmGetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME, 0);
if (pszTrackId)
{
_vecEventTrackIds.push_back(pszTrackId);
nEventNum++;
}
}
while (pszTrackId);
}
void GfRaceManager::save()
{
if (!_hparmHandle)
return;
// Note: No need to save constant properties (never changed).
// Current event in the schedule.
GfParmSetNum(_hparmHandle, RM_SECT_TRACKS, RE_ATTR_CUR_TRACK, NULL,
(tdble)(_nCurrentEventInd + 1));
// Info about each event in the schedule.
std::ostringstream ossSectionPath;
for (unsigned nEventInd = 0; nEventInd < _vecEventTrackIds.size(); nEventInd++)
{
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventInd + 1;
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME,
_vecEventTrackIds[nEventInd].c_str());
GfTrack* pTrack = GfTracks::self()->getTrack(_vecEventTrackIds[nEventInd]);
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_CATEGORY,
pTrack->getCategoryId().c_str());
}
}
GfRaceManager::~GfRaceManager()
{
if (_hparmHandle)
GfParmReleaseHandle(_hparmHandle);
}
const std::string& GfRaceManager::getId() const
{
return _strId;
}
void* GfRaceManager::getDescriptorHandle() const
{
return _hparmHandle;
}
std::string GfRaceManager::getDescriptorFileName() const
{
return const_cast<const char*>(GfParmGetFileName(_hparmHandle));
}
const std::string& GfRaceManager::getName() const
{
return _strName;
@ -222,38 +296,37 @@ const int GfRaceManager::getPriority() const
return _nPriority;
}
void* GfRaceManager::getDescriptorHandle() const
unsigned GfRaceManager::getEventCount() const
{
return _hparmHandle;
return _vecEventTrackIds.size();
}
void GfRaceManager::setId(const std::string& strId)
bool GfRaceManager::stepToNextEvent()
{
_strId = strId;
if (_nCurrentEventInd < (int)_vecEventTrackIds.size() - 1)
{
_nCurrentEventInd++;
return true;
}
return false;
}
void GfRaceManager::setName(const std::string& strName)
GfTrack* GfRaceManager::getCurrentEventTrack()
{
_strName = strName;
GfTrack* pTrack;
// If the current event track is not usable, step to the next event (an so on).
while (!(pTrack = GfTracks::self()->getTrack(_vecEventTrackIds[_nCurrentEventInd]))
&& stepToNextEvent());
return pTrack;
}
void GfRaceManager::setType(const std::string& strType)
void GfRaceManager::setCurrentEventTrack(GfTrack* pTrack)
{
_strType = strType ;
}
if (!pTrack)
return;
void GfRaceManager::setSubType(const std::string& strSubType)
{
_strSubType = strSubType;
_vecEventTrackIds[_nCurrentEventInd] = pTrack->getId();
}
void GfRaceManager::setPriority(int nPriority)
{
_nPriority = nPriority;
}
void GfRaceManager::setDescriptorHandle(void* hparmHandle)
{
_hparmHandle = hparmHandle;
}

View file

@ -25,6 +25,8 @@
#include "tgfdata.h"
class GfTrack;
/** @file
Singleton holding information on the available race managers
@ -35,33 +37,40 @@ class TGFDATA_API GfRaceManager
{
public:
GfRaceManager();
public:
GfRaceManager(const std::string& strId, void* hparmHandle);
void reset(void* hparmHandle, bool bClosePrevHdle = false);
~GfRaceManager();
const std::string& getId() const;
void* getDescriptorHandle() const;
std::string getDescriptorFileName() const;
const std::string& getName() const;
const std::string& getType() const;
const std::string& getSubType() const;
const int getPriority() const;
void* getDescriptorHandle() const;
void setId(const std::string& strId);
void setName(const std::string& strName);
void setType(const std::string& strType);
void setSubType(const std::string& strSubType);
void setPriority(int nPriority);
void setDescriptorHandle(void* hparmHandle);
unsigned getEventCount() const;
bool stepToNextEvent();
GfTrack* getCurrentEventTrack();
void setCurrentEventTrack(GfTrack* pTrack);
//! Save data to params (in-memory).
void save();
protected:
std::string _strId; // XML file name (ex: quickrace, singleevent-endurance, championship-sc)
void* _hparmHandle; // Params handle to the descriptor file.
std::string _strName; // User friendly full name (ex: Quick Race, Supercar Championship).
std::string _strType; // User friendly type name (ex: Quick Race, Single Event, Championship).
std::string _strSubType; // User friendly sub-type name (ex: "", Endurance, Challenge, Supercars").
std::string _strDescFile; // Path-name of the XML descriptor file.
int _nPriority; // Gives the order of the buttons in the race select menu
void* _hparmHandle; // Params handle to the descriptor file.
std::vector<std::string> _vecEventTrackIds; // Id of the track for each event.
int _nCurrentEventInd;
};
class TGFDATA_API GfRaceManagers
@ -76,7 +85,7 @@ public:
GfRaceManager* getRaceManager(const std::string& strId) const;
GfRaceManager* getRaceManagerWithName(const std::string& strName) const;
const std::vector<GfRaceManager*> getRaceManagersWithType(const std::string& strType = "") const;
std::vector<GfRaceManager*> getRaceManagersWithType(const std::string& strType = "") const;
void print() const;

View file

@ -36,6 +36,11 @@
# define TGFDATA_API
#endif
#ifdef _MSC_VER
// Disable useless MSVC warnings
# pragma warning (disable:4251) // class XXX needs a DLL interface ...
#endif
#endif /* __TGFDATA__H__ */

View file

@ -278,6 +278,121 @@ std::vector<std::string> GfTracks::getTrackNamesInCategory(const std::string& st
return vecTrackNames;
}
/**
* GfTracks::getFirstUsableTrack
*
* Retrieve the first usable track in the given category, searching in the given direction
* and skipping the first found if specified
*
* @param strCatId Id of the category to search inside of.
* @param strFromTrackId Id of the track from which to start the search.
* @param nSearchDir <0 = previous, >0 = next.
* @param bSkipFrom If true, skip the first found track.
*/
GfTrack* GfTracks::getFirstUsableTrack(const std::string& strCatId,
const std::string& strFromTrackId,
int nSearchDir, bool bSkipFrom) const
{
// Check and fix nSearchDir.
nSearchDir = nSearchDir > 0 ? +1 : -1;
// Check category.
if (std::find(_pPrivate->vecCatIds.begin(), _pPrivate->vecCatIds.end(), strCatId)
== _pPrivate->vecCatIds.end())
{
GfLogError("GfTracks::getFirstUsableTrack : No such category %s\n", strCatId.c_str());
return 0;
}
// Retrieve tracks in this category.
const std::vector<GfTrack*> vecTracksInCat = getTracksInCategory(strCatId);
if (vecTracksInCat.size() == 0)
{
// Should never happen, empty categories are not even created ...
GfLogError("GfTracks::getFirstUsableTrack : Empty category %s\n", strCatId.c_str());
return 0;
}
// Retrieve the index of the specified track to start from, if any.
int nCurTrackInd = 0;
if (!strFromTrackId.empty())
{
std::vector<GfTrack*>::const_iterator itTrack = vecTracksInCat.begin();
while (itTrack != vecTracksInCat.end())
{
if ((*itTrack)->getId() == strFromTrackId)
{
nCurTrackInd = itTrack - vecTracksInCat.begin();
break;
}
itTrack++;
}
}
int nTrackInd = nCurTrackInd;
if (bSkipFrom || !vecTracksInCat[nTrackInd]->isUsable())
{
const int nPrevTrackInd = nCurTrackInd;
do
{
nTrackInd =
(nTrackInd + nSearchDir + vecTracksInCat.size()) % vecTracksInCat.size();
}
while (nTrackInd != nPrevTrackInd && !vecTracksInCat[nTrackInd]->isUsable());
}
GfTrack* pTrack = 0;
if (vecTracksInCat[nTrackInd]->isUsable())
pTrack = vecTracksInCat[nTrackInd];
return pTrack;
}
/**
* GfTracks::getFirstUsableTrack
*
* Retrieve the first usable track among all categories, searching in the given direction
* from the given category, but skipping it if specified
*
* @param strFromCatId Id of the category to search inside of.
* @param nSearchDir <0 = previous, >0 = next.
* @param bSkipFrom If true, skip the first found track.
*/
GfTrack* GfTracks::getFirstUsableTrack(const std::string& strFromCatId,
int nSearchDir, bool bSkipFrom) const
{
// Check and fix nSearchDir.
nSearchDir = nSearchDir > 0 ? +1 : -1;
// Retrieve and check category.
const std::vector<std::string>& vecCatIds = GfTracks::self()->getCategoryIds();
std::vector<std::string>::const_iterator itFromCat =
std::find(_pPrivate->vecCatIds.begin(), _pPrivate->vecCatIds.end(), strFromCatId);
if (itFromCat == _pPrivate->vecCatIds.end())
{
GfLogError("GfTracks::getFirstUsableTrack : No such category %s\n", strFromCatId.c_str());
return 0;
}
int nCatInd = itFromCat - _pPrivate->vecCatIds.begin();
GfTrack* pTrack = 0;
if (bSkipFrom || !(pTrack = getFirstUsableTrack(_pPrivate->vecCatIds[nCatInd])))
{
const int nPrevCatInd = nCatInd;
do
{
nCatInd =
(nCatInd + nSearchDir + _pPrivate->vecCatIds.size()) % _pPrivate->vecCatIds.size();
pTrack = getFirstUsableTrack(_pPrivate->vecCatIds[nCatInd]);
}
while (nCatInd != nPrevCatInd && !pTrack);
}
return pTrack;
}
void GfTracks::print(bool bVerbose) const
{
GfLogTrace("Track base : %d categories, %d tracks\n",

View file

@ -113,6 +113,12 @@ public:
std::vector<std::string> getTrackIdsInCategory(const std::string& strCatId = "") const;
std::vector<std::string> getTrackNamesInCategory(const std::string& strCatId = "") const;
GfTrack* getFirstUsableTrack(const std::string& strCatId,
const std::string& strFromTrackId = "",
int nSearchDir = +1, bool bSkipFrom = false) const;
GfTrack* getFirstUsableTrack(const std::string& strFromCatId,
int nSearchDir, bool bSkipFrom = false) const;
void print(bool bVerbose = false) const;
protected: