Re #222 (More skinningg targets) Skinnable pit door logo and 3d wheels

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

Former-commit-id: 7415d5ee23be7d5288f3b02c1b5e13fed460a0ee
Former-commit-id: 49747b54268f17f411b8a55967296823917eb711
This commit is contained in:
pouillot 2010-10-23 12:18:49 +00:00
parent 9641d32eec
commit 6f26271d6b
14 changed files with 492 additions and 206 deletions

View file

@ -90,10 +90,24 @@ typedef struct {
t3Dd statGC; /**< Static pos of GC (should be the origin of car axis) */
tWheelSpec wheel[4]; /**< Wheels specifications */
tVisualAttributes visualAttr; /**< Visual attributes */
char carTemplate[MAX_NAME_LEN]; /**< Car master model object (file) name */
char carSkin[MAX_NAME_LEN]; /**< Car skin (= texture file) name if not the default one */
char masterModel[MAX_NAME_LEN]; /**< Master 3D model car name (the exact folder name) */
char skinName[MAX_NAME_LEN]; /**< Custom skin name, if any */
int skinTargets; /**< Target objects for the custom skinning
<br>The possible targets are :
- RM_CAR_SKIN_TARGET_WHOLE_LIVERY
- RM_CAR_SKIN_TARGET_3D_WHEELS
- RM_CAR_SKIN_TARGET_INTERIOR
- RM_CAR_SKIN_TARGET_BOARD
- RM_CAR_SKIN_TARGET_PIT_DOOR
*/
#define RM_CAR_SKIN_TARGET_WHOLE_LIVERY 0x00000001 /**< The whole car external livery */
#define RM_CAR_SKIN_TARGET_3D_WHEELS 0x00000002 /**< The 3D wheels */
#define RM_CAR_SKIN_TARGET_INTERIOR 0x00000010 /**< The car interior */
#define RM_CAR_SKIN_TARGET_BOARD 0x00000020 /**< The interior instrument board */
#define RM_CAR_SKIN_TARGET_PIT_DOOR 0x00000100 /**< The pit door logo */
} tInitCar;
/* structure access short cuts */
/* structure access shortcuts */
#define _name info.name /**< short cut to tInitCar#name */
#define _teamname info.teamname /**< short cut to tInitCar#teamname */
#define _carName info.carName /**< short cut to tInitCar#carName */
@ -123,8 +137,9 @@ typedef struct {
#define _exhaustNb info.visualAttr.exhaustNb /**< short cut to tVisualAttributes#exhaustNb */
#define _exhaustPos info.visualAttr.exhaustPos /**< short cut to tVisualAttributes#exhaustPos */
#define _exhaustPower info.visualAttr.exhaustPower /**< short cut to tVisualAttributes#exhaustPower */
#define _carTemplate info.carTemplate /**< short cut to tInitCar#carTemplate */
#define _carSkin info.carSkin /**< short cut to tInitCar#carSkin */
#define _masterModel info.masterModel /**< short cut to tInitCar#masterModel */
#define _skinName info.skinName /**< short cut to tInitCar#skinName */
#define _skinTargets info.skinTargets /**< short cut to tInitCar#skinTargets */
#define RM_DRV_HUMAN 1
#define RM_DRV_ROBOT 2

View file

@ -284,6 +284,7 @@ typedef struct RmInfo
#define RM_ATTR_IDX "idx"
#define RM_ATTR_CARNAME "car name"
#define RM_ATTR_SKINNAME "skin name"
#define RM_ATTR_SKINTARGETS "skin targets"
#define RM_ATTR_EXTENDED "extended"
#define RM_ATTR_SKILLLEVEL "skill level"
#define RM_ATTR_FOCUSED "focused module"

View file

@ -4,8 +4,7 @@
created : Sat Nov 16 10:34:35 CET 2002
copyright : (C) 2002 by Eric Espie
email : eric.espie@torcs.org
version : $Id$
version : $Id$
***************************************************************************/
/***************************************************************************
@ -640,15 +639,17 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
strncpy(elt->_carName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_CARNAME, ""), MAX_NAME_LEN - 1);
elt->_carName[MAX_NAME_LEN - 1] = 0; /* XML file name */
// Load alternative car skin file name from race info (if specified).
sprintf(path2, "%s/%d", RM_SECT_DRIVERS_RACING, listindex);
// Load custom car skin name and targets from race info (if specified).
snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, listindex);
const char* pszSkinName = GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, "");
if (strlen(pszSkinName) > 0)
{
snprintf(elt->_carSkin, MAX_NAME_LEN - 1, "%s-%s", elt->_carName, pszSkinName);
elt->_carSkin[MAX_NAME_LEN - 1] = 0; // Texture file name (no ext)
strncpy(elt->_skinName, pszSkinName, MAX_NAME_LEN - 1);
elt->_skinName[MAX_NAME_LEN - 1] = 0; // Texture name
}
elt->_skinTargets = (int)GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKINTARGETS, (char*)NULL, 0);
// Load other data from robot descriptor.
elt->_raceNumber = (int)GfParmGetNum(robhdle, path, ROB_ATTR_RACENUM, (char*)NULL, 0);
if (!normal_carname && elt->_driverType != RM_DRV_HUMAN) // Increase racenumber if needed
elt->_raceNumber += elt->_moduleIndex;
@ -669,9 +670,9 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
elt->_endRaceMemPool = NULL;
elt->_shutdownMemPool = NULL;
GfLogTrace("Driver #%d : module='%s', name='%s', car='%s', cat='%s', skin='%s'\n",
carindex, elt->_modName, elt->_name, elt->_carName,
elt->_category, elt->_carSkin);
GfLogTrace("Driver #%d : module='%s', name='%s', car='%s', cat='%s', skin='%s' on %x\n",
carindex, elt->_modName, elt->_name, elt->_carName,
elt->_category, elt->_skinName, elt->_skinTargets);
/* Retrieve and load car specs : merge car default specs,
category specs and driver modifications (=> handle) */

View file

