Added facility to create new animation clip container asset.

Changed raw anim editor to open when double clicking anim container asset/after creating new anim container asset

Changed new clip fields from slider to unsigned int input
This commit is contained in:
Xiao Qi 2023-03-09 01:51:54 +08:00
parent 7df9897598
commit 2c8eca4125
9 changed files with 169 additions and 61 deletions

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 // Compute fps
ticksPerSecond = static_cast<int>(maxFrames / totalTime); ticksPerSecond = static_cast<int>(maxFrames / totalTime);
} }
totalFrames = maxFrames;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -30,6 +30,6 @@ namespace SHADE
struct SH_API SHAnimClipContainerAsset final : SHAssetData struct SH_API SHAnimClipContainerAsset final : SHAssetData
{ {
AssetID animRawDataAssetId; 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 SCENE_FOLDER{ "/Scenes/" };
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" }; 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/" }; constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" };

View File

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

View File

@ -22,6 +22,9 @@
#include "Assets/Asset Types/SHPrefabAsset.h" #include "Assets/Asset Types/SHPrefabAsset.h"
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.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 "Serialization/Prefab/SHPrefabManager.h"
#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h" #include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h"
@ -372,12 +375,7 @@ namespace SHADE
case AssetType::SHADER: break; case AssetType::SHADER: break;
case AssetType::SHADER_BUILT_IN: break; case AssetType::SHADER_BUILT_IN: break;
case AssetType::TEXTURE: break; case AssetType::TEXTURE: break;
case AssetType::MODEL: case AssetType::MODEL: break;
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
{
animInspector->Open(asset->id);
}
break;
case AssetType::MESH: break; case AssetType::MESH: break;
case AssetType::SCENE: case AssetType::SCENE:
{ {
@ -402,6 +400,12 @@ namespace SHADE
scriptEngine->OpenFile(asset->path); scriptEngine->OpenFile(asset->path);
} }
break; break;
case AssetType::ANIM_CONTAINER:
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
{
animInspector->Open(asset->id);
}
break;
case AssetType::MAX_COUNT: break; case AssetType::MAX_COUNT: break;
default:; default:;
} }
@ -487,6 +491,48 @@ namespace SHADE
isAssetBeingCreated = false; isAssetBeingCreated = false;
ImGui::CloseCurrentPopup(); 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(); ImGui::EndPopup();
} }
//if (ImGui::BeginMenu("Create Asset")) //if (ImGui::BeginMenu("Create Asset"))

View File

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

View File

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