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 "Editor/SHEditorUI.h"
#include "Editor/SHEditorWidgets.hpp"
#include "../../Command/SHCommand.hpp"
#include "Editor/Command/SHCommand.hpp"
#include "Input/SHInputManager.h"
namespace SHADE
{
@ -144,8 +145,9 @@ namespace SHADE
SHEditorWindow::Exit();
}
void SHAnimationControllerEditor::Open(const SHAnimationController& controller)
void SHAnimationControllerEditor::Open(SHAnimationController& controllerHandle)
{
controller = controllerHandle;
controllerData = deserialise(controller);
}
/*-----------------------------------------------------------------------------------*/
@ -158,12 +160,12 @@ namespace SHADE
// Save Button
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
{
// TODO
// TODO: Actually save the resource
}
// Discard Button
if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data()))
{
// TODO
Open(controller); // TODO: Actually load the resource
}
ImGui::EndMenuBar();
@ -211,7 +213,6 @@ namespace SHADE
// Put into the new
controllerData->Params[val] = TYPE;
// TODO: This needs to be handled in a custom command
// Update all links
for (auto& link : controllerData->Links)
{
@ -293,10 +294,11 @@ namespace SHADE
ImGui::SameLine();
// Delete Node Button
ImGui::BeginDisabled(ImNodes::NumSelectedNodes() < 1);
if (ImGui::Button(std::format("{} Delete Nodes", ICON_MD_ADD).data()))
ImGui::BeginDisabled((ImNodes::NumSelectedNodes() + ImNodes::NumSelectedLinks()) < 1);
if (ImGui::Button(std::format("{} Delete Objects", ICON_MD_DELETE).data()))
{
deleteSelectedLinks();
deleteSelectedNodes();
}
ImGui::EndDisabled();
ImGui::SameLine();
@ -423,6 +425,13 @@ namespace SHADE
);
}
}
// Delete
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::DEL))
{
deleteSelectedLinks();
deleteSelectedNodes();
}
}
void SHAnimationControllerEditor::drawPropertiesMenuBar()
@ -674,6 +683,34 @@ namespace SHADE
ImGui::Text(TITLE);
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)
{
const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++;
@ -716,6 +753,62 @@ namespace SHADE
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 */
/*-----------------------------------------------------------------------------------*/

View File

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