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
13 changed files with 60 additions and 26 deletions

View File

@ -180,8 +180,8 @@ namespace Sandbox
// Link up SHDebugDraw // Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>()); SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045); //auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045);
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045); //auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
} }
void SBApplication::Update(void) void SBApplication::Update(void)

View File

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

View File

@ -41,25 +41,39 @@ namespace SHADE
/// <param name="rawAnimHandle">Handle to the raw animation data.</param> /// <param name="rawAnimHandle">Handle to the raw animation data.</param>
/// <param name="firstFrame">First frame to be played.</param> /// <param name="firstFrame">First frame to be played.</param>
/// <param name="lastFrame">Last 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 */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; } inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
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 GetStartTimeStamp() const noexcept { return startTimeStamp; } 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: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHRawAnimation> rawAnim; Handle<SHRawAnimation> rawAnim;
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 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) if (!instData.CurrentNode)
return; return;
// Get the clip
Handle<SHAnimationClip> clip = instData.CurrentNode->Clip;
// Update the current playback // Update the current playback
instData.ClipPlaybackTime += dt; instData.ClipPlaybackTime += dt * clip->GetPlaybackSpeedMultiplier();
// Check if we finished playing // Check if we finished playing
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp(); const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - clip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration()) if (CLIP_CURR_PLAYED_TIME > clip->GetTotalDuration())
{ {
// Clamp // Clamp
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration(); instData.ClipPlaybackTime = clip->GetStartTimeStamp() + clip->GetTotalDuration();
// Go to next state // Go to next state
Handle<SHAnimationClip> originalClip = instData.CurrentNode->Clip; Handle<SHAnimationClip> originalClip = clip;
bool stateChanged = false; bool stateChanged = false;
for (const auto& transition : instData.CurrentNode->Transitions) for (const auto& transition : instData.CurrentNode->Transitions)
{ {

View File

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

View File

@ -25,6 +25,7 @@ namespace SHADE
std::string name; std::string name;
uint32_t firstIndex; uint32_t firstIndex;
uint32_t lastIndex; uint32_t lastIndex;
float playbackMultiplier = 1.0f;
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
}; };

View File

@ -79,7 +79,7 @@ namespace SHADE
file.write( file.write(
reinterpret_cast<char const*>(&clip->firstIndex), reinterpret_cast<char const*>(&clip->firstIndex),
sizeof(uint32_t) * 2 sizeof(uint32_t) * 3
); );
} }
} }
@ -118,7 +118,7 @@ namespace SHADE
file.read( file.read(
reinterpret_cast<char*>(&clip->firstIndex), reinterpret_cast<char*>(&clip->firstIndex),
sizeof(uint32_t) * 2 sizeof(uint32_t) * 3
); );
clip->animRawDataAssetId = data->animRawDataAssetId; clip->animRawDataAssetId = data->animRawDataAssetId;

View File

@ -313,7 +313,7 @@ namespace SHADE
.isSubAsset = true, .isSubAsset = true,
.parent = parent .parent = parent
}; };
auto& newClip {animContainer->clips.emplace_back()}; auto& newClip {animContainer->clips.emplace_back(new SHAnimClipAsset())};
newClip->name = name; newClip->name = name;
assetCollection.emplace(id, asset); assetCollection.emplace(id, asset);
assetCollection[parent].subAssets.push_back(&assetCollection[id]); assetCollection[parent].subAssets.push_back(&assetCollection[id]);

View File

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

View File

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

View File

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