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-19 08:41:34 +01:00
parent eb415c78d4
commit afa38f2b0d
Signed by: xavi
GPG key ID: 84FF3612A9BF43F2
21 changed files with 173 additions and 101 deletions

View file

@ -416,7 +416,7 @@ static int getCategory(const std::string &car, std::string &out)
path += PARAMEXT;
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);
goto end;

View file

@ -82,17 +82,12 @@ void GfCars::reload()
_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.
tFList* lstFolders = GfDirGetList("cars/models");
tFList* lstFolders = GfDirGetList(path.c_str());
if (!lstFolders)
{
GfLogFatal("No car available in the 'cars' folder\n");
return;
}
std::string strLastCatId("none");
std::string strCatName;
@ -113,8 +108,10 @@ GfCars::GfCars()
const char* pszCarId = pFolder->name;
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);
if (!hparmCar)
{
GfLogError("Ignoring car %s (file %s not %s)\n",
@ -168,6 +165,14 @@ GfCars::GfCars()
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
{
return _pPrivate->vecCatIds;

View file

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

View file

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

View file

@ -173,6 +173,41 @@ void SDCar::loadCarLights()
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)
{
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;
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);
strTPath = TmpPath+buf;
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);
std::string carmodel = buf;
strPath+=buf;
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());
}
osg::ref_ptr<osg::Node> pCar = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pCar)
std::string localpath = std::string(GfLocalDir()) + carmodel;
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");
else
{
@ -314,53 +357,24 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
{
_wing1 = true;
std::string tmp = GfDataDir();
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
static const struct wing
{
GfLogError("Failed to load %s\n", strPath.c_str());
pWin1 = new osg::Node;
}
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
const char *key, *name;
} wings[] =
{
GfLogError("Failed to load %s\n", strPath.c_str());
pWin2 = new osg::Node;
}
pWin2->setName("WING2");
GfLogDebug("Load Wing2 ACC ! %s\n", strPath.c_str());
{PRM_WING_1, "WING1"},
{PRM_WING_2, "WING2"},
{PRM_WING_3, "WING3"}
};
param = GfParmGetStr(handle, path, PRM_WING_3, NULL);
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
for (size_t i = 0; i < sizeof wings / sizeof *wings; i++)
{
GfLogError("Failed to load %s\n", strPath.c_str());
pWin3 = new osg::Node;
const struct wing &w = wings[i];
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)
{
@ -403,8 +417,10 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
param = GfParmGetStr(handle, path, PRM_REARWINGMODEL, "");
strPath = tmp+param;
osg::ref_ptr<osg::Node> pWing1_branch = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pWing1_branch)
std::string local = std::string(GfLocalDir()) + buf + param;
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());
else
{
@ -437,8 +453,8 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
strPath= tmp+param;
pCockpit = loader.Load3dFile(strPath, true, bCarName, bSkinName);
if (pCockpit)
if (!(pCockpit = loader.Load3dFile(GfLocalDir() + strPath, true, bCarName, bSkinName))
&& !(pCockpit = loader.Load3dFile(strPath, true, bCarName, bSkinName)))
GfLogDebug("Cockpit loaded = %s !\n", strPath.c_str());
else
{
@ -456,14 +472,15 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
if (param)
{
_steer = true;
std::string tmpPath = GfDataDir();
std::string tmpPath = GfLocalDir();
snprintf(buf, nMaxTexPathSize, "cars/models/%s/", car->_carName);
tmpPath = tmpPath+buf;
strPath = tmpPath + param;
osg::ref_ptr<osg::Node> steerEntityLo = loader.Load3dFile(strPath, true, "", "");
if (steerEntityLo == nullptr)
osg::ref_ptr<osg::Node> steerEntityLo;
if (!(steerEntityLo = loader.Load3dFile(GfLocalDir() + strPath, true, "", ""))
&& !(steerEntityLo = loader.Load3dFile(strPath, true, "", "")))
GfLogError("Failed to load %s\n", strPath.c_str());
else
{
@ -505,8 +522,9 @@ osg::ref_ptr<osg::Node> SDCar::loadCar(tCarElt *Car, bool tracktype, bool subcat
tmpPath = tmpPath+buf;
strPath = tmpPath + param;
osg::ref_ptr<osg::Node> steerEntityHi = loader.Load3dFile(strPath, true, "", "");
if (steerEntityHi == nullptr)
osg::ref_ptr<osg::Node> steerEntityHi;
if (!(steerEntityHi = loader.Load3dFile(GfLocalDir() + strPath, true, "", ""))
&& !(steerEntityHi = loader.Load3dFile(strPath, true, "", "")))
{
GfLogError("Failed to load: %s\n", strPath.c_str());
steerEntityHi = new osg::Node;

View file

@ -79,6 +79,10 @@ private :
void setReflectionMap(osg::ref_ptr<osg::Texture> map);
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 :
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;
std::string bSkinName;
std::string TmpPath = GfDataDir();
std::string TmpPath;
if (bCustomSkin)
{
std::string dataDir = GfDataDir(), localDir = GfLocalDir();
snprintf(buf, MaxPathSize, "cars/models/%s/wheel3d-%s.png", car->_carName, car->_skinName);
bSkinName = TmpPath + buf;
bool exist = osgDB::fileExists(bSkinName);
GfLogInfo("Car Texture = %s\n", bSkinName.c_str());
std::string dataSkin = TmpPath + buf,
localSkin = localDir + buf;
if (!exist)
bSkinName.clear();
else
if (osgDB::fileExists(localSkin))
{
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);
bSkinName = buf;
}

View file

@ -2216,7 +2216,9 @@ void SDHUD::Refresh(tSituation *s, const SDFrameInfo* frameInfo,
void *carparam;
char *carName;
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);
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, "%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);
if (bMasterModel)
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");
char buf[512];
std::string paths;
const char *shdTexName;
int i;
float x;
@ -683,11 +683,23 @@ grInitShadow(tCarElt *car)
ssgNormalArray *shd_nrm = new ssgNormalArray(1);
ssgTexCoordArray *shd_tex = new ssgTexCoordArray(GR_SHADOW_POINTS+1);
snprintf(buf, sizeof(buf), "cars/models/%s;", car->_carName);
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);
const char *dirs[] = {GfLocalDir(), GfDataDir()};
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, "");
@ -1069,9 +1081,13 @@ grInitCar(tCarElt *car)
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);
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, "data/objects;");

View file

@ -576,7 +576,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
category specs and driver modifications (=> handle) */
/* Read Car model specifications */
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);
}
else
@ -587,7 +587,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
/* Read Car model specifications */
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);
}
category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL);

