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
9 changed files with 169 additions and 61 deletions
Showing only changes of commit 2c8eca4125 - Show all commits

Binary file not shown.

View File

@ -0,0 +1,37 @@
Name: racoonAnims
ID: 201804216
Type: 12
Sub Assets:
Name: TPose
ID: 231493784
Type: 13
Name: Idle
ID: 227450439
Type: 13
Name: Run
ID: 229125027
Type: 13
Name: Pickup
ID: 219605278
Type: 13
Name: Carry_Idle
ID: 231128260
Type: 13
Name: Carry_Run
ID: 227671720
Type: 13
Name: Throw
ID: 223399345
Type: 13
Name: Sprint
ID: 228149757
Type: 13
Name: Jump_Start
ID: 223009573
Type: 13
Name: Jump_Loop
ID: 230974023
Type: 13
Name: Jump_End
ID: 228134756
Type: 13

View File

@ -60,6 +60,8 @@ namespace SHADE
// Compute fps
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
}
totalFrames = maxFrames;
}
/*-----------------------------------------------------------------------------------*/

View File

@ -30,6 +30,6 @@ namespace SHADE
struct SH_API SHAnimClipContainerAsset final : SHAssetData
{
AssetID animRawDataAssetId;
std::vector<SHAnimClipAsset> clips;
std::vector<SHAnimClipAsset> clips{};
};
}

View File

@ -82,7 +82,7 @@ constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" };
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animations/" };
constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" };
constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" };

View File

