TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
racetrackselect.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : racetrackselect.cpp
4 created : Mon Jun 1 20:00:00 CET 2026
5 copyright : (C) 2026 by Bernhard Wymann
6 email : berniw@bluewin.ch
7
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
22
23#include <stdio.h>
24#include <string.h>
25
26#include <tgf.h>
27#include <track.h>
28#include <raceman.h>
29
30#include "racetrackselect.h"
31
32
33tReTrackCandidate::tReTrackCandidate(const char *trackCategory, const char *trackName)
34 : category(trackCategory ? trackCategory : ""),
35 name(trackName ? trackName : "")
36{
37}
38
39
44
45
53static bool
54reBuildTrackFileName(const char *category, const char *trackName, char *trackFile, int trackFileSize)
55{
56 if (!category || !category[0] || !trackName || !trackName[0] || !trackFile || trackFileSize <= 0) {
57 return false;
58 }
59
60 const int written = snprintf(trackFile, trackFileSize, "tracks/%s/%s/%s.%s", category, trackName, trackName, TRKEXT);
61 return written >= 0 && written < trackFileSize;
62}
63
64
65bool
66ReTrackFileExists(const char *category, const char *trackName, char *trackFile, int trackFileSize)
67{
68 const int BUFSIZE = 1024;
69 char localTrackFile[BUFSIZE];
70 char *fileName = trackFile ? trackFile : localTrackFile;
71 const int fileNameSize = trackFile ? trackFileSize : BUFSIZE;
72
73 if (!reBuildTrackFileName(category, trackName, fileName, fileNameSize)) {
74 return false;
75 }
76
77 void *trackHandle = GfParmReadFile(fileName, GFPARM_RMODE_STD | GFPARM_RMODE_PRIVATE);
78 if (!trackHandle) {
79 return false;
80 }
81
82 GfParmReleaseHandle(trackHandle);
83 return true;
84}
85
86
87std::vector<tReTrackCandidate>
89{
90 std::vector<tReTrackCandidate> tracks;
91 tFList *categoryList = GfDirGetList("tracks");
92
93 if (!categoryList) {
94 return tracks;
95 }
96
97 tFList *category = categoryList;
98 do {
99 const int BUFSIZE = 1024;
100 char path[BUFSIZE];
101 snprintf(path, BUFSIZE, "tracks/%s", category->name);
102
103 tFList *trackList = GfDirGetList(path);
104 if (trackList) {
105 tFList *track = trackList;
106 do {
107 if (ReTrackFileExists(category->name, track->name, NULL, 0)) {
108 tracks.push_back(tReTrackCandidate(category->name, track->name));
109 }
110 track = track->next;
111 } while (track != trackList);
112
113 GfDirFreeList(trackList, NULL, true, true);
114 }
115
116 category = category->next;
117 } while (category != categoryList);
118
119 GfDirFreeList(categoryList, NULL, true, true);
120 return tracks;
121}
122
123
124bool
125ReResolveTrackSelection(void *params, int curTrackIndex, const std::vector<tReTrackCandidate>& availableTracks, tReTrackSelection *selection, bool updateParams)
126{
127 if (!selection) {
128 return false;
129 }
130
131 selection->category.clear();
132 selection->name.clear();
133 selection->fallback = false;
134
135 if (availableTracks.empty()) {
136 return false;
137 }
138
139 const int BUFSIZE = 1024;
140 char path[BUFSIZE];
141 snprintf(path, BUFSIZE, "%s/%d", RM_SECT_TRACKS, curTrackIndex);
142
143 const char *currentCategory = params ? GfParmGetStr(params, path, RM_ATTR_CATEGORY, "") : "";
144 const char *currentTrack = params ? GfParmGetStr(params, path, RM_ATTR_NAME, "") : "";
145 const tReTrackCandidate *firstTrack = NULL;
146 const tReTrackCandidate *firstSameCategoryTrack = NULL;
147 const tReTrackCandidate *selectedTrack = NULL;
148
149 for (std::vector<tReTrackCandidate>::const_iterator it = availableTracks.begin(); it != availableTracks.end(); ++it) {
150 if (it->category.empty() || it->name.empty()) {
151 continue;
152 }
153
154 if (!firstTrack) {
155 firstTrack = &(*it);
156 }
157
158 if (currentCategory[0] && it->category == currentCategory && !firstSameCategoryTrack) {
159 firstSameCategoryTrack = &(*it);
160 }
161
162 if (currentCategory[0] && currentTrack[0] && it->category == currentCategory && it->name == currentTrack) {
163 selectedTrack = &(*it);
164 break;
165 }
166 }
167
168 if (!selectedTrack) {
169 selectedTrack = firstSameCategoryTrack ? firstSameCategoryTrack : firstTrack;
170 }
171
172 if (!selectedTrack) {
173 return false;
174 }
175
176 selection->category = selectedTrack->category;
177 selection->name = selectedTrack->name;
178 selection->fallback = currentCategory[0] == 0 || currentTrack[0] == 0 || selection->category != currentCategory || selection->name != currentTrack;
179
180 if (selection->fallback && updateParams && params) {
181 GfParmSetStr(params, path, RM_ATTR_CATEGORY, selection->category.c_str());
182 GfParmSetStr(params, path, RM_ATTR_NAME, selection->name.c_str());
183 }
184
185 return true;
186}
void GfDirFreeList(tFList *list, tfDirfreeUserData freeUserData, bool freename, bool freedispname)
Free a directory list.
Definition directory.cpp:75
tFList * GfDirGetList(const char *dir)
Get the list of files of a given directory.
Definition directory.cpp:43
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
Definition params.cpp:2453
int GfParmSetStr(void *handle, const char *path, const char *key, const char *val)
Set a string parameter in the parameter set handle.
Definition params.cpp:2623
void GfParmReleaseHandle(void *parmHandle)
Release given parameter set handle parmHandle.
Definition params.cpp:1963
void * GfParmReadFile(const char *file, int mode)
Read parameter set from file and return handle to parameter set.
Definition params.cpp:1173
#define RM_ATTR_NAME
Definition raceman.h:258
#define RM_SECT_TRACKS
Definition raceman.h:240
#define RM_ATTR_CATEGORY
Definition raceman.h:260
bool ReResolveTrackSelection(void *params, int curTrackIndex, const std::vector< tReTrackCandidate > &availableTracks, tReTrackSelection *selection, bool updateParams)
Resolve the current race-manager track entry to an available track.
std::vector< tReTrackCandidate > ReFindAvailableTracks(void)
Find all available tracks under the current TORCS track search path.
bool ReTrackFileExists(const char *category, const char *trackName, char *trackFile, int trackFileSize)
Check whether a track XML file exists and can be parsed.
static bool reBuildTrackFileName(const char *category, const char *trackName, char *trackFile, int trackFileSize)
Build the track XML path for a category/name pair.
Helpers for selecting a valid race-manager track.
struct FList * next
Next entry.
Definition tgf.h:230
char * name
File name.
Definition tgf.h:232
Track directory pair that can be selected by a race manager.
tReTrackCandidate(const char *trackCategory, const char *trackName)
Build a track candidate from category and track directory names.
std::string name
Track directory and XML base name.
std::string category
Track category directory name.
Result of resolving a race-manager track selection.
tReTrackSelection()
Create an empty selection result.
std::string name
Selected track directory and XML base name.
std::string category
Selected track category directory name.
bool fallback
true if the configured track was replaced by a fallback
#define GFPARM_RMODE_STD
Return a new handle sharing cached data for this filename, if available.
Definition tgf.h:264
struct FList tFList
List of (DLL) files for a Directory.
#define GFPARM_RMODE_PRIVATE
Private means the handle is not shared/cached.
Definition tgf.h:267
int track(tModInfo *modInfo)
Definition trackitf.cpp:85