View file

@ -370,7 +370,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
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);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -407,7 +407,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
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);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -525,7 +525,7 @@ ReUpdateQualifCurRes(tCarElt *car)
maxLines = ReUI().getResultsTableRowCount();
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);
char pszTitle[128];
@ -595,7 +595,7 @@ ReUpdateQualifCurRes(tCarElt *car)
for (xx = 0; xx < nCars; ++xx) {
car = ReInfo->s->cars[ xx ];
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));
GfParmReleaseHandle(carparam);
@ -657,7 +657,7 @@ ReUpdateRaceCurRes()
for (xx = 0; xx < ncars; ++xx) {
car = ReInfo->s->cars[ xx ];
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));
GfParmReleaseHandle(carparam);

View file

@ -660,8 +660,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
category specs and driver modifications (=> handle) */
/* Read Car model specifications */
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);
}
else
{
@ -669,7 +668,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
category specs and driver modifications (=> handle) */
/* Read Car model specifications */
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);
}
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",
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) ...",
s->cars[i]->_name, GfParmGetName(carHdle));

View file

@ -290,7 +290,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
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);
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);
GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name);
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);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
GfParmReleaseHandle(carparam);
@ -397,7 +397,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
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);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -436,7 +436,7 @@ ReStoreRaceResults(const char *race)
GfParmSetStr(results, path, RE_ATTR_SNAME, car->_sname);
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);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
@ -555,7 +555,7 @@ ReUpdateQualifCurRes(tCarElt *car)
maxLines = ReUI().getResultsTableRowCount();
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);
char pszTitle[128];
@ -625,7 +625,7 @@ ReUpdateQualifCurRes(tCarElt *car)
for (xx = 0; xx < nCars; ++xx) {
car = ReInfo->s->cars[ xx ];
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));
GfParmReleaseHandle(carparam);
@ -687,7 +687,7 @@ ReUpdateRaceCurRes()
for (xx = 0; xx < ncars; ++xx) {
car = ReInfo->s->cars[ xx ];
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));
GfParmReleaseHandle(carparam);

View file

@ -47,7 +47,9 @@ OpenalSound::OpenalSound(const char* filename, OpenalSoundInterface* sitf,
SDL_AudioSpec wavspec;
Uint32 wavlen;
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))
alDeleteBuffers(1, &buffer);

View file

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

View file

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

View file

@ -410,9 +410,14 @@ rmdsChangeSkin(int dir)
strCurSkinDispName[0] = toupper(strCurSkinDispName[0]);
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).
if (GfFileExists(curSkin.getCarPreviewFileName().c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId, curSkin.getCarPreviewFileName().c_str());
if (GfFileExists(localname.c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId, localname.c_str());
else if (GfFileExists(filename.c_str()))
GfuiStaticImageSet(ScrHandle, CarImageId, filename.c_str());
else
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)
{
const int nCarImageId = getDynamicControlId("PreviewImage");
const std::string &filename = selSkin.getCarPreviewFileName();
std::string local = std::string(GfLocalDir()) + filename;
// Load the preview image.
if (GfFileExists(selSkin.getCarPreviewFileName().c_str()))
GfuiStaticImageSet(getMenuHandle(), nCarImageId, selSkin.getCarPreviewFileName().c_str());
if (GfFileExists(local.c_str()))
GfuiStaticImageSet(getMenuHandle(), nCarImageId, local.c_str());
else if (GfFileExists(filename.c_str()))
GfuiStaticImageSet(getMenuHandle(), nCarImageId, filename.c_str());
else
GfuiStaticImageSet(getMenuHandle(), nCarImageId, "data/img/nocarpreview.png");
}

View file

@ -189,7 +189,9 @@ rmStartRaceMenu(tRmInfo *info, void *startScr, void *abortScr, int start)
if (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);
}