20#include "../system/system_utils.h"
21#include "../system/system_consts.h"
22#include "../NodeGraphCore/GlobalTemplateBlackboard.h"
24#include "../third_party/imgui/imgui.h"
25#include "../third_party/imnodes/imnodes.h"
26#include "../json_helper.h"
27#include "../TaskSystem/TaskGraphLoader.h"
37#include <unordered_set>
60 ImNodes::SetNodeGridSpacePos(
75 ImNodes::SetNodeGridSpacePos(
84 ImNodes::BeginNodeEditor();
152 std::cerr <<
"[VSEditor] Initialized DataPins for GetBBValue (Variable) node #" <<
eNode.nodeID <<
"\n";
159 DataPinDefinition
pinA;
165 DataPinDefinition
pinB;
177 std::cerr <<
"[VSEditor] Initialized DataPins for MathOp node #" <<
eNode.nodeID <<
"\n";
183 DataPinDefinition
pinIn;
184 pinIn.PinName =
"Value";
188 std::cerr <<
"[VSEditor] Initialized DataPins for SetBBValue node #" <<
eNode.nodeID <<
"\n";
191 std::vector<std::pair<std::string, VariableType>>
dataIn,
dataOut;
192 for (
size_t p = 0;
p <
eNode.def.DataPins.size(); ++
p)
194 const DataPinDefinition&
pin =
eNode.def.DataPins[
p];
214 ImNodes::BeginNode(
eNode.nodeID);
230 [](
int nid,
void*
ud) {
231 VisualScriptEditorPanel* panel =
232 static_cast<VisualScriptEditorPanel*>(ud);
233 panel->m_pendingAddPin = true;
234 panel->m_pendingAddPinNodeID = nid;
238 VisualScriptEditorPanel* panel =
239 static_cast<VisualScriptEditorPanel*>(ud);
240 panel->m_pendingRemovePin = true;
241 panel->m_pendingRemovePinNodeID = nid;
242 panel->m_pendingRemovePinDynIdx = dynIdx;
250 ImNodes::PopColorStyle();
251 ImNodes::PopColorStyle();
252 ImNodes::PopColorStyle();
264 if (ImNodes::IsNodeSelected(
eNode.nodeID))
300 ImNodes::Link(
link.linkID,
link.srcAttrID,
link.dstAttrID);
301 ImNodes::PopColorStyle();
308 ImNodes::EndNodeEditor();
342 ImGui::OpenPopup(
"VSNodeContextMenu");
348 ImGui::OpenPopup(
"VSLinkContextMenu");
351 else if (ImNodes::IsEditorHovered())
361 ImGui::OpenPopup(
"VSNodePalette");
362 SYSTEM_LOG <<
"[VSEditor] Opened context menu on CANVAS at ("
373 float currentTime =
static_cast<float>(ImGui::GetTime());
406 if (ImGui::BeginDragDropTarget())
416 ImVec2 canvasPos = ImNodes::EditorContextGetPanning();
432 ImGui::EndDragDropTarget();
445 if (!std::isfinite(
safeX) || !std::isfinite(
safeY) ||
451 SYSTEM_LOG <<
"[VSEditor] Warning: pending node position was garbage; reset to (0, 0)\n";
463 std::cout <<
"[VisualScriptEditorPanel] Node created: ID=" <<
newNodeID
482 VSEditorNode*
eNode =
nullptr;
492 if (
eNode !=
nullptr)
502 <<
": opened modal for safe case editing (Phase 3 FIX)\n";
507 int pinIdx =
static_cast<int>(
eNode->def.DynamicExecOutputPins.size()) + 1;
508 std::string pinName =
"Out_" + std::to_string(
pinIdx);
511 eNode->def.DynamicExecOutputPins.push_back(pinName);
515 std::unique_ptr<ICommand>(
522 <<
" added pin '" << pinName <<
"'\n";
540 VSEditorNode*
eNode =
nullptr;
550 if (
eNode !=
nullptr)
560 <<
": opened modal for safe case removal (Phase 3 FIX)\n";
567 const std::string pinName =
577 ec.SourcePinName == pinName)
586 eNode->def.DynamicExecOutputPins.erase(
591 std::unique_ptr<ICommand>(
602 <<
" removed pin '" << pinName <<
"'\n";
660 const int nodeID =
entry.first;
687 std::unique_ptr<ICommand>(
688 new MoveNodeCommand(nodeID,
718 return n.nodeID == hoveredNode;
723 if (
tip &&
tip[0] !=
'\0')
725 ImGui::BeginTooltip();
726 ImGui::TextUnformatted(
tip);
780 return n.nodeID == dstNodeID;
785 !
dstIt->def.dynamicPins.empty())
813 return n.nodeID == srcNodeID;
845 return n.nodeID == srcNodeID;
849 return n.nodeID == dstNodeID;
863 for (
size_t p = 0;
p <
srcIt->def.DataPins.size(); ++
p)
887 if (!
dstIt->def.dynamicPins.empty())
890 std::cerr <<
"[VSEditor] Data-in pin index corrected to 0 (first available)\n";
901 std::cerr <<
"[VSEditor] Cannot find valid data-in pin on Branch node\n";
916 for (
size_t p = 0;
p <
dstIt->def.DataPins.size(); ++
p)
933 std::cout <<
"[VisualScriptEditorPanel] Created data link: node"
940 std::cerr <<
"[VisualScriptEditorPanel] Cannot create link"
941 " — incompatible pin types (exec/data mismatch)\n";
946 std::cerr <<
"[VisualScriptEditorPanel] Cannot create link"
947 " — incompatible pin types (both inputs or both outputs)\n";
966 if (ImNodes::NumSelectedNodes() == 1)
969 ImNodes::GetSelectedNodes(
selNodes);
972 else if (ImNodes::NumSelectedNodes() == 0)
994 <<
" nodes" << std::endl;
998 ImNodes::GetSelectedNodes(selectedNodes.data());
1000 for (
int nodeID : selectedNodes)
1005 std::cout <<
"[VSEditor] Deleted node " << nodeID << std::endl;
1020 std::cout <<
"[VSEditor] Deleted link " << linkID << std::endl;
1037 if (!ImGui::BeginPopup(
"VSNodePalette"))
1040 ImGui::TextDisabled(
"Add Node");
1044 if (ImGui::BeginMenu(
"Flow Control"))
1047 if (ImGui::MenuItem(label))
1050 ImGui::CloseCurrentPopup();
1063 if (ImGui::BeginMenu(
"Actions"))
1065 if (ImGui::MenuItem(
"AtomicTask"))
1068 ImGui::CloseCurrentPopup();
1073 if (ImGui::BeginMenu(
"Data"))
1075 if (ImGui::MenuItem(
"GetBBValue"))
1078 ImGui::CloseCurrentPopup();
1080 if (ImGui::MenuItem(
"SetBBValue"))
1083 ImGui::CloseCurrentPopup();
1085 if (ImGui::MenuItem(
"MathOp"))
1088 ImGui::CloseCurrentPopup();
1093 if (ImGui::BeginMenu(
"SubGraph"))
1095 if (ImGui::MenuItem(
"SubGraph"))
1098 ImGui::CloseCurrentPopup();
1115 if (ImGui::BeginPopup(
"VSNodeContextMenu"))
1117 if (ImGui::MenuItem(
"Edit Properties"))
1121 <<
" for editing\n";
1126 if (ImGui::MenuItem(
"Delete Node"))
1133 <<
" via context menu\n";
1140 if (ImGui::MenuItem(
hasBP ?
"Remove Breakpoint (F9)" :
"Add Breakpoint (F9)"))
1145 SYSTEM_LOG <<
"[VSEditor] Toggled breakpoint on node #"
1147 << (
hasBP ?
"OFF" :
"ON") <<
"\n";
1153 if (ImGui::MenuItem(
"Duplicate"))
1156 [
this](
const VSEditorNode&
n) { return n.nodeID == m_contextNodeID; });
1159 TaskNodeDefinition
newDef =
it->def;
1161 newDef.NodeName +=
" (Copy)";
1162 newDef.EditorPosX =
it->posX + 50.0f;
1163 newDef.EditorPosY =
it->posY + 50.0f;
1164 newDef.HasEditorPos =
true;
1174 std::unique_ptr<ICommand>(
new AddNodeCommand(
newDef)),
1178 <<
" duplicated as #" <<
newDef.NodeID <<
"\n";
1188 if (ImGui::BeginPopup(
"VSLinkContextMenu"))
1190 if (ImGui::MenuItem(
"Delete Connection"))
1195 <<
" via context menu\n";
UI-side registry of available atomic tasks with display metadata.
Wrapper around the graph blackboard entries for dropdown editors.
Registry of available condition types for Branch/While node dropdowns.
Runtime debug controller for ATS Visual Scripting (Phase 5).
ComponentTypeID GetComponentTypeID_Static()
Defines MathOpOperand — operand references for MathOp nodes.
Hardcoded lists of math and comparison operators for dropdown editors.
Central manager for the multi-graph tab system.
ImNodes-based graph editor for ATS Visual Script graphs (Phase 5).
int GetCurrentNodeID() const
Returns the node being executed (-1 if none).
void ToggleBreakpoint(int graphID, int nodeID, const std::string &graphName="", const std::string &nodeName="")
Toggles the breakpoint at (graphID, nodeID).
static DebugController & Get()
Returns the singleton instance (Meyers pattern).
bool IsDebugging() const
Returns true when a debug session is active.
bool HasBreakpoint(int graphID, int nodeID) const
Returns true if an enabled breakpoint exists at (graphID, nodeID).
void RenderCompleteSelection(const ImVec2 &minScreen, const ImVec2 &maxScreen, ImU32 borderColor, float baseWidth, float canvasZoom=1.0f, float nodeScale=1.0f, float cornerRadius=5.0f) const
Rend l'ensemble de l'effet de sélection (glow + bordure)
std::vector< ExecPinConnection > ExecConnections
Explicit exec connections (ATS VS only)
std::string Name
Friendly name of this template (e.g. "PatrolBehaviour")
void PushCommand(std::unique_ptr< ICommand > cmd, TaskGraphTemplate &graph)
Executes the command on graph, then pushes it onto the undo stack.
static bool IsExecConnectionValid(const TaskGraphTemplate &graph, int srcNodeID, const std::string &srcPinName, int dstNodeID)
Returns true if adding an exec connection from srcNodeID/srcPinName to dstNodeID would be valid (no s...
UndoRedoStack m_undoStack
Undo/Redo command stack for reversible graph editing operations.
float m_contextMenuX
Right-click paste position.
void OnNodeDoubleClicked(int nodeID)
Handles double-click on a node (opens SubGraph, etc).
bool m_pendingRemovePin
Pending dynamic pin removal (from [-] button clicked in canvas)
std::vector< VSEditorLink > m_editorLinks
Editor links (exec + data)
TaskGraphTemplate m_template
The template currently being edited.
int m_lastClickNodeID
Node ID of the last left-click (for double-click detection)
void RemoveNode(int nodeID)
Removes a node from the canvas.
std::unique_ptr< SwitchCaseEditorModal > m_switchCaseModal
Phase 26 — Switch Case Editor Modal.
void RemoveLink(int linkID)
Removes an ImNodes link (and its underlying template connection) by link ID.
bool m_skipPositionSyncNextFrame
Set to true by Undo/Redo; causes next frame to skip SyncNodePositionsFromImNodes() so that the positi...
void ConnectData(int srcNodeID, const std::string &srcPinName, int dstNodeID, const std::string &dstPinName)
Creates a data connection between two nodes.
static std::vector< std::string > GetExecInputPins(TaskNodeType type)
Returns the exec-in pin names for a node type.
static constexpr float DOUBLE_CLICK_THRESHOLD
Threshold for detecting double-click (300ms)
std::unique_ptr< NodeBranchRenderer > m_branchRenderer
Specialized renderer for Branch nodes (4-section layout with conditions).
int m_contextLinkID
Link ID captured at the moment a right-click context menu was opened on a link.
void ConnectExec(int srcNodeID, const std::string &srcPinName, int dstNodeID, const std::string &dstPinName)
Creates an exec connection between two nodes.
int m_pendingRemovePinNodeID
void RenderValidationOverlay()
TaskNodeType m_pendingNodeType
static std::vector< std::string > GetDataOutputPins(TaskNodeType type)
Returns the data-out pin names for a node type.
int m_pendingAddPinNodeID
bool m_pendingNodeDrop
True when a node drop is pending processing this frame.
void RenderContextMenus()
Render node/link context menus opened by right-click detection.
int AddNode(TaskNodeType type, float x, float y)
Creates a new node on the canvas.
VSVerificationResult m_verificationResult
Latest verification result (produced by RunVerification())
int m_pendingRemovePinDynIdx
0-based index in DynamicExecOutputPins
static std::vector< std::string > GetDataInputPins(TaskNodeType type)
Returns the data-in pin names for a node type.
std::unordered_set< int > m_positionedNodes
Nodes for which ImNodes has been given a position.
SelectionEffectRenderer m_selectionRenderer
Renders glow effect for selected nodes (cyan halo + thickened border).
std::unique_ptr< ImNodesCanvasEditor > m_canvasEditor
Canvas editor adapter for minimap support (Phase 37) Abstracts imnodes minimap rendering through ICan...
void RebuildLinks()
Rebuilds ImNodes exec/data link arrays from the template.
int m_focusNodeID
Node ID to focus/scroll to on next RenderCanvas() frame (-1 = none)
void SyncNodePositionsFromImNodes()
Pulls the current node positions from ImNodes into m_editorNodes.
int m_contextNodeID
Node ID captured at the moment a right-click context menu was opened on a node.
bool m_justPerformedUndoRedo
Set to true immediately after Undo/Redo; blocks node movement tracking for 1 frame to allow ImNodes t...
ImNodesEditorContext * m_imnodesContext
std::unordered_map< int, std::pair< float, float > > m_nodeDragStartPositions
Per-node drag-start positions used to record a single MoveNodeCommand per drag gesture instead of one...
int AllocNodeID()
Allocate a unique node ID.
float m_lastClickTime
Frame time of the last left-click (seconds, from ImGui::GetTime())
std::vector< std::string > GetExecOutputPinsForNode(const TaskNodeDefinition &def) const
Returns exec-out pin names for a node definition, including any dynamically-added pins (VSSequence).
bool m_verificationDone
True once RunVerification() has been called at least once for the current graph.
bool m_pendingAddPin
Pending dynamic pin addition (from [+] button clicked in canvas)
std::vector< VSEditorNode > m_editorNodes
Editor nodes (mirrors m_template.Nodes + position/selection state)
int m_selectedNodeID
Currently selected node (for properties panel)
static void RenderNode(int nodeUID, int nodeID, int graphID, const std::string &nodeName, TaskNodeType type, bool hasBreakpoint, bool isActive, const std::vector< std::string > &execInputPins, const std::vector< std::string > &execOutputPins, const std::vector< std::pair< std::string, VariableType > > &dataInputPins, const std::vector< std::pair< std::string, VariableType > > &dataOutputPins, const std::unordered_set< int > &connectedAttrIDs={})
Renders a complete VS node (title + exec pins + data pins).
static void RenderBreakpointIndicator(int nodeUID)
Renders a breakpoint indicator (red circle) next to a node.
static void RenderActiveNodeGlow(int nodeUID)
Renders a "currently executing" glow overlay around a node.
constexpr uint32_t EXEC_CONNECTION_COLOR
Alternative white color for exec connections (Bezier curves).
constexpr uint32_t DATA_CONNECTION_COLOR
Alternative violet color for data connections (Bezier curves).
< Provides AssetID and INVALID_ASSET_ID
const char * GetNodeTypeLabel(TaskNodeType type)
Returns a human-readable label for a TaskNodeType.
@ Float
Single-precision float.
VSNodeStyle
Visual style category for a VS node.
VSNodeStyle GetNodeStyle(TaskNodeType type)
Returns the VSNodeStyle appropriate for a given node 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)
@ Output
Value produced by the node.
@ Input
Value consumed by the node.
unsigned int GetNodeTitleColor(VSNodeStyle style)
Returns the title-bar RGBA colour for a given style.
std::vector< VSVerificationIssue > issues