void ChipReduction::Cleanup() { FREEZ(&m_block_avg); FREEZ(&m_block_smooth); FREEZ(&m_well_cont_block_smooth); FREEZ(&m_good_wells); FREEZ(&m_bad_wells); Zero(); }
static void simplifyToParse( tFormNode **node ) { tFormNode *curNode = *node; tFormNode *prevNode = NULL; char skipChilds; char againThisNode; while( curNode ) { skipChilds = FALSE; againThisNode = FALSE; if( curNode->type == FORMNODE_TYPE_TOPARSE_BLOCK ) { if( curNode->firstChild == NULL ) { prevNode->next = curNode->next; FREEZ( curNode->string ); free( curNode ); curNode = prevNode; skipChilds = TRUE; } else { if( curNode->firstChild->next == NULL ) { if( prevNode ) { prevNode->next = curNode->firstChild; prevNode->next->next = curNode->next; FREEZ( curNode->string ); free( curNode ); curNode = prevNode->next; } else { *node = curNode->firstChild; (*node)->next = curNode->next; FREEZ( curNode->string ); free( curNode ); curNode = *node; } againThisNode = TRUE; } else { GfError( "WARNING: could not simplify all blocks in a formula\n" ); } } } else if( curNode->type == FORMNODE_TYPE_TOPARSE_STRING ) { /* Unparsed string found: assume variable */ curNode->type = FORMNODE_TYPE_VARIABLE; } if( !skipChilds && curNode->firstChild ) simplifyToParse( &(curNode->firstChild) ); if( !againThisNode ) { prevNode = curNode; curNode = curNode->next; } } }
void ReRaceCleanDrivers(void) { int i; tRobotItf *robot; int nCars; tMemoryPool oldPool = NULL; nCars = ReInfo->s->_ncars; for (i = 0; i < nCars; i++) { robot = ReInfo->s->cars[i]->robot; GfPoolMove( &ReInfo->s->cars[i]->_shutdownMemPool, &oldPool ); if (robot->rbShutdown && !(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { robot->rbShutdown(robot->index); } GfPoolFreePool( &oldPool ); GfParmReleaseHandle(ReInfo->s->cars[i]->_paramsHandle); free(robot); free(ReInfo->s->cars[i]->_curSplitTime); free(ReInfo->s->cars[i]->_bestSplitTime); } RtTeamManagerRelease(); FREEZ(ReInfo->s->cars); ReInfo->s->cars = 0; ReInfo->s->_ncars = 0; GfModUnloadList(&ReRacingRobotsModList); }
void ReRaceAbort() { ReShutdownUpdaters(); RePhysicsEngine().shutdown(); RaceEngine::self().unloadPhysicsEngine(); ReUI().onRaceFinishing(); ReRaceCleanDrivers(); if (NetGetNetwork()) NetGetNetwork()->Disconnect(); FREEZ(ReInfo->_reCarInfo); if (ReInfo->params != ReInfo->mainParams) { GfParmReleaseHandle(ReInfo->params); ReInfo->params = ReInfo->mainParams; } // Return to race configuration step ReStateApply((void*)RE_STATE_CONFIG); }
ReSituation::~ReSituation() { // Free ReInfo memory. if (_pReInfo->results) { if (_pReInfo->mainResults != _pReInfo->results) GfParmReleaseHandle(_pReInfo->mainResults); GfParmReleaseHandle(_pReInfo->results); } if (_pReInfo->_reParam) GfParmReleaseHandle(_pReInfo->_reParam); if (_pReInfo->params != _pReInfo->mainParams) { GfParmReleaseHandle(_pReInfo->params); _pReInfo->params = _pReInfo->mainParams; } // if (_pReInfo->movieCapture.outputBase) // free(_pReInfo->movieCapture.outputBase); free(_pReInfo->s); free(_pReInfo->carList); free(_pReInfo->rules); FREEZ(_pReInfo); // Prepare the singleton for next use. _pSelf = 0; }
int ReEventShutdown(void) { int curTrkIdx; void *params = ReInfo->params; int nbTrk = GfParmGetEltNb(params, RM_SECT_TRACKS); int ret = 0; void *results = ReInfo->results; if ( (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) && (ReInfo->_reGraphicItf.shutdowntrack != 0) ) { ReInfo->_reGraphicItf.shutdowntrack(); } int curRaceIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1); curTrkIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1); if (curRaceIdx == 1) { if (curTrkIdx < nbTrk) { // Next track. curTrkIdx++; } else if (curTrkIdx >= nbTrk) { // Back to the beginning. curTrkIdx = 1; } } GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, curTrkIdx); if (curTrkIdx != 1) { ret = RM_NEXT_RACE; } else { ret = RM_NEXT_STEP; } if ((nbTrk != 1) && (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE)) { ReDisplayStandings(); FREEZ(ReInfo->_reCarInfo); return RM_ASYNC | ret; } FREEZ(ReInfo->_reCarInfo); return RM_SYNC | ret; }
void ReResScreenRemoveText(int line) { if (line < LINES) { FREEZ(reResMsg[line]); GfuiLabelSetText(reResScreenHdle, reResMsgId[line], ""); } }
static void reCarsRemovePenalty(tCarElt *car, tCarPenalty *penalty) { GF_TAILQ_REMOVE(&(car->_penaltyList), penalty, link); //GfLogDebug("reCarsRemovePenalty(car #%d) : Removed penalty %p\n", // car->index, penalty); FREEZ(penalty); }
static void reResScreenShutdown(void * /* dummy */) { int i; for (i = 1; i < LINES; i++) { FREEZ(reResMsg[i]); } }
/* Race Engine Exit */ void ReShutdown(void) { /* Free previous situation */ if (ReInfo) { ReInfo->_reTrackItf.trkShutdown(); GfModUnloadList(&reEventModList); if (ReInfo->results) { GfParmReleaseHandle(ReInfo->results); } if (ReInfo->_reParam) { GfParmReleaseHandle(ReInfo->_reParam); } FREEZ(ReInfo->s); FREEZ(ReInfo->carList); FREEZ(ReInfo->rules); FREEZ(ReInfo->_reFilename); FREEZ(ReInfo); } }
void GfFormFreeCommandNewRec( tFormNode *node ) { tFormNode *curNode = node; tFormNode *prevNode; while( curNode ) { FREEZ( curNode->string ); if( curNode->firstChild ) GfFormFreeCommandNewRec( curNode->firstChild ); prevNode = curNode; curNode = curNode->next; free( prevNode ); } }
void ReResScreenSetText(const char *text, int line, int clr) { if (line < LINES) { FREEZ(reResMsg[line]); reResMsg[line] = strdup(text); if ((clr >= 0) && (clr < 2)) { reResMsgClr[line] = clr; } else { reResMsgClr[line] = 0; } GfuiLabelSetText(reResScreenHdle, reResMsgId[line], reResMsg[line]); GfuiLabelSetColor(reResScreenHdle, reResMsgId[line], reColor[reResMsgClr[line]]); } }
void * ReResScreenInit(void) { int i; int y, dy; static const char *title[3] = {"Practice", "Qualifications", "Race"}; if (reResScreenHdle) { GfuiScreenRelease(reResScreenHdle); } reResScreenHdle = GfuiScreenCreateEx(bgcolor, 0, reResScreenActivate, 0, reResScreenShutdown, 0); GfuiTitleCreate(reResScreenHdle, title[ReInfo->s->_raceType], strlen(title[ReInfo->s->_raceType])); const char* img = GfParmGetStr(ReInfo->params, RM_SECT_HEADER, RM_ATTR_RUNIMG, 0); if (img) { GfuiScreenAddBgImg(reResScreenHdle, img); } reAddResKeys(); reResTitleId = GfuiLabelCreateEx(reResScreenHdle, "", red, GFUI_FONT_LARGE_C, 320, 420, GFUI_ALIGN_HC_VB, 50); y = 400; dy = 378 / LINES; for (i = 0; i < LINES; i++) { FREEZ(reResMsg[i]); reResMsgClr[i] = 0; reResMsgId[i] = GfuiLabelCreateEx(reResScreenHdle, "", white, GFUI_FONT_MEDIUM_C, 20, y, GFUI_ALIGN_HL_VB, 120); y -= dy; } reCurLine = 0; return reResScreenHdle; }
/* Launch a race manager */ static void reSelectRaceman(void *params) { char *s, *e, *m; ReInfo->params = params; FREEZ(ReInfo->_reFilename); s = GfParmGetFileName(params); while ((m = strstr(s, "/")) != 0) { s = m + 1; } e = strstr(s, PARAMEXT); ReInfo->_reFilename = strndup(s, e-s+1); ReInfo->_reFilename[e-s] = '\0'; ReInfo->_reName = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, ""); ReStateApply(RE_STATE_CONFIG); }
static void AbortRaceHookActivate(void * /* dummy */) { GfuiScreenActivate(ReInfo->_reGameScreen); ReInfo->_reSimItf.shutdown(); if (ReInfo->_displayMode == RM_DISP_MODE_NORMAL) { ReInfo->_reGraphicItf.shutdowncars(); startMenuMusic(); } ReInfo->_reGraphicItf.shutdowntrack(); ReRaceCleanDrivers(); taManager->RaceEnd(); FREEZ(ReInfo->_reCarInfo); /* Return to race menu */ ReInfo->_reState = RE_STATE_CONFIG; }
void ReRaceAbandon() { // Notify the UI that the race event is finishing now. ReUI().onRaceEventFinishing(); // Shutdown track-physics-related stuff. ReTrackShutdown(); // Cleanup needed stuff. FREEZ(ReInfo->_reCarInfo); if (ReInfo->params != ReInfo->mainParams) { GfParmReleaseHandle(ReInfo->params); ReInfo->params = ReInfo->mainParams; } // Return to race configuration step ReStateApply((void*)RE_STATE_CONFIG); }
void ReRaceCleanDrivers(void) { int i; tRobotItf *robot; int nCars; nCars = ReInfo->s->_ncars; for (i = 0; i < nCars; i++) { robot = ReInfo->s->cars[i]->robot; if (robot->rbShutdown) { robot->rbShutdown(robot->index); } GfParmReleaseHandle(ReInfo->s->cars[i]->_paramsHandle); free(robot); } FREEZ(ReInfo->s->cars); ReInfo->s->cars = 0; ReInfo->s->_ncars = 0; GfModUnloadList(&ReRaceModList); }
/** * Function to load a car. * * @param carindex The index whichs will be used as car->index for the car. * @param listindex The listindex in RM_SECT_DRIVERS_RACING * @param modindex The index of the mod; must be MAX_MOD_ITF if normal_carname is FALSE. * @param robotIdx The index of the robot. * @param normal_carname If this member is TRUE, the car is treated as an ordinary car; * if this member is FALSE, then the car used is the one given * in the xml-file, and there is no restriction on the number of instances. * @param cardllname The dllname of the driver * @return A pointer to the newly created car if successfull; NULL otherwise */ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int relativeRobotIdx, char normal_carname, char const *cardllname ) { tCarElt *elt; tMemoryPool oldPool; char path[256]; char path2[256]; char buf[256]; char buf2[256]; char const *str; char const *category; char const *subcategory; char const *teamname; std::string carname; tModInfoNC *curModInfo; tRobotItf *curRobot; void *robhdle; void *cathdle; void *carhdle; void *handle; int k; int xx; char isHuman; int robotIdx = relativeRobotIdx; /* good robot found */ curModInfo = &((*(ReInfo->robModList))->modInfo[modindex]); subcategory = ReInfo->track->subcategory; #if 0 //SDW if (replayReplay) GfLogInfo("Driver in car %d being driven by replay\n", carindex); else #endif GfLogInfo("Driver's name: %s\n", curModInfo->name); isHuman = strcmp( cardllname, "human" ) == 0 || strcmp( cardllname, "networkhuman" ) == 0; /* Extended is forced for humans, so no need to increase robotIdx */ if (!normal_carname && !isHuman) robotIdx += curModInfo->index; /* Retrieve the driver interface (function pointers) */ curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf)); /* ... and initialize the driver */ #if 0 // SDW if (replayReplay) { // Register against the Replay driver (which does nothing) curModInfo->fctInit(carindex, (void*)(curRobot)); } else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #endif curModInfo->fctInit(robotIdx, (void*)(curRobot)); } else { curRobot->rbNewTrack = NULL; curRobot->rbNewRace = NULL; curRobot->rbResumeRace = NULL; curRobot->rbDrive = NULL; curRobot->rbPitCmd = NULL; curRobot->rbEndRace = NULL; curRobot->rbShutdown = NULL; curRobot->index = 0; } /* Retrieve and load the robotXML file : 1) from user settings dir (local dir) 2) from installed data dir */ snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (normal_carname || isHuman) snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); else snprintf(path, sizeof(path), "%s", ROB_SECT_ARBITRARY); /* Load car/driver info (in race engine data structure) */ if (robhdle) { elt = &(ReInfo->carList[carindex]); GF_TAILQ_INIT(&(elt->_penaltyList)); const std::string strDType = GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT); if (strDType == ROB_VAL_ROBOT){ elt->_driverType = RM_DRV_ROBOT; elt->_networkPlayer = 0; } else if (strDType == ROB_VAL_HUMAN) { elt->_driverType = RM_DRV_HUMAN; std::string strNetPlayer = GfParmGetStr(robhdle, path, "networkrace", "no"); elt->_networkPlayer = (strNetPlayer == "yes") ? 1 : 0; } elt->index = carindex; elt->robot = curRobot; elt->_paramsHandle = robhdle; elt->_driverIndex = robotIdx; elt->_moduleIndex = relativeRobotIdx; strncpy(elt->_modName, cardllname, MAX_NAME_LEN - 1); elt->_modName[MAX_NAME_LEN - 1] = 0; //snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); snprintf( path2, sizeof(path2), "%s/%s/%d/%d", RM_SECT_DRIVERINFO, elt->_modName, normal_carname ? 0 : 1, elt->_moduleIndex ); if (normal_carname || elt->_driverType == RM_DRV_HUMAN) { strncpy(elt->_name, GfParmGetStr(robhdle, path, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(robhdle, path, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(robhdle, path, ROB_ATTR_CODE, "---"), 3); } else { strncpy(elt->_name, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_CODE, "---"), 3); } elt->_name[MAX_NAME_LEN - 1] = 0; elt->_sname[MAX_NAME_LEN - 1] = 0; elt->_cname[3] = 0; teamname = GfParmGetStr(robhdle, path, ROB_ATTR_TEAM, "none"); teamname = GfParmGetStr(ReInfo->params, path2, ROB_ATTR_TEAM, teamname ); //Use the name in params if it has a team name strncpy(elt->_teamname, teamname, MAX_NAME_LEN - 1); elt->_teamname[MAX_NAME_LEN - 1] = 0; elt->_driveSkill = GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKILLLEVEL, NULL, -1.0f); if (normal_carname) /* Even if we get a normal_carname for humans we use it despite of forced extended mode*/ strncpy(elt->_carName, GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""), MAX_NAME_LEN - 1); else 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 custom skin name and targets from race info (if specified). snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, listindex); if (GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, 0)) { strncpy(elt->_skinName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, ""), 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; elt->_skillLevel = 0; str = GfParmGetStr(robhdle, path, ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO); for(k = 0; k < NSkillLevels; k++) { if (strcmp(aPszSkillLevelNames[k], str) == 0) { elt->_skillLevel = k; break; } } elt->_startRank = carindex; elt->_pos = carindex+1; elt->_remainingLaps = ReInfo->s->_totLaps; elt->_newTrackMemPool = NULL; elt->_newRaceMemPool = NULL; elt->_endRaceMemPool = NULL; elt->_shutdownMemPool = NULL; carname = elt->_carName; GfLogTrace("Driver #%d(%d) : module='%s', name='%s', car='%s', cat='%s', skin='%s' on %x\n", carindex, listindex, elt->_modName, elt->_name, elt->_carName, elt->_category, elt->_skinName, elt->_skinTargets); if ((strncmp(carname.c_str(), "mpa1", 4) == 0)) { if (strcmp(subcategory, "long") == 0) carname = carname+"-long"; else if (strcmp(subcategory, "short") == 0) carname = carname+"-short"; else carname = carname+"-road"; GfLogTrace("MPA... Category car = %s \n", carname.c_str()); /* Retrieve and load car specs : merge car default specs, 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); } else { /* Retrieve and load car specs : merge car default specs, 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); } category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL); if (category) { GfLogTrace("Checking/Merging %s specs into %s base setup for %s ...\n", category, elt->_carName, curModInfo->name); strncpy(elt->_category, category, MAX_NAME_LEN - 1); elt->_category[MAX_NAME_LEN - 1] = 0; /* Read Car Category specifications */ snprintf(buf2, sizeof(buf2), "cars/categories/%s.xml", elt->_category); cathdle = GfParmReadFile(buf2, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); int errorcode = 0; if ((errorcode = GfParmCheckHandle(cathdle, carhdle))) { switch (errorcode) { case -1: GfLogError("Car %s NOT in category %s (driver %s) !!!\n", elt->_carName, category, elt->_name); break; case -2: GfLogError("Parameters out of bound for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; case -3: GfLogError("Parameter not allowed for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; default: GfLogError("Unknown error for %s (driver %s)!!!\n",elt->_carName, elt->_name); break; } return NULL; } carhdle = GfParmMergeHandles(cathdle, carhdle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); /* The code below stores the carnames to a separate xml-file such that at newTrack it is known which car is used. TODO: find a better method for this */ snprintf (buf, sizeof(buf), "%sdrivers/curcarnames.xml", GfLocalDir()); handle = GfParmReadFile(buf, GFPARM_RMODE_CREAT); if (handle) { snprintf(path, sizeof(path), "drivers/%s/%d", cardllname, elt->_driverIndex); GfParmSetStr (handle, path, RM_ATTR_CARNAME, elt->_carName); GfParmWriteFile (0, handle, "Car names"); GfParmReleaseHandle (handle); } if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { GfPoolMove(&elt->_newTrackMemPool, &oldPool); curRobot->rbNewTrack(elt->_driverIndex, ReInfo->track, carhdle, &handle, ReInfo->s); GfPoolFreePool( &oldPool ); } else handle = NULL; if (handle && !replayReplay) { GfLogTrace("Checking/Merging %s specific setup into %s setup.\n", curModInfo->name, elt->_carName); if (GfParmCheckHandle(carhdle, handle)) { GfLogError("Bad Car parameters for driver %s\n", elt->_name); return NULL; } handle = GfParmMergeHandles(carhdle, handle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); } else { GfLogTrace("Keeping %s setup as is for %s (no specific setup).\n", elt->_carName, curModInfo->name); handle = carhdle; } elt->_carHandle = handle; /* Initialize sectors */ elt->_currentSector = 0; elt->_curSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); elt->_bestSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); for (xx = 0; xx < ReInfo->track->numberOfSectors - 1; ++xx) { elt->_curSplitTime[xx] = -1.0f; elt->_bestSplitTime[xx] = -1.0f; } } else { elt->_category[ 0 ] = '\0'; GfLogError("Bad Car category for driver %s\n", elt->_name); return NULL; } return elt; } else { GfLogError("No description file for robot %s\n", cardllname); } return NULL; } /** Initialize the cars for a race. The cars are positionned on the starting grid. @return 0 Ok, -1 Error */ int ReInitCars(void) { char buf[512]; char path[512]; int nCars; int index; int i, j; const char *robotModuleName; int robotIdx; void *robhdle; tCarElt *elt; //const char *focused; // Never used. //int focusedIdx; // Never used. void *params = ReInfo->params; /* Get the number of cars (= drivers) racing */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS_RACING); GfLogTrace("Loading %d car(s)\n", nCars); FREEZ(ReInfo->carList); ReInfo->carList = (tCarElt*)calloc(nCars, sizeof(tCarElt)); FREEZ(ReInfo->rules); ReInfo->rules = (tRmCarRules*)calloc(nCars, sizeof(tRmCarRules)); //focused = GfParmGetStr(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); //focusedIdx = (int)GfParmGetNum(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0); index = 0; /* For each car/driver : */ for (i = 1; i < nCars + 1; i++) { /* Get the name of the module (= shared library) of the robot */ snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); robotModuleName = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, ""); robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0); #if 0 // SDW if (replayReplay) // Register against the Replay driver snprintf(path, sizeof(path), "%sdrivers/replay/replay.%s", GfLibDir(), DLLEXT); else #endif snprintf(path, sizeof(path), "%sdrivers/%s/%s.%s", GfLibDir(), robotModuleName, robotModuleName, DLLEXT); /* Load the robot shared library */ if (GfModLoad(CAR_IDENT, path, ReInfo->robModList)) { GfLogError("Failed to load robot module %s\n", path); continue; } /* Load the racing driver info in the race data structure */ elt = NULL; snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); if ((int)GfParmGetNum(ReInfo->params, path, RM_ATTR_EXTENDED, NULL, 0) == 0) { /* Search for the index of the racing driver in the list of interfaces of the module */ for (j = 0; j < (*(ReInfo->robModList))->modInfoSize; j++) { if ((*(ReInfo->robModList))->modInfo[j].name && (*(ReInfo->robModList))->modInfo[j].index == robotIdx) { /* We have the right driver : load it */ elt = reLoadSingleCar( index, i, j, robotIdx, TRUE, robotModuleName ); if (!elt) { GfLogError("No descriptor file for robot %s or parameter errors (1)\n", robotModuleName); snprintf(buf, sizeof(buf), "Error: May be no driver, or some parameters are out of bound"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Have a look at the console window for mode details about the error"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Back to the config menu in 10 s ..."); ReUI().addLoadingMessage(buf); // Wait some time to allow the user to read the message! GfSleep(10.0); // 10 seconds } } } } else { GfLogTrace("Loading robot %s descriptor file\n", robotModuleName ); snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (robhdle && ( strcmp( robotModuleName, "human" ) == 0 || strcmp( robotModuleName, "networkhuman" ) == 0 ) ) { /* Human driver */ elt = reLoadSingleCar( index, i, robotIdx - (*(ReInfo->robModList))->modInfo[0].index, robotIdx, FALSE, robotModuleName ); } else if (robhdle && ( strcmp( GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "foo" ), GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "bar" ) ) == 0 ) ) { elt = reLoadSingleCar( index, i, (*(ReInfo->robModList))->modInfoSize, robotIdx, FALSE, robotModuleName ); } else GfLogError("No descriptor for robot %s (2)\n", robotModuleName ); } if (elt) ++index; } nCars = index; /* real number of cars */ if (nCars == 0) { GfLogError("No driver for that race ; exiting ...\n"); return -1; } else { GfLogInfo("%d driver(s) ready to race\n", nCars); } if (replayReplay) replayRecord = 0; else { char buf[1024]; const char *replayRateSchemeName; snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, "0"); GfParmReleaseHandle(paramHandle); replayRecord = atoi(replayRateSchemeName); } if (replayRecord || replayReplay) { #ifdef THIRD_PARTY_SQLITE3 int result; result = sqlite3_open("/tmp/race.sqlite", &replayDB); if (result) { GfLogError("Replay: Unable to open Database: %s\n", sqlite3_errmsg(replayDB)); sqlite3_close(replayDB); replayDB = NULL; } else { GfLogInfo("Replay: Database Opened 0x8%8.8X\n", replayDB); if (replayRecord) GfLogInfo("Replay: Record Timestep = %f\n", 1/(float)replayRecord); if (replayReplay) GfLogInfo("Replay: Playback from file\n"); /* speed up database by turning of synchronous behaviour/etc */ sqlite3_exec(replayDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA journal_mode = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA count_changes = OFF", NULL, NULL, NULL); #if 0 // This pragma seems to prevent re-opening the sqlite3 database sqlite3_exec(replayDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL, NULL); #endif sqlite3_exec(replayDB, "PRAGMA default_temp_store = MEMORY", NULL, NULL, NULL); //replayBlobs = (sqlite3_stmt *) calloc(nCars, sizeof(void *)); //sqlite3_stmt)); replayTimestamp = -5; ghostcarActive = 0; } #endif } ReInfo->s->_ncars = nCars; FREEZ(ReInfo->s->cars); ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *)); for (i = 0; i < nCars; i++) { ReInfo->s->cars[i] = &(ReInfo->carList[i]); #ifdef THIRD_PARTY_SQLITE3 //open a table for each car if (replayDB) { char command[200]; int result; if (replayRecord) { sprintf(command, "DROP TABLE IF EXISTS car%d", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to drop table car%d: %s\n", i, sqlite3_errmsg(replayDB)); } sprintf(command, "CREATE TABLE IF NOT EXISTS car%d (timestamp, lap, datablob BLOB)", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) { GfLogInfo("Replay: Unable to create table car%d: %s\n", i, sqlite3_errmsg(replayDB)); exit(0); } if (replayReplay) { // Build index to allow faster read access sprintf(command, "CREATE UNIQUE INDEX IF NOT EXISTS index%d ON car%d (timestamp)", i, i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to create index car%d: %s\n", i, sqlite3_errmsg(replayDB)); } } #endif } ReInfo->_rePitRequester = 0; // TODO: reconsider splitting the call into one for cars, track and maybe other objects. // I stuff for now anything into one call because collision detection works with the same // library on all objects, so it is a bit dangerous to distribute the handling to various // locations (because the library maintains global state like a default collision handler etc.). RePhysicsEngine().initialize(nCars, ReInfo->track); initStartingGrid(); initPits(); return 0; }
static void parseIntoBlocks( tFormNode **node ) { tFormNode *curNode = *node; tFormNode *prevNode = NULL; tFormNode *newNode; tFormNode *startNodeBracket1 = NULL; tFormNode *startNodeBracket2 = NULL; tFormNode *startNodeKomma1 = NULL; tFormNode *startNodeKomma2 = NULL; int bracketLevel = 0; char hasKomma = FALSE; while( curNode ) { if( curNode->type == FORMNODE_TYPE_TOPARSE_STRING && curNode->string[ 0 ] == '(' ) { if( bracketLevel == 0 ) { startNodeBracket1 = prevNode; startNodeBracket2 = curNode; } ++bracketLevel; } else if( curNode->type == FORMNODE_TYPE_TOPARSE_STRING && curNode->string[ 0 ] == ')' ) { if( bracketLevel == 1 ) { newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); if( startNodeBracket2->next != curNode ) newNode->firstChild = startNodeBracket2->next; else newNode->firstChild = NULL; newNode->next = curNode->next; newNode->type = FORMNODE_TYPE_TOPARSE_BLOCK; newNode->number = 0.0f; newNode->string = NULL; newNode->func = NULL; prevNode->next = NULL; if( startNodeBracket1 ) startNodeBracket1->next = newNode; else *node = newNode; FREEZ( startNodeBracket2->string ); free( startNodeBracket2 ); prevNode = startNodeBracket1; FREEZ( curNode->string ); free( curNode ); curNode = newNode; } if( bracketLevel > 0 ) --bracketLevel; } else if( bracketLevel == 0 && curNode->type == FORMNODE_TYPE_TOPARSE_STRING && curNode->string[ 0 ] == ',' ) { newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); if( hasKomma ) newNode->firstChild = startNodeKomma2->next; else newNode->firstChild = *node; newNode->next = curNode->next; newNode->type = FORMNODE_TYPE_TOPARSE_BLOCK; newNode->number = 0.0f; newNode->string = NULL; newNode->func = NULL; if( prevNode ) prevNode->next = NULL; if( hasKomma ) { startNodeKomma1->next = newNode; FREEZ(startNodeKomma2->string); free( startNodeKomma2 ); } else { *node = newNode; } startNodeKomma2 = curNode; startNodeKomma1 = newNode; hasKomma = TRUE; } if( curNode->firstChild ) parseIntoBlocks( &(curNode->firstChild) ); prevNode = curNode; curNode = curNode->next; } if( hasKomma ) { /* Wrap finishing block */ newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); newNode->firstChild = startNodeKomma2->next; newNode->next = NULL; newNode->type = FORMNODE_TYPE_TOPARSE_BLOCK; newNode->number = 0.0f; newNode->string = NULL; newNode->func = NULL; parseIntoBlocks( &newNode ); startNodeKomma1->next = newNode; FREEZ( startNodeKomma2->string ); free( startNodeKomma2 ); parseIntoBlocks( &newNode ); } }
static void parseFormStringStep1( tFormNode **node, const char *string ) { tFormNode *newNode; tFormNode *prevNode = NULL; int type = 0; int startPos = -1; int currentPos = 0; int stringLength = strlen( string ); int xx; (*node) = NULL; while( currentPos < stringLength ) { if( startPos >= 0 ) { /* Check if block has ended */ if( type == FORMNODE_TYPE_STRING && string[ currentPos ] == '#' ) { /* String ended here */ newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); newNode->firstChild = NULL; newNode->next = NULL; newNode->type = FORMNODE_TYPE_STRING; newNode->number = 0.0f; newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) ); newNode->func = NULL; for( xx = startPos; xx < currentPos; ++xx ) newNode->string[ xx - startPos ] = string[ xx ]; newNode->string[ currentPos - startPos ] = '\0'; if( *node ) prevNode->next = newNode; else (*node) = newNode; startPos = -1; prevNode = newNode; } else if( type == FORMNODE_TYPE_NUMBER && ( string[ currentPos ] < '0' || string[ currentPos ] > '9' ) && string[ currentPos ] != '.' ) { /* Number ended here */ newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); newNode->firstChild = NULL; newNode->next = NULL; newNode->type = FORMNODE_TYPE_NUMBER; newNode->number = 0.0f; newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) ); newNode->func = NULL; for( xx = startPos; xx < currentPos; ++xx ) newNode->string[ xx - startPos ] = string[ xx ]; newNode->string[ currentPos - startPos ] = '\0'; newNode->number = (tdble)atof( newNode->string ); FREEZ( newNode->string ); if( *node ) prevNode->next = newNode; else (*node) = newNode; prevNode = newNode; startPos = -1; --currentPos; } else if( type == FORMNODE_TYPE_TOPARSE_STRING && ( string[ currentPos ] < 'a' || string[ currentPos ] > 'z' ) && ( string[ currentPos ] < 'A' || string[ currentPos ] > 'Z' ) && ( string[ currentPos ] != '_' ) ) { /* Toparse String ended here */ newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); newNode->firstChild = NULL; newNode->next = NULL; newNode->type = FORMNODE_TYPE_TOPARSE_STRING; newNode->number = 0.0f; newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) ); newNode->func = NULL; for( xx = startPos; xx < currentPos; ++xx ) newNode->string[ xx - startPos ] = string[ xx ]; newNode->string[ currentPos - startPos ] = '\0'; if( *node ) prevNode->next = newNode; else (*node) = newNode; prevNode = newNode; startPos = -1; --currentPos; } } else { if( string[ currentPos ] == '#' ) { startPos = currentPos + 1; type = FORMNODE_TYPE_STRING; } else if( string[ currentPos ] >= '0' && string[ currentPos ] <= '9' ) { startPos = currentPos; type = FORMNODE_TYPE_NUMBER; } else if( ( string[ currentPos ] >= 'a' && string[ currentPos ] <= 'z' ) || ( string[ currentPos ] >= 'A' && string[ currentPos ] <= 'Z' ) ) { startPos = currentPos; type = FORMNODE_TYPE_TOPARSE_STRING; } else if( string[ currentPos ] == '(' || string[ currentPos ] == ')' || string[ currentPos ] == ',' || string[ currentPos ] == '+' || string[ currentPos ] == '-' || string[ currentPos ] == '*' || string[ currentPos ] == '/' || string[ currentPos ] == '\\' ) { /* Extra token */ newNode = (tFormNode*)malloc( sizeof( tFormNode ) ); newNode->firstChild = NULL; newNode->next = NULL; newNode->type = FORMNODE_TYPE_TOPARSE_STRING; newNode->number = 0.0f; newNode->string = (char*)malloc( sizeof( char ) * 3 ); newNode->func = NULL; if( ( string[ currentPos ] == '/' || string[ currentPos ] == '\\' ) && ( string[ currentPos + 1 ] == '/' || string[ currentPos + 1 ] == '\\' ) && string[ currentPos ] != string[ currentPos + 1 ] ) { newNode->string[ 0 ] = string[ currentPos ]; newNode->string[ 1 ] = string[ currentPos + 1 ]; newNode->string[ 2 ] = '\0'; ++currentPos; } else { newNode->string[ 0 ] = string[ currentPos ]; newNode->string[ 1 ] = '\0'; } if( *node ) prevNode->next = newNode; else (*node) = newNode; prevNode = newNode; } else if( string[ currentPos ] != ' ' && string[ currentPos ] != '\n' && string[ currentPos ] != '\r' ) { GfError( "Formula parser: invalid token: \'%c\'\n", string[ currentPos ] ); } } ++currentPos; } }
/** Release the tCtrlMouseInfo structure @ingroup ctrl @param mouseInfo mouse structure @return none */ void GfctrlMouseRelease(tCtrlMouseInfo *mouseInfo) { FREEZ(mouseInfo); }
/* return state mode */ int ReRaceStart(void) { int i; int nCars; int maxCars; const char *raceName = ReInfo->_reRaceName; void *params = ReInfo->params; void *results = ReInfo->results; const int BUFSIZE = 1024; char path[BUFSIZE], path2[BUFSIZE]; FREEZ(ReInfo->_reCarInfo); ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo)); /* Drivers starting order */ GfParmListClean(params, RM_SECT_DRIVERS_RACING); if (ReInfo->s->_raceType == RM_TYPE_QUALIF) { i = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); if (i == 1) { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); RmLoadingScreenSetText("Preparing Starting Grid..."); } else { RmShutdownLoadingScreen(); } snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i); snprintf(path2, BUFSIZE, "%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)); } else { RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png"); RmLoadingScreenSetText("Preparing Starting Grid..."); const char* gridType = GfParmGetStr(params, raceName, RM_ATTR_START_ORDER, RM_VAL_DRV_LIST_ORDER); if (!strcmp(gridType, RM_VAL_LAST_RACE_ORDER)) { /* Starting grid in the arrival of the previous race */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); const char* prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); 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)); } } else if (!strcmp(gridType, RM_VAL_LAST_RACE_RORDER)) { /* Starting grid in the reversed arrival order of the previous race */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); const char* prevRaceName = ReGetPrevRaceName(); if (!prevRaceName) { return RM_QUIT; } for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, nCars - i + 1); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); 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)); } } else { /* Starting grid in the drivers list order */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); for (i = 1; i < nCars + 1; i++) { snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i); snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i); 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)); } } } if (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) { if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_SPLASH_MENU, RM_VAL_NO), RM_VAL_YES)) { RmShutdownLoadingScreen(); RmDisplayStartRace(ReInfo, StartRaceHookInit(), AbandonRaceHookInit()); return RM_ASYNC | RM_NEXT_STEP; } } return reRaceRealStart(); }
int ReRaceEventShutdown(void) { char buf[64]; int curTrkIdx; void *params = ReInfo->params; int nbTrk; void *results = ReInfo->results; int curRaceIdx; bool careerMode = false; bool first = true; // Notify the UI that the race event is finishing now. ReUI().onRaceEventFinishing(); // Shutdown track-physics-related stuff. ReTrackShutdown(); // Determine the track of the next event to come, if not the last one // and, if Career mode, prepare race params / results for the next event or season. do { nbTrk = GfParmGetEltNb(params, RM_SECT_TRACKS); curRaceIdx =(int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1); curTrkIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1); if (curRaceIdx == 1) { if (curTrkIdx < nbTrk) { // Next track. curTrkIdx++; } else if (curTrkIdx >= nbTrk) { // Back to the beginning. curTrkIdx = 1; } } GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, (tdble)curTrkIdx); // Career mode. if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES)) { careerMode = true; const bool lastRaceOfRound = strcmp(GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_LASTSUBFILE, RM_VAL_YES), RM_VAL_YES) == 0; // Previous file <= Current file. GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_PREV_FILE, GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, "")); // Current file <= Next file. GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_NEXTSUBFILE, "")); GfParmWriteFile(NULL, ReInfo->mainResults, NULL); /* Check if the next competition has a free weekend */ if( !first ) { /* Close old params */ GfParmWriteFile( NULL, results, NULL ); GfParmReleaseHandle( results ); GfParmReleaseHandle( params ); }//if !first /* Open params of next race */ params = GfParmReadFile( GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, "" ), GFPARM_RMODE_STD ); if( !params ) break; results = GfParmReadFile( GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_RESULTSUBFILE, ""), GFPARM_RMODE_STD ); if( !results ) { GfParmReleaseHandle( results ); break; } if (lastRaceOfRound && curTrkIdx == 1) { ReCareerNextSeason(); } if ((int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) == 1) { GfParmListClean(results, RE_SECT_STANDINGS); GfParmWriteFile(NULL, results, NULL); } /* Check if it is free */ snprintf( buf, sizeof(buf), "%s/%d", RM_SECT_TRACKS, (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) ); if( !strcmp(GfParmGetStr(params, buf, RM_ATTR_NAME, "free"), "free") == 0) { /* Not a free weekend */ GfParmReleaseHandle( results ); GfParmReleaseHandle( params ); break; } first = false; } else { // Normal mode (no subfiles, so free weekends possible, so nothing to check) break; } } while( true ); // Determine new race state automaton mode. int mode = (curTrkIdx != 1 || careerMode) ? RM_NEXT_RACE : RM_NEXT_STEP; bool careerNonHumanGroup = careerMode && !ReHumanInGroup(); mode |= ReUI().onRaceEventFinished(nbTrk != 1, careerNonHumanGroup) ? RM_SYNC : RM_ASYNC;; if (mode & RM_NEXT_STEP) FREEZ(ReInfo->_reCarInfo); return mode; }
/* Compute the race rules and penalties */ static void ReRaceRules(tCarElt *car) { tCarPenalty *penalty; tTrack *track = ReInfo->track; tRmCarRules *rules = &(ReInfo->rules[car->index]); tTrackSeg *seg = RtTrackGetSeg(&(car->_trkPos)); tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tTrackSeg *prevSeg = RtTrackGetSeg(&(info->prevTrkPos)); static float color[] = {0.0, 0.0, 1.0, 1.0}; // DNF cars which need too much time for the current lap, this is mainly to avoid // that a "hanging" driver can stop the quali from finishing. // Allowed time is longest pitstop possible + time for tracklength with speed??? (currently fixed 10 [m/s]). // for simplicity. Human driver is an exception to this rule, to allow explorers // to enjoy the landscape. // TODO: Make it configurable. if ((car->_curLapTime > 84.5 + ReInfo->track->length/10.0) && (car->_driverType != RM_DRV_HUMAN)) { car->_state |= RM_CAR_STATE_ELIMINATED; return; } if (car->_skillLevel < 3) { /* only for the pros */ return; } penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty) { if (car->_laps > penalty->lapToClear) { /* too late to clear the penalty, out of race */ car->_state |= RM_CAR_STATE_ELIMINATED; return; } switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(car->ctrl.msg[3], "Drive Through Penalty"); break; case RM_PENALTY_STOPANDGO: sprintf(car->ctrl.msg[3], "Stop And Go Penalty"); break; default: *(car->ctrl.msg[3]) = 0; break; } memcpy(car->ctrl.msgColor, color, sizeof(car->ctrl.msgColor)); } if (prevSeg->raceInfo & TR_PITSTART) { /* just entered the pit lane */ if (seg->raceInfo & TR_PIT) { /* may be a penalty can be cleaned up */ if (penalty) { switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(buf, "%s DRIVE THROUGH PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_DRIVETHROUGH; break; case RM_PENALTY_STOPANDGO: sprintf(buf, "%s STOP&GO PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_STOPANDGO; break; } } } } else if (prevSeg->raceInfo & TR_PIT) { if (seg->raceInfo & TR_PIT) { /* the car stopped in pits */ if (car->_state & RM_CAR_STATE_PIT) { if (rules->ruleState & RM_PNST_DRIVETHROUGH) { /* it's not more a drive through */ rules->ruleState &= ~RM_PNST_DRIVETHROUGH; } else if (rules->ruleState & RM_PNST_STOPANDGO) { rules->ruleState |= RM_PNST_STOPANDGO_OK; } } else { if(rules->ruleState & RM_PNST_STOPANDGO_OK && car->_pitStopType != RM_PIT_STOPANDGO) { rules->ruleState &= ~ ( RM_PNST_STOPANDGO | RM_PNST_STOPANDGO_OK ); } } } else if (seg->raceInfo & TR_PITEND) { /* went out of the pit lane, check if the current penalty is cleared */ if (rules->ruleState & (RM_PNST_DRIVETHROUGH | RM_PNST_STOPANDGO_OK)) { /* clear the penalty */ sprintf(buf, "%s penalty cleared", car->_name); ReRaceMsgSet(buf, 5); penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); GF_TAILQ_REMOVE(&(car->_penaltyList), penalty, link); FREEZ(penalty); } rules->ruleState = 0; } else { /* went out of the pit lane illegally... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } } else if (seg->raceInfo & TR_PITEND) { rules->ruleState = 0; } else if (seg->raceInfo & TR_PIT) { /* entrered the pits not from the pit entry... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } if (seg->raceInfo & TR_SPEEDLIMIT) { if (!(rules->ruleState & (RM_PNST_SPD | RM_PNST_STNGO)) && (car->_speed_x > track->pits.speedLimit)) { sprintf(buf, "%s DRIVE THROUGH PENALTY", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_SPD; penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_DRIVETHROUGH; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); } } }
/* return state mode */ int ReRaceStart(void) { char path[128]; char path2[128]; const char *sessionName = ReInfo->_reRaceName; void *params = ReInfo->params; void *results = ReInfo->results; int mode = 0; // Trace race session identification (more to say for the Carer mode). char pszSessionId[128]; if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES)) { const char* pszGroup = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, "<no group>"); snprintf(pszSessionId, sizeof(pszSessionId), "%s %s %s", ReInfo->_reName, pszGroup, sessionName); } else snprintf(pszSessionId, sizeof(pszSessionId), "%s %s", ReInfo->_reName, sessionName); GfLogInfo("Starting %s session at %s\n", pszSessionId, ReInfo->track->name); // Reallocate and reset car info for the race. FREEZ(ReInfo->_reCarInfo); ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo)); ReUI().onRaceInitializing(); // Drivers starting order int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS); GfParmListClean(params, RM_SECT_DRIVERS_RACING); if (nCars == 0) { // This may happen, when playing with the text-only mode, // and forgetting that human are automatically excluded then, // or when getting back to the GUI mode, and not reconfiguring the competitors list. GfLogError("No competitor in this race : cancelled.\n"); mode = RM_ERROR; } else if ((ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE) && ReInfo->s->_totTime < 0.0f /* Timed session? */) //Checks if there is only one driver per session allowed, so practice, qualification without timed session. { // non-timed Qualification or Practice session => 1 driver at a time = the "current" one. int nCurrDrvInd = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1); if (nCurrDrvInd == -1) return RM_ERROR; // Propagate competitor drivers info to the real race starting grid snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, nCurrDrvInd); snprintf(path2, sizeof(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)); GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0)); if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0)) GfParmSetStr(params, path2, RM_ATTR_SKINNAME, GfParmGetStr(params, path, RM_ATTR_SKINNAME, "")); } else { // For a race, add cars to the starting grid in the order stored in ReStartingOrderIdx. ReUI().addLoadingMessage("Preparing Starting Grid ..."); int maxCars = (int)GfParmGetNum(params, sessionName, RM_ATTR_MAX_DRV, NULL, 100); nCars = MIN(nCars, maxCars); int currDriver = -1; int aCars = 0; for (int i = 1; i < nCars + 1; i++) { currDriver = ReStartingOrderIdx[i-1]; if (currDriver == -1) continue; aCars++; snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, currDriver); snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, i); GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RE_ATTR_MODULE, "")); GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RE_ATTR_IDX, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL, GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0)); GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL, GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0)); if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0)) GfParmSetStr(params, path2, RM_ATTR_SKINNAME, GfParmGetStr(params, path, RM_ATTR_SKINNAME, "")); } //no valid drivers present in the list if (aCars == 0) { GfLogError("No competitor in this race : cancelled.\n"); mode = RM_ERROR; } } //ReTrackUpdate(); if (!(mode & RM_ERROR)) { // According to what the UI answers, start the race right now or not. mode = RM_ASYNC | RM_NEXT_STEP; const bool bGoOn = ReUI().onRaceStarting(); if (bGoOn) mode = ReRaceRealStart(); } return mode; }
void ReUpdateQualifCurRes(tCarElt *car) { static const char* pszTableHeader = "Rank \tTime \tDriver \tCar"; int i; int xx; int nCars; int nCarsReal; int printed; int maxLines; void *carparam; char *carName; const char *race = ReInfo->_reRaceName; void *results = ReInfo->results; char *tmp_str; double time_left; if (ReInfo->s->_ncars == 1) { ReUI().eraseResultsTable(); maxLines = ReUI().getResultsTableRowCount(); snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", car->_carName, car->_carName); carparam = GfParmReadFile(buf, GFPARM_RMODE_STD); carName = GfParmGetName(carparam); char pszTitle[128]; snprintf(pszTitle, sizeof(pszTitle), "%s at %s", race, ReInfo->track->name); if (ReInfo->s->_raceType == RM_TYPE_PRACTICE || car->_laps < 1 || car->_laps > ReInfo->s->_totLaps) snprintf(buf, sizeof(buf), "%s (%s)", car->_name, carName); else snprintf(buf, sizeof(buf), "%s (%s) - Lap %d", car->_name, carName, car->_laps); ReUI().setResultsTableTitles(pszTitle, buf); ReUI().setResultsTableHeader(pszTableHeader); printed = 0; snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK); nCarsReal = GfParmGetEltNb(results, path); nCars = MIN(nCarsReal + 1, maxLines); // limit display to only those on 1st page for (i = 1; i < nCars; i++) { snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i); if (!printed && car->_bestLapTime != 0.0 && car->_bestLapTime < GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0)) { tmp_str = GfTime2Str(car->_bestLapTime, " ", false, 3); snprintf(buf, sizeof(buf), " %2d \t%-12s \t%-25s \t%-20s", i, tmp_str, car->_name, carName); free(tmp_str); ReUI().setResultsTableRow(i - 1, buf, /*highlight=*/true); printed = 1; } tmp_str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), " ", false, 3); snprintf(buf, sizeof(buf), " %2d \t%-12s \t%-25s \t%-20s", i + printed, tmp_str, GfParmGetStr(results, path, RE_ATTR_NAME, ""), GfParmGetStr(results, path, RE_ATTR_CAR, "")); free (tmp_str); ReUI().setResultsTableRow(i - 1 + printed, buf); } if (!printed) { tmp_str = GfTime2Str(car->_bestLapTime, " ", false, 3); snprintf(buf, sizeof(buf), " %2d \t%-12s \t%-25s \t%-20s", nCarsReal + 1, tmp_str, car->_name, carName); free(tmp_str); ReUI().setResultsTableRow(i - 1, buf, /*highlight=*/true); } GfParmReleaseHandle(carparam); } else { nCars = ReInfo->s->_ncars; if (nCars > ReUI().getResultsTableRowCount()) nCars = ReUI().getResultsTableRowCount(); char pszTitle[128]; snprintf(pszTitle, sizeof(pszTitle), "%s at %s", race, ReInfo->track->name); if (ReInfo->s->_totTime > ReInfo->s->currentTime) { time_left = ReInfo->s->_totTime - ReInfo->s->currentTime; snprintf( buf, sizeof(buf), "%d:%02d:%02d", (int)floor( time_left / 3600.0f ), (int)floor( time_left / 60.0f ) % 60, (int)floor( time_left ) % 60 ); } else { snprintf( buf, sizeof(buf), "%d laps", ReInfo->s->_totLaps ); } ReUI().setResultsTableTitles(pszTitle, buf); ReUI().setResultsTableHeader(pszTableHeader); 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); carName = strdup(GfParmGetName(carparam)); GfParmReleaseHandle(carparam); if (car->_state & RM_CAR_STATE_DNF) { snprintf(buf, sizeof(buf), "out \t \t%-25s \t%-20s", car->_name, carName); } else if (car->_bestLapTime <= 0.0f) { snprintf(buf, sizeof(buf), " %2d \t --:--- \t%-25s \t%-20s", xx + 1, car->_name, carName); } else { if (xx == 0) tmp_str = GfTime2Str(car->_bestLapTime, " ", false, 3); else tmp_str = GfTime2Str(car->_bestLapTime - ReInfo->s->cars[0]->_bestLapTime, "+", false, 3); snprintf(buf, sizeof(buf), " %2d \t%-12s \t%-25s \t%-20s", xx + 1, tmp_str, car->_name, carName); free(tmp_str); } ReUI().setResultsTableRow(xx, buf); FREEZ(carName); } } }
/** Release the tCtrlJoyInfo structure @ingroup ctrl @param joyInfo joystick structure @return none */ void GfctrlJoyRelease(tCtrlJoyInfo *joyInfo) { FREEZ(joyInfo); }
void ReUpdateRaceCurRes() { static const char* pszTableHeader = "Rank \tTime \tDriver \tCar"; int ncars; int xx; void *carparam; char *carName; tCarElt *car; char *tmp_str; double time_left; ncars = ReInfo->s->_ncars; if (ncars > ReUI().getResultsTableRowCount()) ncars = ReUI().getResultsTableRowCount(); char pszTitle[128]; snprintf(pszTitle, sizeof(pszTitle), "%s at %s", ReInfo->_reRaceName, ReInfo->track->name); if (ReInfo->s->_totTime > ReInfo->s->currentTime) { time_left = ReInfo->s->_totTime - ReInfo->s->currentTime; snprintf( buf, sizeof(buf), "%d:%02d:%02d", (int)floor( time_left / 3600.0f ), (int)floor( time_left / 60.0f ) % 60, (int)floor( time_left ) % 60 ); } else { snprintf( buf, sizeof(buf), "%d laps", ReInfo->s->_totLaps ); } ReUI().setResultsTableTitles(pszTitle, buf); ReUI().setResultsTableHeader(pszTableHeader); 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); carName = strdup(GfParmGetName(carparam)); GfParmReleaseHandle(carparam); if (car->_state & RM_CAR_STATE_DNF) { snprintf(buf, sizeof(buf), "out %-20s %-20s", car->_name, carName); } else if (car->_timeBehindLeader == 0.0f) { if (xx != 0) snprintf(buf, sizeof(buf), " %2d \t --:--- \t%-25s \t%-20s", xx + 1, car->_name, carName); else snprintf(buf, sizeof(buf), " %2d \t%3d laps \t%-25s \t%-20s", xx + 1, car->_laps - 1, car->_name, carName); } else { if (xx == 0) { snprintf(buf, sizeof(buf), " %2d \t%3d laps \t%-25s \t%-20s", xx + 1, car->_laps - 1, car->_name, carName); } else { if (car->_lapsBehindLeader == 0) { tmp_str = GfTime2Str(car->_timeBehindLeader, " ", false, 3); snprintf(buf, sizeof(buf), " %2d \t%-12s\t%-25s \t%-20s", xx + 1, tmp_str, car->_name, carName); free(tmp_str); } else if (car->_lapsBehindLeader == 1) snprintf(buf, sizeof(buf), " %2d \t 1 lap \t%-25s \t%-20s", xx + 1, car->_name, carName); else snprintf(buf, sizeof(buf), " %2d \t %3d laps \t%-25s \t%-20s", xx + 1, car->_lapsBehindLeader, car->_name, carName); } } ReUI().setResultsTableRow(xx, buf); FREEZ(carName); } }
void grInitCar(tCarElt *car) { const int BUFSIZE=4096; char buf[BUFSIZE]; int index; int selIndex; ssgEntity *carEntity; ssgSelector *LODSel; ssgTransform *wheel[4]; int nranges; int i, j; void *handle; const char *param; int lg; const int PATHSIZE=256; char path[PATHSIZE]; myLoaderOptions options; sgVec3 lightPos; int lightNum; const char *lightType; int lightTypeNum; if (!CarsAnchorTmp) { CarsAnchorTmp = new ssgBranch(); } grInitBoardCar(car); TRACE_GL("loadcar: start"); ssgSetCurrentOptions ( &options ) ; grCarIndex = index = car->index; /* current car's index */ handle = car->_carHandle; /* Load visual attributes */ car->_exhaustNb = GfParmGetEltNb(handle, SECT_EXHAUST); car->_exhaustNb = MIN(car->_exhaustNb, 2); car->_exhaustPower = GfParmGetNum(handle, SECT_EXHAUST, PRM_POWER, NULL, 1.0); for (i = 0; i < car->_exhaustNb; i++) { snprintf(path, PATHSIZE, "%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); } snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, SECT_LIGHT); lightNum = GfParmGetEltNb(handle, path); for (i = 0; i < lightNum; i++) { snprintf(path, PATHSIZE, "%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); lightType = GfParmGetStr(handle, path, PRM_TYPE, ""); lightTypeNum = LIGHT_NO_TYPE; if (!strcmp(lightType, VAL_LIGHT_HEAD1)) { lightTypeNum = LIGHT_TYPE_FRONT; } else if (!strcmp(lightType, VAL_LIGHT_HEAD2)) { lightTypeNum = LIGHT_TYPE_FRONT2; } else if (!strcmp(lightType, VAL_LIGHT_BRAKE)) { lightTypeNum = LIGHT_TYPE_BRAKE; } else if (!strcmp(lightType, VAL_LIGHT_BRAKE2)) { lightTypeNum = LIGHT_TYPE_BRAKE2; } else if (!strcmp(lightType, VAL_LIGHT_REAR)) { lightTypeNum = LIGHT_TYPE_REAR; } grAddCarlight(car, lightTypeNum, lightPos, GfParmGetNum(handle, path, PRM_SIZE, NULL, 0.2)); } grLinkCarlights(car); GfOut("[gr] Init(%d) car %s for driver %s index %d\n", index, car->_carName, car->_modName, car->_driverIndex); grFilePath = (char*)malloc(BUFSIZE); lg = 0; lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d;", car->_modName, car->_driverIndex); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%s;", car->_modName, car->_carName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s;", car->_modName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "cars/%s", car->_carName); param = GfParmGetStr(handle, SECT_GROBJECTS, PRM_WHEEL_TEXTURE, ""); if (strlen(param) != 0) { grGammaValue = 1.8; grMipMap = 0; grCarInfo[index].wheelTexture = grSsgLoadTexState(param); } grCarInfo[index].envSelector = (ssgStateSelector*)grEnvSelector->clone(); grCarInfo[index].envSelector->ref(); /* the base transformation of the car (rotation + translation) */ grCarInfo[index].carTransform = new ssgTransform; DBG_SET_NAME(grCarInfo[index].carTransform, car->_modName, index, -1); /* Level of details */ grCarInfo[index].LODSelector = LODSel = new ssgSelector; grCarInfo[index].carTransform->addKid(LODSel); snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, LST_RANGES); nranges = GfParmGetEltNb(handle, path) + 1; if (nranges < 2) { GfOut("Error not enough levels of detail\n"); FREEZ(grFilePath); return; } /* First LOD */ ssgBranch *carBody = new ssgBranch; DBG_SET_NAME(carBody, "LOD", index, 0); LODSel->addKid(carBody); /* The car's model is under cars/<model> */ snprintf(buf, BUFSIZE, "cars/%s", car->_carName); ssgModelPath(buf); snprintf(buf, BUFSIZE, "drivers/%s/%d;drivers/%s;cars/%s", car->_modName, car->_driverIndex, car->_modName, car->_carName); ssgTexturePath(buf); grTexturePath = strdup(buf); /* loading raw car level 0*/ selIndex = 0; /* current selector index */ snprintf(buf, BUFSIZE, "%s.ac", car->_carName); /* default car name */ snprintf(path, PATHSIZE, "%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 = ssgLoad(param);*/ carEntity = grssgCarLoadAC3D(param, NULL, index); grCarInfo[index].carEntity = carEntity; /* Set a selector on the driver */ char* stmp = strdup("DRIVER"); ssgBranch *b = (ssgBranch *)carEntity->getByName(stmp); free(stmp); grCarInfo[index].driverSelector = new ssgSelector; if (b) { ssgBranch *bp = b->getParent(0); bp->addKid(grCarInfo[index].driverSelector); grCarInfo[index].driverSelector->addKid(b); bp->removeKid(b); grCarInfo[index].driverSelector->select(1); grCarInfo[index].driverSelectorinsg = true; } else { grCarInfo[index].driverSelectorinsg = false; } DBG_SET_NAME(carEntity, "Body", index, -1); carBody->addKid(carEntity); /* add wheels */ for (i = 0; i < 4; i++){ wheel[i] = initWheel(car, i); carBody->addKid(wheel[i]); } grCarInfo[index].LODSelectMask[0] = 1 << selIndex; /* car mask */ selIndex++; grCarInfo[index].sx=carTrackRatioX; grCarInfo[index].sy=carTrackRatioY; /* Other LODs */ for (i = 2; i < nranges; i++) { carBody = new ssgBranch; snprintf(buf, BUFSIZE, "%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); */ carEntity = grssgCarLoadAC3D(param, NULL, index);; DBG_SET_NAME(carEntity, "LOD", index, i-1); carBody->addKid(carEntity); if (!strcmp(GfParmGetStr(handle, buf, PRM_WHEELSON, "no"), "yes")) { /* add wheels */ for (j = 0; j < 4; j++){ carBody->addKid(wheel[j]); } } LODSel->addKid(carBody); grCarInfo[index].LODSelectMask[i-1] = 1 << selIndex; /* car mask */ selIndex++; } /* default range selection */ LODSel->select(grCarInfo[index].LODSelectMask[0]); CarsAnchor->addKid(grCarInfo[index].carTransform); //grCarInfo[index].carTransform->print(stdout, "-", 1); FREEZ(grTexturePath); FREEZ(grFilePath); TRACE_GL("loadcar: end"); }
static void parseFunctionList( tFormNode **node, tFuncBindList *funcList ) { tFormNode *prevNode = NULL; tFormNode *prevPrevNode = NULL; tFormNode *curNode = *node; tFormNode *newNext = NULL; int xx, yy; while( curNode ) { for( xx = 0; xx < funcList->length; ++xx ) { if( curNode->type == FORMNODE_TYPE_TOPARSE_STRING && curNode->firstChild == NULL && strcmp( curNode->string, funcList->list[ xx ].funcName ) == 0 ) { /* Function found */ curNode->type = FORMNODE_TYPE_FUNCTION; curNode->func = funcList->list[ xx ].func; if( funcList->list[ xx ].hasArgBeforeFuncName ) { curNode->firstChild = prevNode; curNode->firstChild->next = NULL; if( prevPrevNode ) prevPrevNode->next = curNode; else *node = curNode; prevNode = prevPrevNode; prevPrevNode = NULL; if( funcList->list[ xx ].arity > 1 ) { curNode->firstChild->next = curNode->next; newNext = curNode; } yy = 1; } else if( funcList->list[ xx ].arity > 1 ) { yy = funcList->list[ xx ].arity; if( curNode->next ) { curNode->firstChild = curNode->next->firstChild; newNext = curNode->next->next; FREEZ( curNode->next->string ); free( curNode->next ); curNode->next = newNext; } newNext = NULL; } else { curNode->firstChild = curNode->next; newNext = curNode; yy = 0; } while( yy < funcList->list[ xx ].arity ) { if( newNext ) newNext = newNext->next; ++yy; } /* newNext is the last new child */ if( newNext ) { if( curNode != newNext ) { curNode->next = newNext->next; newNext->next = NULL; } else { /* Elsewise no additional arity */ if( funcList->list[ xx ].hasArgBeforeFuncName ) curNode->firstChild->next = NULL; else curNode->firstChild = NULL; } } FREEZ( curNode->string ); break; } } if( curNode->firstChild ) parseFunctionList( &curNode->firstChild, funcList ); prevPrevNode = prevNode; prevNode = curNode; curNode = curNode->next; } }