Support reading car data from GfLocalDir()

This would allow users to extract car data into GfLocalDir(), which is
guaranteed to have write permissions, as opposed to GfDataDir().
This commit is contained in:
Xavier Del Campo Romero 2025-01-17 16:16:16 +01:00
parent 6ec6efadf8
commit 853c45a62b
Signed by: xavi
GPG key ID: 84FF3612A9BF43F2
20 changed files with 171 additions and 99 deletions

View file

@ -416,7 +416,7 @@ static int getCategory(const std::string &car, std::string &out)
path += PARAMEXT; path += PARAMEXT;
cpath = path.c_str(); cpath = path.c_str();
if (!(h = GfParmReadFile(cpath, GFPARM_RMODE_STD))) if (!(h = GfParmReadFileBoth(cpath, GFPARM_RMODE_STD)))
{ {
LogSimplix.error("Failed to open %s\n", cpath); LogSimplix.error("Failed to open %s\n", cpath);
goto end; goto end;

View file

@ -82,17 +82,12 @@ void GfCars::reload()
_pSelf = new GfCars; _pSelf = new GfCars;
} }
GfCars::GfCars() void GfCars::list(const std::string &path)
{ {
_pPrivate = new Private;
// Get the list of sub-dirs in the "cars" folder. // Get the list of sub-dirs in the "cars" folder.
tFList* lstFolders = GfDirGetList("cars/models"); tFList* lstFolders = GfDirGetList(path.c_str());
if (!lstFolders) if (!lstFolders)
{
GfLogFatal("No car available in the 'cars' folder\n");
return; return;
}
std::string strLastCatId("none"); std::string strLastCatId("none");
std::string strCatName; std::string strCatName;
@ -113,8 +108,10 @@ GfCars::GfCars()
const char* pszCarId = pFolder->name; const char* pszCarId = pFolder->name;
std::ostringstream ossCarFileName; std::ostringstream ossCarFileName;
ossCarFileName << "cars/models/" << pszCarId << '/' << pszCarId << PARAMEXT; ossCarFileName << path << '/' << pszCarId << '/' << pszCarId << PARAMEXT;
GfLogInfo("ossCarFileName=%s\n", ossCarFileName.str().c_str());
void* hparmCar = GfParmReadFile(ossCarFileName.str(), GFPARM_RMODE_STD); void* hparmCar = GfParmReadFile(ossCarFileName.str(), GFPARM_RMODE_STD);
if (!hparmCar) if (!hparmCar)
{ {
GfLogError("Ignoring car %s (file %s not %s)\n", GfLogError("Ignoring car %s (file %s not %s)\n",
@ -168,6 +165,14 @@ GfCars::GfCars()
print(); print();
} }
GfCars::GfCars()
{
_pPrivate = new Private;
list(std::string(GfLocalDir()) + "cars/models");
list(std::string(GfDataDir()) + "cars/models");
}
const std::vector<std::string>& GfCars::getCategoryIds() const const std::vector<std::string>& GfCars::getCategoryIds() const
{ {
return _pPrivate->vecCatIds; return _pPrivate->vecCatIds;

View file

@ -120,6 +120,7 @@ public:
std::vector<std::string> getCarIdsInCategory(const std::string& strCatId = "") const; std::vector<std::string> getCarIdsInCategory(const std::string& strCatId = "") const;
std::vector<std::string> getCarNamesInCategory(const std::string& strCatId = "") const; std::vector<std::string> getCarNamesInCategory(const std::string& strCatId = "") const;
void list(const std::string &path);
void print() const; void print() const;
protected: protected:

View file

@ -1455,6 +1455,10 @@ std::vector<GfDriverSkin> GfDriver::getPossibleSkins(const std::string& strAltCa
ossDirPath << "drivers/" << _strModName; ossDirPath << "drivers/" << _strModName;
getPossibleSkinsInFolder(strCarId, ossDirPath.str(), vecPossSkins); getPossibleSkinsInFolder(strCarId, ossDirPath.str(), vecPossSkins);
ossDirPath.str("");
ossDirPath << GfLocalDir() << "cars/models/" << strCarId;
getPossibleSkinsInFolder(strCarId, ossDirPath.str(), vecPossSkins);
ossDirPath.str(""); ossDirPath.str("");
ossDirPath << "cars/models/" << strCarId; ossDirPath << "cars/models/" << strCarId;
getPossibleSkinsInFolder(strCarId, ossDirPath.str(), vecPossSkins); getPossibleSkinsInFolder(strCarId, ossDirPath.str(), vecPossSkins);

View file

@ -173,6 +173,41 @@ void SDCar::loadCarLights()
carLights->getLightsRoot()->addChild(lights_branch); carLights->getLightsRoot()->addChild(lights_branch);
} }
int SDCar::loadWing(void *handle, const char *path, const char *key,
osgLoader &loader, const std::string &bCarName,
const std::string &bSkinName, const char *name, bool value,
osg::ref_ptr<osg::Switch> &wing) const
{
const char *ext = GfParmGetStr(handle, path, key, NULL);
if (!ext)
return -1;
std::string carpath = "cars/models/";
carpath += car->_carName;
carpath += "/";
carpath += ext;
std::vector<std::string> paths;
paths.push_back(std::string(GfLocalDir()) + carpath);
paths.push_back(std::string(GfDataDir()) + carpath);
osg::ref_ptr<osg::Node> node;
for (const std::string &path : paths)
if ((node = loader.Load3dFile(path, true, bCarName, bSkinName)))
break;
if (!node)
node = new osg::Node;
node->setName(name);
wing->addChild(node, value);
return 0;
}
osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat, int carshader) osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat, int carshader)
{ {
this->carTransform = new osg::MatrixTransform; this->carTransform = new osg::MatrixTransform;
@ -246,6 +281,10 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
strTPath = TmpPath+buf; strTPath = TmpPath+buf;
loader.AddSearchPath(strTPath); loader.AddSearchPath(strTPath);
snprintf(buf, nMaxTexPathSize, "%scars/models/%s/", GfLocalDir(), car->_carName);
strTPath = TmpPath+buf;
loader.AddSearchPath(strTPath);
snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName); snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName);
strTPath = TmpPath+buf; strTPath = TmpPath+buf;
loader.AddSearchPath(strTPath); loader.AddSearchPath(strTPath);
@ -269,6 +308,8 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
snprintf(buf, nMaxTexPathSize, "cars/models/%s/%s", bMasterModel ? car->_masterModel : car->_carName, param); snprintf(buf, nMaxTexPathSize, "cars/models/%s/%s", bMasterModel ? car->_masterModel : car->_carName, param);
std::string carmodel = buf;
strPath+=buf; strPath+=buf;
std::string name = car->_carName; std::string name = car->_carName;
@ -297,8 +338,10 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
GfLogDebug("Car Texture = %s - Car Name = %s\n", bSkinName.c_str(), bCarName.c_str()); GfLogDebug("Car Texture = %s - Car Name = %s\n", bSkinName.c_str(), bCarName.c_str());
} }
osg::ref_ptr<osg::Node> pCar = loader.Load3dFile(strPath, true, bCarName, bSkinName); std::string localpath = std::string(GfLocalDir()) + carmodel;
if (pCar) osg::ref_ptr<osg::Node> pCar;
if ((pCar = loader.Load3dFile(localpath, true, bCarName, bSkinName))
|| (pCar = loader.Load3dFile(strPath, true, bCarName, bSkinName)))
GfLogDebug("Load Car ACC !\n"); GfLogDebug("Load Car ACC !\n");
else else
{ {
@ -314,53 +357,24 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
{ {
_wing1 = true; _wing1 = true;
std::string tmp = GfDataDir(); static const struct wing
snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName);
tmp = tmp+buf;
param = GfParmGetStr(handle, path, PRM_WING_1, NULL);
strPath=tmp+param;
osg::ref_ptr<osg::Node> pWin1 = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pWin1)
GfLogDebug("Load Wing1 ACC ! %s\n", strPath.c_str() );
else
{ {
GfLogError("Failed to load %s\n", strPath.c_str()); const char *key, *name;
pWin1 = new osg::Node; } wings[] =
}
pWin1->setName("WING1");
param = GfParmGetStr(handle, path, PRM_WING_2, NULL);
strPath=tmp+param;
osg::ref_ptr<osg::Node> pWin2 = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pWin2)
GfLogDebug("Load Wing2 ACC ! %s\n", strPath.c_str());
else
{ {
GfLogError("Failed to load %s\n", strPath.c_str()); {PRM_WING_1, "WING1"},
pWin2 = new osg::Node; {PRM_WING_2, "WING2"},
} {PRM_WING_3, "WING3"}
pWin2->setName("WING2"); };
GfLogDebug("Load Wing2 ACC ! %s\n", strPath.c_str());
param = GfParmGetStr(handle, path, PRM_WING_3, NULL); for (size_t i = 0; i < sizeof wings / sizeof *wings; i++)
strPath=tmp+param;
osg::ref_ptr<osg::Node> pWin3 = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pWin3)
GfLogDebug("Load Wing3 ACC ! %s\n", strPath.c_str());
else
{ {
GfLogError("Failed to load %s\n", strPath.c_str()); const struct wing &w = wings[i];
pWin3 = new osg::Node;
if (loadWing(handle, path, w.key, loader, bCarName,
bSkinName, w.name, false, pWing))
GfLogError("loadWing %s failed\n", w.name);
} }
pWin3->setName("WING3");
GfLogDebug("Load Wing3 ACC ! %s\n", strPath.c_str());
pWing->addChild(pWin1.get(), false);
pWing->addChild(pWin2.get(), false);
pWing->addChild(pWin3.get(), true);
GfLogDebug("tracktype = %d - subcat = %d\n", tracktype, subcat);
if (tracktype == false) if (tracktype == false)
{ {
@ -403,8 +417,10 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
param = GfParmGetStr(handle, path, PRM_REARWINGMODEL, ""); param = GfParmGetStr(handle, path, PRM_REARWINGMODEL, "");
strPath = tmp+param; strPath = tmp+param;
osg::ref_ptr<osg::Node> pWing1_branch = loader.Load3dFile(strPath, true, bCarName, bSkinName); std::string local = std::string(GfLocalDir()) + buf + param;
if (pWing1_branch) osg::ref_ptr<osg::Node> pWing1_branch;
if ((pWing1_branch = loader.Load3dFile(local, true, bCarName, bSkinName))
|| (pWing1_branch = loader.Load3dFile(strPath, true, bCarName, bSkinName)))
GfLogDebug("Loading Wing animate %i - %s !\n", i, strPath.c_str()); GfLogDebug("Loading Wing animate %i - %s !\n", i, strPath.c_str());
else else
{ {
@ -437,8 +453,8 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
strPath= tmp+param; strPath= tmp+param;
pCockpit = loader.Load3dFile(strPath, true, bCarName, bSkinName); if (!(pCockpit = loader.Load3dFile(GfLocalDir() + strPath, true, bCarName, bSkinName))
if (pCockpit) && !(pCockpit = loader.Load3dFile(strPath, true, bCarName, bSkinName)))
GfLogDebug("Cockpit loaded = %s !\n", strPath.c_str()); GfLogDebug("Cockpit loaded = %s !\n", strPath.c_str());
else else
{ {
@ -456,14 +472,15 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
if (param) if (param)
{ {
_steer = true; _steer = true;
std::string tmpPath = GfDataDir(); std::string tmpPath = GfLocalDir();
snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName); snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName);
tmpPath = tmpPath+buf; tmpPath = tmpPath+buf;
strPath = tmpPath + param; strPath = tmpPath + param;
osg::ref_ptr<osg::Node> steerEntityLo = loader.Load3dFile(strPath, true, "", ""); osg::ref_ptr<osg::Node> steerEntityLo;
if (steerEntityLo == nullptr) if (!(steerEntityLo = loader.Load3dFile(GfLocalDir() + strPath, true, "", ""))
&& !(steerEntityLo = loader.Load3dFile(strPath, true, "", "")))
GfLogError("Failed to load %s\n", strPath.c_str()); GfLogError("Failed to load %s\n", strPath.c_str());
else else
{ {
@ -505,8 +522,9 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
tmpPath = tmpPath+buf; tmpPath = tmpPath+buf;
strPath = tmpPath + param; strPath = tmpPath + param;
osg::ref_ptr<osg::Node> steerEntityHi = loader.Load3dFile(strPath, true, "", ""); osg::ref_ptr<osg::Node> steerEntityHi;
if (steerEntityHi == nullptr) if (!(steerEntityHi = loader.Load3dFile(GfLocalDir() + strPath, true, "", ""))
&& !(steerEntityHi = loader.Load3dFile(strPath, true, "", "")))
{ {
GfLogError("Failed to load: %s\n", strPath.c_str()); GfLogError("Failed to load: %s\n", strPath.c_str());
steerEntityHi = new osg::Node; steerEntityHi = new osg::Node;

View file

@ -79,6 +79,10 @@ private :
void setReflectionMap(osg::ref_ptr<osg::Texture> map); void setReflectionMap(osg::ref_ptr<osg::Texture> map);
void loadCarLights(); void loadCarLights();
int loadWing(void *handle, const char *path, const char *key,
osgLoader &loader, const std::string &bCarName,
const std::string &bSkinName, const char *name, bool value,
osg::ref_ptr<osg::Switch> &wing) const;
public : public :
SDCar(void); SDCar(void);

View file

@ -112,19 +112,24 @@ osg::ref_ptr<osg::MatrixTransform> SDWheels::initWheel(int wheelIndex, bool comp
const bool bCustomSkin = strlen(this->car->_skinName) != 0; const bool bCustomSkin = strlen(this->car->_skinName) != 0;
std::string bSkinName; std::string bSkinName;
std::string TmpPath = GfDataDir(); std::string TmpPath;
if (bCustomSkin) if (bCustomSkin)
{ {
std::string dataDir = GfDataDir(), localDir = GfLocalDir();
snprintf(buf, MaxPathSize, "cars/models/%s/wheel3d-%s.png", car->_carName, car->_skinName); snprintf(buf, MaxPathSize, "cars/models/%s/wheel3d-%s.png", car->_carName, car->_skinName);
bSkinName = TmpPath + buf; std::string dataSkin = TmpPath + buf,
bool exist = osgDB::fileExists(bSkinName); localSkin = localDir + buf;
GfLogInfo("Car Texture = %s\n", bSkinName.c_str());
if (!exist) if (osgDB::fileExists(localSkin))
bSkinName.clear();
else
{ {
TmpPath = localDir;
snprintf(buf, MaxPathSize, "wheel3d-%s", car->_skinName);
bSkinName = buf;
}
else if (osgDB::fileExists(dataSkin))
{
TmpPath = dataDir;
snprintf(buf, MaxPathSize, "wheel3d-%s", car->_skinName); snprintf(buf, MaxPathSize, "wheel3d-%s", car->_skinName);
bSkinName = buf; bSkinName = buf;
} }

View file

@ -2216,7 +2216,9 @@ void SDHUD::Refresh(tSituation *s, const SDFrameInfo* frameInfo,
void *carparam; void *carparam;
char *carName; char *carName;
temp << "cars/models/" << currCar->_carName << "/" << currCar->_carName << ".xml"; temp << "cars/models/" << currCar->_carName << "/" << currCar->_carName << ".xml";
carparam = GfParmReadFile(temp.str().c_str(), GFPARM_RMODE_STD); carparam = GfParmReadFileLocal(temp.str().c_str(), GFPARM_RMODE_STD);
if (!carparam)
carparam = GfParmReadFile(temp.str().c_str(), GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);

View file

@ -1671,6 +1671,10 @@ void grInitBoardCar(tCarElt *car)
lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName); lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName);
lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "%scars/models/%s;", GfLocalDir(), car->_carName);
if (bMasterModel)
lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "%scars/models/%s;", GfLocalDir(), car->_masterModel);
lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_carName); lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_carName);
if (bMasterModel) if (bMasterModel)
lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_masterModel); lg += snprintf(filePath + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_masterModel);

View file

@ -670,7 +670,7 @@ grInitShadow(tCarElt *car)
{ {
GfLogInfo("Init shadow static SSG\n"); GfLogInfo("Init shadow static SSG\n");
char buf[512]; std::string paths;
const char *shdTexName; const char *shdTexName;
int i; int i;
float x; float x;
@ -683,11 +683,23 @@ grInitShadow(tCarElt *car)
ssgNormalArray *shd_nrm = new ssgNormalArray(1); ssgNormalArray *shd_nrm = new ssgNormalArray(1);
ssgTexCoordArray *shd_tex = new ssgTexCoordArray(GR_SHADOW_POINTS+1); ssgTexCoordArray *shd_tex = new ssgTexCoordArray(GR_SHADOW_POINTS+1);
snprintf(buf, sizeof(buf), "cars/models/%s;", car->_carName); const char *dirs[] = {GfLocalDir(), GfDataDir()};
if (strlen(car->_masterModel) > 0) // Add the master model path if we are using a template.
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "cars/models/%s;", car->_masterModel);
grSetFilePath(buf); for (size_t i = 0; i < sizeof dirs / sizeof *dirs; i++)
{
const char *dir = dirs[i],
*models[] = {car->_carName, car->_masterModel};
for (size_t i = 0; i < sizeof models / sizeof *models; i++)
{
paths += dir;
paths += "cars/models/";
paths += models[i];
paths += ";";
}
}
grSetFilePath(paths.c_str());
shdTexName = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_SHADOW_TEXTURE, ""); shdTexName = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_SHADOW_TEXTURE, "");
@ -1069,9 +1081,13 @@ grInitCar(tCarElt *car)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName); lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%scars/models/%s;", GfLocalDir(), car->_carName);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_carName); lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_carName);
if (bMasterModel) if (bMasterModel)
{
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%scars/models/%s;", GfLocalDir(), car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_masterModel); lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/models/%s;", car->_masterModel);
}
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "data/objects;"); lg += snprintf(buf + lg, nMaxTexPathSize - lg, "data/objects;");

View file

@ -370,7 +370,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -407,7 +407,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_NAME, car->_name); GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -525,7 +525,7 @@ ReUpdateQualifCurRes(tCarElt *car)
maxLines = ReUI().getResultsTableRowCount(); maxLines = ReUI().getResultsTableRowCount();
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
char pszTitle[128]; char pszTitle[128];
@ -595,7 +595,7 @@ ReUpdateQualifCurRes(tCarElt *car)
for (xx = 0; xx < nCars; ++xx) { for (xx = 0; xx < nCars; ++xx) {
car = ReInfo->s->cars[ xx ]; car = ReInfo->s->cars[ xx ];
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = strdup(GfParmGetName(carparam)); carName = strdup(GfParmGetName(carparam));
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);
@ -657,7 +657,7 @@ ReUpdateRaceCurRes()
for (xx = 0; xx < ncars; ++xx) { for (xx = 0; xx < ncars; ++xx) {
car = ReInfo->s->cars[ xx ]; car = ReInfo->s->cars[ xx ];
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = strdup(GfParmGetName(carparam)); carName = strdup(GfParmGetName(carparam));
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);

View file

@ -660,8 +660,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
category specs and driver modifications (=> handle) */ category specs and driver modifications (=> handle) */
/* Read Car model specifications */ /* Read Car model specifications */
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, carname.c_str()); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, carname.c_str());
carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); carhdle = GfParmReadFileBoth(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
} }
else else
{ {
@ -669,7 +668,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
category specs and driver modifications (=> handle) */ category specs and driver modifications (=> handle) */
/* Read Car model specifications */ /* Read Car model specifications */
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, elt->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, elt->_carName);
carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); carhdle = GfParmReadFileBoth(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
} }
category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL); category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL);

