Implemented Animation Clip asset and animation controller #410

Merged
XiaoQiDigipen merged 66 commits from SP3-22-AnimationController into main 2023-03-09 16:19:40 +08:00
5 changed files with 36 additions and 12 deletions
Showing only changes of commit 7f170deb27 - Show all commits

View File

@ -1,4 +1,6 @@
namespace SHADE.Test using System;
namespace SHADE.Test
{ {
public class AnimTest : Script public class AnimTest : Script
{ {
@ -25,21 +27,26 @@
protected override void update() protected override void update()
{ {
// Play loop if shift is held
Action<AnimationClipAsset> playFunc = Input.GetKey(Input.KeyCode.LeftShift) ? (x) => Animator.Play(x)
: (x) => Animator.PlayOneShot(x);
// Play animations
if (Input.GetKeyUp(Input.KeyCode.Equals)) if (Input.GetKeyUp(Input.KeyCode.Equals))
{ {
Animator.Play(fullClip); playFunc(fullClip);
} }
else if (Input.GetKeyUp(Input.KeyCode.Alpha1)) else if (Input.GetKeyUp(Input.KeyCode.Alpha1))
{ {
Animator.Play(idleClip); playFunc(idleClip);
} }
else if (Input.GetKeyUp(Input.KeyCode.Alpha2)) else if (Input.GetKeyUp(Input.KeyCode.Alpha2))
{ {
Animator.Play(runClip); playFunc(runClip);
} }
else if (Input.GetKeyUp(Input.KeyCode.Alpha3)) else if (Input.GetKeyUp(Input.KeyCode.Alpha3))
{ {
Animator.Play(pickUpClip); playFunc(pickUpClip);
} }
} }
#endregion #endregion

View File

@ -25,11 +25,14 @@ namespace SHADE
, startFrameIndex { firstFrame } , startFrameIndex { firstFrame }
, endFrameIndex { lastFrame } , endFrameIndex { lastFrame }
, duration { 0.0f } , duration { 0.0f }
, startTimeStamp { 0.0f }
{ {
if (!rawAnim) if (!rawAnim)
return; return;
const float SECS_PER_TICK = 1.0f / static_cast<float>(rawAnim->GetTicksPerSecond());
const int ONE_PAST_LAST_FRAME = lastFrame + 1; const int ONE_PAST_LAST_FRAME = lastFrame + 1;
duration = (ONE_PAST_LAST_FRAME - firstFrame) / rawAnim->GetTicksPerSecond(); duration = static_cast<float>(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK;
startTimeStamp = static_cast<float>(firstFrame) * SECS_PER_TICK;
} }
} }

View File

@ -50,6 +50,7 @@ namespace SHADE
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
inline float GetTotalDuration() const noexcept { return duration; } inline float GetTotalDuration() const noexcept { return duration; }
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -59,5 +60,6 @@ namespace SHADE
int startFrameIndex; // First Frame int startFrameIndex; // First Frame
int endFrameIndex; // Last Frame (inclusive) int endFrameIndex; // Last Frame (inclusive)
float duration; // Total playback time float duration; // Total playback time
float startTimeStamp; // Starting time stamp of the raw anim
}; };
} }

View File

@ -65,18 +65,21 @@ namespace SHADE
instData.ClipPlaybackTime += dt; instData.ClipPlaybackTime += dt;
// Check if we finished playing // Check if we finished playing
if (instData.ClipPlaybackTime > instData.CurrentNode->Clip->GetTotalDuration()) const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration())
{ {
// Clamp // Clamp
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetTotalDuration(); instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration();
// Go to next state // Go to next state
bool stateChanged = false;
for (const auto& transition : instData.CurrentNode->Transitions) for (const auto& transition : instData.CurrentNode->Transitions)
{ {
// Check for no condition special case // Check for no condition special case
if (transition.Condition == Transition::ConditionType::None) if (transition.Condition == Transition::ConditionType::None)
{ {
changeNode(instData, transition.Target); changeNode(instData, transition.Target);
stateChanged = true;
break; break;
} }
else else
@ -90,6 +93,7 @@ namespace SHADE
if (transition.EvaluateCondition(param)) if (transition.EvaluateCondition(param))
{ {
changeNode(instData, transition.Target); changeNode(instData, transition.Target);
stateChanged = true;
// If trigger, we need to unset it // If trigger, we need to unset it
if (param.ParamType == AnimParam::Type::Trigger) if (param.ParamType == AnimParam::Type::Trigger)
@ -101,6 +105,12 @@ namespace SHADE
} }
} }
} }
// Handle if there is no next state, we repeat
if (!stateChanged)
{
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp();
}
} }
} }

View File

@ -62,6 +62,7 @@ namespace SHADE
{ {
// Calculate secs for the clip // Calculate secs for the clip
secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond(); secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond();
currPlaybackTime = currClip->GetStartTimeStamp();
// Start playback // Start playback
Play(); Play();
@ -232,17 +233,18 @@ namespace SHADE
void SHAnimatorComponent::updateManualClipState(float dt) void SHAnimatorComponent::updateManualClipState(float dt)
{ {
currPlaybackTime += dt; currPlaybackTime += dt;
if (currPlaybackTime > currClip->GetTotalDuration()) const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
{ {
if (playOnce) if (playOnce)
{ {
playOnce = false; playOnce = false;
isPlaying = false; isPlaying = false;
currPlaybackTime = currClip->GetTotalDuration(); currPlaybackTime = currClip->GetStartTimeStamp() + currClip->GetTotalDuration();
} }
else else
{ {
currPlaybackTime = currPlaybackTime - currClip->GetTotalDuration(); currPlaybackTime = currClip->GetStartTimeStamp();
} }
} }
} }