@ -499,7 +499,8 @@ ReRaceStart(void)
const char *raceName = ReInfo->_reRaceName;
void *params = ReInfo->params;
void *results = ReInfo->results;
// Some debug traces about weather/rain parameters.
#ifdef DEBUG
tTrack *track = ReInfo->track;
GfLogDebug("ReRaceStart : Track timeday=%d, weather=%d, rain=%d, rainp=%d, rainlp=%d\n",
@ -515,17 +516,19 @@ ReRaceStart(void)
} while (curSurf);
#endif
// Reallocate car info for the race.
FREEZ(ReInfo->_reCarInfo);
ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo));
/* Drivers starting order */
// Drivers starting order
GfParmListClean(params, RM_SECT_DRIVERS_RACING);
if ((ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE)
&& ReInfo->s->_totTime < 0.0f)
{
GfLogInfo("Starting %s %s session\n",
ReInfo->_reName, ReInfo->s->_raceType == RM_TYPE_PRACTICE ? "practice" : "qualification");
// Race loading screen
i = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1);
if (i == 1) {
RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-raceload.png");
@ -534,13 +537,16 @@ ReRaceStart(void)
RmShutdownLoadingScreen();
}
// Propagate competitor drivers info to the real race starting grid
sprintf(path, "%s/%d", RM_SECT_DRIVERS, i);
sprintf(path2, "%s/%d", RM_SECT_DRIVERS_RACING, 1);
GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, ""));
GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0));
GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0));
const char* pszSkinName = GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0);
if (pszSkinName && strlen(pszSkinName) > 0)
const int nSkinTgts = (int)GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0);
GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, nSkinTgts);
const char* pszSkinName = GfParmGetStr(params, path, RM_ATTR_SKINNAME, "");
if (strlen(pszSkinName) > 0)
GfParmSetStr(params, path2, RM_ATTR_SKINNAME, pszSkinName);
}
else
@ -550,7 +556,7 @@ ReRaceStart(void)
gridType = GfParmGetStr(params, raceName, RM_ATTR_START_ORDER, RM_VAL_DRV_LIST_ORDER);
/* Starting grid in the arrival order of the previous race */
// Starting grid in the arrival order of the previous race
if (!strcmp(gridType, RM_VAL_LAST_RACE_ORDER))
{
GfLogInfo("Starting %s : Starting grid in the order of the last race\n", ReInfo->_reName);
@ -568,13 +574,15 @@ ReRaceStart(void)
GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, ""));
GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0));
const char* pszSkinName = GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0);
if (pszSkinName && strlen(pszSkinName) > 0)
const int nSkinTgts = (int)GfParmGetNum(results, path, RM_ATTR_SKINTARGETS, (char*)NULL, 0);
GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, nSkinTgts);
const char* pszSkinName = GfParmGetStr(results, path, RM_ATTR_SKINNAME, "");
if (strlen(pszSkinName) > 0)
GfParmSetStr(params, path2, RM_ATTR_SKINNAME, pszSkinName);
}
}
/* Starting grid in the reversed arrival order of the previous race */
// Starting grid in the reversed arrival order of the previous race
else if (!strcmp(gridType, RM_VAL_LAST_RACE_RORDER))
{
GfLogInfo("Starting %s : Starting grid in the reverse order of the last race\n", ReInfo->_reName);
@ -592,13 +600,15 @@ ReRaceStart(void)
GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, ""));
GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0));
const int nSkinTgts = (int)GfParmGetNum(results, path, RM_ATTR_SKINTARGETS, (char*)NULL, 0);
GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, nSkinTgts);
const char* pszSkinName = GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0);
if (pszSkinName && strlen(pszSkinName) > 0)
GfParmSetStr(params, path2, RM_ATTR_SKINNAME, pszSkinName);
}
}
/* Starting grid in the drivers list order */
// Starting grid in the drivers list order
else
{
GfLogInfo("Starting %s : Starting grid in the order of the driver list\n", ReInfo->_reName);
@ -612,6 +622,8 @@ ReRaceStart(void)
GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, ""));
GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0));
GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0));
const int nSkinTgts = (int)GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, (char*)NULL, 0);
GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, nSkinTgts);
const char* pszSkinName = GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0);
if (pszSkinName && strlen(pszSkinName) > 0)
GfParmSetStr(params, path2, RM_ATTR_SKINNAME, pszSkinName);

View file

