Properly store and restore node positions in editor.

RefactorUnifiedBlendTreeStateMachineHandling
Martin Felis 2024-05-01 12:50:16 +02:00
parent 7c7a765455
commit 84fc49af30
2 changed files with 39 additions and 18 deletions

View File

@ -160,7 +160,11 @@ void SkinnedMeshWidget(SkinnedMesh* skinned_mesh) {
void AnimGraphEditorRenderSidebar( void AnimGraphEditorRenderSidebar(
BlendTreeResource& blend_tree_resource, BlendTreeResource& blend_tree_resource,
AnimNodeResource* node_resource) { AnimNodeResource* node_resource) {
ImGui::Text("[%s]", node_resource->m_node_type_name.c_str()); ImGui::Text(
"[%s (%2.2f, %2.2f)]",
node_resource->m_node_type_name.c_str(),
node_resource->m_position[0],
node_resource->m_position[1]);
char node_name_buffer[256]; char node_name_buffer[256];
memset(node_name_buffer, 0, sizeof(node_name_buffer)); memset(node_name_buffer, 0, sizeof(node_name_buffer));
@ -263,7 +267,10 @@ void AnimGraphEditorRenderSidebar(
} }
void AnimGraphEditorClear() { void AnimGraphEditorClear() {
sEditorState.hierarchyStack.clear(); if (ax::NodeEditor::GetCurrentEditor() != nullptr) {
ax::NodeEditor::ClearSelection();
}
delete sEditorState.rootGraphResource; delete sEditorState.rootGraphResource;
sEditorState.rootGraphResource = new AnimGraphResource(); sEditorState.rootGraphResource = new AnimGraphResource();
@ -271,9 +278,11 @@ void AnimGraphEditorClear() {
sEditorState.rootGraphResource->m_graph_type_name = "BlendTree"; sEditorState.rootGraphResource->m_graph_type_name = "BlendTree";
sEditorState.rootGraphResource->m_blend_tree_resource.InitGraphConnectors(); sEditorState.rootGraphResource->m_blend_tree_resource.InitGraphConnectors();
sEditorState.hierarchyStack.clear();
sEditorState.hierarchyStack.push_back(sEditorState.rootGraphResource); sEditorState.hierarchyStack.push_back(sEditorState.rootGraphResource);
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] = sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] =
sEditorState.hierarchyStack.back(); sEditorState.hierarchyStack.back();
sEditorState.hierarchyStackIndex = 0;
} }
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) { void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
@ -287,6 +296,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
sEditorState.rootGraphResource->SaveToFile("editor_graph.json"); sEditorState.rootGraphResource->SaveToFile("editor_graph.json");
} }
if (ImGui::Button("Load")) { if (ImGui::Button("Load")) {
AnimGraphEditorClear();
sEditorState.rootGraphResource->LoadFromFile("editor_graph.json"); sEditorState.rootGraphResource->LoadFromFile("editor_graph.json");
sEditorState.isGraphLoadedThisFrame = true; sEditorState.isGraphLoadedThisFrame = true;
} }
@ -348,18 +358,15 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
// //
ax::NodeEditor::Begin("Graph Editor"); ax::NodeEditor::Begin("Graph Editor");
for (size_t node_id = 0, for (size_t node_index = 0,
n = sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] n = sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
->m_blend_tree_resource.GetNumNodes(); ->m_blend_tree_resource.GetNumNodes();
node_id < n; node_index < n;
node_id++) { node_index++) {
AnimNodeResource* node_resource = AnimNodeResource* node_resource =
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
->m_blend_tree_resource.GetNode(node_id); ->m_blend_tree_resource.GetNode(node_index);
ax::NodeEditor::NodeId node_id(node_resource);
if (node_id == 0 || node_id == 1) {
// continue;
}
if (sEditorState.isGraphLoadedThisFrame) { if (sEditorState.isGraphLoadedThisFrame) {
ax::NodeEditor::SetNodePosition( ax::NodeEditor::SetNodePosition(
@ -377,7 +384,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
Socket& socket = node_inputs[j]; Socket& socket = node_inputs[j];
ax::NodeEditor::BeginPin( ax::NodeEditor::BeginPin(
NodeIndexAndSocketIndexToInputPinId( NodeIndexAndSocketIndexToInputPinId(
static_cast<int>(node_id), static_cast<int>(node_index),
static_cast<int>(j)), static_cast<int>(j)),
ax::NodeEditor::PinKind::Input); ax::NodeEditor::PinKind::Input);
ImGui::Text("%s", socket.m_name.c_str()); ImGui::Text("%s", socket.m_name.c_str());
@ -392,7 +399,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
Socket& socket = node_outputs[j]; Socket& socket = node_outputs[j];
ax::NodeEditor::BeginPin( ax::NodeEditor::BeginPin(
NodeIndexAndSocketIndexToOutputPinId( NodeIndexAndSocketIndexToOutputPinId(
static_cast<int>(node_id), static_cast<int>(node_index),
static_cast<int>(j)), static_cast<int>(j)),
ax::NodeEditor::PinKind::Output); ax::NodeEditor::PinKind::Output);
ImGui::Text("%s", socket.m_name.c_str()); ImGui::Text("%s", socket.m_name.c_str());
@ -597,22 +604,32 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
AnimGraphEditorRenderSidebar( AnimGraphEditorRenderSidebar(
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
->m_blend_tree_resource, ->m_blend_tree_resource,
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] selected_node_id.AsPointer<AnimNodeResource>());
->m_blend_tree_resource.GetNode(selected_node_id.Get()));
} }
} }
ImGui::Columns(1); ImGui::Columns(1);
// Clear flag, however it may be re-set further down when handling double
// clicking into subgraphs.
sEditorState.isGraphLoadedThisFrame = false;
//
// Handle double click into subgraphs
//
ax::NodeEditor::NodeId double_clicked_node_id = ax::NodeEditor::NodeId double_clicked_node_id =
ax::NodeEditor::GetDoubleClickedNode(); ax::NodeEditor::GetDoubleClickedNode();
if (!double_clicked_node_id.Invalid) { if (!double_clicked_node_id.Invalid) {
AnimNodeResource* clicked_node_resource = AnimNodeResource* clicked_node_resource =
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] double_clicked_node_id.AsPointer<AnimNodeResource>();
->m_blend_tree_resource.GetNode(double_clicked_node_id.Get());
if (clicked_node_resource->m_node_type_name == "BlendTree") { if (clicked_node_resource != nullptr
&& clicked_node_resource->m_node_type_name == "BlendTree") {
AnimGraphResource* clicked_graph_resource = AnimGraphResource* clicked_graph_resource =
dynamic_cast<AnimGraphResource*>(clicked_node_resource); dynamic_cast<AnimGraphResource*>(clicked_node_resource);
assert(clicked_graph_resource != nullptr);
if (sEditorState.hierarchyStack.size() if (sEditorState.hierarchyStack.size()
> sEditorState.hierarchyStackIndex + 1 > sEditorState.hierarchyStackIndex + 1
&& sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex + 1] && sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex + 1]
@ -625,12 +642,12 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
sEditorState.hierarchyStackIndex++; sEditorState.hierarchyStackIndex++;
} }
sEditorState.isGraphLoadedThisFrame = true;
ax::NodeEditor::ClearSelection(); ax::NodeEditor::ClearSelection();
} }
} }
ax::NodeEditor::SetCurrentEditor(nullptr); ax::NodeEditor::SetCurrentEditor(nullptr);
sEditorState.isGraphLoadedThisFrame = false;
} }
void AnimGraphEditorGetRuntimeGraph(AnimGraphBlendTree& blend_tree) { void AnimGraphEditorGetRuntimeGraph(AnimGraphBlendTree& blend_tree) {

View File

@ -256,6 +256,8 @@ static json sAnimGraphResourceBlendTreeToJson(
result["name"] = anim_graph_resource.m_name; result["name"] = anim_graph_resource.m_name;
result["type"] = "AnimNodeResource"; result["type"] = "AnimNodeResource";
result["node_type"] = "BlendTree"; result["node_type"] = "BlendTree";
result["position"][0] = anim_graph_resource.m_position[0];
result["position"][1] = anim_graph_resource.m_position[1];
const BlendTreeResource& blend_tree_resource = const BlendTreeResource& blend_tree_resource =
anim_graph_resource.m_blend_tree_resource; anim_graph_resource.m_blend_tree_resource;
@ -307,6 +309,8 @@ static bool sAnimGraphResourceBlendTreeFromJson(
result_graph_resource->m_graph_type_name = "BlendTree"; result_graph_resource->m_graph_type_name = "BlendTree";
result_graph_resource->m_node_type_name = "BlendTree"; result_graph_resource->m_node_type_name = "BlendTree";
result_graph_resource->m_name = json_data["name"]; result_graph_resource->m_name = json_data["name"];
result_graph_resource->m_position[0] = json_data["position"][0];
result_graph_resource->m_position[1] = json_data["position"][1];
// Load nodes // Load nodes
for (size_t i = 0, n = json_data["nodes"].size(); i < n; i++) { for (size_t i = 0, n = json_data["nodes"].size(); i < n; i++) {