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:
parent
80caa830df
commit
854364e933
27 changed files with 1168 additions and 747 deletions
|
@ -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()
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <racescreens.h>
|
||||
#include <network.h>
|
||||
|
||||
#include "raceutil.h" // RmGetFeaturesList
|
||||
#include "racesituation.h"
|
||||
#include "racecareer.h"
|
||||
#include "raceinit.h"
|
||||
|
|
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
#include <cstdio>
|
||||
|
||||
#include <tgfclient.h>
|
||||
|
||||
#include <raceman.h>
|
||||
|
||||
#include <racescreens.h>
|
||||
|
||||
#include "racesituation.h"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
34
src/libs/raceengineclient/raceutil.h
Normal file
34
src/libs/raceengineclient/raceutil.h
Normal 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_ */
|
||||
|
||||
|
||||
|
|
@ -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()
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue