66 ImGui::Begin(
"Node Graph Editor");
76 ImGui::TextColored(
ImVec4(0.5f, 1.0f, 0.5f, 1.0f),
81 ImGui::TextColored(
ImVec4(0.7f, 0.7f, 0.9f, 1.0f),
82 "Editing BehaviorTree Asset (no entity context)");
93 ImGui::BeginDisabled();
95 if (ImGui::Button(
"Save"))
102 ImGui::OpenPopup(
"ValidationError");
107 const std::string& filepath =
activeGraph->GetFilepath();
110 std::cout <<
"[NodeGraphPanel] Saved graph to: " << filepath << std::endl;
114 std::cout <<
"[NodeGraphPanel] Failed to save graph!" << std::endl;
120 ImGui::EndDisabled();
124 ImGui::SetTooltip(
"No filepath set. Use 'Save As...' first.");
130 if (ImGui::Button(
"Save As..."))
134 ImGui::OpenPopup(
"SaveAsPopup");
141 ImGui::TextColored(
ImVec4(1.0f, 0.7f, 0.2f, 1.0f),
"*");
142 if (ImGui::IsItemHovered())
144 ImGui::SetTooltip(
"Unsaved changes");
152 if (ImGui::BeginPopup(
"SaveAsPopup"))
161 ImGui::Text(
"Save graph as:");
164 if (ImGui::Button(
"Save",
ImVec2(120, 0)))
167 if (!filepath.empty())
175 ImGui::CloseCurrentPopup();
176 ImGui::OpenPopup(
"ValidationError");
181 if (filepath.size() < 5 || filepath.substr(filepath.size() - 5) !=
".json")
187 std::cout <<
"[NodeGraphPanel] Saved graph as: " << filepath << std::endl;
189 ImGui::CloseCurrentPopup();
193 std::cout <<
"[NodeGraphPanel] Failed to save graph!" << std::endl;
199 if (ImGui::Button(
"Cancel",
ImVec2(120, 0)))
202 ImGui::CloseCurrentPopup();
214 ImGui::TextColored(
ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
"Cannot save: Graph validation failed!");
224 if (ImGui::Button(
"OK",
ImVec2(120, 0)))
226 ImGui::CloseCurrentPopup();
247 ImGui::Text(
"No graph open. Create or load a graph to begin.");
248 if (ImGui::Button(
"Create New Behavior Tree"))
253 if (ImGui::Button(
"Create New HFSM"))
443 std::cerr <<
"[NodeGraphPanel] Invalid graph ID" << std::endl;
452 ImGui::Text(
"Canvas too small to render graph");
456 ImNodes::BeginNodeEditor();
459 auto nodes =
graph->GetAllNodes();
473 ImNodes::BeginNodeTitleBar();
474 ImGui::TextUnformatted(
node->name.c_str());
475 ImNodes::EndNodeTitleBar();
481 ImNodes::EndInputAttribute();
488 ImGui::Text(
"Action: %s",
node->actionType.c_str());
492 ImGui::Text(
"Condition: %s",
node->conditionType.c_str());
496 ImGui::Text(
"Decorator: %s",
node->decoratorType.c_str());
503 ImNodes::EndOutputAttribute();
510 for (
size_t i = 0;
i <
links.size(); ++
i)
527 ImNodes::EndNodeEditor();
564 auto cmd = std::make_unique<UnlinkNodesCommand>(graphId,
link.fromNode,
link.toNode);
595 ImGui::OpenPopup(
"NodeContextMenu");
601 ImNodes::IsEditorHovered() &&
604 ImGui::OpenPopup(
"NodeCreationMenu");
611 if (ImGui::BeginPopup(
"NodeContextMenu"))
617 if (ImGui::MenuItem(
"Edit",
"Double-click"))
632 if (ImGui::MenuItem(
"Duplicate",
"Ctrl+D"))
646 if (ImGui::MenuItem(
"Delete",
"Del"))
660 if (ImGui::BeginDragDropTarget())
713 std::cout <<
"[NodeGraphPanel] Created Action node: " << actionType
719 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid ActionType: " << actionType <<
"\n";
720 ImGui::SetTooltip(
"Invalid ActionType: %s", actionType.c_str());
736 std::cout <<
"[NodeGraphPanel] Created Condition node: " << conditionType
742 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid ConditionType: " << conditionType <<
"\n";
743 ImGui::SetTooltip(
"Invalid ConditionType: %s", conditionType.c_str());
759 std::cout <<
"[NodeGraphPanel] Created Decorator node: " << decoratorType
765 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid DecoratorType: " << decoratorType <<
"\n";
766 ImGui::SetTooltip(
"Invalid DecoratorType: %s", decoratorType.c_str());
776 std::cout <<
"[NodeGraphPanel] Created " <<
nodeTypeData <<
" node"
782 std::cerr <<
"[NodeGraphPanel] ERROR: Unknown node type: " <<
nodeTypeData <<
"\n";
783 ImGui::SetTooltip(
"Unknown node type: %s",
nodeTypeData.c_str());
788 std::cerr <<
"[NodeGraphPanel] Failed to create node from DnD payload\n";
793 std::cerr <<
"[NodeGraphPanel] Invalid DnD payload received (null or empty)\n";
796 ImGui::EndDragDropTarget();
1041 ImGui::OpenPopup(
"Edit Node");
1054 ImGui::Text(
"ID: %d",
node->id);
1063 ImGui::Text(
"Action Type:");
1065 if (ImGui::BeginCombo(
"##actiontype",
node->actionType.c_str()))
1069 bool isSelected = (
node->actionType == actionType);
1070 if (ImGui::Selectable(actionType.c_str(), isSelected))
1073 node->actionType = actionType;
1077 ImGui::SetItemDefaultFocus();
1084 ImGui::Text(
"Parameters:");
1107 if (!
actionDef->tooltip.empty() && ImGui::IsItemHovered())
1109 ImGui::SetTooltip(
"%s",
actionDef->tooltip.c_str());
1117 ImGui::Text(
"Condition Type:");
1119 if (ImGui::BeginCombo(
"##conditiontype",
node->conditionType.c_str()))
1123 bool isSelected = (
node->conditionType == conditionType);
1124 if (ImGui::Selectable(conditionType.c_str(), isSelected))
1126 node->conditionType = conditionType;
1129 ImGui::SetItemDefaultFocus();
1136 ImGui::Text(
"Parameters:");
1161 ImGui::Text(
"Decorator Type:");
1163 if (ImGui::BeginCombo(
"##decoratortype",
node->decoratorType.c_str()))
1167 bool isSelected = (
node->decoratorType == decoratorType);
1168 if (ImGui::Selectable(decoratorType.c_str(), isSelected))
1170 node->decoratorType = decoratorType;
1173 ImGui::SetItemDefaultFocus();
1181 if (ImGui::Button(
"OK",
ImVec2(120, 0)))
1200 if (ImGui::Button(
"Cancel",
ImVec2(120, 0)))
static EditorContext & Get()