@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <algorithm>
#include <string>
#include <sstream>
#include <carinfo.h>
@ -41,8 +42,7 @@ 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);
@ -77,6 +77,18 @@ const char* RmCarSelectMenu::getSelectedCarSkin() const
return GfuiComboboxGetText(GetMenuHandle(), GetDynamicControlId("skincombo"));
}
int RmCarSelectMenu::getSelectedCarSkinTargets() const
{
int nSkinTargets = 0;
const std::map<std::string, int>::const_iterator itSkinTargets =
_mapSkinTargets.find(getSelectedCarSkin());
if (itSkinTargets != _mapSkinTargets.end())
nSkinTargets = itSkinTargets->second;
return nSkinTargets;
}
void RmCarSelectMenu::onChangeCategory(tComboBoxInfo *pInfo)
{
// Get the RmCarSelectMenu instance from call-back user data.
@ -132,6 +144,7 @@ void RmCarSelectMenu::onAcceptCB(void *pCarSelectMenu)
free(pMenu->getDriver()->skinName);
pMenu->getDriver()->skinName = strdup(pszNewCarSkin);
}
pMenu->getDriver()->skinTargets = pMenu->getSelectedCarSkinTargets();
// Save car choice into the driver structure (only human drivers can change it).
if (pMenu->getDriver()->isHuman)
@ -295,7 +308,8 @@ void RmCarSelectMenu::resetCarSkinComboBox(const std::string& strCarRealName,
// Get really available skins and previews for this car and current driver.
const char* pszCarName =
CarInfo::self()->GetCarDataFromRealName(strCarRealName)->strName.c_str();
rmdGetCarSkinsInSearchPath(getDriver(), pszCarName, _vecSkinNames, _mapPreviewFiles);
rmdGetCarSkinsInSearchPath(getDriver(), pszCarName,
_vecSkinNames, _mapSkinTargets, _mapPreviewFiles);
// Load the skin list in the combo-box (and determine the selected skin index).
GfuiComboboxClear(GetMenuHandle(), nSkinComboId);

View file

@ -54,11 +54,12 @@ protected:
const CarData* getSelectedCarModel() const;
const char* getSelectedCarSkin() const;
int getSelectedCarSkinTargets() const;
void setSelectedCarParamsHandle(void* hdle);
void* getSelectedCarParamsHandle() const;
// Control callback functions (must be static).
// Control callback functions (have to be static, as used as tgfclient controls callbacks).
static void onActivateCB(void *pCarSelectMenu);
static void onChangeCategory(tComboBoxInfo *pInfo);
static void onChangeModel(tComboBoxInfo *pInfo);
@ -75,8 +76,9 @@ private:
// Currently selected car params handle.
void* _hCarParams;
// Skin names and associated preview files
// Skin names and targets + associated skinned livery preview files
std::vector<std::string> _vecSkinNames;
std::map<std::string, int> _mapSkinTargets;
std::map<std::string, std::string> _mapPreviewFiles;
size_t _nCurSkinIndex;

View file

@ -39,6 +39,8 @@ const char* rmdStdSkinName = "standard";
static const char* pszSkinFileExt = ".png";
static const char* pszPreviewFileSuffix = "-preview.jpg";
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* apszExcludedSkinFileSuffixes[] =
{ "rpm.png", "speed.png", "int.png" };
@ -81,17 +83,16 @@ void rmdGetDriverType(const char* moduleName, char* driverType, size_t maxSize)
void rmdGetCarSkinsInFolder(const char* pszCarName, const char* pszFolderPath,
std::vector<std::string>& vecSkinNames,
std::map<std::string, int>& mapSkinTargets,
std::map<std::string, std::string>& mapPreviewFiles)
{
//struct stat st;
tFList *pSkinFileList, *pCurSkinFile;
//GfLogDebug(" rmdGetCarSkinsInFolder(car=%s, path=%s) ...\n", pszCarName, pszFolderPath);
//GfLogDebug("rmdGetCarSkinsInFolder(%s) :\n", pszFolderPath);
pCurSkinFile = pSkinFileList =
GfDirGetListFiltered(pszFolderPath, pszCarName, pszSkinFileExt);
// Search for livery skin files, and asociated preview files if any.
tFList *pSkinFileList = GfDirGetListFiltered(pszFolderPath, pszCarName, pszSkinFileExt);
if (pSkinFileList)
{
tFList *pCurSkinFile = pSkinFileList;
do
{
pCurSkinFile = pCurSkinFile->next;
@ -121,6 +122,14 @@ void rmdGetCarSkinsInFolder(const char* pszCarName, const char* pszFolderPath,
{
// Add found skin in the list
vecSkinNames.push_back(strSkinName);
// Add the whole car livery to the skin targets.
if (mapSkinTargets.find(strSkinName) == mapSkinTargets.end())
mapSkinTargets[strSkinName] = 0;
mapSkinTargets[strSkinName] |= RM_CAR_SKIN_TARGET_WHOLE_LIVERY;
GfLogDebug(" Found %s%s livery\n", strSkinName.c_str(),
strSkinName == rmdStdSkinName ? "" : "-skinned");
// Add associated preview image, without really checking file existence
// (warn only ; up to the client GUI to do what to do if it doesn't exist).
@ -133,69 +142,152 @@ void rmdGetCarSkinsInFolder(const char* pszCarName, const char* pszFolderPath,
struct stat st;
if (stat(ossPreviewName.str().c_str(), &st))
GfLogWarning("No preview file %s found for '%s' skin\n",
ossPreviewName.str().c_str(), strSkinName.c_str());
GfLogWarning("Preview file not found for %s %s skin (%s)\n",
pszCarName, strSkinName.c_str(), ossPreviewName.str().c_str());
//GfLogDebug("* found skin=%s, preview=%s\n",
// strSkinName.c_str(), ossPreviewName.str().c_str());
}
} while (pCurSkinFile != pSkinFileList);
}
GfDirFreeList(pSkinFileList, NULL);
// Search for skinned logo files if any.
tFList *pLogoFileList =
GfDirGetListFiltered(pszFolderPath, pszLogoFileName, pszSkinFileExt);
if (pLogoFileList)
{
tFList *pCurLogoFile = pLogoFileList;
do
{
pCurLogoFile = pCurLogoFile->next;
// Extract the skin name from the logo file name.
const int nSkinNameLen = // Expecting "logo-<skin name>.png"
strlen(pCurLogoFile->name) - strlen(pszLogoFileName)
- 1 - strlen(pszSkinFileExt);
if (nSkinNameLen > 0)
{
const std::string strSkinName =
std::string(pCurLogoFile->name)
.substr(strlen(pszLogoFileName) + 1, nSkinNameLen);
// Add the pit door to the skin targets.
if (mapSkinTargets.find(strSkinName) == mapSkinTargets.end())
mapSkinTargets[strSkinName] = 0;
mapSkinTargets[strSkinName] |= RM_CAR_SKIN_TARGET_PIT_DOOR;
GfLogDebug(" Found %s-skinned logo (targets:%x)\n",
strSkinName.c_str(), mapSkinTargets[strSkinName]);
}
} while (pCurLogoFile != pLogoFileList);
}
GfDirFreeList(pLogoFileList, NULL);
// Search for skinned 3D wheel files if any.
tFList *pWheel3DFileList =
GfDirGetListFiltered(pszFolderPath, pszWheel3DFileName, pszSkinFileExt);
if (pWheel3DFileList)
{
tFList *pCurWheel3DFile = pWheel3DFileList;
do
{
pCurWheel3DFile = pCurWheel3DFile->next;
// Extract the skin name from the 3D wheel texture file name.
const int nSkinNameLen = // Expecting "logo-<skin name>.png"
strlen(pCurWheel3DFile->name) - strlen(pszWheel3DFileName)
- 1 - strlen(pszSkinFileExt);
if (nSkinNameLen > 0)
{
const std::string strSkinName =
std::string(pCurWheel3DFile->name)
.substr(strlen(pszWheel3DFileName) + 1, nSkinNameLen);
// Add the 3D wheels to the skin targets.
if (mapSkinTargets.find(strSkinName) == mapSkinTargets.end())
mapSkinTargets[strSkinName] = 0;
mapSkinTargets[strSkinName] |= RM_CAR_SKIN_TARGET_3D_WHEELS;
GfLogDebug(" Found %s-skinned 3D wheels (targets:%x)\n",
strSkinName.c_str(), mapSkinTargets[strSkinName]);
}
} while (pCurWheel3DFile != pWheel3DFileList);
}
GfDirFreeList(pWheel3DFileList, NULL);
}
void rmdGetCarSkinsInSearchPath(const trmdDrvElt *pDriver, const char* pszForcedCarName,
std::vector<std::string>& vecSkinNames,
std::map<std::string, int>& mapSkinTargets,
std::map<std::string, std::string>& mapPreviewFiles)
{
const char* pszCarName = pszForcedCarName ? pszForcedCarName : pDriver->carName;
std::ostringstream ossDirPath;
std::string strPreviewName;
//GfLogDebug("rmdGetCarSkinsInSearchPath : module=%s, idx=%d, car=%s ...\n",
// pDriver->moduleName, pDriver->interfaceIndex, pszCarName);
GfLogDebug("Checking skins for %s ...\n", pszCarName);
// Clear the skin and preview lists.
vecSkinNames.clear();
mapPreviewFiles.clear();
mapSkinTargets.clear();
// Get/check skins/skin targets/previews from the directories in the search path
// WARNING: Must be consistent with the search paths used in grcar.cpp, grboard.cpp,
// grscene.cpp ... etc ... but it is not currently 100% achieved
// (pit door logos are not searched by the graphics engine
// in the car-dedicated folders ... so they may be "over-detected" here).
ossDirPath << GetLocalDir() << "drivers/" << pDriver->moduleName
<< '/' << pDriver->interfaceIndex << '/' << pszCarName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapSkinTargets, mapPreviewFiles);
// Get skins/previews from the directories in the search path
// (WARNING: Must be consistent with the search path passed to ssgTexturePath in grcar.cpp,
// at least for the car skin file search).
ossDirPath.str("");
ossDirPath << GetLocalDir() << "drivers/" << pDriver->moduleName
<< '/' << pszCarName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << GetLocalDir() << "drivers/" << pDriver->moduleName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << "drivers/" << pDriver->moduleName
<< '/' << pDriver->interfaceIndex << '/' << pszCarName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << "drivers/" << pDriver->moduleName
<< '/' << pDriver->interfaceIndex;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << "drivers/" << pDriver->moduleName
<< '/' << pszCarName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << "drivers/" << pDriver->moduleName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
ossDirPath.str("");
ossDirPath << "cars/" << pszCarName;
rmdGetCarSkinsInFolder(pszCarName, ossDirPath.str().c_str(),
vecSkinNames, mapPreviewFiles);
vecSkinNames, mapSkinTargets, mapPreviewFiles);
// If we have at least 1 skin, make sure that if the standard one is inside,
// it is the first one.
@ -214,8 +306,8 @@ void rmdGetCarSkinsInSearchPath(const trmdDrvElt *pDriver, const char* pszForced
// (that way, the skin list will never be empty, and that's safer)
else
{
GfLogWarning("No skin found for '%s/%d/%s' : adding dummy '%s' one\n",
pDriver->moduleName, pDriver->interfaceIndex, pszCarName, rmdStdSkinName);
GfLogError("No skin at all found for '%s/%d/%s' : adding dummy '%s' one\n",
pDriver->moduleName, pDriver->interfaceIndex, pszCarName, rmdStdSkinName);
// Skin.
vecSkinNames.push_back(rmdStdSkinName);
@ -228,8 +320,7 @@ void rmdGetCarSkinsInSearchPath(const trmdDrvElt *pDriver, const char* pszForced
struct stat st;
if (stat(ossPreviewName.str().c_str(), &st))
GfLogWarning("No preview file %s found for '%s' skin\n",
GfLogWarning("No preview file %s found for dummy '%s' skin\n",
ossPreviewName.str().c_str(), rmdStdSkinName);
}
}

View file

@ -40,7 +40,8 @@ typedef struct rmdDrvElt
int isSelected; // Selected for race ?
int isHuman; // Human driver ?
char *carName; // Car (folder) name
char *skinName; // Skin 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;
@ -58,11 +59,13 @@ extern int rmdDriverMatchesFilters(const trmdDrvElt *drv, const char* carCat, co
//! Retrieve the skins and associated preview images found in the given folder for the given car.
extern void rmdGetCarSkinsInFolder(const char* pszCarName, const char* pszFolderPath,
std::vector<std::string>& vecSkinNames,
std::map<std::string, int>& mapSkinTargets,
std::map<std::string, std::string>& mapPreviewFiles);
//! Retrieve the skins and associated preview images found in the search path for the given driver (use pszForcedCarName in place of pDriver->carName if not null).
extern void rmdGetCarSkinsInSearchPath(const trmdDrvElt *pDriver, const char* pszForcedCarName,
std::vector<std::string>& vecSkinNames,
std::map<std::string, int>& mapSkinTargets,
std::map<std::string, std::string>& mapPreviewFiles);
#endif /* __DRIVER_H__ */

View file

@ -90,9 +90,10 @@ static const char* AnyDriverType = "--- All ---";
static std::vector<std::string> VecDriverTypes;
static size_t CurDriverTypeIndex = 0;
// Skin names and associated preview files
static std::vector<std::string> VecSkinNames;
static std::map<std::string, std::string> MapSkins2PreviewFiles; // Key = skin name.
// Skin names, targets and associated preview files for the currently selected driver.
static std::vector<std::string> VecCurDriverSkinNames;
static std::map<std::string, std::string> MapCurDriverSkinPreviewFiles; // Key = skin name.
static std::map<std::string, int> MapCurDriverSkinTargets; // Key = skin name.
static size_t CurSkinIndex = 0;
// Driver full list
@ -111,9 +112,36 @@ static void rmdsClickOnDriver(void * /* dummy */);
static void
rmdsActivate(void * /* notused */)
{
//GfLogDebug("rmdsActivate\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 selected driver displayed info
// 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;
int index = 0;
const char* name;
while ((name = GfuiScrollListGetElement(ScrHandle, CompetitorsScrollListId,
index, (void**)&curDrv)))
{
// Get really available (now) skins, skin targets and preview files for the driver's car.
rmdGetCarSkinsInSearchPath(curDrv, 0, vecSkinNames, mapSkinTargets, mapSkinPreviewFiles);
// Update skin targets for the choosen skin (targets might have changed).
curDrv->skinTargets = 0;
if (curDrv->skinName)
{
std::map<std::string, int>::const_iterator itSkinTargets =
mapSkinTargets.find(curDrv->skinName);
if (itSkinTargets != mapSkinTargets.end())
curDrv->skinTargets = itSkinTargets->second;
}
// Next competitor.
index++;
}
// Update selected driver displayed info
rmdsClickOnDriver(NULL);
}
@ -121,13 +149,11 @@ rmdsActivate(void * /* notused */)
static void
rmdsDeactivate(void *nextScreenHdle)
{
//GfLogDebug("rmdsDeactivate\n");
rmdsCleanup();
GfuiScreenRelease(ScrHandle);
if (nextScreenHdle)
GfuiScreenActivate(nextScreenHdle);
GfuiScreenActivate(nextScreenHdle);
}
static void
@ -163,19 +189,21 @@ rmdsChangeDriverType(void *vp)
static void
rmdsChangeSkin(void *vp)
{
if (VecSkinNames.empty())
if (VecCurDriverSkinNames.empty())
return;
// Update GUI.
CurSkinIndex = (CurSkinIndex + VecSkinNames.size() + (int)(long)vp) % VecSkinNames.size();
CurSkinIndex = (CurSkinIndex + VecCurDriverSkinNames.size()
+ (int)(long)vp) % VecCurDriverSkinNames.size();
const char* pszCurSkinName = VecSkinNames[CurSkinIndex].c_str();
const char* pszCurSkinName = VecCurDriverSkinNames[CurSkinIndex].c_str();
GfuiLabelSetText(ScrHandle, SkinEditId, pszCurSkinName);
// Load associated preview image (or "no preview panel" if none available).
// Load associated preview image (or "no preview" panel if none available).
struct stat st;
if (!stat(MapSkins2PreviewFiles[pszCurSkinName].c_str(), &st))
GfuiStaticImageSet(ScrHandle, CarImageId, MapSkins2PreviewFiles[pszCurSkinName].c_str(),
if (!stat(MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(), &st))
GfuiStaticImageSet(ScrHandle, CarImageId,
MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(),
/* index= */ 0, /* canDeform= */false);
else
GfuiStaticImageSet(ScrHandle, CarImageId, "data/img/nocarpreview.png");
@ -187,6 +215,7 @@ rmdsChangeSkin(void *vp)
if (pDriver->skinName)
free(pDriver->skinName);
pDriver->skinName = strdup(pszCurSkinName);
pDriver->skinTargets = MapCurDriverSkinTargets[pszCurSkinName];
}
}
@ -199,11 +228,11 @@ rmdsSetFocus(void * /* dummy */)
name = GfuiScrollListGetSelectedElement(ScrHandle, CompetitorsScrollListId, (void**)&curDrv);
if (name) {
GfParmSetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED,
curDrv->moduleName);
GfParmSetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX,
(char*)NULL, curDrv->interfaceIndex);
GfuiLabelSetText(ScrHandle, FocusedDriverLabelId, curDrv->name);
GfParmSetStr(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED,
curDrv->moduleName);
GfParmSetNum(MenuData->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX,
(char*)NULL, curDrv->interfaceIndex);
GfuiLabelSetText(ScrHandle, FocusedDriverLabelId, curDrv->name);
}
}
#endif
@ -223,7 +252,8 @@ rmdsNextMenu(void * /* dummy */)
// (for each competitor, module name, interface index, car name if human, skin name if any).
int index = 1;
while ((name = GfuiScrollListExtractElement(ScrHandle, CompetitorsScrollListId,
0, (void**)&curDrv))) {
0, (void**)&curDrv)))
{
sprintf(drvSec, "%s/%d", RM_SECT_DRIVERS, index);
GfParmSetNum(MenuData->param, drvSec, RM_ATTR_IDX, (char*)NULL, curDrv->interfaceIndex);
GfParmSetStr(MenuData->param, drvSec, RM_ATTR_MODULE, curDrv->moduleName);
@ -251,9 +281,14 @@ rmdsNextMenu(void * /* dummy */)
/* Not extended for robots yet in driverconfig */
GfParmSetNum(MenuData->param, drvSec, RM_ATTR_EXTENDED, NULL, 0);
}
// Skin and skin targets.
GfParmSetNum(MenuData->param, drvSec, RM_ATTR_SKINTARGETS, (char*)NULL, curDrv->skinTargets);
if ((curDrv->skinName && strcmp(curDrv->skinName, rmdStdSkinName))
|| GfParmGetStr(MenuData->param, drvSec, RM_ATTR_SKINNAME, 0))
GfParmSetStr(MenuData->param, drvSec, RM_ATTR_SKINNAME, curDrv->skinName);
// Next competitor.
index++;
}
@ -332,25 +367,32 @@ rmdsClickOnDriver(void * /* dummy */)
GfuiLabelSetText(ScrHandle, PickedDriverCarCategoryLabelId,
GfParmGetStr(curDrv->carParmHdle, SECT_CAR, PRM_CATEGORY, ""));
// Get really available skins and previews for the driver's car.
rmdGetCarSkinsInSearchPath(curDrv, 0, VecSkinNames, MapSkins2PreviewFiles);
// Get really available skins, skin targets and preview files for the driver's car.
rmdGetCarSkinsInSearchPath(curDrv, 0, VecCurDriverSkinNames,
MapCurDriverSkinTargets, MapCurDriverSkinPreviewFiles);
// Set currently selected skin for this driver.
CurSkinIndex = 0;
if (curDrv->skinName && strcmp(curDrv->skinName, rmdStdSkinName))
{
std::vector<std::string>::const_iterator iterSkin =
std::find(VecSkinNames.begin(), VecSkinNames.end(), curDrv->skinName);
if (iterSkin != VecSkinNames.end())
CurSkinIndex = iterSkin - VecSkinNames.begin();
std::find(VecCurDriverSkinNames.begin(), VecCurDriverSkinNames.end(),
curDrv->skinName);
if (iterSkin != VecCurDriverSkinNames.end())
CurSkinIndex = iterSkin - VecCurDriverSkinNames.begin();
// Update skin targets in case they changed since the menu was loaded.
curDrv->skinTargets = MapCurDriverSkinTargets[curDrv->skinName];
}
const char* pszCurSkinName = VecSkinNames[CurSkinIndex].c_str();
const char* pszCurSkinName = VecCurDriverSkinNames[CurSkinIndex].c_str();
GfuiLabelSetText(ScrHandle, SkinEditId, pszCurSkinName);
// Load associated preview image (or "no preview" image if none available).
struct stat st;
if (!stat(MapSkins2PreviewFiles[pszCurSkinName].c_str(), &st))
GfuiStaticImageSet(ScrHandle, CarImageId, MapSkins2PreviewFiles[pszCurSkinName].c_str(),
if (!stat(MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(), &st))
GfuiStaticImageSet(ScrHandle, CarImageId,
MapCurDriverSkinPreviewFiles[pszCurSkinName].c_str(),
/* index= */ 0, /* canDeform= */false);
else
GfuiStaticImageSet(ScrHandle, CarImageId, "data/img/nocarpreview.png");
@ -504,6 +546,7 @@ RmDriversSelect(void *vs)
char *sp;
const char *moduleName;
const char *skinName;
int skinTargets;
int i, index;
trmdDrvElt *curDrv;
int nDrivers, robotIdx;
@ -601,7 +644,8 @@ RmDriversSelect(void *vs)
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; // Initialized later if needed from race params.
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);
@ -657,6 +701,7 @@ RmDriversSelect(void *vs)
moduleName = GfParmGetStr(MenuData->param, path, RM_ATTR_MODULE, "");
robotIdx = (int)GfParmGetNum(MenuData->param, path, RM_ATTR_IDX, (char*)NULL, 0);
skinName = GfParmGetStr(MenuData->param, path, RM_ATTR_SKINNAME, rmdStdSkinName);
skinTargets = (int)GfParmGetNum(MenuData->param, path, RM_ATTR_SKINTARGETS, (char*)NULL, 0);
extended = GfParmGetNum(MenuData->param, path, RM_ATTR_EXTENDED, NULL, 0);
//GfLogDebug("Competitor #%d : ext=%d, itf %d\n", i, extended, robotIdx);
@ -712,7 +757,8 @@ RmDriversSelect(void *vs)
}
}
// Get the chosen car skin/livery if any specified.
// Get the chosen car skin (and skin targets) if any specified.
curDrv->skinTargets = skinTargets;
if (skinName && strcmp(skinName, rmdStdSkinName))
curDrv->skinName = strdup(skinName);
@ -763,8 +809,8 @@ rmdsCleanup(void)
VecCarCategories.clear();
VecDriverTypes.clear();
VecSkinNames.clear();
MapSkins2PreviewFiles.clear();
VecCurDriverSkinNames.clear();
MapCurDriverSkinPreviewFiles.clear();
while ((curDrv = GF_TAILQ_FIRST(&DriverList))) {
GF_TAILQ_REMOVE(&DriverList, curDrv, link);

View file

@ -22,10 +22,10 @@
#include <iostream>
#include <plib/ssg.h>
#include <glfeatures.h>
#include <robottools.h> //RELAXATION
#include <portability.h> // snprintf
#include <glfeatures.h>
#include <robottools.h> //RELAXATION
#include "grboard.h"
#include "grmain.h" //grWinX, grHandle, grMaxDamage
@ -1213,7 +1213,7 @@ static int nstate = 0;
void grInitBoardCar(tCarElt *car)
{
char buf[4096];
static const int nMaxTexPathSize = 4096;
int index;
void *handle;
const char *param;
@ -1223,7 +1223,7 @@ void grInitBoardCar(tCarElt *car)
tdble xSz, ySz, xpos, ypos;
tdble needlexSz, needleySz;
int lg;
const bool bTemplate = strlen(car->_carTemplate) != 0;
const bool bMasterModel = strlen(car->_masterModel) != 0;
grssgSetCurrentOptions ( &options ) ;
@ -1233,36 +1233,58 @@ void grInitBoardCar(tCarElt *car)
/* Set tachometer/speedometer textures search path :
1) driver level specified, in the user settings,
2) driver level specified,
2) driver level specified,
3) car level specified,
4) common textures */
param = GfParmGetStr(handle, SECT_GROBJECTS, PRM_TACHO_TEX, "rpm8000.png");
grFilePath = (char*)malloc(4096);
grFilePath = (char*)malloc(nMaxTexPathSize);
lg = 0;
lg += snprintf(grFilePath + lg, 4096 - lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carName);
if (bTemplate)
lg += snprintf(grFilePath + lg, 4096 - lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carTemplate);
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName);
if (bTemplate)
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carTemplate);
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s/%d;", car->_modName, car->_driverIndex);
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s/%s;", car->_modName, car->_carName);
if (bTemplate)
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s/%s;", car->_modName, car->_carTemplate);
lg += snprintf(grFilePath + lg, 4096 - lg, "drivers/%s;", car->_modName);
lg += snprintf(grFilePath + lg, 4096 - lg, "cars/%s;", car->_carName);
if (bTemplate)
lg += snprintf(grFilePath + lg, 4096 - lg, "cars/%s;", car->_carTemplate);
lg += snprintf(grFilePath + lg, 4096 - lg, "data/textures");
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s;",
GetLocalDir(), car->_modName);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d;",
car->_modName, car->_driverIndex);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "cars/%s;", car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "cars/%s;", car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "data/textures");
/* Tachometer --------------------------------------------------------- */
curInst = &(carInfo->instrument[0]);
/* Load the Tachometer texture */
param = GfParmGetStr(handle, SECT_GROBJECTS, PRM_TACHO_TEX, "rpm8000.png");
curInst->texture = (ssgSimpleState*)grSsgLoadTexState(param);
if (curInst->texture == 0) {
if (curInst->texture == 0)
curInst->texture = (ssgSimpleState*)grSsgLoadTexState("rpm8000.rgb");
}
cleanup[nstate] = curInst->texture;
nstate++;
@ -1327,9 +1349,8 @@ void grInitBoardCar(tCarElt *car)
param = GfParmGetStr(handle, SECT_GROBJECTS, PRM_SPEEDO_TEX, "speed360.png");
curInst->texture = (ssgSimpleState*)grSsgLoadTexState(param);
if (curInst->texture == 0) {
if (curInst->texture == 0)
curInst->texture = (ssgSimpleState*)grSsgLoadTexState("speed360.rgb");
}
free(grFilePath);
@ -1390,7 +1411,6 @@ void grInitBoardCar(tCarElt *car)
}
glEnd();
glEndList();
}
void grShutdownBoardCar(void)

