Re #99 Driver select menu : Category filter follow the last human driver car choice, even after changing car + display user friendly category names (except in the picked driver infos)

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

Former-commit-id: 27a3670f44b8d876d2d997b875b7a2db0ae7c7a0
Former-commit-id: 4d1cea6c2caa3f469f1a5e96859e55cca9a8b09d
This commit is contained in:
pouillot 2010-11-20 17:14:57 +00:00
parent d0f622abd0
commit f4fa156640
8 changed files with 288 additions and 175 deletions

View file

@ -97,7 +97,7 @@ bool HostSettingsMenu::Init(void* pMenu)
CreateStaticControls();
int carCatId = CreateComboboxControl("carcatcombobox",NULL,CarControlCB);
const std::vector<std::string> vecCategories = CarInfo::self()->GetCategoryNames();
const std::vector<std::string>& vecCategories = CarInfo::self()->GetCategoryNames();
int CatIndex = 0;
for (unsigned int i=0;i<vecCategories.size();i++)

View file

@ -33,7 +33,7 @@
void RmCarSelectMenu::onActivateCB(void *pCarSelectMenu)
{
//GfLogDebug("RmCarSelectMenu::onActivateCB\n");
GfLogTrace("Entering Car Select menu\n");
// Get the RmCarSelectMenu instance.
RmCarSelectMenu* pMenu = static_cast<RmCarSelectMenu*>(pCarSelectMenu);
@ -42,11 +42,8 @@ void RmCarSelectMenu::onActivateCB(void *pCarSelectMenu)
// (use the 1st one from the 1st category if none).
CarData* pCurCar = CarInfo::self()->GetCarData(pMenu->getDriver()->carName);
if (!pCurCar)
pCurCar = &CarInfo::self()->GetCarsInCategory(CarInfo::self()->GetCategoryNames()[0])[0];
pCurCar = CarInfo::self()->GetCarsInCategory(CarInfo::self()->GetCategoryNames()[0])[0];
// Store current car params handle.
pMenu->setSelectedCarParamsHandle(pMenu->getDriver()->carParmHdle);
// Get currently selected skin name for the current driver.
const char* pszCurSkinName =
pMenu->getDriver()->skinName ? pMenu->getDriver()->skinName : rmdStdSkinName;
@ -54,8 +51,8 @@ void RmCarSelectMenu::onActivateCB(void *pCarSelectMenu)
// Initialize the GUI contents.
GfuiLabelSetText(pMenu->GetMenuHandle(), pMenu->GetDynamicControlId("drivernamelabel"),
pMenu->getDriver()->name);
pMenu->resetCarCategoryComboBox(pCurCar->strCategoryName);
pMenu->resetCarModelComboBox(pCurCar->strCategoryName, pCurCar->strRealName);
pMenu->resetCarCategoryComboBox(pCurCar->strCategoryRealName);
pMenu->resetCarModelComboBox(pCurCar->strCategoryRealName, pCurCar->strRealName);
pMenu->resetCarDataSheet(pCurCar->strName);
pMenu->resetCarSkinComboBox(pCurCar->strRealName, pszCurSkinName);
pMenu->resetCarPreviewImage(pszCurSkinName);
@ -146,21 +143,33 @@ void RmCarSelectMenu::onAcceptCB(void *pCarSelectMenu)
}
pMenu->getDriver()->skinTargets = pMenu->getSelectedCarSkinTargets();
// Save car choice into the driver structure (only human drivers can change it).
// Save car choice into the driver structure if any change
// (only human drivers can change it).
if (pMenu->getDriver()->isHuman)
{
const CarData* pNewCar = pMenu->getSelectedCarModel();
// Car name.
const char* pszOldCarName = pMenu->getDriver()->carName;
const char* pszNewCarName = pMenu->getSelectedCarModel()->strName.c_str();
const char* pszNewCarName = pNewCar->strName.c_str();
if (pszNewCarName && (!pszOldCarName || strcmp(pszOldCarName, pszNewCarName)))
{
if (pszOldCarName)
if (pMenu->getDriver()->carName)
free(pMenu->getDriver()->carName);
pMenu->getDriver()->carName = strdup(pszNewCarName);
}
// Car XML file.
pMenu->getDriver()->carParmHdle = pMenu->getSelectedCarParamsHandle();
// Car real name.
if (pMenu->getDriver()->carRealName)
free(pMenu->getDriver()->carRealName);
const char* pszNewCarRealName = pNewCar->strRealName.c_str();
pMenu->getDriver()->carRealName = strdup(pszNewCarRealName);
// Car category.
if (pMenu->getDriver()->carCategory)
free(pMenu->getDriver()->carCategory);
const char* pszNewCarCatName = pNewCar->strCategoryName.c_str();
pMenu->getDriver()->carCategory = strdup(pszNewCarCatName);
}
}
// Back to previous screen.
@ -177,11 +186,11 @@ void RmCarSelectMenu::onCancelCB(void *pCarSelectMenu)
}
RmCarSelectMenu::RmCarSelectMenu()
: GfuiMenuScreen("carselectmenu.xml"), _nCurSkinIndex(0), _pDriver(0), _hCarParams(0)
: GfuiMenuScreen("carselectmenu.xml"), _nCurSkinIndex(0), _pDriver(0)
{
}
void RmCarSelectMenu::resetCarCategoryComboBox(const std::string& strSelectedCategoryName)
void RmCarSelectMenu::resetCarCategoryComboBox(const std::string& strSelectedCategoryRealName)
{
const int nCategoryComboId = GetDynamicControlId("categorycombo");
@ -189,15 +198,15 @@ void RmCarSelectMenu::resetCarCategoryComboBox(const std::string& strSelectedCat
GfuiEnable(GetMenuHandle(), nCategoryComboId, getDriver()->isHuman ? GFUI_ENABLE : GFUI_DISABLE);
// Retrieve the available car categories.
const std::vector<std::string> vecCatNames = CarInfo::self()->GetCategoryNames();
const std::vector<std::string>& vecCatRealNames = CarInfo::self()->GetCategoryRealNames();
// Load the combo-box from their names (and determine the requested category index).
unsigned nCurrentCategoryIndex = 0;
GfuiComboboxClear(GetMenuHandle(), nCategoryComboId);
for (unsigned nCatIndex = 0; nCatIndex < vecCatNames.size(); nCatIndex++)
for (unsigned nCatIndex = 0; nCatIndex < vecCatRealNames.size(); nCatIndex++)
{
GfuiComboboxAddText(GetMenuHandle(), nCategoryComboId, vecCatNames[nCatIndex].c_str());
if (!strSelectedCategoryName.empty() && vecCatNames[nCatIndex] == strSelectedCategoryName)
GfuiComboboxAddText(GetMenuHandle(), nCategoryComboId, vecCatRealNames[nCatIndex].c_str());
if (!strSelectedCategoryRealName.empty() && vecCatRealNames[nCatIndex] == strSelectedCategoryRealName)
nCurrentCategoryIndex = nCatIndex;
}
@ -205,10 +214,10 @@ void RmCarSelectMenu::resetCarCategoryComboBox(const std::string& strSelectedCat
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nCategoryComboId, nCurrentCategoryIndex);
//GfLogDebug("resetCarCategoryComboBox(%s) : cur=%d\n",
// strSelectedCategoryName.c_str(), nCurrentCategoryIndex);
// strSelectedCategoryRealName.c_str(), nCurrentCategoryIndex);
}
void RmCarSelectMenu::resetCarModelComboBox(const std::string& strCategoryName,
void RmCarSelectMenu::resetCarModelComboBox(const std::string& strCategoryRealName,
const std::string& strSelectedCarRealName)
{
const int nModelComboId = GetDynamicControlId("modelcombo");
@ -217,8 +226,8 @@ void RmCarSelectMenu::resetCarModelComboBox(const std::string& strCategoryName,
GfuiEnable(GetMenuHandle(), nModelComboId, getDriver()->isHuman ? GFUI_ENABLE : GFUI_DISABLE);
// Retrieve car models in the selected category.
const std::vector<CarData> vecCarsInCat =
CarInfo::self()->GetCarsInCategory(strCategoryName);
const std::vector<CarData*> vecCarsInCat =
CarInfo::self()->GetCarsInCategoryRealName(strCategoryRealName);
// Load the combo-box from their real names (and determine the selected model index).
unsigned nCurrentCarIndexInCategory = 0;
@ -226,9 +235,9 @@ void RmCarSelectMenu::resetCarModelComboBox(const std::string& strCategoryName,
for (unsigned nCarIndex = 0; nCarIndex < vecCarsInCat.size(); nCarIndex++)
{
GfuiComboboxAddText(GetMenuHandle(), nModelComboId,
vecCarsInCat[nCarIndex].strRealName.c_str());
vecCarsInCat[nCarIndex]->strRealName.c_str());
if (!strSelectedCarRealName.empty()
&& vecCarsInCat[nCarIndex].strRealName == strSelectedCarRealName)
&& vecCarsInCat[nCarIndex]->strRealName == strSelectedCarRealName)
nCurrentCarIndexInCategory = nCarIndex;
}
@ -236,7 +245,7 @@ void RmCarSelectMenu::resetCarModelComboBox(const std::string& strCategoryName,
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nModelComboId, nCurrentCarIndexInCategory);
//GfLogDebug("resetCarModelComboBox(cat=%s, selCar=%s) : cur=%d (nCarsInCat=%d)\n",
// strCategoryName.c_str(), strSelectedCarRealName.c_str(),
// strCategoryRealName.c_str(), strSelectedCarRealName.c_str(),
// nCurrentCarIndexInCategory, vecCarsInCat.size());
}
@ -246,12 +255,9 @@ void RmCarSelectMenu::resetCarDataSheet(const std::string& strSelectedCarName)
// Open new car params.
std::ostringstream ossCarXMLFileName;
ossCarXMLFileName << "cars/" << strSelectedCarName << '/' << strSelectedCarName << ".xml";
ossCarXMLFileName << "cars/" << strSelectedCarName << '/' << strSelectedCarName << PARAMEXT;
void* newHdle = GfParmReadFile(ossCarXMLFileName.str().c_str(), GFPARM_RMODE_STD);
// Store new car params handle.
setSelectedCarParamsHandle(newHdle);
// Update GUI.
std::ostringstream ossSpecValue;
std::ostringstream ossSpecPath;
@ -346,8 +352,6 @@ void RmCarSelectMenu::resetCarPreviewImage(const std::string& strSelectedSkinNam
void RmCarSelectMenu::RunMenu(trmdDrvElt* pDriver)
{
//GfLogDebug("RmCarSelectMenu::RunMenu\n");
// Initialize if not already done.
if (!GetMenuHandle())
Initialize();
@ -361,10 +365,6 @@ void RmCarSelectMenu::RunMenu(trmdDrvElt* pDriver)
bool RmCarSelectMenu::Initialize()
{
//GfLogDebug("RmCarSelectMenu::Initialize\n");
CarInfo::self()->print();
// Create the menu and all its controls.
CreateMenuEx(NULL, this, onActivateCB, NULL, (tfuiCallback)NULL, 1);
@ -415,24 +415,4 @@ trmdDrvElt* RmCarSelectMenu::getDriver()
void RmCarSelectMenu::setDriver(trmdDrvElt* pDriver)
{
_pDriver = pDriver;
_hCarParams = 0; // No newly selected car for the moment.
}
void RmCarSelectMenu::setSelectedCarParamsHandle(void* hdle)
{
if (!hdle)
return;
// Close old car params if not null and not the current driver's one
// (and if it really changes).
if (_hCarParams && _hCarParams != _pDriver->carParmHdle && _hCarParams != hdle)
GfParmReleaseHandle(_hCarParams);
// Store the new one.
_hCarParams = hdle;
}
void* RmCarSelectMenu::getSelectedCarParamsHandle() const
{
return _hCarParams;
}

View file

@ -56,9 +56,6 @@ protected:
const char* getSelectedCarSkin() const;
int getSelectedCarSkinTargets() const;
void setSelectedCarParamsHandle(void* hdle);
void* getSelectedCarParamsHandle() const;
// Control callback functions (have to be static, as used as tgfclient controls callbacks).
static void onActivateCB(void *pCarSelectMenu);
static void onChangeCategory(tComboBoxInfo *pInfo);
@ -74,7 +71,7 @@ private:
struct rmdDrvElt* _pDriver;
// Currently selected car params handle.
void* _hCarParams;
//void* _hCarParams;
// Skin names and targets + associated skinned livery preview files
std::vector<std::string> _vecSkinNames;

View file

@ -43,15 +43,14 @@ static const char* pszSkinIntFileSuffix = "-int";
static const char* pszLogoFileName = "logo"; // Warning: Must be consistent with grscene.cpp
static const char* pszWheel3DFileName = "wheel3d"; // Warning: Must be consistent with wheel<i>.ac/acc
static const char* apszExcludedSkinNamePrefixes[] = { "rpm", "speed", "int" };
static const char* apszExcludedSkinNamePrefixes[] = { "rpm", "speed", "int", "0", "1", "2", "3" };
static const int nExcludedSkinNamePrefixes = sizeof(apszExcludedSkinNamePrefixes) / sizeof(char*);
int rmdDriverMatchesFilters(const trmdDrvElt *drv, const char* carCat, const char* drvTyp,
const char* anyCarCat, const char* anyDrvTyp)
{
return (!strcmp(carCat, anyCarCat)
|| !strcmp(GfParmGetStr(drv->carParmHdle, SECT_CAR, PRM_CATEGORY, ""), carCat))
return (!strcmp(carCat, anyCarCat) || !strcmp(carCat, drv->carCategory))
&& (!strcmp(drvTyp, anyDrvTyp)
|| strstr(drv->moduleName, drvTyp) == drv->moduleName);
}

View file

@ -29,6 +29,7 @@
#include <map>
#include <tgf.h>
#include <carinfo.h>
// Driver description
@ -39,10 +40,11 @@ typedef struct rmdDrvElt
char *name; // Driver name
int isSelected; // Selected for race ?
int isHuman; // Human driver ?
char *carName; // Car (folder) name
char *carName; // Car XML file / folder name
char *carRealName; // Car user-friendly name
char *carCategory; // Car category XML file / folder name
int skinTargets; // Skin targets bit-field (see car.h for possible values)
char *skinName; // Skin name (or 0 if standard skin)
void *carParmHdle; // Handle to the car XML params file
GF_TAILQ_ENTRY(struct rmdDrvElt) link;
} trmdDrvElt;

View file

@ -82,7 +82,8 @@ static int NbMaxSelectedDrivers;
// Car categories
static const char* AnyCarCategory = "--- All ---";
static std::vector<std::string> VecCarCategories;
static std::vector<std::string> VecCarCategories; // Category folder/file names
static std::vector<std::string> VecCarCategoryNames; // Category real/displayed names
static size_t CurCarCategoryIndex = 0;
// Driver types
@ -100,6 +101,8 @@ static size_t CurSkinIndex = 0;
GF_TAILQ_HEAD(DriverListHead, trmdDrvElt);
static tDriverListHead DriverList;
trmdDrvElt *PPickedDriver;
// Local functions.
static void rmdsCleanup(void);
static void rmdsFilterDriverScrollList(const char* carCat, const char* driverType);
@ -112,37 +115,90 @@ static void rmdsClickOnDriver(void * /* dummy */);
static void
rmdsActivate(void * /* notused */)
{
GfLogTrace("Entering Driver Select menu\n");
std::vector<std::string> vecSkinNames;
std::map<std::string, std::string> mapSkinPreviewFiles; // Key = skin name.
std::map<std::string, int> mapSkinTargets; // Key = skin name.
// Update competitors skinning data (in case things changed since the menu was last open ;
// ex: the user added a 3D wheel skinned texture in its user settings)
trmdDrvElt *curDrv;
trmdDrvElt *driver;
int index = 0;
const char* name;
while ((name = GfuiScrollListGetElement(ScrHandle, CompetitorsScrollListId,
index, (void**)&curDrv)))
index, (void**)&driver)))
{
// Get really available (now) skins, skin targets and preview files for the driver's car.
rmdGetCarSkinsInSearchPath(curDrv, 0, vecSkinNames, mapSkinTargets, mapSkinPreviewFiles);
rmdGetCarSkinsInSearchPath(driver, 0, vecSkinNames, mapSkinTargets, mapSkinPreviewFiles);
// Update skin targets for the choosen skin (targets might have changed).
curDrv->skinTargets = 0;
if (curDrv->skinName)
driver->skinTargets = 0;
if (driver->skinName)
{
std::map<std::string, int>::const_iterator itSkinTargets =
mapSkinTargets.find(curDrv->skinName);
mapSkinTargets.find(driver->skinName);
if (itSkinTargets != mapSkinTargets.end())
curDrv->skinTargets = itSkinTargets->second;
driver->skinTargets = itSkinTargets->second;
}
// Next competitor.
index++;
}
// Update selected driver displayed info
rmdsClickOnDriver(NULL);
// Select the current driver in the relevant scroll-list
if (PPickedDriver)
{
const char* name;
int curDrvIndex = -1;
index = 0;
while ((name = GfuiScrollListGetElement(ScrHandle, CompetitorsScrollListId,
index, (void**)&driver)))
{
if (driver == PPickedDriver)
{
curDrvIndex = index;
break;
}
index++;
}
if (curDrvIndex >= 0)
{
GfuiScrollListSetSelectedElement(ScrHandle, CompetitorsScrollListId, curDrvIndex);
//GfLogDebug("Selecting competitor #%d '%s'\n", curDrvIndex, name);
}
else
{
curDrvIndex = -1;
index = 0;
while ((name = GfuiScrollListGetElement(ScrHandle, CandidatesScrollListId,
index, (void**)&driver)))
{
if (driver == PPickedDriver)
{
curDrvIndex =index;
break;
}
index++;
}
if (curDrvIndex >= 0)
{
GfuiScrollListSetSelectedElement(ScrHandle, CandidatesScrollListId, curDrvIndex);
//GfLogDebug("Selecting candidate #%d '%s'\n", curDrvIndex, name);
}
}
}
// Update car category filter criteria : use the one of the current driver if any.
const char* curDrvCarCat = PPickedDriver ? PPickedDriver->carCategory : AnyCarCategory;
CurCarCategoryIndex =
(std::find(VecCarCategories.begin(), VecCarCategories.end(), curDrvCarCat)
- VecCarCategories.begin() + VecCarCategories.size()) % VecCarCategories.size();
//GfLogDebug("Car cat filter : %p '%s' %d\n", PPickedDriver, curDrvCarCat, CurCarCategoryIndex);
rmdsFilterDriverScrollList(curDrvCarCat, VecDriverTypes[CurDriverTypeIndex].c_str());
GfuiLabelSetText(ScrHandle, DriverTypeEditId, VecDriverTypes[CurDriverTypeIndex].c_str());
GfuiLabelSetText(ScrHandle, CarCategoryEditId, VecCarCategoryNames[CurCarCategoryIndex].c_str());
}
// Screen de-activation call-back.
@ -162,7 +218,7 @@ rmdsChangeCarCategory(void *vp)
CurCarCategoryIndex =
(CurCarCategoryIndex + VecCarCategories.size() + (int)(long)vp) % VecCarCategories.size();
GfuiLabelSetText(ScrHandle, CarCategoryEditId, VecCarCategories[CurCarCategoryIndex].c_str());
GfuiLabelSetText(ScrHandle, CarCategoryEditId, VecCarCategoryNames[CurCarCategoryIndex].c_str());
rmdsFilterDriverScrollList(VecCarCategories[CurCarCategoryIndex].c_str(),
VecDriverTypes[CurDriverTypeIndex].c_str());
@ -201,7 +257,7 @@ rmdsChangeSkin(void *vp)
// Load associated preview image (or "no preview" panel if none available).
struct stat st;
if (!stat(MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(), &st))
if (GfFileExists(MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId,
MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(),
/* index= */ 0, /* canDeform= */false);
@ -306,14 +362,10 @@ rmdsPreviousMenu(void *screen)
static void
rmdsCarSelectMenu(void *pPreviousMenu)
{
//GfLogDebug("rmdsCarSelectMenu\n");
trmdDrvElt *pDriver = rmdsGetHighlightedDriver();
if (pDriver)
if (PPickedDriver)
{
CarSelectMenu.SetPreviousMenuHandle(pPreviousMenu);
CarSelectMenu.RunMenu(pDriver);
CarSelectMenu.RunMenu(PPickedDriver);
}
}
@ -326,8 +378,7 @@ rmdsMoveDriver(void *vd)
static void
rmdsClickOnDriver(void * /* dummy */)
{
static const unsigned maxBufSize = 64;
char buf[maxBufSize];
char buf[64];
const char *name;
trmdDrvElt *curDrv;
@ -361,11 +412,14 @@ rmdsClickOnDriver(void * /* dummy */)
// Update selected driver (if any) displayed infos.
if (name)
{
rmdGetDriverType(curDrv->moduleName, buf, maxBufSize);
// The selected driver is the new picked one.
PPickedDriver = curDrv;
// Update picked driver info.
rmdGetDriverType(curDrv->moduleName, buf, sizeof(buf));
GfuiLabelSetText(ScrHandle, PickedDriverTypeLabelId, buf);
GfuiLabelSetText(ScrHandle, PickedDriverCarLabelId, GfParmGetName(curDrv->carParmHdle));
GfuiLabelSetText(ScrHandle, PickedDriverCarCategoryLabelId,
GfParmGetStr(curDrv->carParmHdle, SECT_CAR, PRM_CATEGORY, ""));
GfuiLabelSetText(ScrHandle, PickedDriverCarLabelId, curDrv->carRealName);
GfuiLabelSetText(ScrHandle, PickedDriverCarCategoryLabelId, curDrv->carCategory);
// Get really available skins, skin targets and preview files for the driver's car.
rmdGetCarSkinsInSearchPath(curDrv, 0, VecCurDriverSkinNames,
@ -551,15 +605,15 @@ RmDriversSelect(void *vs)
trmdDrvElt *curDrv;
int nDrivers, robotIdx;
void *robhdle;
struct stat st;
const char *carName;
const char *carRealName;
const char *carCat;
int extended;
void *carhdle;
void *cathdle;
int human;
const char* initCarCat;
//GfLogDebug("RmDriversSelect\n");
// Initialize drivers selection
MenuData = (tRmDriverSelect*)vs;
@ -605,6 +659,7 @@ RmDriversSelect(void *vs)
GF_TAILQ_INIT(&DriverList);
VecCarCategories.push_back(AnyCarCategory);
VecCarCategoryNames.push_back(AnyCarCategory);
VecDriverTypes.push_back(AnyDriverType);
list = 0;
@ -637,41 +692,54 @@ RmDriversSelect(void *vs)
carName = GfParmGetStr(robhdle, path, ROB_ATTR_CAR, "");
human = strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT);
sprintf(path, "cars/%s/%s.xml", carName, carName);
if (!stat(path, &st)) {
carhdle = GfParmReadFile(path, GFPARM_RMODE_STD);
if (carhdle) {
curDrv = (trmdDrvElt*)calloc(1, sizeof(trmdDrvElt));
curDrv->interfaceIndex = curmod->modInfo[i].index;
curDrv->moduleName = strdup(modName);
curDrv->carName = strdup(carName); // Default one if not specified in race file.
curDrv->skinName = 0; // Set later if needed from race params.
curDrv->skinTargets = 0; // Set later if needed from race params.
curDrv->name = strdup(curmod->modInfo[i].name);
curDrv->carParmHdle = carhdle;
//GfLogDebug("Candidate %s : %s on %s\n", modName, curDrv->name, carName);
const char* carCat = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, "");
if (std::find(VecCarCategories.begin(), VecCarCategories.end(), carCat) == VecCarCategories.end()) {
VecCarCategories.push_back(carCat);
}
rmdGetDriverType(modName, drvType, drvTypeMaxSize);
if (std::find(VecDriverTypes.begin(), VecDriverTypes.end(), drvType) == VecDriverTypes.end()) {
VecDriverTypes.push_back(drvType);
}
curDrv->isHuman = human ? 1 : 0;
if (human) {
GF_TAILQ_INSERT_HEAD(&DriverList, curDrv, link);
carhdle = GfParmReadFile(path, GFPARM_RMODE_STD);
if (carhdle) {
carCat = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, "");
carRealName = GfParmGetName(carhdle);
curDrv = (trmdDrvElt*)calloc(1, sizeof(trmdDrvElt));
curDrv->interfaceIndex = curmod->modInfo[i].index;
curDrv->moduleName = strdup(modName);
curDrv->carName = strdup(carName); // Default one if not specified in race file.
curDrv->carRealName = strdup(carRealName); // For the default car.
curDrv->carCategory = strdup(carCat); // For the default car.
curDrv->skinName = 0; // Set later if needed from race params.
curDrv->skinTargets = 0; // Set later if needed from race params.
curDrv->name = strdup(curmod->modInfo[i].name);
//GfLogDebug("Candidate %s : %s on %s\n", modName, curDrv->name, carName);
if (std::find(VecCarCategories.begin(), VecCarCategories.end(), carCat) == VecCarCategories.end()) {
VecCarCategories.push_back(carCat);
sprintf(path, "categories/%s.xml", carCat);
cathdle = GfParmReadFile(path, GFPARM_RMODE_STD);
if (cathdle) {
carCat = GfParmGetName(cathdle);
} else {
GF_TAILQ_INSERT_TAIL(&DriverList, curDrv, link);
GfLogWarning("Car %s category file %s not %s for '%s' (%s #%d)\n",
carName, path, GfFileExists(path) ? "readable" : "found",
curmod->modInfo[i].name, modName, i);
}
NbTotDrivers++;
} else {
GfLogWarning("Ignoring '%s' (%s #%d) because '%s' is not readable\n",
curmod->modInfo[i].name, modName, i, path);
VecCarCategoryNames.push_back(carCat);
if (cathdle)
GfParmReleaseHandle(cathdle);
}
GfParmReleaseHandle(carhdle);
rmdGetDriverType(modName, drvType, drvTypeMaxSize);
if (std::find(VecDriverTypes.begin(), VecDriverTypes.end(), drvType) == VecDriverTypes.end()) {
VecDriverTypes.push_back(drvType);
}
curDrv->isHuman = human ? 1 : 0;
if (human) {
GF_TAILQ_INSERT_HEAD(&DriverList, curDrv, link);
} else {
GF_TAILQ_INSERT_TAIL(&DriverList, curDrv, link);
}
NbTotDrivers++;
} else {
GfLogWarning("Ignoring '%s' (%s #%d) because '%s' was not found\n",
curmod->modInfo[i].name, modName, i, path);
GfLogWarning("Ignoring '%s' (%s #%d) because '%s' file not %s\n",
curmod->modInfo[i].name, modName, i, path,
GfFileExists(path) ? "readable" : "found");
}
}
}
@ -693,7 +761,7 @@ RmDriversSelect(void *vs)
(int)GfParmGetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0);
nDrivers = GfParmGetEltNb(MenuData->param, RM_SECT_DRIVERS);
//GfLogDebug("Competitors : n=%d (max=%d)\n", nDrivers, NbMaxSelectedDrivers);
initCarCat = 0;
PPickedDriver = 0;
index = 1;
for (i = 1; i < nDrivers+1; i++) {
// Get driver infos from the the starting grid in the race params file
@ -723,10 +791,10 @@ RmDriversSelect(void *vs)
GfuiScrollListInsertElement(ScrHandle, CompetitorsScrollListId,
curDrv->name, index, (void*)curDrv);
// Try and determine the initial car category for the filtering combo-box
// (the car category of the last human driver, or else of the last driver).
if (!initCarCat || curDrv->isHuman)
initCarCat = GfParmGetStr(curDrv->carParmHdle, SECT_CAR, PRM_CATEGORY, "");
// Initialize the picked driver
// (the last human driver, or else of the last driver).
if (!PPickedDriver || curDrv->isHuman)
PPickedDriver = curDrv;
// Get the chosen car for the race if any specified (human only).
if (curDrv->isHuman && extended)
@ -735,16 +803,21 @@ RmDriversSelect(void *vs)
sprintf(path, "%s/%s/%d/%d", RM_SECT_DRIVERINFO, moduleName, extended, robotIdx);
carName = GfParmGetStr(MenuData->param, path, RM_ATTR_CARNAME, 0);
sprintf(path, "cars/%s/%s.xml", carName, carName);
if (!stat(path, &st)) {
if (GfFileExists(path)) {
carhdle = GfParmReadFile(path, GFPARM_RMODE_STD);
if (carhdle) {
//GfLogDebug(" Car XML OK : %s\n", path);
if (curDrv->carParmHdle)
GfParmReleaseHandle(curDrv->carParmHdle);
curDrv->carParmHdle = carhdle;
if (curDrv->carName)
free(curDrv->carName);
curDrv->carName = strdup(carName);
carCat = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, "");
if (curDrv->carCategory)
free(curDrv->carCategory);
curDrv->carCategory = strdup(carCat);
carRealName = GfParmGetName(carhdle);
if (curDrv->carRealName)
free(curDrv->carRealName);
curDrv->carRealName = strdup(carRealName);
GfParmReleaseHandle(carhdle);
} else {
GfLogError("Falling back to default car '%s' "
"for %s because '%s' is not readable\n",
@ -771,15 +844,10 @@ RmDriversSelect(void *vs)
}
}
// Initialize Candidates scroll-list filter criteria and fill-in the scroll-list.
CurDriverTypeIndex = 0;
if (!initCarCat)
initCarCat = AnyCarCategory;
CurCarCategoryIndex = std::find(VecCarCategories.begin(), VecCarCategories.end(), initCarCat) - VecCarCategories.begin();
CurCarCategoryIndex = CurCarCategoryIndex % VecCarCategories.size();
rmdsFilterDriverScrollList(initCarCat, AnyDriverType);
GfuiLabelSetText(ScrHandle, DriverTypeEditId, AnyDriverType);
GfuiLabelSetText(ScrHandle, CarCategoryEditId, initCarCat);
// Initialize driver type filter criteria to "all types".
CurDriverTypeIndex =
(std::find(VecDriverTypes.begin(), VecDriverTypes.end(), AnyDriverType)
- VecDriverTypes.begin() + VecDriverTypes.size()) % VecDriverTypes.size();
// Picked Driver Info
PickedDriverTypeLabelId = CreateLabelControl(ScrHandle,menuDescHdle,"pickeddrivertypelabel");
@ -808,6 +876,7 @@ rmdsCleanup(void)
trmdDrvElt *curDrv;
VecCarCategories.clear();
VecCarCategoryNames.clear();
VecDriverTypes.clear();
VecCurDriverSkinNames.clear();
MapCurDriverSkinPreviewFiles.clear();
@ -817,9 +886,10 @@ rmdsCleanup(void)
free(curDrv->name);
free(curDrv->moduleName);
free(curDrv->carName);
free(curDrv->carRealName);
free(curDrv->carCategory);
if (curDrv->skinName)
free(curDrv->skinName);
GfParmReleaseHandle(curDrv->carParmHdle);
free(curDrv);
}
}

View file

@ -17,8 +17,8 @@
***************************************************************************/
#include <map>
#include <set>
#include <sstream>
#include <algorithm>
#include "carinfo.h"
@ -31,8 +31,11 @@ struct PrivateData
// Map for quick access to CarData by name
std::map<std::string, int> mapCarNameIndices;
// Set of category names.
std::set<std::string> setCategoryNames;
// Vector of category names.
std::vector<std::string> vecCategoryNames;
// Vector of category real names.
std::vector<std::string> vecCategoryRealNames;
};
@ -55,12 +58,14 @@ CarInfo::CarInfo()
tFList *curFile;
void *carParmHdle;
// Load the category list from the "cars" folder contents.
// Load the car list from the "cars" folder contents.
curFile = files = GfDirGetList("cars");
if (curFile)
{
do
{
//GfLogDebug("Examining car %s\n", curFile->name);
// Ignore "." and ".." folders.
if (curFile->name[0] == '.')
continue;
@ -77,7 +82,7 @@ CarInfo::CarInfo()
continue;
}
// Read car info and store it in the CarData structure.
// Read car info and store it in the CarData structure (category real name = later).
CarData carData;
carData.strName = pszCarName;
carData.strCategoryName = GfParmGetStr(carParmHdle, "Car", "category", "");
@ -87,7 +92,10 @@ CarInfo::CarInfo()
// Update the CarInfo singleton.
m_priv->vecCars.push_back(carData);
m_priv->mapCarNameIndices[pszCarName] = m_priv->vecCars.size() - 1;
m_priv->setCategoryNames.insert(carData.strCategoryName);
if (std::find(m_priv->vecCategoryNames.begin(),
m_priv->vecCategoryNames.end(), carData.strCategoryName)
== m_priv->vecCategoryNames.end())
m_priv->vecCategoryNames.push_back(carData.strCategoryName);
// Close the XML file of the car.
GfParmReleaseHandle(carParmHdle);
@ -96,6 +104,24 @@ CarInfo::CarInfo()
}
GfDirFreeList(files, NULL, true, true);
// Sort car categories.
std::sort(m_priv->vecCategoryNames.begin(), m_priv->vecCategoryNames.end());
// Set car category real name (only here because m_priv->vecCategoryNames
// has to be completed before we can GetCategoryRealNames().
const std::vector<std::string> vecCatRealNames = GetCategoryRealNames();
std::vector<std::string>::const_iterator iterCatName;
for (int nCatIndex = 0; nCatIndex < m_priv->vecCategoryNames.size(); nCatIndex++)
{
std::vector<CarData*> vecCarsInCat =
GetCarsInCategory(m_priv->vecCategoryNames[nCatIndex]);
std::vector<CarData*>::iterator iterCar;
for (iterCar = vecCarsInCat.begin(); iterCar != vecCarsInCat.end(); iterCar++)
(*iterCar)->strCategoryRealName = vecCatRealNames[nCatIndex];
}
print();
}
std::string CarInfo::GetCarRealName(const std::string& strCarName) const
@ -124,28 +150,63 @@ std::vector<std::string> CarInfo::GetCarNamesInCategory(const std::string& strCa
return vecCarNames;
}
std::vector<CarData> CarInfo::GetCarsInCategory(const std::string& strCatName) const
std::vector<CarData*> CarInfo::GetCarsInCategory(const std::string& strCatName) const
{
std::vector<CarData> vecCarsInCat;
std::vector<CarData*> vecCarsInCat;
std::vector<CarData>::const_iterator iterCar;
std::vector<CarData>::iterator iterCar;
for (iterCar = m_priv->vecCars.begin(); iterCar != m_priv->vecCars.end(); iterCar++)
if (strCatName == "All" || iterCar->strCategoryName == strCatName)
vecCarsInCat.push_back(*iterCar);
vecCarsInCat.push_back(&(*iterCar));
return vecCarsInCat;
}
std::vector<std::string> CarInfo::GetCategoryNames() const
std::vector<CarData*> CarInfo::GetCarsInCategoryRealName(const std::string& strCatRealName) const
{
std::vector<std::string> vecCatNames;
std::set<std::string>::const_iterator iterCat;
for (iterCat = m_priv->setCategoryNames.begin();
iterCat != m_priv->setCategoryNames.end(); iterCat++)
vecCatNames.push_back(*iterCat);
return vecCatNames;
std::vector<CarData*> vecCarsInCat;
std::vector<CarData>::iterator iterCar;
for (iterCar = m_priv->vecCars.begin(); iterCar != m_priv->vecCars.end(); iterCar++)
if (strCatRealName == "All" || iterCar->strCategoryRealName == strCatRealName)
vecCarsInCat.push_back(&(*iterCar));
return vecCarsInCat;
}
const std::vector<std::string>& CarInfo::GetCategoryNames() const
{
return m_priv->vecCategoryNames;
}
const std::vector<std::string>& CarInfo::GetCategoryRealNames() const
{
if (m_priv->vecCategoryRealNames.empty())
{
std::vector<std::string>::const_iterator iterCatName;
for (iterCatName = m_priv->vecCategoryNames.begin();
iterCatName != m_priv->vecCategoryNames.end(); iterCatName++)
{
std::ostringstream ossCatFileName;
ossCatFileName << "categories/" << *iterCatName << PARAMEXT;
const std::string strCatFileName = ossCatFileName.str();
void* hCat = GfParmReadFile(strCatFileName.c_str(), GFPARM_RMODE_STD);
if (hCat)
{
m_priv->vecCategoryRealNames.push_back(GfParmGetName(hCat));
GfParmReleaseHandle(hCat);
}
else
{
m_priv->vecCategoryRealNames.push_back(*iterCatName); // Fall-back.
GfLogWarning("Car category file %s not %s\n",
strCatFileName.c_str(),
GfFileExists(strCatFileName.c_str()) ? "readable" : "found");
}
}
}
return m_priv->vecCategoryRealNames;
}
std::vector<std::string> CarInfo::GetCarRealNamesInCategory(const std::string& strCatName) const
@ -182,19 +243,20 @@ CarData* CarInfo::GetCarData(const std::string& strCarName) const
void CarInfo::print() const
{
GfLogDebug("CarInfo : %d cars, %d categories\n",
m_priv->vecCars.size(), m_priv->setCategoryNames.size());
std::set<std::string>::const_iterator iterCat;
for (iterCat = m_priv->setCategoryNames.begin();
iterCat != m_priv->setCategoryNames.end(); iterCat++)
GfLogDebug("Found %d cars in %d categories\n",
m_priv->vecCars.size(), m_priv->vecCategoryNames.size());
std::vector<std::string>::const_iterator iterCat;
for (int nCatIndex = 0; nCatIndex < m_priv->vecCategoryNames.size(); nCatIndex++)
{
GfLogDebug(" %s category :\n", iterCat->c_str());
const std::vector<CarData> vecCarsInCat = GetCarsInCategory(iterCat->c_str());
std::vector<CarData>::const_iterator iterCar;
GfLogDebug(" %s (%s) :\n", m_priv->vecCategoryRealNames[nCatIndex].c_str(),
m_priv->vecCategoryNames[nCatIndex].c_str());
const std::vector<CarData*> vecCarsInCat =
GetCarsInCategory(m_priv->vecCategoryNames[nCatIndex]);
std::vector<CarData*>::const_iterator iterCar;
for (iterCar = vecCarsInCat.begin(); iterCar != vecCarsInCat.end(); iterCar++)
{
GfLogDebug(" %s (%s) : %s\n", iterCar->strRealName.c_str(),
iterCar->strName.c_str(), iterCar->strXMLPath.c_str());
GfLogDebug(" %s (%s) : %s\n", (*iterCar)->strRealName.c_str(),
(*iterCar)->strName.c_str(), (*iterCar)->strXMLPath.c_str());
}
}
}

