From ff27925f2d644ff442206fdc7f603f19a9766254 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 7 Mar 2023 20:05:37 +0800 Subject: [PATCH] Added ability to reset state, delete links and nodes --- .../Animation/SHAnimationControllerEditor.cpp | 109 ++++++++++++++++-- .../Animation/SHAnimationControllerEditor.h | 11 +- 2 files changed, 111 insertions(+), 9 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp index 4be0c7b0..9659f036 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp @@ -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 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 selectedLinks(NUM_SELECTED_LINKS); + ImNodes::GetSelectedLinks(selectedLinks.data()); + + for (auto linkId : selectedLinks) + { + deleteLink(controllerData.value(), linkId); + } + } + } std::list::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 */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h index 60e939c7..1066fc7b 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h @@ -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 controllerData; // Persistent Cached Data std::vector 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::iterator createNode(AnimControllerData& data); static LinkMap::iterator createLink(AnimControllerData& data, std::list::iterator sourceNode, std::list::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); };