View file

@ -1,4 +1,3 @@
/***************************************************************************
file : grcar.cpp
@ -22,8 +21,9 @@
#include <windows.h>
#endif
#include <robottools.h>
#include <portability.h> // snprintf
#include <glfeatures.h>
#include <robottools.h> //RELAXATION
#include "grcar.h"
#include "grmain.h"
@ -237,8 +237,8 @@ initWheel(tCarElt *car, int wheel_index, const char *wheel_mod_name)
// Load speed-dependant 3D wheel model if available
ssgEntity *whl3d = 0;
if (wheel_mod_name && strlen(wheel_mod_name)) {
sprintf(wheel_file_name, "%s%d.acc", wheel_mod_name, j);
whl3d = grssgCarLoadAC3D(wheel_file_name, NULL, car->index);
snprintf(wheel_file_name, 32, "%s%d.acc", wheel_mod_name, j);
whl3d = grssgCarLoadAC3D(wheel_file_name, NULL, car->index);
}
// If we have a 3D wheel, use it, otherwise use auto- generated wheel...
@ -404,9 +404,9 @@ grInitShadow(tCarElt *car)
ssgNormalArray *shd_nrm = new ssgNormalArray(1);
ssgTexCoordArray *shd_tex = new ssgTexCoordArray(GR_SHADOW_POINTS+1);
sprintf(buf, "cars/%s;", car->_carName);
if (strlen(car->_carTemplate) > 0) // Add the master model path if we are using a template.
sprintf(buf + strlen(buf), "cars/%s;", car->_carTemplate);
snprintf(buf, 256, "cars/%s;", car->_carName);
if (strlen(car->_masterModel) > 0) // Add the master model path if we are using a template.
snprintf(buf + strlen(buf), 256 - strlen(buf), "cars/%s;", car->_masterModel);
grFilePath = buf;
@ -519,15 +519,17 @@ grPropagateDamage (tSituation *s)
void
grPreInitCar(tCarElt *car)
{
strncpy(car->_carTemplate,
strncpy(car->_masterModel,
GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_TEMPLATE, ""), MAX_NAME_LEN - 1);
car->_carTemplate[MAX_NAME_LEN - 1] = 0;
car->_masterModel[MAX_NAME_LEN - 1] = 0;
}
void
grInitCar(tCarElt *car)
{
char buf[4096];
static const char* pszTexFileExt = ".png";
static const int nMaxTexPathSize = 4096;
char buf[nMaxTexPathSize];
int index;
int selIndex;
ssgEntity *carEntity;
@ -545,7 +547,6 @@ grInitCar(tCarElt *car)
int lightNum;
const char *lightType;
int lightTypeNum;
bool bTemplate;
TRACE_GL("loadcar: start");
@ -559,19 +560,41 @@ grInitCar(tCarElt *car)
/* Initialize board */
grInitBoardCar(car);
/* Set texture mapping if we are using an alternative skin or a master 3D model */
bTemplate = strlen(car->_carTemplate) != 0;
/* Schedule texture mapping if we are using a custom skin and/or a master 3D model */
const bool bMasterModel = strlen(car->_masterModel) != 0;
const bool bCustomSkin = strlen(car->_skinName) != 0;
GfLogTrace("Loading graphics for %s (driver:%s, skin:%s.%x, master model:%s)\n",
car->_carName, car->_name,
bCustomSkin ? car->_skinName : "standard", car->_skinTargets,
bMasterModel ? car->_masterModel : "self");
std::string strSrcTexName(bTemplate ? car->_carTemplate : car->_carName);
std::string strTgtTexName(strlen(car->_carSkin) != 0 ? car->_carSkin : car->_carName);
/* 1) Whole livery */
std::string strSrcTexName(bMasterModel ? car->_masterModel : car->_carName);
std::string strTgtTexName(car->_carName);
if (bCustomSkin && car->_skinTargets & RM_CAR_SKIN_TARGET_WHOLE_LIVERY)
{
strTgtTexName += '-';
strTgtTexName += car->_skinName;
}
if (strSrcTexName != strTgtTexName)
{
strSrcTexName += ".png";
strTgtTexName += ".png";
strSrcTexName += pszTexFileExt;
strTgtTexName += pszTexFileExt;
options.addTextureMapping(strSrcTexName.c_str(), strTgtTexName.c_str());
GfLogDebug("Using skinned livery %s\n", strTgtTexName.c_str());
}
/* 2) 3D wheels if present */
if (bCustomSkin && car->_skinTargets & RM_CAR_SKIN_TARGET_3D_WHEELS)
{
strSrcTexName = "wheel3d"; // Warning: Must be consistent with wheel<i>.ac/.acc contents
strTgtTexName = strSrcTexName + '-' + car->_skinName + pszTexFileExt;
strSrcTexName += pszTexFileExt;
options.addTextureMapping(strSrcTexName.c_str(), strTgtTexName.c_str());
GfLogDebug("Using skinned 3D wheels %s\n", strTgtTexName.c_str());
}
GfOut("grInitCar(%s, %s) : tpl='%s', skin='%s'\n",
car->_name, car->_carName, car->_carTemplate, car->_carSkin);
grssgSetCurrentOptions(&options);
@ -580,16 +603,16 @@ grInitCar(tCarElt *car)
car->_exhaustNb = MIN(car->_exhaustNb, 2);
car->_exhaustPower = GfParmGetNum(handle, SECT_EXHAUST, PRM_POWER, NULL, 1.0);
for (i = 0; i < car->_exhaustNb; i++) {
sprintf(path, "%s/%d", SECT_EXHAUST, i + 1);
snprintf(path, 256, "%s/%d", SECT_EXHAUST, i + 1);
car->_exhaustPos[i].x = GfParmGetNum(handle, path, PRM_XPOS, NULL, -car->_dimension_x / 2.0);
car->_exhaustPos[i].y = -GfParmGetNum(handle, path, PRM_YPOS, NULL, car->_dimension_y / 2.0);
car->_exhaustPos[i].z = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0.1);
}
sprintf(path, "%s/%s", SECT_GROBJECTS, SECT_LIGHT);
snprintf(path, 256, "%s/%s", SECT_GROBJECTS, SECT_LIGHT);
lightNum = GfParmGetEltNb(handle, path);
for (i = 0; i < lightNum; i++) {
sprintf(path, "%s/%s/%d", SECT_GROBJECTS, SECT_LIGHT, i + 1);
snprintf(path, 256, "%s/%s/%d", SECT_GROBJECTS, SECT_LIGHT, i + 1);
lightPos[0] = GfParmGetNum(handle, path, PRM_XPOS, NULL, 0);
lightPos[1] = GfParmGetNum(handle, path, PRM_YPOS, NULL, 0);
lightPos[2] = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0);
@ -616,26 +639,45 @@ grInitCar(tCarElt *car)
/* Set textures search path : 0) driver level specified, in the user settings
1) driver level specified, 2) car level specified, 3) common textures */
grFilePath = (char*)malloc(4096);
grFilePath = (char*)malloc(nMaxTexPathSize);
lg = 0;
lg += sprintf(grFilePath + lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carName);
if (bTemplate)
lg += sprintf(grFilePath + lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carTemplate);
lg += sprintf(grFilePath + lg, "%sdrivers/%s/%d/%s;", GetLocalDir(), car->_modName, car->_driverIndex, car->_carName);
if (bTemplate)
lg += sprintf(grFilePath + lg, "%sdrivers/%s/%d/%s;", GetLocalDir(), car->_modName, car->_driverIndex, car->_carTemplate);
lg += sprintf(grFilePath + lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName);
if (bTemplate)
lg += sprintf(grFilePath + lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carTemplate);
lg += sprintf(grFilePath + lg, "drivers/%s/%d;", car->_modName, car->_driverIndex);
lg += sprintf(grFilePath + lg, "drivers/%s/%s;", car->_modName, car->_carName);
if (bTemplate)
lg += sprintf(grFilePath + lg, "drivers/%s/%s;", car->_modName, car->_carTemplate);
lg += sprintf(grFilePath + lg, "drivers/%s;", car->_modName);
lg += sprintf(grFilePath + lg, "cars/%s;", car->_carName);
if (bTemplate)
lg += sprintf(grFilePath + lg, "cars/%s;", car->_carTemplate);
lg += sprintf(grFilePath + lg, "data/textures");
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "%sdrivers/%s;",
GetLocalDir(), car->_modName);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%d;",
car->_modName, car->_driverIndex);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "cars/%s;", car->_carName);
if (bMasterModel)
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "cars/%s;", car->_masterModel);
lg += snprintf(grFilePath + lg, nMaxTexPathSize - lg, "data/textures");
grCarInfo[index].envSelector = (ssgStateSelector*)grEnvSelector->clone();
grCarInfo[index].envSelector->ref();
@ -647,7 +689,7 @@ grInitCar(tCarElt *car)
/* Level of details */
grCarInfo[index].LODSelector = LODSel = new ssgSelector;
grCarInfo[index].carTransform->addKid(LODSel);
sprintf(path, "%s/%s", SECT_GROBJECTS, LST_RANGES);
snprintf(path, 256, "%s/%s", SECT_GROBJECTS, LST_RANGES);
nranges = GfParmGetEltNb(handle, path) + 1;
if (nranges < 2) {
GfOut("Error not enough levels of detail\n");
@ -663,32 +705,54 @@ grInitCar(tCarElt *car)
/* Set textures/models search path : 0) driver level specified, in the user settings
1) driver level specified, 2) car level specified, 3) common models / textures */
lg = 0;
lg += sprintf(buf + lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carName);
if (bTemplate)
lg += sprintf(buf + lg, "%sdrivers/%s/%s;", GetLocalDir(), car->_modName, car->_carTemplate);
lg += sprintf(buf + lg, "%sdrivers/%s/%d/%s;", GetLocalDir(), car->_modName, car->_driverIndex, car->_carName);
if (bTemplate)
lg += sprintf(buf + lg, "%sdrivers/%s/%d/%s;", GetLocalDir(), car->_modName, car->_driverIndex, car->_carTemplate);
lg += sprintf(buf + lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName);
if (bTemplate)
lg += sprintf(buf + lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carTemplate);
lg += sprintf(buf + lg, "drivers/%s/%d;", car->_modName, car->_driverIndex);
lg += sprintf(buf + lg, "drivers/%s/%s;", car->_modName, car->_carName);
if (bTemplate)
lg += sprintf(buf + lg, "drivers/%s/%s;", car->_modName, car->_carTemplate);
lg += sprintf(buf + lg, "drivers/%s;", car->_modName);
lg += sprintf(buf + lg, "cars/%s;", car->_carName);
if (bTemplate)
lg += sprintf(buf + lg, "cars/%s;", car->_carTemplate);
lg += sprintf(buf + lg, "data/objects;");
lg += sprintf(buf + lg, "data/textures");
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%d/%s;",
GetLocalDir(), car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%sdrivers/%s/%s;",
GetLocalDir(), car->_modName, car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "%sdrivers/%s;",
GetLocalDir(), car->_modName);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_carName);
if (bMasterModel)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s/%d/%s;",
car->_modName, car->_driverIndex, car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s/%d;",
car->_modName, car->_driverIndex);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_carName);
if (bMasterModel)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s/%s;",
car->_modName, car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "drivers/%s;", car->_modName);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/%s;", car->_carName);
if (bMasterModel)
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "cars/%s;", car->_masterModel);
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "data/objects;");
lg += snprintf(buf + lg, nMaxTexPathSize - lg, "data/textures");
ssgModelPath(buf);
ssgTexturePath(buf);
/* loading raw car level 0*/
selIndex = 0; /* current selector index */
sprintf(buf, "%s.ac", bTemplate ? car->_carTemplate : car->_carName); /* default car 3D model file */
sprintf(path, "%s/%s/1", SECT_GROBJECTS, LST_RANGES);
snprintf(buf, nMaxTexPathSize, "%s.ac",
bMasterModel ? car->_masterModel : car->_carName); /* default car 3D model file */
snprintf(path, 256, "%s/%s/1", SECT_GROBJECTS, LST_RANGES);
param = GfParmGetStr(handle, path, PRM_CAR, buf);
grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, path, PRM_THRESHOLD, NULL, 0.0);
carEntity = grssgCarLoadAC3D(param, NULL, index);
@ -762,7 +826,7 @@ grInitCar(tCarElt *car)
/* Other LODs */
for (i = 2; i < nranges; i++) {
carBody = new ssgBranch;
sprintf(buf, "%s/%s/%d", SECT_GROBJECTS, LST_RANGES, i);
snprintf(buf, nMaxTexPathSize, "%s/%s/%d", SECT_GROBJECTS, LST_RANGES, i);
param = GfParmGetStr(handle, buf, PRM_CAR, "");
grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, buf, PRM_THRESHOLD, NULL, 0.0);
/* carEntity = ssgLoad(param); */
@ -783,7 +847,7 @@ grInitCar(tCarElt *car)
LODSel->select(grCarInfo[index].LODSelectMask[0]);
/* add Steering Wheel 0 (if one exists) */
sprintf(path, "%s/%s", SECT_GROBJECTS, SECT_STEERWHEEL);
snprintf(path, 256, "%s/%s", SECT_GROBJECTS, SECT_STEERWHEEL);
param = GfParmGetStr(handle, path, PRM_SW_MODEL, NULL);
if (param)
{
@ -851,7 +915,7 @@ grInitCar(tCarElt *car)
}
// separate driver models for animation according to steering wheel angle ...
sprintf(path, "%s/%s", SECT_GROBJECTS, LST_DRIVER);
snprintf(path, 256, "%s/%s", SECT_GROBJECTS, LST_DRIVER);
nranges = GfParmGetEltNb(handle, path) + 1;
grCarInfo[index].nDRM = nranges - 1;
grCarInfo[index].DRMSelector = NULL;
@ -873,7 +937,7 @@ grInitCar(tCarElt *car)
ssgTransform *driverLoc = new ssgTransform;
sgCoord driverpos;
sprintf(buf, "%s/%s/%d", SECT_GROBJECTS, LST_DRIVER, i);
snprintf(buf, nMaxTexPathSize, "%s/%s/%d", SECT_GROBJECTS, LST_DRIVER, i);
param = GfParmGetStr(handle, buf, PRM_DRIVERMODEL, "");
grCarInfo[index].DRMThreshold[selIndex] = GfParmGetNum(handle, buf, PRM_DRIVERSTEER, NULL, 0.0);