View file

@ -32,6 +32,7 @@ public:
std::string strName; // XML file / folder name (ex: "sc-boxer-96")
std::string strRealName; // User friendly name (ex: "SC Boxer 96").
std::string strCategoryName; // Category name (ex: "LS-GT1").
std::string strCategoryRealName; // Category name (ex: "Long Day Series GT1").
std::string strXMLPath; // Path-name of the car XML file.
};
@ -42,13 +43,15 @@ public:
// Accessor to the unique instance of the singleton.
static CarInfo* self();
std::vector<std::string> GetCategoryNames() const;
const std::vector<std::string>& GetCategoryNames() const;
const std::vector<std::string>& GetCategoryRealNames() const;
CarData* GetCarData(const std::string& strCarName) const;
std::string GetCarRealName(const std::string& strCarName) const;
CarData* GetCarDataFromRealName(const std::string& strCarRealName) const;
std::vector<CarData> GetCarsInCategory(const std::string& strCatName = "All") const;
std::vector<CarData*> GetCarsInCategory(const std::string& strCatName = "All") const;
std::vector<CarData*> GetCarsInCategoryRealName(const std::string& strCatRealName = "All") const;
std::vector<std::string> GetCarNamesInCategory(const std::string& strCatName = "All") const;
std::vector<std::string> GetCarRealNamesInCategory(const std::string& strCatName = "All") const;