Added extra field in animation clip container for time multiplier #427

Merged
XiaoQiDigipen merged 3 commits from SP3-22-AnimationController into main 2023-03-14 16:50:24 +08:00
8 changed files with 55 additions and 21 deletions
Showing only changes of commit f844079eea - Show all commits

View File

@ -20,12 +20,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------------*/
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
: rawAnim { rawAnimHandle }
, startFrameIndex { firstFrame }
, endFrameIndex { lastFrame }
, duration { 0.0f }
, startTimeStamp { 0.0f }
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier)
: rawAnim { rawAnimHandle }
, startFrameIndex { firstFrame }
, endFrameIndex { lastFrame }
, duration { 0.0f }
, startTimeStamp { 0.0f }
, playbackSpeedMultiplier { playbackMultiplier }
{
if (!rawAnim)
return;

View File

@ -41,25 +41,39 @@ namespace SHADE
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
/// <param name="firstFrame">First frame to be played.</param>
/// <param name="lastFrame">Last frame to be played.</param>
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame);
/// <param name="playbackMultiplier">Multiplier for the playback speed.</param>
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier = 1.0f);
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
inline float GetTotalDuration() const noexcept { return duration; }
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }\
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
inline float GetPlaybackSpeedMultiplier() const noexcept { return playbackSpeedMultiplier; }
/// <summary>
/// Retrieves the duration of the animation as if the playback speed multiplier is
/// in it's default value of 1.0f.
/// </summary>
/// <returns>Duration of the animation in seconds.</returns>
inline float GetTotalDuration() const noexcept { return duration; }
/// <summary>
/// Retrieves the duration of the animation with the playback speed multiplier
/// taken into account.
/// </summary>
/// <returns>True duration of the animation in seconds.</returns>
inline float GetTrueDuration() const noexcept { return duration / playbackSpeedMultiplier; }
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
Handle<SHRawAnimation> rawAnim;
int startFrameIndex; // First Frame
int endFrameIndex; // Last Frame (inclusive)
float duration; // Total playback time
float startTimeStamp; // Starting time stamp of the raw anim
int startFrameIndex; // First Frame
int endFrameIndex; // Last Frame (inclusive)
float duration; // Total playback time
float startTimeStamp; // Starting time stamp of the raw anim
float playbackSpeedMultiplier; // Multiplier applied to the playback of an animation clip
};
}

View File

@ -62,18 +62,21 @@ namespace SHADE
if (!instData.CurrentNode)
return;
// Get the clip
Handle<SHAnimationClip> clip = instData.CurrentNode->Clip;
// Update the current playback
instData.ClipPlaybackTime += dt;
instData.ClipPlaybackTime += dt * clip->GetPlaybackSpeedMultiplier();
// Check if we finished playing
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration())
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - clip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > clip->GetTotalDuration())
{
// Clamp
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration();
instData.ClipPlaybackTime = clip->GetStartTimeStamp() + clip->GetTotalDuration();
// Go to next state
Handle<SHAnimationClip> originalClip = instData.CurrentNode->Clip;
Handle<SHAnimationClip> originalClip = clip;
bool stateChanged = false;
for (const auto& transition : instData.CurrentNode->Transitions)
{

View File

@ -254,7 +254,7 @@ namespace SHADE
}
void SHAnimatorComponent::updateManualClipState(float dt)
{
currPlaybackTime += dt;
currPlaybackTime += dt * currClip->GetPlaybackSpeedMultiplier();
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
{

View File

@ -26,6 +26,7 @@ namespace SHADE
uint32_t firstIndex;
uint32_t lastIndex;
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
float playbackMultiplier = 1.0f;
};
struct SH_API SHAnimClipContainerAsset final : SHAssetData

View File

@ -54,6 +54,7 @@ namespace SHADE
newAssetName.clear();
firstIndex = 0;
lastIndex = rawAnimation->GetTotalFrames();
playbackMultiplier = 1.0f;
}
// Assign callback
@ -72,6 +73,9 @@ namespace SHADE
SHEditorUI::PushID(1);
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
SHEditorUI::PopID();
SHEditorUI::PushID(2);
SHEditorUI::InputFloat("Playback Multiplier", playbackMultiplier);
SHEditorUI::PopID();
// Invalid values
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
@ -88,6 +92,7 @@ namespace SHADE
animClip->firstIndex = firstIndex;
animClip->lastIndex = lastIndex;
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
animClip->playbackMultiplier = playbackMultiplier;
SHAssetManager::SaveAsset(containerAsset->id);
// Close
@ -168,6 +173,7 @@ namespace SHADE
int firstIndex = animClip->GetStartFrameIndex();
int endIndex = animClip->GetEndFrameIndex();
float playbackMp = animClip->GetPlaybackSpeedMultiplier();
ImGui::Separator();
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
@ -183,12 +189,18 @@ namespace SHADE
[&]() { return endIndex; },
[&](int i) { endIndex = i; }
);
changed |= SHEditorWidgets::DragFloat
(
"Playback Multiplier",
[&]() { return playbackMp; },
[&](float f) { playbackMp = f; }
);
// If there's a change we need to commit changes
if (changed && firstIndex < endIndex)
{
// Update runtime asset
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex);
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex, playbackMp);
// Update serialized asset
auto assetId = SHResourceManager::GetAssetID(animClip);
@ -197,6 +209,7 @@ namespace SHADE
auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
animAsset->firstIndex = firstIndex;
animAsset->lastIndex = endIndex;
animAsset->playbackMultiplier = playbackMp;
SHAssetManager::SaveAsset(containerAsset->id);
}
}

View File

@ -62,6 +62,7 @@ namespace SHADE
std::string newAssetName;
uint32_t firstIndex = 0;
uint32_t lastIndex = 0;
float playbackMultiplier = 1.0f;
Handle<SHRawAnimation> rawAnimation;
SHAsset* containerAsset{nullptr};
SHAnimClipContainerAsset* container{nullptr};

View File

@ -372,7 +372,8 @@ namespace SHADE
(
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
assetData.firstIndex,
assetData.lastIndex
assetData.lastIndex,
assetData.playbackMultiplier
);
}
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)