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

View File

@ -23,7 +23,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Animation/SHAnimationController.h" #include "Animation/SHAnimationController.h"
#include "Editor/SHEditorUI.h" #include "Editor/SHEditorUI.h"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "../../Command/SHCommand.hpp" #include "Editor/Command/SHCommand.hpp"
#include "Input/SHInputManager.h"
namespace SHADE namespace SHADE
{ {
@ -144,8 +145,9 @@ namespace SHADE
SHEditorWindow::Exit(); SHEditorWindow::Exit();
} }
void SHAnimationControllerEditor::Open(const SHAnimationController& controller) void SHAnimationControllerEditor::Open(SHAnimationController& controllerHandle)
{ {
controller = controllerHandle;
controllerData = deserialise(controller); controllerData = deserialise(controller);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -158,12 +160,12 @@ namespace SHADE
// Save Button // Save Button
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data())) if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
{ {
// TODO // TODO: Actually save the resource
} }
// Discard Button // Discard Button
if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data())) if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data()))
{ {
// TODO Open(controller); // TODO: Actually load the resource
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
@ -211,7 +213,6 @@ namespace SHADE
// Put into the new // Put into the new
controllerData->Params[val] = TYPE; controllerData->Params[val] = TYPE;
// TODO: This needs to be handled in a custom command
// Update all links // Update all links
for (auto& link : controllerData->Links) for (auto& link : controllerData->Links)
{ {
@ -293,10 +294,11 @@ namespace SHADE
ImGui::SameLine(); ImGui::SameLine();
// Delete Node Button // Delete Node Button
ImGui::BeginDisabled(ImNodes::NumSelectedNodes() < 1); ImGui::BeginDisabled((ImNodes::NumSelectedNodes() + ImNodes::NumSelectedLinks()) < 1);
if (ImGui::Button(std::format("{} Delete Nodes", ICON_MD_ADD).data())) if (ImGui::Button(std::format("{} Delete Objects", ICON_MD_DELETE).data()))
{ {
deleteSelectedLinks();
deleteSelectedNodes();
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
@ -423,6 +425,13 @@ namespace SHADE
); );
} }
} }
// Delete
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::DEL))
{
deleteSelectedLinks();
deleteSelectedNodes();
}
} }
void SHAnimationControllerEditor::drawPropertiesMenuBar() void SHAnimationControllerEditor::drawPropertiesMenuBar()
@ -674,6 +683,34 @@ namespace SHADE
ImGui::Text(TITLE); ImGui::Text(TITLE);
ImNodes::EndOutputAttribute(); ImNodes::EndOutputAttribute();
} }
void SHAnimationControllerEditor::deleteSelectedNodes()
{
const int NUM_SELECTED_NODES= ImNodes::NumSelectedNodes();
if (NUM_SELECTED_NODES > 0)
{
std::vector<int> selectedNodes(NUM_SELECTED_NODES);
ImNodes::GetSelectedNodes(selectedNodes.data());
for (auto nodeId : selectedNodes)
{
deleteNode(controllerData.value(), nodeId);
}
}
}
void SHAnimationControllerEditor::deleteSelectedLinks()
{
const int NUM_SELECTED_LINKS = ImNodes::NumSelectedLinks();
if (NUM_SELECTED_LINKS > 0)
{
std::vector<int> selectedLinks(NUM_SELECTED_LINKS);
ImNodes::GetSelectedLinks(selectedLinks.data());
for (auto linkId : selectedLinks)
{
deleteLink(controllerData.value(), linkId);
}
}
}
std::list<SHAnimationControllerEditor::Node>::iterator SHAnimationControllerEditor::createNode(AnimControllerData& data) std::list<SHAnimationControllerEditor::Node>::iterator SHAnimationControllerEditor::createNode(AnimControllerData& data)
{ {
const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++; const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++;
@ -716,6 +753,62 @@ namespace SHADE
return EMPLACE_DATA.first; return EMPLACE_DATA.first;
} }
void SHAnimationControllerEditor::deleteLink(AnimControllerData& data, LinkIndex link)
{
const NodeLinkIndex LINK_IDX { link };
// Error check, don't do anything if they don't exist
if (!data.IndexToNodeMap.contains(LINK_IDX.SourceAttribute.OwnerNodeIndex) ||
!data.IndexToNodeMap.contains(LINK_IDX.DestinationAttribute.OwnerNodeIndex))
return;
// Get source node and attributes
auto& sourceNode = *data.IndexToNodeMap[LINK_IDX.SourceAttribute.OwnerNodeIndex];
auto& destNode = *data.IndexToNodeMap[LINK_IDX.DestinationAttribute.OwnerNodeIndex];
// Remove attributes
std::erase(sourceNode.OutputAttribs, LINK_IDX.SourceAttribute);
std::erase(destNode.InputAttribs, LINK_IDX.DestinationAttribute);
// Remove link
std::erase(sourceNode.Transitions, LINK_IDX);
data.Links.erase(link);
}
void SHAnimationControllerEditor::deleteNode(AnimControllerData& data, NodeIndex nodeIndex)
{
// Get node to delete
if (!data.IndexToNodeMap.contains(nodeIndex))
return;
auto nodeToDeleteIter = data.IndexToNodeMap[nodeIndex];
// Remove all links to other nodes
for (auto link : nodeToDeleteIter->Transitions)
{
deleteLink(data, link.Raw);
}
// Remove all links from other nodes
for (auto node : data.Nodes)
{
for (NodeLinkIndex link : node.Transitions)
{
if (link.DestinationAttribute.OwnerNodeIndex == nodeIndex)
{
deleteLink(data, link.Raw);
}
}
}
// Then finally, delete this node
data.IndexToNodeMap.erase(nodeIndex);
data.Nodes.erase(nodeToDeleteIter);
// If the starting node was this node, we need to reassign
if (data.StartingNode == nodeIndex)
{
data.StartingNode = data.Nodes.empty() ? data.NextNodeIndex : data.Nodes.front().Index;
}
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Helper Functions */ /* Static Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -45,7 +45,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Open(const SHAnimationController& controller); void Open(SHAnimationController& controller);
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -61,6 +61,8 @@ namespace SHADE
NodeIndex OwnerNodeIndex; NodeIndex OwnerNodeIndex;
int8_t AttributeIndex; // Negative is input, positive is output int8_t AttributeIndex; // Negative is input, positive is output
}; };
bool operator==(NodeAttributeIndex rhs) const noexcept { return Raw == rhs.Raw; }
}; };
union NodeLinkIndex union NodeLinkIndex
{ {
@ -70,6 +72,8 @@ namespace SHADE
NodeAttributeIndex SourceAttribute; NodeAttributeIndex SourceAttribute;
NodeAttributeIndex DestinationAttribute; NodeAttributeIndex DestinationAttribute;
}; };
bool operator==(NodeLinkIndex rhs) const noexcept { return Raw != rhs.Raw; }
}; };
struct Node struct Node
@ -111,6 +115,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHAnimationController controller;
std::optional<AnimControllerData> controllerData; std::optional<AnimControllerData> controllerData;
// Persistent Cached Data // Persistent Cached Data
std::vector<std::string> conditionsList; std::vector<std::string> conditionsList;
@ -130,12 +135,16 @@ namespace SHADE
NodeAttributeIndex getExtraOutputAttrib(uint32_t nodeIndex); NodeAttributeIndex getExtraOutputAttrib(uint32_t nodeIndex);
void drawInputNode(int id, ImNodesPinShape_ pinShape); void drawInputNode(int id, ImNodesPinShape_ pinShape);
void drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape); void drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape);
void deleteSelectedNodes();
void deleteSelectedLinks();
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Static Helper Functions */ /* Static Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static std::list<Node>::iterator createNode(AnimControllerData& data); static std::list<Node>::iterator createNode(AnimControllerData& data);
static LinkMap::iterator createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode); static LinkMap::iterator createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode);
static void deleteLink(AnimControllerData& data, LinkIndex link);
static void deleteNode(AnimControllerData& data, NodeIndex nodeIndex);
static AnimControllerData deserialise(const SHAnimationController& controller); static AnimControllerData deserialise(const SHAnimationController& controller);
static SHAnimationController serialise(const AnimControllerData& data); static SHAnimationController serialise(const AnimControllerData& data);
}; };