Added breadcrumb navigation for embedded graphs.
parent
44087d7a7c
commit
e3baa65c3b
|
@ -15,7 +15,10 @@
|
|||
|
||||
struct EditorState {
|
||||
AnimGraphResource* rootGraphResource = nullptr;
|
||||
AnimGraphResource* currentGraphResource = nullptr;
|
||||
|
||||
std::vector<AnimGraphResource*> hierarchyStack;
|
||||
size_t hierarchyStackIndex = 0;
|
||||
|
||||
bool isGraphLoadedThisFrame = false;
|
||||
};
|
||||
|
||||
|
@ -259,18 +262,25 @@ void AnimGraphEditorRenderSidebar(
|
|||
}
|
||||
|
||||
void AnimGraphEditorClear() {
|
||||
sEditorState.currentGraphResource = nullptr;
|
||||
sEditorState.hierarchyStack.clear();
|
||||
delete sEditorState.rootGraphResource;
|
||||
|
||||
sEditorState.rootGraphResource = new AnimGraphResource();
|
||||
sEditorState.rootGraphResource->m_name = "Root";
|
||||
sEditorState.rootGraphResource->m_graph_type_name = "BlendTree";
|
||||
sEditorState.rootGraphResource->m_blend_tree_resource.InitGraphConnectors();
|
||||
sEditorState.currentGraphResource = sEditorState.rootGraphResource;
|
||||
|
||||
sEditorState.hierarchyStack.push_back(sEditorState.rootGraphResource);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex] =
|
||||
sEditorState.hierarchyStack.back();
|
||||
}
|
||||
|
||||
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||
ax::NodeEditor::SetCurrentEditor(context);
|
||||
|
||||
//
|
||||
// Menu bar
|
||||
//
|
||||
ImGui::BeginMenuBar();
|
||||
if (ImGui::Button("Save")) {
|
||||
sEditorState.rootGraphResource->SaveToFile("editor_graph.json");
|
||||
|
@ -289,14 +299,47 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
memset(graph_name_buffer, 0, sizeof(graph_name_buffer));
|
||||
strncpy(
|
||||
graph_name_buffer,
|
||||
sEditorState.currentGraphResource->m_name.c_str(),
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_name.c_str(),
|
||||
sizeof(graph_name_buffer));
|
||||
if (ImGui::InputText("Name", graph_name_buffer, sizeof(graph_name_buffer))) {
|
||||
sEditorState.currentGraphResource->m_name = graph_name_buffer;
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]->m_name =
|
||||
graph_name_buffer;
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
|
||||
//
|
||||
// Breadcrumb navigation
|
||||
//
|
||||
for (size_t i = 0, n = sEditorState.hierarchyStack.size(); i < n; i++) {
|
||||
AnimGraphResource* graph_resource =
|
||||
dynamic_cast<AnimGraphResource*>(sEditorState.hierarchyStack[i]);
|
||||
ImGui::PushID(graph_resource);
|
||||
|
||||
bool highlight_button = i == sEditorState.hierarchyStackIndex;
|
||||
|
||||
if (highlight_button) {
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Button,
|
||||
(ImVec4)ImColor::HSV(1. / 7.0f, 0.6f, 0.6f));
|
||||
}
|
||||
|
||||
if (ImGui::Button(graph_resource->m_name.c_str())) {
|
||||
sEditorState.hierarchyStackIndex = i;
|
||||
}
|
||||
|
||||
if (highlight_button) {
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
if (i < n - 1) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Columns(2);
|
||||
|
||||
//
|
||||
|
@ -305,13 +348,13 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
ax::NodeEditor::Begin("Graph Editor");
|
||||
|
||||
for (size_t node_id = 0,
|
||||
n = sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNumNodes();
|
||||
n = sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNumNodes();
|
||||
node_id < n;
|
||||
node_id++) {
|
||||
AnimNodeResource* node_resource =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
node_id);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(node_id);
|
||||
|
||||
if (node_id == 0 || node_id == 1) {
|
||||
// continue;
|
||||
|
@ -327,8 +370,8 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
|
||||
// Inputs
|
||||
std::vector<Socket> node_inputs =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNodeInputSockets(node_resource);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNodeInputSockets(node_resource);
|
||||
for (size_t j = 0, ni = node_inputs.size(); j < ni; j++) {
|
||||
Socket& socket = node_inputs[j];
|
||||
ax::NodeEditor::BeginPin(
|
||||
|
@ -342,8 +385,8 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
|
||||
// Outputs
|
||||
std::vector<Socket> node_outputs =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNodeOutputSockets(node_resource);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNodeOutputSockets(node_resource);
|
||||
for (size_t j = 0, ni = node_outputs.size(); j < ni; j++) {
|
||||
Socket& socket = node_outputs[j];
|
||||
ax::NodeEditor::BeginPin(
|
||||
|
@ -364,23 +407,25 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
|
||||
int link_id = 0;
|
||||
for (size_t connection_id = 0,
|
||||
n = sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNumConnections();
|
||||
n = sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNumConnections();
|
||||
connection_id < n;
|
||||
connection_id++) {
|
||||
const BlendTreeConnectionResource* connection_resource =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetConnection(
|
||||
connection_id);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetConnection(connection_id);
|
||||
|
||||
const AnimNodeResource* source_node_resource =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(
|
||||
connection_resource->source_node_index);
|
||||
int source_socket_index =
|
||||
source_node_resource->m_socket_accessor->GetOutputIndex(
|
||||
connection_resource->source_socket_name.c_str());
|
||||
|
||||
const AnimNodeResource* target_node_resource =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(
|
||||
connection_resource->target_node_index);
|
||||
int target_socket_index =
|
||||
target_node_resource->m_socket_accessor->GetInputIndex(
|
||||
|
@ -411,8 +456,8 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
&source_node_socket_index);
|
||||
|
||||
const AnimNodeResource* source_node =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
source_node_index);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(source_node_index);
|
||||
if (source_node->m_socket_accessor->m_outputs.size()
|
||||
< source_node_socket_index) {
|
||||
source_node_socket_index = -1;
|
||||
|
@ -427,21 +472,21 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
&target_node_socket_index);
|
||||
|
||||
const AnimNodeResource* target_node =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
target_node_index);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(target_node_index);
|
||||
if (target_node->m_socket_accessor->m_inputs.size()
|
||||
< target_node_socket_index) {
|
||||
target_node_socket_index = -1;
|
||||
}
|
||||
|
||||
const Socket* source_socket =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNodeOutputSocketByIndex(
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNodeOutputSocketByIndex(
|
||||
source_node,
|
||||
source_node_socket_index);
|
||||
const Socket* target_socket =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.GetNodeInputSocketByIndex(
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNodeInputSocketByIndex(
|
||||
target_node,
|
||||
target_node_socket_index);
|
||||
|
||||
|
@ -458,8 +503,8 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
->m_inputs[target_node_socket_index]
|
||||
.m_name;
|
||||
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource
|
||||
.ConnectSockets(
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.ConnectSockets(
|
||||
source_node,
|
||||
source_socket_name,
|
||||
target_node,
|
||||
|
@ -522,11 +567,12 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
if (!node_type_name.empty()) {
|
||||
AnimNodeResource* node_resource =
|
||||
AnimNodeResourceFactory(node_type_name);
|
||||
size_t node_id = sEditorState.currentGraphResource
|
||||
size_t node_id =
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNumNodes();
|
||||
ax::NodeEditor::SetNodePosition(node_id, popup_mouse_position);
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.AddNode(
|
||||
node_resource);
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.AddNode(node_resource);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
|
@ -549,9 +595,10 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
|
||||
if (selected_node_id.Get() != 0) {
|
||||
AnimGraphEditorRenderSidebar(
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource,
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
selected_node_id.Get()));
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource,
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(selected_node_id.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,11 +608,23 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
|||
ax::NodeEditor::GetDoubleClickedNode();
|
||||
if (!double_clicked_node_id.Invalid) {
|
||||
AnimNodeResource* clicked_node_resource =
|
||||
sEditorState.currentGraphResource->m_blend_tree_resource.GetNode(
|
||||
double_clicked_node_id.Get());
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(double_clicked_node_id.Get());
|
||||
if (clicked_node_resource->m_node_type_name == "BlendTree") {
|
||||
sEditorState.currentGraphResource =
|
||||
AnimGraphResource* clicked_graph_resource =
|
||||
dynamic_cast<AnimGraphResource*>(clicked_node_resource);
|
||||
if (sEditorState.hierarchyStack.size()
|
||||
> sEditorState.hierarchyStackIndex + 1
|
||||
&& sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex + 1]
|
||||
== clicked_graph_resource) {
|
||||
sEditorState.hierarchyStackIndex++;
|
||||
} else {
|
||||
sEditorState.hierarchyStack.resize(
|
||||
sEditorState.hierarchyStackIndex + 1);
|
||||
sEditorState.hierarchyStack.push_back(clicked_graph_resource);
|
||||
sEditorState.hierarchyStackIndex++;
|
||||
}
|
||||
|
||||
ax::NodeEditor::ClearSelection();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue