12#include "../../system/system_utils.h"
13#include "../../third_party/imgui/imgui.h"
14#include "../../third_party/imnodes/imnodes.h"
15#include "../AIGraphPlugin_BT/BTGraphValidator.h"
16#include "../../NodeGraphCore/Commands/CreateNodeCommand.h"
17#include "../../NodeGraphCore/Commands/ConnectPinsCommand.h"
18#include "../../NodeGraphCore/Commands/ToggleNodeBreakpointCommand.h"
34 , m_showNodePalette(
true)
35 , m_showBlackboardPanel(
false)
36 , m_showSensesPanel(
false)
37 , m_showRuntimeDebugPanel(
false)
54 SYSTEM_LOG <<
"[AIEditorGUI] Initializing..." << std::endl;
59 SYSTEM_LOG <<
"[AIEditorGUI] ERROR: Failed to create ImNodes context" << std::endl;
67 SYSTEM_LOG <<
"[AIEditorGUI] Loaded " <<
allTypes.size() <<
" node types" << std::endl;
77 SYSTEM_LOG <<
"[AIEditorGUI] Initialization complete" << std::endl;
83 SYSTEM_LOG <<
"[AIEditorGUI] Shutting down..." << std::endl;
188 auto cmd = std::unique_ptr<NodeGraph::ICommand>(
190 &
doc->GetNodeAnnotations(), nodeId));
203 ImGui::SetNextWindowPos(
ImVec2(0, 0));
204 ImGui::SetNextWindowSize(ImGui::GetIO().
DisplaySize);
213 ImGui::Begin(
"AI Editor",
nullptr,
flags);
219 ImGui::BeginChild(
"AssetBrowser",
ImVec2(250, 0),
true);
225 ImGui::BeginChild(
"NodeGraph",
ImVec2(-350, 0),
true);
231 ImGui::BeginChild(
"Inspector",
ImVec2(0, 0),
true);
262 if (ImGui::BeginMenuBar()) {
264 if (ImGui::BeginMenu(
"File")) {
265 if (ImGui::MenuItem(
"New Behavior Tree",
"Ctrl+N")) {
268 if (ImGui::MenuItem(
"New HFSM",
"Ctrl+Shift+N")) {
272 if (ImGui::MenuItem(
"Open",
"Ctrl+O")) {
275 if (ImGui::MenuItem(
"Save",
"Ctrl+S")) {
278 if (ImGui::MenuItem(
"Save As",
"Ctrl+Shift+S")) {
282 if (ImGui::MenuItem(
"Close",
"Ctrl+W")) {
289 if (ImGui::BeginMenu(
"Edit")) {
293 if (ImGui::MenuItem(
"Undo",
"Ctrl+Z",
false, canUndo)) {
296 if (ImGui::MenuItem(
"Redo",
"Ctrl+Y",
false, canRedo)) {
300 if (ImGui::MenuItem(
"Cut",
"Ctrl+X")) {
303 if (ImGui::MenuItem(
"Copy",
"Ctrl+C")) {
306 if (ImGui::MenuItem(
"Paste",
"Ctrl+V")) {
309 if (ImGui::MenuItem(
"Delete",
"Delete")) {
313 if (ImGui::MenuItem(
"Select All",
"Ctrl+A")) {
320 if (ImGui::BeginMenu(
"View")) {
326 if (ImGui::MenuItem(
"Reset Layout")) {
329 if (ImGui::MenuItem(
"Auto Layout")) {
336 if (ImGui::BeginMenu(
"Help")) {
337 if (ImGui::MenuItem(
"About")) {
353 ImGui::Text(
"Asset Browser");
386 if (ImGui::Selectable(
filename.c_str())) {
387 SYSTEM_LOG <<
"[AIEditorGUI] Selected asset: " << fullPath << std::endl;
398 ImGui::Text(
"Node Graph");
405 if (
doc ==
nullptr) {
406 ImGui::Text(
"No active graph. Create a new one from File menu.");
417 ImNodes::BeginNodeEditor();
423 if (
doc !=
nullptr) {
425 const std::vector<NodeGraph::NodeData>& nodes =
doc->
GetNodes();
426 for (
size_t i = 0;
i < nodes.size(); ++
i) {
434 ImNodes::EndNodeEditor();
447 if (
doc ==
nullptr) {
452 if (nodeData ==
nullptr) {
458 doc->GetNodeAnnotations().GetAnnotation(
static_cast<int>(nodeId.
value));
461 bool isSelected =
false;
477 if (
doc ==
nullptr) {
482 for (
size_t i = 0;
i <
links.size(); ++
i) {
484 int fromPin =
static_cast<int>(
links[
i].fromPin.value);
485 int toPin =
static_cast<int>(
links[
i].toPin.value);
487 ImNodes::Link(
linkId, fromPin, toPin);
528 if (
doc !=
nullptr) {
534 doc->ConnectPins(fromPin, toPin);
545 ImGui::Text(
"Inspector");
553 ImGui::Text(
"No selection");
574 ImGui::Text(
"AI Senses");
578 ImGui::Text(
"(Not yet implemented)");
587 ImGui::Text(
"Runtime Execution");
591 ImGui::Text(
"(Not yet implemented)");
602 SYSTEM_LOG <<
"[AIEditorGUI] Creating new Behavior Tree" << std::endl;
606 mgr.SetActiveGraph(
id);
611 SYSTEM_LOG <<
"[AIEditorGUI] Creating new HFSM" << std::endl;
615 mgr.SetActiveGraph(
id);
620 SYSTEM_LOG <<
"[AIEditorGUI] Open file dialog" << std::endl;
623 if (!filepath.empty()) {
624 m_lastOpenPath = filepath.substr(0, filepath.find_last_of(
"\\/"));
630 mgr.SetActiveGraph(
id);
631 SYSTEM_LOG <<
"[AIEditorGUI] Loaded: " << filepath << std::endl;
633 SYSTEM_LOG <<
"[AIEditorGUI] ERROR: Failed to load: " << filepath << std::endl;
643 if (
doc ==
nullptr) {
644 SYSTEM_LOG <<
"[AIEditorGUI] No active graph to save" << std::endl;
653 std::string filepath =
"Blueprints/AI/autosave_bt.json";
658 SYSTEM_LOG <<
"[AIEditorGUI] Saved to: " << filepath << std::endl;
660 SYSTEM_LOG <<
"[AIEditorGUI] ERROR: Save failed" << std::endl;
666 SYSTEM_LOG <<
"[AIEditorGUI] Save As file dialog" << std::endl;
671 if (
doc ==
nullptr) {
672 SYSTEM_LOG <<
"[AIEditorGUI] No active graph to save" << std::endl;
677 if (!filepath.empty()) {
678 m_lastSavePath = filepath.substr(0, filepath.find_last_of(
"\\/"));
681 SYSTEM_LOG <<
"[AIEditorGUI] Saved to: " << filepath << std::endl;
692 SYSTEM_LOG <<
"[AIEditorGUI] Auto-layout failed: No active graph" << std::endl;
699 SYSTEM_LOG <<
"[AIEditorGUI] Auto-layout failed: Document not found" << std::endl;
711 SYSTEM_LOG <<
"[AIEditorGUI] Auto-layout applied successfully" << std::endl;
715 SYSTEM_LOG <<
"[AIEditorGUI] Auto-layout failed - check graph has root node" << std::endl;
721 SYSTEM_LOG <<
"[AIEditorGUI] Close current graph" << std::endl;
750 if (
doc ==
nullptr) {
751 SYSTEM_LOG <<
"[AIEditorGUI] No active graph for cut" << std::endl;
756 std::vector<NodeGraph::NodeId> selectedNodes;
760 selectedNodes.push_back(nodeId);
763 if (selectedNodes.empty()) {
764 SYSTEM_LOG <<
"[AIEditorGUI] No nodes selected for cut" << std::endl;
774 SYSTEM_LOG <<
"[AIEditorGUI] Cut " << selectedNodes.size() <<
" nodes" << std::endl;
781 if (
doc ==
nullptr) {
782 SYSTEM_LOG <<
"[AIEditorGUI] No active graph for copy" << std::endl;
787 std::vector<NodeGraph::NodeId> selectedNodes;
791 selectedNodes.push_back(nodeId);
794 if (selectedNodes.empty()) {
795 SYSTEM_LOG <<
"[AIEditorGUI] No nodes selected for copy" << std::endl;
802 SYSTEM_LOG <<
"[AIEditorGUI] Copied " << selectedNodes.size() <<
" nodes" << std::endl;
809 if (
doc ==
nullptr) {
810 SYSTEM_LOG <<
"[AIEditorGUI] No active graph for paste" << std::endl;
815 SYSTEM_LOG <<
"[AIEditorGUI] Clipboard is empty" << std::endl;
836 if (
doc ==
nullptr) {
837 SYSTEM_LOG <<
"[AIEditorGUI] No active graph for delete" << std::endl;
842 SYSTEM_LOG <<
"[AIEditorGUI] No nodes selected for deletion" << std::endl;
850 doc->DeleteNode(nodeId);
863 if (
doc ==
nullptr) {
864 SYSTEM_LOG <<
"[AIEditorGUI] No active graph for select all" << std::endl;
872 const std::vector<NodeGraph::NodeData>& nodes =
doc->
GetNodes();
873 for (
size_t i = 0;
i < nodes.size(); ++
i) {
882 SYSTEM_LOG <<
"[AIEditorGUI] Reset Layout" << std::endl;
913 SYSTEM_LOG <<
"[AIEditorGUI] About dialog (not yet implemented)" << std::endl;
922 size_t lastSlash = filepath.find_last_of(
"/\\");
926 return std::string();
931 size_t lastSlash = filepath.find_last_of(
"/\\");
Clipboard system for AI Editor (Cut/Copy/Paste)
Native file dialog wrapper for AI Editor (Phase 1.5)
Main GUI class for AI Editor (Phase 1.3)
Node renderer for AI Editor with ImNodes.
ComponentTypeID GetComponentTypeID_Static()
void Cut(const std::vector< NodeGraph::NodeId > &nodeIds, NodeGraph::GraphDocument *doc)
Cut selected nodes (copy + delete)
static AIEditorClipboard & Get()
Get singleton instance.
void Copy(const std::vector< NodeGraph::NodeId > &nodeIds, NodeGraph::GraphDocument *doc)
Copy selected nodes to clipboard.
std::vector< NodeGraph::NodeId > Paste(NodeGraph::GraphDocument *doc, Vector pasteOffset)
Paste clipboard nodes into active graph.
static std::string OpenFile(const std::string &filterList="json,btree", const std::string &defaultPath="")
Open a native file dialog to select an existing file.
static std::string SaveFile(const std::string &filterList="json,btree", const std::string &defaultPath="", const std::string &defaultName="new_ai_graph.json")
Open a native save file dialog.
static std::string ExtractDirectory(const std::string &filepath)
Extract directory from filepath.
void MenuAction_AutoLayout()
void RenderInspector()
Render inspector panel (right)
void HandleNodeCreation()
Handle node creation from palette.
std::string m_lastOpenPath
void MenuAction_ShowNodePalette()
void RenderNodeGraphCanvas()
Render node graph with ImNodes.
std::unique_ptr< BTNodePalette > m_nodePalette
std::vector< int > m_selectedLinkIds
void MenuAction_ResetLayout()
void Shutdown()
Shutdown and cleanup.
std::vector< std::string > m_assetFiles
static bool EndsWith(const std::string &str, const std::string &suffix)
Check if string ends with suffix.
static std::string ExtractFilename(const std::string &filepath)
Extract filename from filepath.
void RenderRuntimeDebugPanel()
Render runtime debug panel (entity list + execution)
void Render()
Render the complete UI.
void MenuAction_ShowBlackboard()
void RenderNode(NodeGraph::NodeId nodeId)
Render a single node.
void HandleLinkCreation()
Handle link creation.
bool m_showRuntimeDebugPanel
void RenderBlackboardPanel()
Render blackboard inspector panel.
BlackboardPanel m_blackboardPanel
void RenderMenuBar()
Render main menu bar.
void MenuAction_NewHFSM()
void MenuAction_ShowSensesPanel()
bool m_showBlackboardPanel
void RenderSensesPanel()
Render AI senses debug panel.
void MenuAction_SelectAll()
void HandleNodeSelection()
Handle node selection.
void RenderNodeGraph()
Render node graph panel (center)
char m_assetSearchFilter[256]
std::string m_lastSavePath
void RenderConnections()
Render connections between nodes.
std::vector< int > m_selectedNodeIds
void RenderAssetEntry(const std::string &filename, const std::string &fullPath)
Render asset entry.
void ScanAIGraphDirectory(const std::string &directory)
Scan directory for AI graphs.
void Update(float deltaTime)
Update (called per frame)
bool Initialize()
Initialize the editor.
void MenuAction_ShowRuntimeDebug()
void RenderAssetBrowser()
Render asset browser panel (left)
NodeGraph::CommandStack m_commandStack
static void RenderNode(const NodeGraph::NodeData &nodeData, bool isSelected=false, bool isExecuting=false, const NodeGraph::NodeAnnotation *annotation=nullptr)
Render a single node with ImNodes.
UI palette for BT node selection.
Singleton registry for all BT node types.
static BTNodeRegistry & Get()
Get singleton instance.
void Render(NodeGraph::BlackboardSystem *blackboard, bool *pOpen=nullptr)
Render the panel.
Manages named blackboard variables for a graph.
void Undo()
Undo the last command.
bool CanUndo() const
Check if undo is available.
void Clear()
Clear all commands.
std::string GetUndoDescription() const
Get description of next undo command.
std::string GetRedoDescription() const
Get description of next redo command.
void Redo()
Redo the last undone command.
bool CanRedo() const
Check if redo is available.
void ExecuteCommand(std::unique_ptr< ICommand > cmd)
Execute a command and add to undo stack.
Main document class for a node graph.
const std::vector< LinkData > & GetLinks() const
const std::vector< NodeData > & GetNodes() const
Singleton manager for multiple node graphs.
static NodeGraphManager & Get()
Get singleton instance.
Toggles the breakpoint state of a node (undo/redo-able)
const char *const DEFAULT_AI_GRAPH_NAME
const char *const DEFAULT_AI_GRAPH_FILTER
const char *const DEFAULT_AI_GRAPH_EXT
< Provides AssetID and INVALID_ASSET_ID
Holds annotation data for a single node.