Update UI player animation handling to match CGame

Fix "Error parsing animation file" messages in UI. Caused by fixing the
handling of missing tokens in animation.cfg parser in a past commit.
Fix new Team Arena torso animation frame numbers in UI.
Add support for fixedtorso and fixedlegs keywords.
Add support for reversed animations (negative numframes).
This commit is contained in:
Zack Middleton 2017-09-10 19:16:47 -05:00
parent 098d97bdb0
commit 11b3bca555
4 changed files with 135 additions and 17 deletions

View file

@ -486,6 +486,9 @@ typedef struct {
animation_t animations[MAX_ANIMATIONS];
qboolean fixedlegs; // true if legs yaw is always the same as torso yaw
qboolean fixedtorso; // true if torso never changes yaw
qhandle_t weaponModel;
qhandle_t barrelModel;
qhandle_t flashModel;

View file

@ -363,7 +363,7 @@ UI_RunLerpFrame
===============
*/
static void UI_RunLerpFrame( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation ) {
int f;
int f, numFrames;
animation_t *anim;
// see if the animation sequence is switching
@ -379,25 +379,41 @@ static void UI_RunLerpFrame( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation
// get the next frame based on the animation
anim = lf->animation;
if ( !anim->frameLerp ) {
return; // shouldn't happen
}
if ( dp_realtime < lf->animationTime ) {
lf->frameTime = lf->animationTime; // initial lerp
} else {
lf->frameTime = lf->oldFrameTime + anim->frameLerp;
}
f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
if ( f >= anim->numFrames ) {
f -= anim->numFrames;
numFrames = anim->numFrames;
if (anim->flipflop) {
numFrames *= 2;
}
if ( f >= numFrames ) {
f -= numFrames;
if ( anim->loopFrames ) {
f %= anim->loopFrames;
f += anim->numFrames - anim->loopFrames;
} else {
f = anim->numFrames - 1;
f = numFrames - 1;
// the animation is stuck at the end, so it
// can immediately transition to another sequence
lf->frameTime = dp_realtime;
}
}
lf->frame = anim->firstFrame + f;
if ( anim->reversed ) {
lf->frame = anim->firstFrame + anim->numFrames - 1 - f;
}
else if (anim->flipflop && f>=anim->numFrames) {
lf->frame = anim->firstFrame + anim->numFrames - 1 - (f%anim->numFrames);
}
else {
lf->frame = anim->firstFrame + f;
}
if ( dp_realtime > lf->frameTime ) {
lf->frameTime = dp_realtime;
}
@ -615,6 +631,16 @@ static void UI_PlayerAngles( playerInfo_t *pi, vec3_t legs[3], vec3_t torso[3],
UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
torsoAngles[PITCH] = pi->torso.pitchAngle;
if ( pi->fixedtorso ) {
torsoAngles[PITCH] = 0.0f;
}
if ( pi->fixedlegs ) {
legsAngles[YAW] = torsoAngles[YAW];
legsAngles[PITCH] = 0.0f;
legsAngles[ROLL] = 0.0f;
}
// pull the angles back out of the hierarchial chain
AnglesSubtract( headAngles, torsoAngles, headAngles );
AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
@ -930,7 +956,7 @@ static qboolean UI_RegisterClientSkin( playerInfo_t *pi, const char *modelName,
UI_ParseAnimationFile
======================
*/
static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animations ) {
static qboolean UI_ParseAnimationFile( const char *filename, playerInfo_t *pi ) {
char *text_p, *prev;
int len;
int i;
@ -939,9 +965,15 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
int skip;
char text[20000];
fileHandle_t f;
animation_t *animations;
animations = pi->animations;
memset( animations, 0, sizeof( animation_t ) * MAX_ANIMATIONS );
pi->fixedlegs = qfalse;
pi->fixedtorso = qfalse;
// load the file
len = trap_FS_FOpenFile( filename, &f, FS_READ );
if ( len <= 0 ) {
@ -987,6 +1019,12 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
break;
}
continue;
} else if ( !Q_stricmp( token, "fixedlegs" ) ) {
pi->fixedlegs = qtrue;
continue;
} else if ( !Q_stricmp( token, "fixedtorso" ) ) {
pi->fixedtorso = qtrue;
continue;
}
// if it is a number, start parsing animations
@ -1003,6 +1041,16 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
token = COM_Parse( &text_p );
if ( !token[0] ) {
if( i >= TORSO_GETFLAG && i <= TORSO_NEGATIVE ) {
animations[i].firstFrame = animations[TORSO_GESTURE].firstFrame;
animations[i].frameLerp = animations[TORSO_GESTURE].frameLerp;
animations[i].initialLerp = animations[TORSO_GESTURE].initialLerp;
animations[i].loopFrames = animations[TORSO_GESTURE].loopFrames;
animations[i].numFrames = animations[TORSO_GESTURE].numFrames;
animations[i].reversed = qfalse;
animations[i].flipflop = qfalse;
continue;
}
break;
}
animations[i].firstFrame = atoi( token );
@ -1010,7 +1058,7 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
if ( i == LEGS_WALKCR ) {
skip = animations[LEGS_WALKCR].firstFrame - animations[TORSO_GESTURE].firstFrame;
}
if ( i >= LEGS_WALKCR ) {
if ( i >= LEGS_WALKCR && i<TORSO_GETFLAG) {
animations[i].firstFrame -= skip;
}
@ -1020,6 +1068,14 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
}
animations[i].numFrames = atoi( token );
animations[i].reversed = qfalse;
animations[i].flipflop = qfalse;
// if numFrames is negative the animation is reversed
if (animations[i].numFrames < 0) {
animations[i].numFrames = -animations[i].numFrames;
animations[i].reversed = qtrue;
}
token = COM_Parse( &text_p );
if ( !token[0] ) {
break;
@ -1110,7 +1166,7 @@ qboolean UI_RegisterClientModelname( playerInfo_t *pi, const char *modelSkinName
// load the animations
Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName );
if ( !UI_ParseAnimationFile( filename, pi->animations ) ) {
if ( !UI_ParseAnimationFile( filename, pi ) ) {
Com_Printf( "Failed to load animation file %s\n", filename );
return qfalse;
}

View file

@ -533,6 +533,9 @@ typedef struct {
animation_t animations[MAX_TOTALANIMATIONS];
qboolean fixedlegs; // true if legs yaw is always the same as torso yaw
qboolean fixedtorso; // true if torso never changes yaw
qhandle_t weaponModel;
qhandle_t barrelModel;
qhandle_t flashModel;

View file

@ -364,7 +364,7 @@ UI_RunLerpFrame
===============
*/
static void UI_RunLerpFrame( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation ) {
int f;
int f, numFrames;
animation_t *anim;
// see if the animation sequence is switching
@ -380,25 +380,41 @@ static void UI_RunLerpFrame( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation
// get the next frame based on the animation
anim = lf->animation;
if ( !anim->frameLerp ) {
return; // shouldn't happen
}
if ( dp_realtime < lf->animationTime ) {
lf->frameTime = lf->animationTime; // initial lerp
} else {
lf->frameTime = lf->oldFrameTime + anim->frameLerp;
}
f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
if ( f >= anim->numFrames ) {
f -= anim->numFrames;
numFrames = anim->numFrames;
if (anim->flipflop) {
numFrames *= 2;
}
if ( f >= numFrames ) {
f -= numFrames;
if ( anim->loopFrames ) {
f %= anim->loopFrames;
f += anim->numFrames - anim->loopFrames;
} else {
f = anim->numFrames - 1;
f = numFrames - 1;
// the animation is stuck at the end, so it
// can immediately transition to another sequence
lf->frameTime = dp_realtime;
}
}
lf->frame = anim->firstFrame + f;
if ( anim->reversed ) {
lf->frame = anim->firstFrame + anim->numFrames - 1 - f;
}
else if (anim->flipflop && f>=anim->numFrames) {
lf->frame = anim->firstFrame + anim->numFrames - 1 - (f%anim->numFrames);
}
else {
lf->frame = anim->firstFrame + f;
}
if ( dp_realtime > lf->frameTime ) {
lf->frameTime = dp_realtime;
}
@ -616,6 +632,16 @@ static void UI_PlayerAngles( playerInfo_t *pi, vec3_t legs[3], vec3_t torso[3],
UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
torsoAngles[PITCH] = pi->torso.pitchAngle;
if ( pi->fixedtorso ) {
torsoAngles[PITCH] = 0.0f;
}
if ( pi->fixedlegs ) {
legsAngles[YAW] = torsoAngles[YAW];
legsAngles[PITCH] = 0.0f;
legsAngles[ROLL] = 0.0f;
}
// pull the angles back out of the hierarchial chain
AnglesSubtract( headAngles, torsoAngles, headAngles );
AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
@ -1015,7 +1041,7 @@ static qboolean UI_RegisterClientSkin( playerInfo_t *pi, const char *modelName,
UI_ParseAnimationFile
======================
*/
static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animations ) {
static qboolean UI_ParseAnimationFile( const char *filename, playerInfo_t *pi ) {
char *text_p, *prev;
int len;
int i;
@ -1024,9 +1050,15 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
int skip;
char text[20000];
fileHandle_t f;
animation_t *animations;
animations = pi->animations;
memset( animations, 0, sizeof( animation_t ) * MAX_ANIMATIONS );
pi->fixedlegs = qfalse;
pi->fixedtorso = qfalse;
// load the file
len = trap_FS_FOpenFile( filename, &f, FS_READ );
if ( len <= 0 ) {
@ -1074,6 +1106,12 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
break;
}
continue;
} else if ( !Q_stricmp( token, "fixedlegs" ) ) {
pi->fixedlegs = qtrue;
continue;
} else if ( !Q_stricmp( token, "fixedtorso" ) ) {
pi->fixedtorso = qtrue;
continue;
}
// if it is a number, start parsing animations
@ -1090,6 +1128,16 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
token = COM_Parse( &text_p );
if ( !token[0] ) {
if( i >= TORSO_GETFLAG && i <= TORSO_NEGATIVE ) {
animations[i].firstFrame = animations[TORSO_GESTURE].firstFrame;
animations[i].frameLerp = animations[TORSO_GESTURE].frameLerp;
animations[i].initialLerp = animations[TORSO_GESTURE].initialLerp;
animations[i].loopFrames = animations[TORSO_GESTURE].loopFrames;
animations[i].numFrames = animations[TORSO_GESTURE].numFrames;
animations[i].reversed = qfalse;
animations[i].flipflop = qfalse;
continue;
}
break;
}
animations[i].firstFrame = atoi( token );
@ -1097,7 +1145,7 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
if ( i == LEGS_WALKCR ) {
skip = animations[LEGS_WALKCR].firstFrame - animations[TORSO_GESTURE].firstFrame;
}
if ( i >= LEGS_WALKCR ) {
if ( i >= LEGS_WALKCR && i<TORSO_GETFLAG) {
animations[i].firstFrame -= skip;
}
@ -1107,6 +1155,14 @@ static qboolean UI_ParseAnimationFile( const char *filename, animation_t *animat
}
animations[i].numFrames = atoi( token );
animations[i].reversed = qfalse;
animations[i].flipflop = qfalse;
// if numFrames is negative the animation is reversed
if (animations[i].numFrames < 0) {
animations[i].numFrames = -animations[i].numFrames;
animations[i].reversed = qtrue;
}
token = COM_Parse( &text_p );
if ( !token[0] ) {
break;
@ -1225,9 +1281,9 @@ qboolean UI_RegisterClientModelname( playerInfo_t *pi, const char *modelSkinName
// load the animations
Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName );
if ( !UI_ParseAnimationFile( filename, pi->animations ) ) {
if ( !UI_ParseAnimationFile( filename, pi ) ) {
Com_sprintf( filename, sizeof( filename ), "models/players/characters/%s/animation.cfg", modelName );
if ( !UI_ParseAnimationFile( filename, pi->animations ) ) {
if ( !UI_ParseAnimationFile( filename, pi ) ) {
Com_Printf( "Failed to load animation file %s\n", filename );
return qfalse;
}