Implemented Animation Clip asset and animation controller #410
|
@ -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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue