mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 05:21:16 +00:00
Decoupled Animation fixes and improvements
* fixes looping that uses `loopFrame` * adds `endFrame` * adds `SAF_NOOVERRIDE` * fixes crash on SetAnimation if a BaseFrame isn't defined
This commit is contained in:
parent
f2072cec95
commit
7c93cfa97b
5 changed files with 47 additions and 35 deletions
|
@ -709,7 +709,7 @@ struct AnimOverride
|
||||||
double startFrame;
|
double startFrame;
|
||||||
int flags = ANIMOVERRIDE_NONE;
|
int flags = ANIMOVERRIDE_NONE;
|
||||||
float framerate;
|
float framerate;
|
||||||
double startTic; // when the animation starts if interpolating from previous animation
|
double startTic; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation)
|
||||||
double switchTic; // when the animation was changed -- where to interpolate the switch from
|
double switchTic; // when the animation was changed -- where to interpolate the switch from
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5125,11 +5125,10 @@ enum ESetAnimationFlags
|
||||||
{
|
{
|
||||||
SAF_INSTANT = 1 << 0,
|
SAF_INSTANT = 1 << 0,
|
||||||
SAF_LOOP = 1 << 1,
|
SAF_LOOP = 1 << 1,
|
||||||
SAF_USEACTORROLL = 1 << 2,
|
SAF_NOOVERRIDE = 1 << 2,
|
||||||
SAF_USEACTORPITCH = 1 << 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int interpolateTics, int flags, double ticFrac)
|
void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags, double ticFrac)
|
||||||
{
|
{
|
||||||
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
|
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
|
||||||
|
|
||||||
|
@ -5138,6 +5137,11 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
||||||
ThrowAbortException(X_OTHER, "Cannot set animation for non-decoupled actors");
|
ThrowAbortException(X_OTHER, "Cannot set animation for non-decoupled actors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!BaseSpriteModelFrames.CheckKey(self->GetClass()))
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_OTHER, "Actor class is missing a MODELDEF definition or a MODELDEF BaseFrame");
|
||||||
|
}
|
||||||
|
|
||||||
if(interpolateTics <= 0) interpolateTics = 1;
|
if(interpolateTics <= 0) interpolateTics = 1;
|
||||||
|
|
||||||
EnsureModelData(self);
|
EnsureModelData(self);
|
||||||
|
@ -5168,6 +5172,13 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
||||||
Printf("Could not find animation %s\n", animName.GetChars());
|
Printf("Could not find animation %s\n", animName.GetChars());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != ANIMOVERRIDE_NONE && self->modelData->curAnim.firstFrame == animStart)
|
||||||
|
{
|
||||||
|
//same animation as current, skip setting it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int animEnd = mdl->FindLastFrame(animName);
|
int animEnd = mdl->FindLastFrame(animName);
|
||||||
|
|
||||||
if(framerate < 0)
|
if(framerate < 0)
|
||||||
|
@ -5180,18 +5191,24 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
||||||
if(startFrame >= len)
|
if(startFrame >= len)
|
||||||
{
|
{
|
||||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||||
Printf("frame %d is past the end of animation %s\n", startFrame, animName.GetChars());
|
Printf("frame %d (startFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(loopFrame >= len)
|
else if(loopFrame >= len)
|
||||||
{
|
{
|
||||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||||
Printf("frame %d is past the end of animation %s\n", startFrame, animName.GetChars());
|
Printf("frame %d (loopFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(endFrame >= len)
|
||||||
|
{
|
||||||
|
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||||
|
Printf("frame %d (endFrame) is past the end of animation %s\n", endFrame, animName.GetChars());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->modelData->curAnim.firstFrame = animStart;
|
self->modelData->curAnim.firstFrame = animStart;
|
||||||
self->modelData->curAnim.lastFrame = animEnd - 1;
|
self->modelData->curAnim.lastFrame = endFrame < 0 ? animEnd - 1 : animStart + endFrame;
|
||||||
self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame;
|
self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame;
|
||||||
self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame;
|
self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame;
|
||||||
self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0;
|
self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0;
|
||||||
|
@ -5208,14 +5225,14 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnimationNative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int interpolateTics, int flags)
|
void SetAnimationNative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags)
|
||||||
{
|
{
|
||||||
SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, interpolateTics, flags, 1);
|
SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnimationUINative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int interpolateTics, int flags)
|
void SetAnimationUINative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags)
|
||||||
{
|
{
|
||||||
SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, interpolateTics, flags, I_GetTimeFrac());
|
SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, I_GetTimeFrac());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern double getCurrentFrame(const AnimOverride &anim, double tic);
|
extern double getCurrentFrame(const AnimOverride &anim, double tic);
|
||||||
|
@ -5471,10 +5488,11 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimation, SetAnimationNative)
|
||||||
PARAM_FLOAT(framerate);
|
PARAM_FLOAT(framerate);
|
||||||
PARAM_INT(startFrame);
|
PARAM_INT(startFrame);
|
||||||
PARAM_INT(loopFrame);
|
PARAM_INT(loopFrame);
|
||||||
|
PARAM_INT(endFrame);
|
||||||
PARAM_INT(interpolateTics);
|
PARAM_INT(interpolateTics);
|
||||||
PARAM_INT(flags);
|
PARAM_INT(flags);
|
||||||
|
|
||||||
SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, interpolateTics, flags, 1);
|
SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5486,10 +5504,11 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimationUI, SetAnimationUINative)
|
||||||
PARAM_FLOAT(framerate);
|
PARAM_FLOAT(framerate);
|
||||||
PARAM_INT(startFrame);
|
PARAM_INT(startFrame);
|
||||||
PARAM_INT(loopFrame);
|
PARAM_INT(loopFrame);
|
||||||
|
PARAM_INT(endFrame);
|
||||||
PARAM_INT(interpolateTics);
|
PARAM_INT(interpolateTics);
|
||||||
PARAM_INT(flags);
|
PARAM_INT(flags);
|
||||||
|
|
||||||
SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, interpolateTics, flags, I_GetTimeFrac());
|
SetAnimationInternal(self, animName, framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, I_GetTimeFrac());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,12 +261,19 @@ double getCurrentFrame(const AnimOverride &anim, double tic)
|
||||||
{
|
{
|
||||||
if(anim.framerate <= 0) return anim.startFrame;
|
if(anim.framerate <= 0) return anim.startFrame;
|
||||||
|
|
||||||
double duration = double(anim.lastFrame - anim.firstFrame) / double(anim.framerate); // duration in seconds
|
double frame = ((tic - anim.startTic) / GameTicRate) * anim.framerate; // position in frames
|
||||||
double startPos = double(anim.startFrame - anim.firstFrame) / double(anim.framerate);
|
|
||||||
|
|
||||||
double pos = startPos + ((tic - anim.startTic) / GameTicRate); // position in seconds
|
double duration = double(anim.lastFrame) - anim.startFrame;
|
||||||
|
|
||||||
return (((anim.flags & ANIMOVERRIDE_LOOP) ? fmod(pos, duration) : min(pos, duration)) * anim.framerate) + anim.firstFrame;
|
if((anim.flags & ANIMOVERRIDE_LOOP) && frame >= duration)
|
||||||
|
{
|
||||||
|
frame = frame - duration;
|
||||||
|
return fmod(frame, anim.lastFrame - anim.loopFrame) + anim.loopFrame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return min(frame, duration) + anim.startFrame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &prev, int &next)
|
static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &prev, int &next)
|
||||||
|
@ -277,22 +284,7 @@ static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &
|
||||||
|
|
||||||
inter = frame - prev;
|
inter = frame - prev;
|
||||||
|
|
||||||
if(frame > anim.lastFrame)
|
next = int(ceil(frame));
|
||||||
{
|
|
||||||
if(anim.flags & ANIMOVERRIDE_LOOP)
|
|
||||||
{
|
|
||||||
next = anim.loopFrame + (prev - anim.lastFrame);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inter = 0;
|
|
||||||
prev = next = anim.lastFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next = int(ceil(frame));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
||||||
|
|
|
@ -1305,8 +1305,8 @@ class Actor : Thinker native
|
||||||
native bool A_AttachLight(Name lightid, int type, Color lightcolor, int radius1, int radius2, int flags = 0, Vector3 ofs = (0,0,0), double param = 0, double spoti = 10, double spoto = 25, double spotp = 0);
|
native bool A_AttachLight(Name lightid, int type, Color lightcolor, int radius1, int radius2, int flags = 0, Vector3 ofs = (0,0,0), double param = 0, double spoti = 10, double spoto = 25, double spotp = 0);
|
||||||
native bool A_RemoveLight(Name lightid);
|
native bool A_RemoveLight(Name lightid);
|
||||||
|
|
||||||
native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int interpolateTics = -1, int flags = 0);
|
native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int endFrame = -1, int interpolateTics = -1, int flags = 0);
|
||||||
native version("4.12") ui void SetAnimationUI(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int interpolateTics = -1, int flags = 0);
|
native version("4.12") ui void SetAnimationUI(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0);
|
||||||
|
|
||||||
native version("4.12") void SetAnimationFrameRate(double framerate);
|
native version("4.12") void SetAnimationFrameRate(double framerate);
|
||||||
native version("4.12") ui void SetAnimationFrameRateUI(double framerate);
|
native version("4.12") ui void SetAnimationFrameRateUI(double framerate);
|
||||||
|
|
|
@ -375,6 +375,7 @@ enum ESetAnimationFlags
|
||||||
{
|
{
|
||||||
SAF_INSTANT = 1 << 0,
|
SAF_INSTANT = 1 << 0,
|
||||||
SAF_LOOP = 1 << 1,
|
SAF_LOOP = 1 << 1,
|
||||||
|
SAF_NOOVERRIDE = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Change model flags
|
// Change model flags
|
||||||
|
|
Loading…
Reference in a new issue