/* ====================== CG_ParseAnimationFile Read a configuration file containing animation coutns and rates models/players/visor/animation.cfg, etc ====================== */ qboolean G_ParseAnimationFile( const char *af_filename ) { const char *text_p; int len; int i; const char *token; float fps; int skip; char text[40000]; int animNum; animation_t *animations = level.knownAnimFileSets[level.numKnownAnimFileSets].animations; len = gi.RE_GetAnimationCFG(af_filename, NULL, 0); if (len <= 0) { return qfalse; } if ( len <= 0 ) { return qfalse; } if ( len >= sizeof( text ) - 1 ) { G_Error( "G_ParseAnimationFile: File %s too long\n (%d > %d)", af_filename, len, sizeof( text ) - 1); return qfalse; } len = gi.RE_GetAnimationCFG(af_filename, text, sizeof(text)); // parse the text text_p = text; skip = 0; // quiet the compiler warning //FIXME: have some way of playing anims backwards... negative numFrames? //initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100 for(i = 0; i < MAX_ANIMATIONS; i++) { animations[i].firstFrame = 0; animations[i].numFrames = 0; animations[i].loopFrames = -1; animations[i].frameLerp = 100; animations[i].initialLerp = 100; } // read information for each frame while(1) { token = COM_Parse( &text_p ); if ( !token || !token[0]) { break; } animNum = GetIDForString(animTable, token); if(animNum == -1) { //#ifndef FINAL_BUILD #ifdef _DEBUG Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, af_filename); #endif continue; } token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].firstFrame = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].numFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].loopFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } fps = atof( token ); if ( fps == 0 ) { fps = 1;//Don't allow divide by zero error } if ( fps < 0 ) {//backwards animations[animNum].frameLerp = floor(1000.0f / fps); } else { animations[animNum].frameLerp = ceil(1000.0f / fps); } animations[animNum].initialLerp = ceil(1000.0f / fabs(fps)); } #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING if (strstr(af_filename, "humanoid")) { SpewDebugStuffToFile(animations); } #endif return qtrue; }
qboolean BG_ParseAnimationFile(const char *filename) { char *text_p; int len; int i; char *token; float fps; int skip; fileHandle_t f; int animNum; // load the file if (!BGPAFtextLoaded) { //rww - We are always using the same animation config now. So only load it once. len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( len <= 0 ) { return qfalse; } if ( len >= sizeof( BGPAFtext ) - 1 ) { //Com_Printf( "File %s too long\n", filename ); return qfalse; } trap_FS_Read( BGPAFtext, len, f ); BGPAFtext[len] = 0; trap_FS_FCloseFile( f ); } else { return qtrue; } // parse the text text_p = BGPAFtext; skip = 0; // quiet the compiler warning //FIXME: have some way of playing anims backwards... negative numFrames? //initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100 for(i = 0; i < MAX_ANIMATIONS; i++) { bgGlobalAnimations[i].firstFrame = 0; bgGlobalAnimations[i].numFrames = 0; bgGlobalAnimations[i].loopFrames = -1; bgGlobalAnimations[i].frameLerp = 100; bgGlobalAnimations[i].initialLerp = 100; } // read information for each frame while(1) { token = COM_Parse( (const char **)(&text_p) ); if ( !token || !token[0]) { break; } animNum = GetIDForString(animTable, token); if(animNum == -1) { //#ifndef FINAL_BUILD #ifdef _DEBUG Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, filename); #endif continue; } token = COM_Parse( (const char **)(&text_p) ); if ( !token ) { break; } bgGlobalAnimations[animNum].firstFrame = atoi( token ); token = COM_Parse( (const char **)(&text_p) ); if ( !token ) { break; } bgGlobalAnimations[animNum].numFrames = atoi( token ); token = COM_Parse( (const char **)(&text_p) ); if ( !token ) { break; } bgGlobalAnimations[animNum].loopFrames = atoi( token ); token = COM_Parse( (const char **)(&text_p) ); if ( !token ) { break; } fps = atof( token ); if ( fps == 0 ) { fps = 1;//Don't allow divide by zero error } if ( fps < 0 ) {//backwards bgGlobalAnimations[animNum].frameLerp = floor(1000.0f / fps); } else { bgGlobalAnimations[animNum].frameLerp = ceil(1000.0f / fps); } bgGlobalAnimations[animNum].initialLerp = ceil(1000.0f / fabs(fps)); } #ifdef _DEBUG //Check the array, and print the ones that have nothing in them. for(i = 0; i < MAX_ANIMATIONS; i++) { if (animTable[i].name != NULL) // This animation reference exists. { if (bgGlobalAnimations[i].firstFrame <= 0 && bgGlobalAnimations[i].numFrames <=0) { // This is an empty animation reference. Com_Printf("***ANIMTABLE reference #%d (%s) is empty!\n", i, animTable[i].name); } } } #endif // _DEBUG #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING SpewDebugStuffToFile(); #endif BGPAFtextLoaded = qtrue; return qtrue; }