/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”). Wolf ET Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wolf ET Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ /* ** Animation group code */ #include "q_shared.h" #include "bg_public.h" #define MAX_ANIMPOOL_SIZE 5 * MAX_MODEL_ANIMATIONS static animation_t animationPool[MAX_ANIMPOOL_SIZE]; void BG_ClearAnimationPool( void ) { memset( animationPool, 0, sizeof( animationPool ) ); } #ifdef CGAMEDLL static animation_t* BG_RAG_FindFreeAnimation( qhandle_t mdxFile, const char *name ) #else static animation_t * BG_RAG_FindFreeAnimation( const char *mdxFileName, const char *name ) #endif // CGAMEDLL { int i; for ( i = 0; i < MAX_ANIMPOOL_SIZE; i++ ) { #ifdef CGAMEDLL if ( animationPool[i].mdxFile == mdxFile && !Q_stricmp( animationPool[i].name, name ) ) { #else if ( *animationPool[i].mdxFileName && !Q_stricmp( animationPool[i].mdxFileName, mdxFileName ) && !Q_stricmp( animationPool[i].name, name ) ) { #endif // CGAMEDLL return( &animationPool[i] ); } } for ( i = 0; i < MAX_ANIMPOOL_SIZE; i++ ) { #ifdef CGAMEDLL if ( !animationPool[i].mdxFile ) { animationPool[i].mdxFile = mdxFile; #else if ( !animationPool[i].mdxFileName[0] ) { Q_strncpyz( animationPool[i].mdxFileName, mdxFileName, sizeof( animationPool[i].mdxFileName ) ); #endif // CGAMEDLL Q_strncpyz( animationPool[i].name, name, sizeof( animationPool[i].name ) ); return( &animationPool[i] ); } } return NULL; } static qboolean BG_RAG_ParseError( int handle, char *format, ... ) { int line; char filename[128]; va_list argptr; static char string[4096]; va_start( argptr, format ); Q_vsnprintf( string, sizeof( string ), format, argptr ); va_end( argptr ); filename[0] = '\0'; line = 0; trap_PC_SourceFileAndLine( handle, filename, &line ); Com_Printf( S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string ); trap_PC_FreeSource( handle ); return qfalse; } static qboolean BG_RAG_ParseAnimation( int handle, animation_t *animation ) { int i; animation->flags = 0; if ( !PC_Int_Parse( handle, &animation->firstFrame ) ) { return BG_RAG_ParseError( handle, "expected first frame integer" ); } if ( !PC_Int_Parse( handle, &animation->numFrames ) ) { return BG_RAG_ParseError( handle, "expected length integer" ); } if ( !PC_Int_Parse( handle, &animation->loopFrames ) ) { return BG_RAG_ParseError( handle, "expected looping integer" ); } if ( !PC_Int_Parse( handle, &i ) ) { return BG_RAG_ParseError( handle, "expected fps integer" ); } if ( i == 0 ) { i = 1; } animation->frameLerp = 1000 / (float)i; animation->initialLerp = 1000 / (float)i; if ( !PC_Int_Parse( handle, &animation->moveSpeed ) ) { return BG_RAG_ParseError( handle, "expected move speed integer" ); } if ( !PC_Int_Parse( handle, &animation->animBlend ) ) { return BG_RAG_ParseError( handle, "expected transition integer" ); } if ( !PC_Int_Parse( handle, &i ) ) { return BG_RAG_ParseError( handle, "expected reversed integer" ); } if ( i == 1 ) { animation->flags |= ANIMFL_REVERSED; } // calculate the duration animation->duration = animation->initialLerp + animation->frameLerp * animation->numFrames + animation->animBlend; // get the nameHash animation->nameHash = BG_StringHashValue( animation->name ); // hacky-ish stuff if ( !Q_strncmp( animation->name, "climb", 5 ) ) { animation->flags |= ANIMFL_LADDERANIM; } if ( strstr( animation->name, "firing" ) ) { animation->flags |= ANIMFL_FIRINGANIM; animation->initialLerp = 40; } return qtrue; } #ifdef CGAMEDLL extern qhandle_t trap_R_RegisterModel( const char *name ); #endif // CGAMEDLL; static qboolean BG_RAG_ParseAnimFile( int handle, animModelInfo_t *animModelInfo ) { pc_token_t token; #ifdef CGAMEDLL qhandle_t mdxFile; #else char mdxFileName[MAX_QPATH]; #endif // CGAMEDLL animation_t *animation; if ( !trap_PC_ReadToken( handle, &token ) ) { return BG_RAG_ParseError( handle, "expected mdx filename" ); } #ifdef CGAMEDLL if ( !( mdxFile = trap_R_RegisterModel( token.string ) ) ) { return BG_RAG_ParseError( handle, "failed to load %s", token.string ); } #else Q_strncpyz( mdxFileName, token.string, sizeof( mdxFileName ) ); #endif // CGAMEDLL if ( !trap_PC_ReadToken( handle, &token ) || Q_stricmp( token.string, "{" ) ) { return BG_RAG_ParseError( handle, "expected '{'" ); } while ( 1 ) { if ( !trap_PC_ReadToken( handle, &token ) ) { return BG_RAG_ParseError( handle, "unexpected EOF" ); } if ( token.string[0] == '}' ) { break; } #ifdef CGAMEDLL if ( !( animation = BG_RAG_FindFreeAnimation( mdxFile, token.string ) ) ) { #else if ( !( animation = BG_RAG_FindFreeAnimation( mdxFileName, token.string ) ) ) { #endif // CGAMEDLL return BG_RAG_ParseError( handle, "out of animation storage space" ); } Q_strncpyz( animation->name, token.string, sizeof( animation->name ) ); Q_strlwr( animation->name ); if ( !BG_RAG_ParseAnimation( handle, animation ) ) { return qfalse; } animModelInfo->animations[animModelInfo->numAnimations] = animation; animModelInfo->numAnimations++; } return qtrue; } qboolean BG_R_RegisterAnimationGroup( const char *filename, animModelInfo_t *animModelInfo ) { pc_token_t token; int handle; animModelInfo->numAnimations = 0; animModelInfo->footsteps = FOOTSTEP_NORMAL; animModelInfo->gender = GENDER_MALE; animModelInfo->isSkeletal = qtrue; animModelInfo->version = 3; animModelInfo->numHeadAnims = 0; handle = trap_PC_LoadSource( filename ); if ( !handle ) { return qfalse; } if ( !trap_PC_ReadToken( handle, &token ) || Q_stricmp( token.string, "animgroup" ) ) { return BG_RAG_ParseError( handle, "expected 'animgroup'" ); } if ( !trap_PC_ReadToken( handle, &token ) || Q_stricmp( token.string, "{" ) ) { return BG_RAG_ParseError( handle, "expected '{'" ); } while ( 1 ) { if ( !trap_PC_ReadToken( handle, &token ) ) { break; } if ( token.string[0] == '}' ) { break; } if ( !Q_stricmp( token.string, "animfile" ) ) { if ( !BG_RAG_ParseAnimFile( handle, animModelInfo ) ) { return qfalse; } } else { return BG_RAG_ParseError( handle, "unknown token '%s'", token.string ); } } trap_PC_FreeSource( handle ); return qtrue; }