@ -254,13 +254,11 @@ namespace SHADE
newPath += ANIM_CONTAINER_EXTENSION;
{
auto animClip = new SHAnimClipAsset();
animClip->name = name;
auto animClip = new SHAnimClipContainerAsset();
data = animClip;
}
break;
default:
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name);
return 0;
@ -338,7 +336,7 @@ namespace SHADE
asset.type == AssetType::SCENE ||
asset.type == AssetType::PREFAB ||
asset.type == AssetType::MATERIAL ||
asset.type == AssetType::ANIM_CLIP
asset.type == AssetType::ANIM_CONTAINER
)
{
if (assetData.contains(id))
@ -531,9 +529,9 @@ namespace SHADE
//Reload data
auto result = GetAsset(target);
if (result.has_value())
if (result)
{
auto const& asset{ result.value() };
auto const& asset{ *result };
auto newData = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
delete assetData[target];
assetData[target] = newData;
@ -656,16 +654,37 @@ namespace SHADE
else
{
assetData.emplace(parent.id, parentData);
if (parent.type == AssetType::MODEL)
switch(parent.type)
{
auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
for (auto i {0}; i < parent.subAssets.size(); ++i)
case AssetType::MODEL:
{
assetData.emplace(
parent.subAssets[i]->id,
parentModel->meshes[i]
);
const auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
for (auto i {0}; i < parent.subAssets.size(); ++i)
{
assetData.emplace(
parent.subAssets[i]->id,
parentModel->meshes[i]
);
}
}
break;
case AssetType::ANIM_CONTAINER:
{
const auto parentContainer = reinterpret_cast<SHAnimClipContainerAsset*>(parentData);
for (auto i {0}; i < parent.subAssets.size(); ++i)
{
assetData.emplace(
parent.subAssets[i]->id,
&parentContainer->clips[i]
);
}
}
break;
default:
SHLOG_WARNING("[Asset Manager] Parent type not supported to load sub assets, aborting...");
return nullptr;
}
return assetData[asset.id];

View File

@ -22,6 +22,9 @@
#include "Assets/Asset Types/SHPrefabAsset.h"
#include "Serialization/SHSerialization.h"
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h>
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
#include "Assets/Asset Types/Models/SHModelAsset.h"
#include "Serialization/Prefab/SHPrefabManager.h"
#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h"
@ -368,17 +371,12 @@ namespace SHADE
{
switch (asset->type)
{
case AssetType::INVALID: break;
case AssetType::SHADER: break;
case AssetType::SHADER_BUILT_IN: break;
case AssetType::TEXTURE: break;
case AssetType::MODEL:
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
{
animInspector->Open(asset->id);
}
break;
case AssetType::MESH: break;
case AssetType::INVALID: break;
case AssetType::SHADER: break;
case AssetType::SHADER_BUILT_IN: break;
case AssetType::TEXTURE: break;
case AssetType::MODEL: break;
case AssetType::MESH: break;
case AssetType::SCENE:
{
if(editor->LoadScene(asset->id))
@ -389,7 +387,7 @@ namespace SHADE
}
}
break;
case AssetType::PREFAB: break;
case AssetType::PREFAB: break;
case AssetType::MATERIAL:
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
{
@ -402,6 +400,12 @@ namespace SHADE
scriptEngine->OpenFile(asset->path);
}
break;
case AssetType::ANIM_CONTAINER:
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
{
animInspector->Open(asset->id);
}
break;
case AssetType::MAX_COUNT: break;
default:;
}
@ -487,6 +491,48 @@ namespace SHADE
isAssetBeingCreated = false;
ImGui::CloseCurrentPopup();
}
{
auto const models {SHAssetManager::GetAllRecordOfType(AssetType::MODEL)};
ImGui::RadioButton("Animation Clip Container", true);
ImGui::SameLine();
static char const* const modelPrompt = "Select a model with animations";
char const* currentItem = modelPrompt;
AssetID selected {0};
if (ImGui::BeginCombo("##combo", currentItem, ImGuiComboFlags_None))
{
for (auto const& model : models)
{
bool isSelected = currentItem == model.name;
if (ImGui::Selectable(model.name.data(), isSelected))
{
auto const data {SHAssetManager::GetConstData<SHModelAsset>(model.id)};
if (!data->anims.empty())
{
const auto animContainerId = SHAssetManager::CreateNewAsset(AssetType::ANIM_CONTAINER, model.name + "Anims");
auto data = SHAssetManager::GetData<SHAnimClipContainerAsset>(animContainerId);
data->animRawDataAssetId = model.id;
SHAssetManager::SaveAsset(animContainerId);
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
{
animInspector->Open(animContainerId);
}
QueueRefresh();
isAssetBeingCreated = false;
ImGui::CloseCurrentPopup();
}
}
if (isSelected)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
}
ImGui::EndPopup();
}
//if (ImGui::BeginMenu("Create Asset"))

View File

@ -38,8 +38,15 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* SHAnimClipCreatePrompt - Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void SHAnimClipCreatePrompt::Init(Handle<SHRawAnimation> rawAnim, std::function<void(AssetID)> onClose)
void SHAnimClipCreatePrompt::Init(
SHAsset* contAsset,
SHAnimClipContainerAsset* cont,
Handle<SHRawAnimation> rawAnim,
std::function<void(AssetID)> onClose
)
{
containerAsset = contAsset;
container = cont;
rawAnimation = rawAnim;
// Set default parameters
@ -61,10 +68,10 @@ namespace SHADE
// Properties
SHEditorUI::InputTextField("Name", newAssetName);
SHEditorUI::PushID(0);
SHEditorUI::InputSlider("First Frame Index", 0, rawAnimation->GetTotalFrames(), firstIndex);
SHEditorUI::InputUnsignedInt("First Frame Index", firstIndex);
SHEditorUI::PopID();
SHEditorUI::PushID(1);
SHEditorUI::InputSlider("Last Frame Index", 0, rawAnimation->GetTotalFrames(), lastIndex);
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
SHEditorUI::PopID();
// Invalid values
@ -76,11 +83,12 @@ namespace SHADE
if (ImGui::Button("Save"))
{
// Generate new asset
const AssetID NEW_ASSET_ID = SHAssetManager::CreateNewAsset(AssetType::ANIM_CLIP, newAssetName);
const AssetID NEW_ASSET_ID = SHAssetManager::CreateNewSubAsset(AssetType::ANIM_CLIP, newAssetName, containerAsset->id);
auto animClip = SHAssetManager::GetData<SHAnimClipAsset>(NEW_ASSET_ID);
animClip->name = newAssetName;
animClip->firstIndex = firstIndex;
animClip->lastIndex = lastIndex;
SHAssetManager::SaveAsset(NEW_ASSET_ID);
SHAssetManager::SaveAsset(containerAsset->id);
// Close
isOpen = false;
@ -128,7 +136,7 @@ namespace SHADE
if (Begin())
{
// Ignore if no asset
if (currRawAnim)
if (container)
{
drawMenuBar();
@ -136,7 +144,7 @@ namespace SHADE
if (ImGui::Button(std::format("{} Create Animation Clip", ICON_MD_ADD).data()))
{
auto prompt = SHEditorWindowManager::GetPopupWindow<SHAnimClipCreatePrompt>();
prompt->Init(currRawAnim, [this](AssetID createdAssetId)
prompt->Init(containerAsset, container, currRawAnim, [this](AssetID createdAssetId)
{
if (createdAssetId != INVALID_ASSET_ID)
{
@ -216,11 +224,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
void SHRawAnimInspector::Open(AssetID assetId)
{
currRawAnim = SHResourceManager::LoadOrGet<SHRawAnimation>(assetId);
containerAsset = SHAssetManager::GetAsset(assetId);
container = SHAssetManager::GetData<SHAnimClipContainerAsset>(assetId);
// Load anim clips
if (currRawAnim)
if (container)
{
currRawAnim = SHResourceManager::LoadOrGet<SHRawAnimation>(container->animRawDataAssetId);
childAnimClips = getChildAnimClips(assetId);
}
else
@ -248,31 +258,14 @@ namespace SHADE
}
}
std::vector<Handle<SHAnimationClip>> SHRawAnimInspector::getChildAnimClips(AssetID rawAnimId)
std::vector<Handle<SHAnimationClip>> SHRawAnimInspector::getChildAnimClips(AssetID containerId)
{
auto const containerAsset {*SHAssetManager::GetAsset(containerId)};
std::vector<Handle<SHAnimationClip>> animClips;
//const auto ALL_ANIM_CLIPS = SHAssetManager::GetAllRecordOfType(AssetType::ANIM_CLIP);
//for (auto asset : ALL_ANIM_CLIPS)
//{
// const SHAnimClipAsset* ANIM_CLIP = SHAssetManager::GetData<SHAnimClipAsset>(asset.id);
// if (ANIM_CLIP->animRawDataAssetId == rawAnimId)
// {
// animClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(asset.id));
// }
//}
const auto ALL_ANIM_CLIPS = SHAssetManager::GetAllRecordOfType(AssetType::ANIM_CONTAINER);
for (auto const& asset : ALL_ANIM_CLIPS)
for (auto const& asset : containerAsset.subAssets)
{
auto const ANIM_CLIP {SHAssetManager::GetData<SHAnimClipContainerAsset>(asset.id)};
if (ANIM_CLIP->animRawDataAssetId == rawAnimId)
{
for (auto const& subAsset : asset.subAssets)
{
animClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(subAsset->id));
}
}
animClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(asset->id));
}
return animClips;

View File

@ -16,6 +16,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Editor/EditorWindow/SHEditorWindow.h"
#include "Resource/SHHandle.h"
#include "Animation/SHRawAnimation.h"
#include "Assets/SHAsset.h"
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
#include "Editor/EditorWindow/SHPopUpWindow.h"
namespace SHADE
@ -45,7 +47,12 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void Init(Handle<SHRawAnimation> rawAnim, std::function<void(AssetID)> onClose = nullptr);
void Init(
SHAsset* contAsset,
SHAnimClipContainerAsset* cont,
Handle<SHRawAnimation> rawAnim,
std::function<void(AssetID)> onClose = nullptr
);
void Draw() override;
private:
@ -53,9 +60,11 @@ namespace SHADE
/* Data Members */
/*---------------------------------------------------------------------------------*/
std::string newAssetName;
int firstIndex = 0;
int lastIndex = 0;
uint32_t firstIndex = 0;
uint32_t lastIndex = 0;
Handle<SHRawAnimation> rawAnimation;
SHAsset* containerAsset{nullptr};
SHAnimClipContainerAsset* container{nullptr};
std::function<void(AssetID)> onClose;
};
@ -87,6 +96,8 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHAsset* containerAsset{nullptr};
SHAnimClipContainerAsset* container {nullptr};
Handle<SHRawAnimation> currRawAnim;
std::vector<Handle<SHAnimationClip>> childAnimClips;
@ -94,6 +105,6 @@ namespace SHADE
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void drawMenuBar();
std::vector<Handle<SHAnimationClip>> getChildAnimClips(AssetID rawAnimId);
std::vector<Handle<SHAnimationClip>> getChildAnimClips(AssetID containerId);
};
}