Support reading trackdata from GfLocalDir()

This would allow users to extract track 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-18 09:35:46 +01:00
parent b76d0cbdbb
commit e5e83f3921
Signed by: xavi
GPG key ID: 84FF3612A9BF43F2
14 changed files with 160 additions and 112 deletions

View file

@ -86,10 +86,8 @@ GfTracks::~GfTracks()
_pPrivate = 0;
}
GfTracks::GfTracks()
void GfTracks::list(const std::string &path)
{
_pPrivate = new GfTracks::Private;
// Get the list of sub-dirs in the "tracks" folder (the track categories).
tFList* lstCatFolders = GfDirGetList("tracks");
if (!lstCatFolders)
@ -113,7 +111,7 @@ GfTracks::GfTracks()
continue;
// Get the list of sub-dirs in the "tracks" folder (the track categories).
std::string strDirName("tracks/");
std::string strDirName(path);
strDirName += pszCatId;
tFList* lstTrackFolders = GfDirGetList(strDirName.c_str());
if (!lstTrackFolders)
@ -143,7 +141,7 @@ GfTracks::GfTracks()
continue;
std::ostringstream ossFileName;
ossFileName << "tracks/" << pszCatId << '/' << pszTrackId
ossFileName << path << pszCatId << '/' << pszTrackId
<< '/' << pszTrackId << '.' << TRKEXT;
const std::string strTrackFileName(ossFileName.str());
if (!GfFileExists(strTrackFileName.c_str()))
@ -155,13 +153,13 @@ GfTracks::GfTracks()
// Get 1st level track info (those which don't need to open any file).
ossFileName.str("");
ossFileName << "tracks/" << pszCatId << '/' << pszTrackId
ossFileName << path << pszCatId << '/' << pszTrackId
<< '/' << pszTrackId << ".jpg";
std::string strPreviewFileName(ossFileName.str());
if (!GfFileExists(strPreviewFileName.c_str()))
{
ossFileName.str("");
ossFileName << "tracks/" << pszCatId << '/' << pszTrackId
ossFileName << path << pszCatId << '/' << pszTrackId
<< '/' << pszTrackId << ".png";
strPreviewFileName = ossFileName.str();
}
@ -169,7 +167,7 @@ GfTracks::GfTracks()
strPreviewFileName = "data/img/splash-trackselect.jpg";
ossFileName.str("");
ossFileName << "tracks/" << pszCatId << '/' << pszTrackId << '/' << "outline.png";
ossFileName << path << pszCatId << '/' << pszTrackId << '/' << "outline.png";
std::string strOutlineFileName(ossFileName.str());
if (!GfFileExists(strOutlineFileName.c_str()))
strOutlineFileName = "data/img/notrackoutline.png";
@ -201,6 +199,14 @@ GfTracks::GfTracks()
print(false); // No verbose here, otherwise infinite recursion.
}
GfTracks::GfTracks()
{
_pPrivate = new GfTracks::Private;
list(std::string(GfLocalDir()) + "tracks/");
list(std::string(GfDataDir()) + "tracks/");
}
ITrackLoader* GfTracks::getTrackLoader() const
{
return _pPrivate->piTrackLoader;
@ -226,7 +232,7 @@ const std::vector<std::string>& GfTracks::getCategoryNames() const
{
std::ostringstream ossFileName;
ossFileName << "data/tracks/" << *itCatId << '.' << TRKEXT;
void* hparmCat = GfParmReadFile(ossFileName.str(), GFPARM_RMODE_STD);
void* hparmCat = GfParmReadFileBoth(ossFileName.str(), GFPARM_RMODE_STD);
const char* pszCatName;
if (!hparmCat)
{
@ -624,10 +630,13 @@ bool GfTrack::load() const
std::ostringstream ossFileName;
ossFileName << "tracks/" << _strCatId << '/' << _strId << '/'
<< (pTrack->graphic.model3d ? pTrack->graphic.model3d : "track.ac");
if (!GfFileExists(ossFileName.str().c_str()))
std::string path = ossFileName.str();
if (!GfFileExists((GfLocalDir() + path).c_str())
&& !GfFileExists((GfDataDir() + path).c_str()))
{
GfLogWarning("Unusable track %s : could not find 3D model %s\n",
_strId.c_str(), ossFileName.str().c_str());
_strId.c_str(), path.c_str());
return false;
}

View file

@ -128,6 +128,8 @@ protected:
GfTracks();
~GfTracks();
void list(const std::string &path);
protected:
// The singleton itself.

View file

@ -530,7 +530,11 @@ int initTrack(tTrack *track)
// TODO: Find a solution to init the graphics first independent of objects.
// Now, do the real track loading job.
grTrackHandle = GfParmReadFile(track->filename, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
grTrackHandle = GfParmReadFileBoth(track->filename, GFPARM_RMODE_STD);
if (!grTrackHandle) {
GfLogError("GfParmReadFileBoth %s failed\n", track->filename);
return -1;
}
//Options = new SDOptions;
@ -538,7 +542,9 @@ int initTrack(tTrack *track)
render = new SDRender;
//cam = new SDCamera;
scenery->LoadScene(track);
if (scenery->LoadScene(track))
return -1;
render->Init(track);
Clouds = track->local.clouds;

View file

@ -44,13 +44,16 @@ void SDBackground::build(int X, int Y, int Z, const std::string& TrackPath)
{
osgDB::Registry::instance()->clearObjectCache();
std::string LocalPath = GfDataDir();
std::string DataPath = GfDataDir(), LocalPath = GfLocalDir();
osgDB::FilePathList pathList = osgDB::Registry::instance()->getDataFilePathList();
pathList.push_front(DataPath + "data/objects/");
pathList.push_front(DataPath + "data/textures/");
pathList.push_front(DataPath + TrackPath);
pathList.push_front(LocalPath + "data/objects/");
pathList.push_front(LocalPath + "data/textures/");
pathList.push_front(TrackPath);
pathList.push_front(LocalPath + TrackPath);
osgDB::Registry::instance()->setDataFilePathList(pathList);
//osg::ref_ptr<osg::MatrixTransform> _background_transform = new osg::MatrixTransform;

View file

@ -422,10 +422,16 @@ void SDPit::build(const tTrack *track)
// load pit indicator
if (bHasPitIndicator)
{
loader.AddSearchPath(std::string("tracks/") + track->category + "/" + track->internalname);
loader.AddSearchPath("data/objects");
loader.AddSearchPath("data/textures");
loader.AddSearchPath("data/img");
std::string localdir = GfLocalDir(), datadir = GfDataDir();
loader.AddSearchPath(localdir + "tracks/" + track->category + "/" + track->internalname);
loader.AddSearchPath(localdir + "data/objects");
loader.AddSearchPath(localdir + "data/textures");
loader.AddSearchPath(localdir + "data/img");
loader.AddSearchPath(datadir + "tracks/" + track->category + "/" + track->internalname);
loader.AddSearchPath(datadir + "data/objects");
loader.AddSearchPath(datadir + "data/textures");
loader.AddSearchPath(datadir + "data/img");
std::string filename = pits->pitindicator == 1
? "pit_indicator.ac"

View file

@ -69,7 +69,7 @@ SDScenery::~SDScenery(void)
}
}
void SDScenery::LoadScene(const tTrack *track)
int SDScenery::LoadScene(const tTrack *track)
{
void *hndl = grTrackHandle;
const char *acname;
@ -118,44 +118,37 @@ void SDScenery::LoadScene(const tTrack *track)
GfLogError("No specified track 3D model file\n");
}
std::string PathTmp = GfDataDir();
_bgsky = strcmp(GfParmGetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_DYNAMICSKYDOME, GR_ATT_DYNAMICSKYDOME_DISABLED), GR_ATT_DYNAMICSKYDOME_ENABLED) == 0;
if (_bgsky)
{
std::string strPath = PathTmp;
snprintf(buf, 256, "tracks/%s/%s/", SDTrack->category, SDTrack->internalname);
strPath += buf;
m_background->build(grWrldX, grWrldY, grWrldZ, strPath);
snprintf(buf, 256, "tracks/%s/%s/", track->category, track->internalname);
m_background->build(grWrldX, grWrldY, grWrldZ, buf);
GfLogDebug("Background loaded\n");
}
std::string strPath = GfDataDir();
snprintf(buf, 256, "tracks/%s/%s/", SDTrack->category, SDTrack->internalname);
snprintf(buf, 256, "tracks/%s/%s/", track->category, track->internalname);
std::string ext = osgDB::getFileExtension(acname);
if (ext == "acc")
{
GfLogDebug("Load 3D Model Scene ACC\n");
strPath+=buf;
_strTexturePath = strPath;
strPath+=acname;
LoadTrack(strPath);
if (!LoadTrack(buf, acname))
{
GfLogError("LoadTrack %s%s failed\n", buf, acname);
return -1;
}
}
else
{
strPath+=buf;
std::string strTPath = GfDataDir();
std::string localdir = GfLocalDir(), datadir = GfDataDir();
osgDB::FilePathList pathList = osgDB::Registry::instance()->getDataFilePathList();
pathList.push_back(strPath);
GfLogDebug("Track Path : %s\n", pathList.back().c_str());
pathList.push_back(strTPath+"data/objects/");
GfLogDebug("Texture Path : %s\n", pathList.back().c_str());
pathList.push_back(strTPath+"data/textures/");
GfLogDebug("Texture Path : %s\n", pathList.back().c_str());
pathList.push_back(localdir + buf);
pathList.push_back(localdir + "data/objects/");
pathList.push_back(localdir + "data/textures/");
pathList.push_back(datadir + buf);
pathList.push_back(datadir + "data/objects/");
pathList.push_back(datadir + "data/textures/");
osgDB::Registry::instance()->setDataFilePathList(pathList);
osg::ref_ptr<osg::Node> pTrack = osgDB::readNodeFile(acname);
@ -184,6 +177,7 @@ void SDScenery::LoadScene(const tTrack *track)
osgDB::Registry::instance()->setDataFilePathList( osgDB::FilePathList() );
osgDB::Registry::instance()->clearObjectCache();
return 0;
}
void SDScenery::LoadSkyOptions()
@ -219,22 +213,19 @@ void SDScenery::ShutdownScene(void)
_scenery = NULL;
}
bool SDScenery::LoadTrack(std::string& strTrack)
bool SDScenery::LoadTrack(const std::string &dir, const std::string &file)
{
std::string name;
GfLogDebug("Track Path : %s\n", strTrack.c_str());
std::string localdir = GfLocalDir();
osgLoader loader;
GfLogDebug("Texture Path : %s\n", _strTexturePath.c_str());
loader.AddSearchPath(_strTexturePath);
loader.AddSearchPath(dir);
loader.AddSearchPath(localdir + "data/textures/");
loader.AddSearchPath("data/textures/");
std::string strTPath = GfDataDir();
strTPath += "data/textures/";
GfLogDebug("Texture Path : %s\n", strTPath.c_str());
loader.AddSearchPath(strTPath);
std::string path = dir + file;
osg::Node *pTrack;
osg::Node *pTrack = loader.Load3dFile(strTrack, false, "", name);
if (pTrack)
if ((pTrack = loader.Load3dFile(GfLocalDir() + path))
|| (pTrack = loader.Load3dFile(path)))
{
pTrack->getOrCreateStateSet()->setRenderBinDetails(TRACKBIN,"RenderBin");
_scenery->addChild(pTrack);

View file

@ -104,8 +104,6 @@ private:
osg::ref_ptr<osg::Group> _scenery;
tTrack *SDTrack;
int _max_visibility;
int _nb_cloudlayer;
int _DynamicSkyDome;
@ -116,8 +114,6 @@ private:
bool _speedWay;
bool _speedWayLong;
std::string _strTexturePath;
static double grWrldX;
static double grWrldY;
static double grWrldZ;
@ -126,7 +122,7 @@ private:
void LoadGraphicsOptions();
void LoadSkyOptions();
void CustomizePits(void);
bool LoadTrack(std::string& strTrack);
bool LoadTrack(const std::string &dir, const std::string &file);
public:
/* Constructor */
@ -135,7 +131,7 @@ public:
/* Destructor */
~SDScenery(void);
void LoadScene(const tTrack *track);
int LoadScene(const tTrack *track);
void ShutdownScene(void);
void reposition(double X, double Y, double Z);
void update_tracklights(double currentTime, double totTime, int raceType);

View file

@ -502,8 +502,11 @@ grLoadBackground()
GfLogDebug("Loading background ...\n");
snprintf(buf, sizeof(buf), "tracks/%s/%s;data/img;data/textures;.",
grTrack->category, grTrack->internalname);
std::string trackpath = grTrackPath();
const char *track = trackpath.c_str();
snprintf(buf, sizeof(buf), "%s%s;%s;data/img;data/textures;.",
GfLocalDir(), track, track);
grSetFilePath(buf);
grGammaValue = 1.8;
grMipMap = 0;
@ -894,11 +897,13 @@ void grLoadBackgroundSky(void)
char buf2[256];
const char *bgsky;
ssgEntity *desc2;
std::string trackpath = grTrackPath();
const char *track = trackpath.c_str();
bgsky = "background-sky.ac";
snprintf(buf2, sizeof(buf2), "tracks/%s/%s;data/textures;.", grTrack->category, grTrack->internalname);
snprintf(buf2, sizeof(buf2), "%s%s;%s;data/textures;.", GfLocalDir(), track, track);
ssgTexturePath(buf2);
snprintf(buf2, sizeof(buf2), "tracks/%s/%s;data/objects", grTrack->category, grTrack->internalname);
snprintf(buf2, sizeof(buf2), "%s%s;%s;data/objects", GfLocalDir(), track, track);
ssgModelPath(buf2);
desc2 = grssgLoadAC3D(bgsky, NULL);

View file

@ -952,7 +952,12 @@ initTrack(tTrack *track)
grssgSetCurrentOptions(&options);
// Now, do the real track loading job.
grTrackHandle = GfParmReadFile(track->filename, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
grTrackHandle = GfParmReadFileBoth(track->filename, GFPARM_RMODE_STD);
if (!grTrackHandle) {
GfLogError("GfParmReadFileBoth %s failed\n", track->filename);
return -1;
}
if (grNbActiveScreens > 0)
return grLoadScene(track);

View file

@ -77,6 +77,16 @@ ssgBranch *CarlightAnchor = NULL;
ssgBranch *TrackLightAnchor = NULL;
ssgBranch *ThePits = NULL;
std::string
grTrackPath()
{
std::string trackpath = "tracks/";
trackpath += grTrack->category;
trackpath += "/";
trackpath += grTrack->internalname;
return trackpath;
}
// Must have (Question: What for ?)
int preScene(ssgEntity *e)
@ -227,9 +237,11 @@ grLoadScene(tTrack *track)
if ( grSkyDomeDistance > 0 )
grLoadBackgroundSky();
snprintf(buf, sizeof(buf), "tracks/%s/%s;data/textures;data/img;.", grTrack->category, grTrack->internalname);
std::string trackpath = grTrackPath();
const char *tr = trackpath.c_str();
snprintf(buf, sizeof(buf), "%s%s;%s;data/textures;data/img;.", GfLocalDir(), tr, tr);
ssgTexturePath(buf);
snprintf(buf, sizeof(buf), "tracks/%s/%s", grTrack->category, grTrack->internalname);
snprintf(buf, sizeof(buf), "%s%s;%s", GfLocalDir(), tr, tr);
ssgModelPath(buf);
desc = grssgLoadAC3D(acname, NULL);

View file

@ -27,6 +27,7 @@
#include <track.h> //tTrack
#include <raceman.h> // tSituation
#include "grmultitexstate.h"
#include <string>
namespace ssggraph {
@ -67,6 +68,7 @@ extern void grShutdownScene(void);
extern void grCustomizePits(void);
extern void grLoadPitsIndicator(tdble x,tdble y, tdble z, char *buf, int Pitind);
extern void grDrawBackground(class cGrCamera *, class cGrBackgroundCam *bgCam);
std::string grTrackPath();
//TODO: Question: What is this??? kilo
// Possible answer: Some try to lower GPU load by filtering the scene ? JP

View file

@ -46,12 +46,15 @@ tTrack *
TrackBuildv1(const char *trackfile)
{
TrackShutdown();
void *h = GfParmReadFileBoth (trackfile, GFPARM_RMODE_STD);
if (!h)
return nullptr;
theTrack = (tTrack*)calloc(1, sizeof(tTrack));
theCamList = (tRoadCam*)NULL;
theTrack->params = TrackHandle =
GfParmReadFile (trackfile, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT | GFPARM_RMODE_PRIVATE);
theTrack->params = TrackHandle = h;
theTrack->filename = strdup(trackfile);
@ -86,7 +89,7 @@ TrackBuildEx(const char *trackfile)
theTrack = (tTrack*)calloc(1, sizeof(tTrack));
theCamList = (tRoadCam*)NULL;
theTrack->params = TrackHandle = GfParmReadFile (trackfile, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT | GFPARM_RMODE_PRIVATE);
theTrack->params = TrackHandle = GfParmReadFileBoth (trackfile, GFPARM_RMODE_STD);
theTrack->filename = strdup(trackfile);

View file

@ -172,7 +172,7 @@ GetTrackName(const char *category, const char *trackName)
std::string name;
sprintf(buf, "tracks/%s/%s/%s.%s", category, trackName, trackName, TRKEXT);
trackHandle = GfParmReadFile(buf, GFPARM_RMODE_STD);
trackHandle = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
if (trackHandle) {
name = GfParmGetStr(trackHandle, TRK_SECT_HDR, TRK_ATT_NAME, trackName);
@ -195,37 +195,41 @@ GetTrackName(const char *category, const char *trackName)
static std::string
GetTrackPreviewFileName(const char *pszCategory, const char *pszTrack)
{
char buf[256];
static const char *extensions[] = {"jpg", "png"};
// Try JPEG first.
snprintf(buf, sizeof(buf), "tracks/%s/%s/%s.jpg", pszCategory, pszTrack, pszTrack);
buf[255] = 0; /* snprinf manual is not clear about that ... */
// Then PNG if not found.
if (!GfFileExists(buf))
for (size_t i = 0; i < sizeof extensions / sizeof *extensions; i++)
{
snprintf(buf, sizeof(buf), "tracks/%s/%s/%s.png", pszCategory, pszTrack, pszTrack);
buf[255] = 0; /* snprinf manual is not clear about that ... */
const char *ext = extensions[i];
std::string dirs[] = {GfLocalDir(), GfDataDir()};
for (size_t i = 0; i < sizeof dirs / sizeof *dirs; i++)
{
std::string path = dirs[i] + "tracks/" + pszCategory
+ "/" + pszTrack + "/" + pszTrack + "." + ext;
if (GfFileExists(path.c_str()))
return path;
}
}
// Then fallback.
if (!GfFileExists(buf))
strncpy(buf, "data/img/splash-networkrace.jpg", sizeof(buf));
return std::string(buf);
return "data/img/splash-networkrace.jpg";
}
static std::string
GetTrackOutlineFileName(const char *pszCategory,const char *pszTrack)
{
char buf[256];
std::string dirs[] = {GfLocalDir(), GfDataDir()};
snprintf(buf, sizeof(buf), "tracks/%s/%s/outline.png", pszCategory, pszTrack);
for (size_t i = 0; i < sizeof dirs / sizeof *dirs; i++)
{
std::string path = dirs[i] + "tracks/" + pszCategory + "/" + pszTrack
+ "/outline.png";
if (!GfFileExists(buf))
strncpy(buf, "data/img/transparent.png", sizeof(buf));
if (GfFileExists(path.c_str()))
return path;
}
return std::string(buf);
return "data/img/transparent.png";
}
// Called by both server and client

View file

@ -169,7 +169,7 @@ GetTrackName(const char *category, const char *trackName)
std::string name;
sprintf(buf, "tracks/%s/%s/%s.%s", category, trackName, trackName, TRKEXT);
trackHandle = GfParmReadFile(buf, GFPARM_RMODE_STD);
trackHandle = GfParmReadFileBoth(buf, GFPARM_RMODE_STD);
if (trackHandle) {
name = GfParmGetStr(trackHandle, TRK_SECT_HDR, TRK_ATT_NAME, trackName);
@ -192,37 +192,41 @@ GetTrackName(const char *category, const char *trackName)
static std::string
GetTrackPreviewFileName(const char *pszCategory, const char *pszTrack)
{
char buf[256];
static const char *extensions[] = {"jpg", "png"};
// Try JPEG first.
snprintf(buf, sizeof(buf), "tracks/%s/%s/%s.jpg", pszCategory, pszTrack, pszTrack);
buf[255] = 0; /* snprinf manual is not clear about that ... */
// Then PNG if not found.
if (!GfFileExists(buf))
for (size_t i = 0; i < sizeof extensions / sizeof *extensions; i++)
{
snprintf(buf, sizeof(buf), "tracks/%s/%s/%s.png", pszCategory, pszTrack, pszTrack);
buf[255] = 0; /* snprinf manual is not clear about that ... */
const char *ext = extensions[i];
std::string dirs[] = {GfLocalDir(), GfDataDir()};
for (size_t i = 0; i < sizeof dirs / sizeof *dirs; i++)
{
std::string path = dirs[i] + "tracks/" + pszCategory
+ "/" + pszTrack + "/" + pszTrack + "." + ext;
if (GfFileExists(path.c_str()))
return path;
}
}
// Then fallback.
if (!GfFileExists(buf))
strncpy(buf, "data/img/splash-networkrace.jpg", sizeof(buf));
return std::string(buf);
return "data/img/splash-networkrace.jpg";
}
static std::string
GetTrackOutlineFileName(const char *pszCategory,const char *pszTrack)
{
char buf[256];
std::string dirs[] = {GfLocalDir(), GfDataDir()};
snprintf(buf, sizeof(buf), "tracks/%s/%s/outline.png", pszCategory, pszTrack);
for (size_t i = 0; i < sizeof dirs / sizeof *dirs; i++)
{
std::string path = dirs[i] + "tracks/" + pszCategory + "/" + pszTrack
+ "/outline.png";
if (!GfFileExists(buf))
strncpy(buf, "data/img/transparent.png", sizeof(buf));
if (GfFileExists(path.c_str()))
return path;
}
return std::string(buf);
return "data/img/transparent.png";
}
static void