View file

@ -799,7 +799,7 @@ ReRaceRealStart(void)
{ {
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml",
s->cars[i]->_carName, s->cars[i]->_carName); s->cars[i]->_carName, s->cars[i]->_carName);
carHdle = GfParmReadFile(buf, GFPARM_RMODE_STD); carHdle = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
snprintf(buf, sizeof(buf), "Loading %s driver (%s) ...", snprintf(buf, sizeof(buf), "Loading %s driver (%s) ...",
s->cars[i]->_name, GfParmGetName(carHdle)); s->cars[i]->_name, GfParmGetName(carHdle));

View file

@ -290,7 +290,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname); GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -328,7 +328,7 @@ ReStoreRaceResults(const char *race)
snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race); snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name); GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);
@ -397,7 +397,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname); GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -436,7 +436,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname); GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName); GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -555,7 +555,7 @@ ReUpdateQualifCurRes(tCarElt *car)
maxLines = ReUI().getResultsTableRowCount(); maxLines = ReUI().getResultsTableRowCount();
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam); carName = GfParmGetName(carparam);
char pszTitle[128]; char pszTitle[128];
@ -625,7 +625,7 @@ ReUpdateQualifCurRes(tCarElt *car)
for (xx = 0; xx < nCars; ++xx) { for (xx = 0; xx < nCars; ++xx) {
car = ReInfo->s->cars[ xx ]; car = ReInfo->s->cars[ xx ];
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = strdup(GfParmGetName(carparam)); carName = strdup(GfParmGetName(carparam));
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);
@ -687,7 +687,7 @@ ReUpdateRaceCurRes()
for (xx = 0; xx < ncars; ++xx) { for (xx = 0; xx < ncars; ++xx) {
car = ReInfo->s->cars[ xx ]; car = ReInfo->s->cars[ xx ];
snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carparam = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
carName = strdup(GfParmGetName(carparam)); carName = strdup(GfParmGetName(carparam));
GfParmReleaseHandle(carparam); GfParmReleaseHandle(carparam);

View file

@ -47,7 +47,9 @@ OpenalSound::OpenalSound(const char* filename, OpenalSoundInterface* sitf,
SDL_AudioSpec wavspec; SDL_AudioSpec wavspec;
Uint32 wavlen; Uint32 wavlen;
Uint8 *wavbuf; Uint8 *wavbuf;
if (!SDL_LoadWAV(filename, &wavspec, &wavbuf, &wavlen)) std::string localpath = std::string(GfLocalDir()) + filename;
if (!SDL_LoadWAV(localpath.c_str(), &wavspec, &wavbuf, &wavlen)
&& !SDL_LoadWAV(filename, &wavspec, &wavbuf, &wavlen))
{ {
if (alIsBuffer(buffer)) if (alIsBuffer(buffer))
alDeleteBuffers(1, &buffer); alDeleteBuffers(1, &buffer);

View file

@ -102,7 +102,8 @@ void grInitSound(tSituation* s, int ncars)
car->_carName, car->_carName,
(int)(sizeof(filename) - strlen(car->_carName) - strlen("cars/models//")), (int)(sizeof(filename) - strlen(car->_carName) - strlen("cars/models//")),
param); param);
if (!GfFileExists(filename)) std::string localname = std::string(GfLocalDir()) + filename;
if (!GfFileExists(localname.c_str()) && !GfFileExists(filename))
{ {
sprintf(filename, "data/sound/%.*s", sprintf(filename, "data/sound/%.*s",
(int)(sizeof(filename) - strlen(car->_carName) - strlen("data/sound/")), (int)(sizeof(filename) - strlen(car->_carName) - strlen("data/sound/")),

View file

@ -405,7 +405,7 @@ void CarSetupMenu::loadSettings()
std::ostringstream ossCarFileName; std::ostringstream ossCarFileName;
std::string strCarId = getCar()->getId(); std::string strCarId = getCar()->getId();
ossCarFileName << "cars/models/" << strCarId << '/' << strCarId << PARAMEXT; ossCarFileName << "cars/models/" << strCarId << '/' << strCarId << PARAMEXT;
void *hparmCar = GfParmReadFile(ossCarFileName.str(), GFPARM_RMODE_STD); void *hparmCar = GfParmReadFileBoth(ossCarFileName.str(), GFPARM_RMODE_STD);
if (!hparmCar) if (!hparmCar)
{ {
GfLogError("Car %s (file %s not %s)\n", GfLogError("Car %s (file %s not %s)\n",

View file

@ -410,9 +410,14 @@ rmdsChangeSkin(int dir)
strCurSkinDispName[0] = toupper(strCurSkinDispName[0]); strCurSkinDispName[0] = toupper(strCurSkinDispName[0]);
GfuiLabelSetText(ScrHandle, SkinEditId, strCurSkinDispName.c_str()); GfuiLabelSetText(ScrHandle, SkinEditId, strCurSkinDispName.c_str());
const std::string &filename = curSkin.getCarPreviewFileName();
std::string localname = std::string(GfLocalDir()) + filename;
// Load associated preview image (or "no preview" panel if none available). // Load associated preview image (or "no preview" panel if none available).
if (GfFileExists(curSkin.getCarPreviewFileName().c_str())) if (GfFileExists(localname.c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId, curSkin.getCarPreviewFileName().c_str()); GfuiStaticImageSet(ScrHandle, CarImageId, localname.c_str());
else if (GfFileExists(filename.c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId, filename.c_str());
else else
GfuiStaticImageSet(ScrHandle, CarImageId, "data/img/nocarpreview.png"); GfuiStaticImageSet(ScrHandle, CarImageId, "data/img/nocarpreview.png");

View file

@ -380,10 +380,14 @@ void RmGarageMenu::resetSkinComboBox(const std::string& strCarName,
void RmGarageMenu::resetCarPreviewImage(const GfDriverSkin& selSkin) void RmGarageMenu::resetCarPreviewImage(const GfDriverSkin& selSkin)
{ {
const int nCarImageId = getDynamicControlId("PreviewImage"); const int nCarImageId = getDynamicControlId("PreviewImage");
const std::string &filename = selSkin.getCarPreviewFileName();
std::string local = std::string(GfLocalDir()) + filename;
// Load the preview image. // Load the preview image.
if (GfFileExists(selSkin.getCarPreviewFileName().c_str())) if (GfFileExists(local.c_str()))
GfuiStaticImageSet(getMenuHandle(), nCarImageId, selSkin.getCarPreviewFileName().c_str()); GfuiStaticImageSet(getMenuHandle(), nCarImageId, local.c_str());
else if (GfFileExists(filename.c_str()))
GfuiStaticImageSet(getMenuHandle(), nCarImageId, filename.c_str());
else else
GfuiStaticImageSet(getMenuHandle(), nCarImageId, "data/img/nocarpreview.png"); GfuiStaticImageSet(getMenuHandle(), nCarImageId, "data/img/nocarpreview.png");
} }

View file

@ -189,7 +189,9 @@ rmStartRaceMenu(tRmInfo *info, void *startScr, void *abortScr, int start)
if (carName) if (carName)
{ {
snprintf(path, sizeof(path), "cars/models/%s/%s.xml", carName, carName); snprintf(path, sizeof(path), "cars/models/%s/%s.xml", carName, carName);
carHdle = GfParmReadFile(path, GFPARM_RMODE_STD); carHdle = GfParmReadFileLocal(path, GFPARM_RMODE_STD);
if (!carHdle)
carHdle = GfParmReadFile(path, GFPARM_RMODE_STD);
carName = GfParmGetName(carHdle); carName = GfParmGetName(carHdle);
} }