6#include "BlueprintEditor.h"
16#include "../system/system_consts.h"
17#include "../TaskSystem/AtomicTaskRegistry.h"
18#include "../TaskSystem/TaskGraphTypes.h"
19#include "../third_party/imgui/imgui.h"
20#include "../third_party/imnodes/imnodes.h"
28#include "../NodeGraphShared/BlueprintAdapter.h"
93 std::cout <<
"[NodeGraphPanel] Initialized\n";
116 std::cout <<
"[NodeGraphPanel] Shutdown\n";
121 ImGui::Begin(
"Node Graph Editor");
136 if (ImGui::IsItemHovered())
137 ImGui::SetTooltip(
"Snap-to-grid (Ctrl+G)");
139 ImGui::SetNextItemWidth(60.0f);
140 ImGui::DragFloat(
"Grid", &
m_SnapGridSize, 1.0f, 4.0f, 128.0f,
"%.0f");
141 if (ImGui::IsItemHovered())
142 ImGui::SetTooltip(
"Grid cell size");
152 if (ImGui::IsItemHovered())
153 ImGui::SetTooltip(
"Minimap (Ctrl+M)");
159 ImGui::SetNextItemWidth(50.0f);
161 if (ImGui::DragFloat(
"##mmsize", &
minimapSize, 0.01f, 0.05f, 0.5f,
"%.2f"))
165 if (ImGui::IsItemHovered())
166 ImGui::SetTooltip(
"Minimap scale (0.05-0.5)");
170 ImGui::SetNextItemWidth(80.0f);
172 const char*
positionNames[] = {
"TopLeft",
"TopRight",
"BottomLeft",
"BottomRight"};
177 if (ImGui::IsItemHovered())
178 ImGui::SetTooltip(
"Minimap position");
199 ImGui::BeginDisabled();
201 if (ImGui::Button(
"Save"))
208 ImGui::OpenPopup(
"ValidationError");
215 const std::string& filepath =
activeGraph->GetFilepath();
218 std::cout <<
"[NodeGraphPanel] Saved graph to: " << filepath << std::endl;
222 std::cout <<
"[NodeGraphPanel] Failed to save graph!" << std::endl;
228 ImGui::EndDisabled();
232 ImGui::SetTooltip(
"No filepath set. Use 'Save As...' first.");
238 if (ImGui::Button(
"Save As..."))
242 ImGui::OpenPopup(
"SaveAsPopup");
249 ImGui::TextColored(
ImVec4(1.0f, 0.7f, 0.2f, 1.0f),
"*");
250 if (ImGui::IsItemHovered())
252 ImGui::SetTooltip(
"Unsaved changes");
261 ImGui::TextColored(
ImVec4(0.5f, 1.0f, 0.5f, 1.0f),
266 ImGui::TextColored(
ImVec4(0.7f, 0.7f, 0.9f, 1.0f),
267 "Editing BehaviorTree Asset (no entity context)");
275 if (ImGui::BeginPopup(
"SaveAsPopup"))
284 ImGui::Text(
"Save graph as:");
287 if (ImGui::Button(
"Save",
ImVec2(120, 0)))
290 if (!filepath.empty())
298 ImGui::CloseCurrentPopup();
299 ImGui::OpenPopup(
"ValidationError");
304 if (filepath.size() < 5 || filepath.substr(filepath.size() - 5) !=
".json")
312 std::cout <<
"[NodeGraphPanel] Saved graph as: " << filepath << std::endl;
314 ImGui::CloseCurrentPopup();
318 std::cout <<
"[NodeGraphPanel] Failed to save graph!" << std::endl;
324 if (ImGui::Button(
"Cancel",
ImVec2(120, 0)))
327 ImGui::CloseCurrentPopup();
339 ImGui::TextColored(
ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
"Cannot save: Graph validation failed!");
349 if (ImGui::Button(
"OK",
ImVec2(120, 0)))
351 ImGui::CloseCurrentPopup();
376 ImGui::TextDisabled(
"No graph active. Create a new graph from the menu or load an existing one.");
393 if (ImGui::BeginTabBar(
"GraphTabs"))
414 if (ImGui::BeginTabItem(graphName.c_str(), &
tabOpen,
flags))
436 ImGui::OpenPopup(
"ConfirmCloseUnsaved");
450 ImGui::OpenPopup(
"CreateGraphPopup");
459 ImGui::TextColored(
ImVec4(1.0f, 0.7f, 0.2f, 1.0f),
"Warning: Unsaved Changes!");
463 ImGui::TextWrapped(
"The graph '%s' has unsaved changes.", graphName.c_str());
464 ImGui::TextWrapped(
"Do you want to save before closing?");
469 if (ImGui::Button(
"Save and Close",
ImVec2(120, 0)))
479 ImGui::CloseCurrentPopup();
480 ImGui::OpenPopup(
"ValidationError");
490 ImGui::CloseCurrentPopup();
498 ImGui::CloseCurrentPopup();
499 ImGui::OpenPopup(
"SaveAsPopup");
506 if (ImGui::Button(
"Close Without Saving",
ImVec2(150, 0)))
511 ImGui::CloseCurrentPopup();
517 if (ImGui::Button(
"Cancel",
ImVec2(120, 0)))
521 ImGui::CloseCurrentPopup();
537 if (ImGui::BeginPopup(
"CreateGraphPopup"))
539 if (ImGui::MenuItem(
"New Behavior Tree"))
543 if (ImGui::MenuItem(
"New HFSM"))
561 std::cerr <<
"[NodeGraphPanel] Invalid graph ID" << std::endl;
567 ImVec2 canvasSize = ImGui::GetContentRegionAvail();
570 ImGui::Text(
"Canvas too small to render graph");
579 "BehaviorTreeEditor",
593 ImNodes::BeginNodeEditor();
596 auto nodes =
graph->GetAllNodes();
652 headerHoveredColor =
IM_COL32(100, 255, 100, 255);
653 headerSelectedColor =
IM_COL32(150, 255, 150, 255);
658 headerColor =
IM_COL32(200, 180, 20, 255);
659 headerHoveredColor =
IM_COL32(220, 200, 40, 255);
660 headerSelectedColor =
IM_COL32(240, 220, 60, 255);
673 ImNodes::PopColorStyle();
674 ImNodes::PopColorStyle();
675 ImNodes::PopColorStyle();
682 for (
size_t i = 0;
i <
links.size(); ++
i)
688 int toNodeUID = (graphID * GRAPH_ID_MULTIPLIER) +
link.toNode;
713 ImNodes::EndNodeEditor();
757 auto cmd = std::make_unique<UnlinkNodesCommand>(graphId,
link.fromNode,
link.toNode);
777 ImGui::OpenPopup(
"NodeContextMenu");
783 ImNodes::IsEditorHovered() &&
786 ImGui::OpenPopup(
"NodeCreationMenu");
793 if (ImGui::BeginPopup(
"NodeContextMenu"))
812 if (ImGui::MenuItem(
"Duplicate",
"Ctrl+D"))
818 ImGui::CloseCurrentPopup();
832 ImGui::BeginDisabled(
true);
833 ImGui::MenuItem(
"Delete",
"Del");
834 ImGui::EndDisabled();
835 if (ImGui::IsItemHovered())
837 ImGui::SetTooltip(
"Root node cannot be deleted");
840 else if (ImGui::MenuItem(
"Delete",
"Del"))
846 ImGui::CloseCurrentPopup();
860 ImGui::OpenPopup(
"LinkContextMenu");
865 if (ImGui::BeginPopup(
"LinkContextMenu"))
877 if (fromNode && toNode)
879 ImGui::Text(
"Link: %s -> %s", fromNode->
name.c_str(), toNode->
name.c_str());
883 ImGui::Text(
"Link: %d -> %d",
link.fromNode,
link.toNode);
890 if (ImGui::MenuItem(
"Delete Link",
"Del"))
893 auto cmd = std::make_unique<UnlinkNodesCommand>(graphId,
link.fromNode,
link.toNode);
896 ImGui::CloseCurrentPopup();
902 ImGui::Text(
"Invalid link");
909 if (ImGui::BeginDragDropTarget())
916 std::cerr <<
"[NodeGraphPanel] ERROR: NODE_TYPE payload has null or empty data\n";
946 std::cout <<
"[NodeGraphPanel] Received NODE_TYPE payload: " <<
nodeTypeData <<
"\n";
968 std::cout <<
"[NodeGraphPanel] Created Action node: " << actionType
969 <<
" at canvas pos (" << canvasPos.x <<
", " << canvasPos.y <<
")\n";
974 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid ActionType: " << actionType <<
"\n";
975 ImGui::SetTooltip(
"Invalid ActionType: %s", actionType.c_str());
991 std::cout <<
"[NodeGraphPanel] Created Condition node: " << conditionType
992 <<
" at canvas pos (" << canvasPos.x <<
", " << canvasPos.y <<
")\n";
997 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid ConditionType: " << conditionType <<
"\n";
998 ImGui::SetTooltip(
"Invalid ConditionType: %s", conditionType.c_str());
1014 std::cout <<
"[NodeGraphPanel] Created Decorator node: " << decoratorType
1015 <<
" at canvas pos (" << canvasPos.x <<
", " << canvasPos.y <<
")\n";
1020 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid DecoratorType: " << decoratorType <<
"\n";
1021 ImGui::SetTooltip(
"Invalid DecoratorType: %s", decoratorType.c_str());
1031 std::cout <<
"[NodeGraphPanel] Created " <<
nodeTypeData <<
" node"
1032 <<
" at canvas pos (" << canvasPos.x <<
", " << canvasPos.y <<
")\n";
1037 std::cerr <<
"[NodeGraphPanel] ERROR: Unknown node type: " <<
nodeTypeData <<
"\n";
1038 ImGui::SetTooltip(
"Unknown node type: %s",
nodeTypeData.c_str());
1043 std::cerr <<
"[NodeGraphPanel] Failed to create node from DnD payload\n";
1055 std::cout <<
"[NodeGraphPanel] Received VS_NODE_TYPE_ENUM payload: "
1075 std::cerr <<
"[NodeGraphPanel] ERROR: Unhandled TaskNodeType enum: "
1085 std::cout <<
"[NodeGraphPanel] Created VS node from palette: " <<
nodeTypeName <<
"\n";
1089 std::cerr <<
"[NodeGraphPanel] Failed to create node from VS_NODE_TYPE_ENUM payload\n";
1094 std::cerr <<
"[NodeGraphPanel] ERROR: Invalid VS_NODE_TYPE_ENUM payload - ";
1096 std::cerr <<
"null data\n";
1098 std::cerr <<
"wrong size (expected " <<
sizeof(
uint8_t)
1099 <<
", got " <<
payload->DataSize <<
")\n";
1103 ImGui::EndDragDropTarget();
1136 ?
graph->GetFilepath() :
"";
1138 static_cast<double>(ImGui::GetTime()),
1142 if (
g &&
g->IsDirty())
1144 return std::string();
1147 "GameData/AI/autosave_");
1204 std::unordered_map<std::string, std::string>
params;
1261 ImGui::TextUnformatted(label);
1262 ImNodes::EndInputAttribute();
1267 ImGui::TextUnformatted(label);
1268 ImNodes::EndOutputAttribute();
1283 ImNodes::BeginNodeTitleBar();
1284 if (style.
icon[0] !=
'\0')
1285 ImGui::Text(
"[%s] %s", style.
icon,
node->name.c_str());
1287 ImGui::TextUnformatted(
node->name.c_str());
1288 ImNodes::EndNodeTitleBar();
1294 auto it =
node->parameters.find(
"text");
1296 ImGui::SetNextItemWidth(180.0f);
1300 std::string
inputId = std::string(
"##comment") + std::to_string(
node->id);
1326 ImGui::Columns(3,
"node_pins",
false);
1327 ImGui::SetColumnWidth(0, 60.0f);
1328 ImGui::SetColumnWidth(1, 100.0f);
1335 ImGui::NextColumn();
1337 ImGui::Text(
"%s",
node->actionType.c_str());
1339 ImGui::Text(
"%s",
node->conditionType.c_str());
1341 ImGui::Text(
"%s",
node->decoratorType.c_str());
1346 ImGui::NextColumn();
1366 float t = 0.5f + 0.5f * std::sin(
static_cast<float>(ImGui::GetTime()) * 4.0f);
1367 float alpha = 0.6f + 0.4f *
t;
1371 static_cast<int>(180.0f +
t * 75.0f),
1372 static_cast<int>(140.0f +
t * 115.0f),
1374 static_cast<int>(
alpha * 255.0f));
1377 for (
size_t i = 0;
i <
links.size(); ++
i)
1385 int fromUID = graphID * GRAPH_ID_MULTIPLIER +
link.fromNode;
1386 int toUID = graphID * GRAPH_ID_MULTIPLIER +
link.toNode;
1395 const float po = ImNodes::GetStyle().PinOffset;
1417 if (
graph ==
nullptr)
1477 const float po = ImNodes::GetStyle().PinOffset;
1490 0.125f *
p1.x + 0.375f *
p2.x + 0.375f *
p3.x + 0.125f *
p4.x,
1491 0.125f *
p1.y + 0.375f *
p2.y + 0.375f *
p3.y + 0.125f *
p4.y
1523 if (ImGui::BeginPopup(
"NodeCreationMenu"))
1526 ImGui::Text(
"Create Node");
1530 ImGui::SetNextItemWidth(-1.0f);
1532 ImGui::SameLine(0.0f, 0.0f);
1533 ImGui::TextDisabled(
" (search)");
1555 if (ImGui::BeginMenu(
"Composite"))
1557 if (ImGui::MenuItem(
"Sequence"))
1559 if (ImGui::MenuItem(
"Selector"))
1564 if (ImGui::BeginMenu(
"Action"))
1569 if (ImGui::MenuItem(actionType.c_str()))
1577 allNodes.back()->actionType = actionType;
1584 if (ImGui::BeginMenu(
"Condition"))
1589 if (ImGui::MenuItem(conditionType.c_str()))
1597 allNodes.back()->conditionType = conditionType;
1604 if (ImGui::BeginMenu(
"Decorator"))
1609 if (ImGui::MenuItem(decoratorType.c_str()))
1617 allNodes.back()->decoratorType = decoratorType;
1625 ImGui::TextDisabled(
"-- Atomic Tasks --");
1627 if (ImGui::MenuItem(
"Comment Box"))
1638 ImGui::CloseCurrentPopup();
1654 if (ImGui::MenuItem(
taskId.c_str()))
1683 std::cerr <<
"[NodeGraphPanel] Cannot create node: No active graph\n";
1691 if (!std::isfinite(canvasPos.x) || !std::isfinite(canvasPos.y))
1693 std::cerr <<
"[NodeGraphPanel] Invalid coordinates for node creation\n";
1697 std::cout <<
"[NodeGraphPanel] Creating " << nodeType <<
" at canvas pos ("
1698 << canvasPos.x <<
", " << canvasPos.y <<
")\n";
1704 int createdId =
adapter.CreateNode(nodeType, canvasPos.x, canvasPos.y, nodeType);
1706 std::cout <<
"[NodeGraphPanel] Requested create node of type " << nodeType <<
" via command stack, id=" <<
createdId <<
"\n";
1712 ImNodes::ClearNodeSelection();
1716 ImNodes::EditorContextMoveToNode(
globalUID);
1735 if (
io.KeyCtrl && ImGui::IsKeyPressed(
ImGuiKey_Z) && !
io.KeyShift)
1754 ImNodes::GetSelectedNodes(selectedNodes.data());
1755 if (selectedNodes.size() > 0)
1757 int nodeId = selectedNodes[0];
1759 auto cmd = std::make_unique<Olympe::Blueprint::DuplicateNodeCommand>(graphId, nodeId);
1803 ImNodes::EditorContextResetPanning(
ImVec2(0.0f, 0.0f));
1827 ImGui::OpenPopup(
"Edit Node");
1840 ImGui::Text(
"ID: %d",
node->id);
1849 ImGui::Text(
"Action Type:");
1851 if (ImGui::BeginCombo(
"##actiontype",
node->actionType.c_str()))
1855 bool isSelected = (
node->actionType == actionType);
1856 if (ImGui::Selectable(actionType.c_str(), isSelected))
1859 node->actionType = actionType;
1863 ImGui::SetItemDefaultFocus();
1870 ImGui::Text(
"Parameters:");
1893 if (!
actionDef->tooltip.empty() && ImGui::IsItemHovered())
1895 ImGui::SetTooltip(
"%s",
actionDef->tooltip.c_str());
1903 ImGui::Text(
"Condition Type:");
1905 if (ImGui::BeginCombo(
"##conditiontype",
node->conditionType.c_str()))
1909 bool isSelected = (
node->conditionType == conditionType);
1910 if (ImGui::Selectable(conditionType.c_str(), isSelected))
1912 node->conditionType = conditionType;
1915 ImGui::SetItemDefaultFocus();
1922 ImGui::Text(
"Parameters:");
1947 ImGui::Text(
"Decorator Type:");
1949 if (ImGui::BeginCombo(
"##decoratortype",
node->decoratorType.c_str()))
1953 bool isSelected = (
node->decoratorType == decoratorType);
1954 if (ImGui::Selectable(decoratorType.c_str(), isSelected))
1956 node->decoratorType = decoratorType;
1959 ImGui::SetItemDefaultFocus();
1967 if (ImGui::Button(
"OK",
ImVec2(120, 0)))
1986 if (ImGui::Button(
"Cancel",
ImVec2(120, 0)))
2002 if (ImGui::BeginTabBar(
"SubgraphTabs"))
2021 if (ImGui::BeginTabItem(label.c_str(),
pOpen,
flags))
2024 ImGui::EndTabItem();
2033 ImGui::OpenPopup(
"NewSubgraphPopup");
2039 if (ImGui::BeginPopup(
"NewSubgraphPopup"))
2041 ImGui::Text(
"SubGraph name:");
2042 ImGui::SetNextItemWidth(200.0f);
2046 if (ImGui::Button(
"Create") ||
2047 (ImGui::IsItemFocused() &&
2055 ImGui::CloseCurrentPopup();
2059 if (ImGui::Button(
"Cancel"))
2062 ImGui::CloseCurrentPopup();
2070 const std::string& displayName)
2083 std::string path =
"subgraphs/" + subgraphUUID;
2087 std::cout <<
"[NodeGraphPanel] Opened subgraph tab: " << displayName
2088 <<
" (" << subgraphUUID <<
")\n";
2096 std::cout <<
"[NodeGraphPanel] Closed subgraph tab: "
2117 std::replace(
uuid.begin(),
uuid.end(),
' ',
'_');
2119 std::cout <<
"[NodeGraphPanel] Created empty subgraph '" << name
2120 <<
"' with UUID: " <<
uuid <<
"\n";
2139 if (
tab &&
tab->tabID !=
"root")
UI-side registry of available atomic tasks with display metadata.
Node-graph clipboard: copy/paste selected nodes via ImGui system clipboard.
ComponentTypeID GetComponentTypeID_Static()
Editor mode and capabilities management.
Per-NodeType visual style registry (header colour, icon, pin colours).
std::vector< std::string > GetAllTaskIDs() const
Returns a vector of all registered task IDs.
static AtomicTaskRegistry & Get()
Returns the singleton instance.
static AtomicTaskUIRegistry & Get()
Returns the singleton instance.
const TaskSpec * GetTaskSpec(const std::string &id) const
Returns the TaskSpec for the given id, or nullptr if not found.
uint64_t GetSelectedEntity() const
Blueprint::CommandStack * GetCommandStack()
static BlueprintEditor & Get()
CommandStack - Manages undo/redo command history Maintains two stacks for undo and redo operations.
void ExecuteCommand(std::unique_ptr< EditorCommand > cmd)
void Init(std::function< void()> saveFn, float debounceSec=1.5f, float periodicIntervalSec=60.0f)
Set the timing parameters and an optional legacy save callback.
void Flush()
Block until any running async save finishes.
void ScheduleSave(double nowSec)
Notify the manager that a change occurred (legacy overload).
void Tick(double nowSec)
Must be called once per frame to advance timers and launch saves.
static EditorContext & Get()
static EntityInspectorManager & Get()
EntityInfo GetEntityInfo(EntityID entity) const
const CatalogType * FindActionType(const std::string &id) const
std::vector< std::string > GetDecoratorTypes() const
std::vector< std::string > GetActionTypes() const
static EnumCatalogManager & Get()
std::vector< std::string > GetConditionTypes() const
const CatalogType * FindConditionType(const std::string &id) const
InspectorPanel - Adaptive inspector panel Displays properties based on current selection context.
static InspectorPanel * GetInstance()
Get the active InspectorPanel instance (singleton access).
void PasteNodes(NodeGraph *graph, int graphID, float mousePosX, float mousePosY, bool snapToGrid=false, float snapGridSize=16.0f)
Read the system clipboard, deserialise nodes and create them in the active graph under the current mo...
static NodeGraphClipboard & Get()
Returns the singleton instance.
void CopySelectedNodes(NodeGraph *graph, int graphID)
Serialise currently selected nodes to JSON and write to the system clipboard.
int GetActiveGraphId() const
NodeGraph * GetActiveGraph()
bool CloseGraph(int graphId)
std::vector< int > GetAllGraphIds() const
void SetActiveGraph(int graphId)
NodeGraph * GetGraph(int graphId)
std::string GetGraphName(int graphId) const
int CreateGraph(const std::string &name, const std::string &type)
static NodeGraphManager & Get()
void RenderSubgraphTabBar()
Renders the subgraph-aware tab bar above the graph canvas.
const GraphTab * GetActiveTab() const
Returns the GraphTab for the currently active tab.
void CreateNewNode(const char *nodeType, float x, float y)
ImNodesEditorContext * m_imnodesContext
Dedicated imnodes rendering context for this panel instance.
void HandleKeyboardShortcuts()
char m_NewSubgraphNameBuffer[128]
Buffer used by the "New SubGraph" name input popup.
int m_lastActiveGraphId
Graph ID that was active last frame; used to detect graph switches so m_positionedNodes can be cleare...
void CloseSubgraphTab(int index)
Closes the tab at index.
void RenderNodeEditModal()
bool m_SnapToGrid
When true node positions are rounded to the nearest grid cell on move.
float m_SnapGridSize
Grid cell size in canvas units used when snap-to-grid is enabled.
std::vector< GraphTab > m_SubgraphTabs
Ordered list of open subgraph tabs. Index 0 is always the root graph.
void OpenSubgraphTab(const std::string &subgraphUUID, const std::string &displayName)
Opens (or focuses) the subgraph identified by subgraphUUID in a new tab.
void RenderActiveLinks(NodeGraph *graph, int graphID)
Overlay glow-coloured lines on links that connect to/from the active debug node, giving a visual "act...
static int s_ActiveDebugNodeId
Backing storage for SetActiveDebugNode: the local node ID currently executing (-1 = none).
char m_NodeNameBuffer[256]
bool m_SuppressGraphTabs
When true, RenderGraphTabs() is skipped (used by BehaviorTreeRenderer)
void RenderNodeProperties()
int m_ActiveSubgraphTabIndex
Index into m_SubgraphTabs of the currently visible tab.
bool m_ShowMinimap
When true the built-in ImNodes minimap is rendered in the bottom-right corner of the node editor canv...
std::unordered_set< int > m_positionedNodes
Tracks which global node UIDs have already had their ImNodes position initialised.
std::string GetActiveSubgraphUUID() const
Returns the subgraph UUID for the active tab, or empty string if the root graph is active.
void SyncNodePositionsFromImNodes(int graphID)
void RenderTypedPin(int attrId, const char *label, bool isInput, bool isExec, const std::unordered_set< int > &connectedAttrIDs={})
Render a single typed attribute pin using ImDrawList shapes.
int GlobalUIDToLocalNodeID(int globalUID, int graphID) const
std::unique_ptr< class ImNodesCanvasEditor > m_canvasEditor
Canvas editor adapter for minimap support (Phase 36) Abstracts imnodes minimap rendering through ICan...
char m_ContextMenuSearch[128]
void HandleNodeInteractions(int graphID)
EditorAutosaveManager m_autosave
Async autosave manager – persists node positions without blocking the UI.
void CreateEmptySubgraph(const std::string &name)
Creates an empty subgraph, inserts it into the active blueprint's data.subgraphs dict,...
void RenderNodePinsAndContent(GraphNode *node, int globalNodeUID, int graphID, const std::unordered_set< int > &connectedAttrIDs={})
Render a single node with a coloured title bar, icon, and typed pins.
void RenderConnectionIndices(NodeGraph *graph, int graphID)
Render execution indices (1, 2, 3, ...n) on connection lines for Sequence and Selector nodes based on...
static void SetActiveDebugNode(int localNodeId)
Set the local node ID that is currently executing.
nlohmann::json ToJson() const
std::vector< GraphNode * > GetAllNodes()
const NodeStyle & GetStyle(NodeType type) const
Returns the style for the given node type.
static NodeStyleRegistry & Get()
Returns the singleton instance.
constexpr uint32_t BT_ROOT_NODE_COLOR
Green color for Root node (entry point of behavior tree).
static uint32_t ToImU32_ABGR(uint32_t rgbaColor)
Helper function to extract ImU32 color (ImGui format).
< Provides AssetID and INVALID_ASSET_ID
@ BT_OnEvent
Phase 38b: Event-driven root (green, event-triggered)
@ BT_Root
Phase 38b: Root entry point (green, fixed position)
const char * NodeTypeToString(NodeType type)
TaskNodeType
Identifies the role of a node in the task graph.
@ AtomicTask
Leaf node that executes a single atomic task.
@ While
Conditional loop (Loop / Completed exec outputs)
@ SubGraph
Sub-graph call (SubTask)
@ DoOnce
Single-fire execution (reset via Reset pin)
@ Delay
Timer (Completed exec output after N seconds)
@ GetBBValue
Data node – reads a Blackboard key.
@ MathOp
Data node – arithmetic operation (+, -, *, /)
@ SetBBValue
Data node – writes a Blackboard key.
@ ForEach
Iterate over BB list (Loop Body / Completed exec outputs)
@ Switch
Multi-branch on value (N exec outputs)
@ EntryPoint
Unique entry node for VS graphs (replaces Root)
@ Branch
If/Else conditional (Then / Else exec outputs)
@ VSSequence
Execute N outputs in order ("VS" prefix avoids collision with BT Sequence=1)
ImVec2 ScreenSpaceToGridSpace(const ImVec2 &screenPos)
constexpr int LINK_ID_MULTIPLIER
constexpr int GRAPH_ID_MULTIPLIER
constexpr int ATTR_ID_MULTIPLIER
std::vector< CatalogParameter > parameters
std::string conditionType
std::string decoratorType
std::map< std::string, std::string > parameters
Represents one open tab in the NodeGraphPanel tab bar.
std::string displayName
Label shown on the tab ("Root" or subgraph name)
Visual descriptor for a single node type.
ImU32 headerColor
Title-bar background colour (ImNodes TitleBar colour slot).
ImU32 headerSelectedColor
Title-bar colour when the node is selected.
const char * icon
Short ASCII icon displayed before the node title (no emoji/extended chars).
ImU32 headerHoveredColor
Title-bar colour when the node is hovered.
Display metadata for a single atomic task type.
std::string displayName
Human-readable name (e.g. "Move To Goal")