View file

@ -1338,9 +1338,6 @@ const char* grssgLoaderOptions::mapTexture(const char* pszSrcFileName) const
{
const std::map<std::string, std::string>::const_iterator iterTex =
_mapTextures.find(pszSrcFileName);
// GfTrace("grssgLoaderOptions::mapTexture(%s) : %s\n",
// pszSrcFileName,
// iterTex != _mapTextures.end() ? iterTex->second.c_str() : pszSrcFileName);
return iterTex != _mapTextures.end() ? iterTex->second.c_str() : pszSrcFileName;
}

View file

@ -28,6 +28,7 @@
#include <plib/ssgAux.h>
#include <glfeatures.h> //gluXXX
#include <robottools.h> //RtXXX()
#include <portability.h> // snprintf
#include "grscene.h"
#include "grmain.h"
@ -941,10 +942,9 @@ initBackground(void) {
grEnvShadowState=(grMultiTexState*)grSsgEnvTexState("envshadow.png");
if (grEnvShadowState == NULL) {
ulSetError ( UL_WARNING, "grscene:initBackground Failed to open envshadow.png for reading") ;
ulSetError ( UL_WARNING, " mandatory for top env mapping ") ;
ulSetError ( UL_WARNING, " should be in the .xml !! ") ;
ulSetError ( UL_WARNING, " copy the envshadow.png from g-track-2 to the track you selected ") ;
ulSetError ( UL_WARNING, " c'est pas classe comme sortie, mais ca evite un crash ") ;
ulSetError ( UL_WARNING, " mandatory for top env mapping (should be in the .xml !!) ") ;
ulSetError ( UL_WARNING, " copy the envshadow.png from 'chemisay' to the track you selected ") ;
ulSetError ( UL_WARNING, " (sorry for exiting, but it would have actually crashed).") ;
GfScrShutdown();
exit(-1);
}//if grEnvShadowState
@ -994,24 +994,44 @@ grCustomizePits(void)
sgVec4 clr = {0, 0, 0, 1};
pit_clr->add(clr);
std::string strLogoFileName("logo"); // Default driver logo file name (pit door).
if (pits->driversPits[i].car[0]) {
// If we have more than one car in the pit use the team pit logo of driver 0.
if (pits->driversPits[i].freeCarIndex == 1) {
// One car assigned to the pit.
sprintf(buf, "drivers/%s/%d;drivers/%s;data/textures;data/img;.",
pits->driversPits[i].car[0]->_modName,
pits->driversPits[i].car[0]->_driverIndex,
pits->driversPits[i].car[0]->_modName);
} else {
// Multiple cars assigned to the pit.
sprintf(buf, "drivers/%s;data/textures;data/img;.",
pits->driversPits[i].car[0]->_modName);
}//if ...freeCarIndex == 1
snprintf(buf, sizeof(buf),
"%sdrivers/%s/%d;%sdrivers/%s;drivers/%s/%d;drivers/%s;data/textures",
GetLocalDir(),
pits->driversPits[i].car[0]->_modName,
pits->driversPits[i].car[0]->_driverIndex,
GetLocalDir(),
pits->driversPits[i].car[0]->_modName,
pits->driversPits[i].car[0]->_modName,
pits->driversPits[i].car[0]->_driverIndex,
pits->driversPits[i].car[0]->_modName);
// If a custom skin was selected, and it can apply to the pit door,
// update the logo file name accordingly
if (strlen(pits->driversPits[i].car[0]->_skinName) != 0
&& pits->driversPits[i].car[0]->_skinTargets & RM_CAR_SKIN_TARGET_PIT_DOOR)
{
strLogoFileName += '-';
strLogoFileName += pits->driversPits[i].car[0]->_skinName;
GfLogDebug("Using skinned pit door logo %s\n", strLogoFileName.c_str());
}
} else {
sprintf(buf, "data/textures;data/img;.");
snprintf(buf, sizeof(buf), "data/textures");
}//if pits->driverPits[i].car[0]
ssgState *st = grSsgLoadTexStateEx("logo.rgb", buf, FALSE, FALSE);
// Load logo texture (.rgb first, for backwards compatibility, then .png)
const std::string strRGBLogoFileName = strLogoFileName + ".rgb";
ssgState *st = grSsgLoadTexStateEx(strRGBLogoFileName.c_str(), buf, FALSE, FALSE);
if (!st)
{
const std::string strPNGLogoFileName = strLogoFileName + ".png";
st = grSsgLoadTexStateEx(strPNGLogoFileName.c_str(), buf, FALSE, FALSE);
}
((ssgSimpleState*)st)->setShininess(50);
tdble x, y;
@ -1116,7 +1136,7 @@ grUpdateTime(tSituation *s)
double sol_angle = bodies[SUN]->getAngle();
double sky_brightness = (1.0 + cos(sol_angle)) / 2.0;
double scene_brightness = pow(sky_brightness, 0.5);
double scene_brightness = pow(sky_brightness, 0.5);
sky_color[0] = base_sky_color[0] * (float)sky_brightness;
sky_color[1] = base_sky_color[1] * (float)sky_brightness;

View file

@ -200,7 +200,7 @@ grSsgLoadTexStateEx(const char *img, const char *filepath, int wrap, int mipmap)
const char *s;
grManagedState *st;
// remove the directory
// remove the directory path
s = strrchr(img, '/');
if (s == NULL) {
s = img;
@ -209,7 +209,7 @@ grSsgLoadTexStateEx(const char *img, const char *filepath, int wrap, int mipmap)
}
if (!grGetFilename(s, filepath, buf)) {
GfOut("File %s not found\n", s);
GfLogWarning("Texture file %s not found in search path %s\n", s, filepath);
return NULL;
}