9#include "../system/system_utils.h"
23 , graphKind(
"BehaviorTree")
56 [
id](
const NodeData&
n) { return n.id == id; });
136 SYSTEM_LOG <<
"[GraphDocument] Updated node ID="
139 <<
" pos=(" <<
newData.position.x
140 <<
"," <<
newData.position.y <<
")"
147 SYSTEM_LOG <<
"[GraphDocument] WARNING: UpdateNode failed - node ID="
148 << nodeId.
value <<
" not found" << std::endl;
160 link.fromPin = fromPin;
172 [
id](
const LinkData&
l) { return l.id == id; });
213 errorMessage =
"Graph has no nodes";
223 errorMessage =
"Root node not found";
231 errorMessage =
"Graph contains cycles";
238 if (
node.type ==
"BT_Selector" ||
node.type ==
"BT_Sequence")
240 if (
node.children.empty())
242 errorMessage =
"Composite node '" +
node.name +
"' has 0 children";
281 for (
const auto& childId :
node->children)
295 if (
node->decoratorChild.value != 0)
318 json j = json::object();
320 j[
"schemaVersion"] = 2;
345 json dataJson = json::object();
364 for (
const auto& childId :
node.children)
366 childrenJson.push_back(
static_cast<int>(childId.value));
372 for (
auto it =
node.parameters.begin();
it !=
node.parameters.end(); ++
it)
379 if (
node.decoratorChild.value != 0)
381 nodeJson[
"decoratorChildId"] =
static_cast<int>(
node.decoratorChild.value);
409 j[
"data"] = dataJson;
429 if (
j.contains(
"metadata") &&
j[
"metadata"].is_object())
431 doc.metadata =
j[
"metadata"];
435 if (
j.contains(
"editorState") &&
j[
"editorState"].is_object())
437 const json&
es =
j[
"editorState"];
441 if (
es.contains(
"scrollOffset") &&
es[
"scrollOffset"].is_object())
448 if (
es.contains(
"selectedNodes") &&
es[
"selectedNodes"].is_array())
457 doc.editorState.selectedNodes.push_back(nodeId);
464 if (
j.contains(
"data") &&
j[
"data"].is_object())
466 const json& data =
j[
"data"];
471 if (data.contains(
"nodes") && data[
"nodes"].is_array())
500 node.children.push_back(childId);
511 std::string
key =
it.key();
513 if (
it.value().is_string())
514 value =
it.value().get<std::string>();
515 else if (
it.value().is_number())
516 value = std::to_string(
it.value().get<
double>());
517 else if (
it.value().is_boolean())
518 value =
it.value().get<
bool>() ?
"true" :
"false";
530 if (
node.id.value >=
doc.m_nextNodeId)
532 doc.m_nextNodeId =
node.id.value + 1;
538 if (data.contains(
"links") && data[
"links"].is_array())
563 if (
link.id.value >=
doc.m_nextLinkId)
565 doc.m_nextLinkId =
link.id.value + 1;
572 if (
j.contains(
"annotations") &&
j[
"annotations"].is_array())
574 doc.m_nodeAnnotations.FromJson(
j[
"annotations"]);
578 if (
j.contains(
"blackboard") &&
j[
"blackboard"].is_array())
580 doc.m_blackboard.FromJson(
j[
"blackboard"]);
583 doc.m_isDirty =
false;
594 if (
config.direction == LayoutDirection::LeftToRight ||
595 config.direction == LayoutDirection::RightToLeft)
597 SYSTEM_LOG <<
"[GraphDocument] AutoLayout failed: LeftToRight and RightToLeft not yet implemented" << std::endl;
604 SYSTEM_LOG <<
"[GraphDocument] AutoLayout failed: No root node defined" << std::endl;
610 SYSTEM_LOG <<
"[GraphDocument] AutoLayout failed: Graph is empty" << std::endl;
618 SYSTEM_LOG <<
"[GraphDocument] AutoLayout failed: Root node not found" << std::endl;
625 std::map<NodeId, bool>
visited;
633 SYSTEM_LOG <<
"[GraphDocument] Auto-layout completed successfully" << std::endl;
643 std::map<NodeId, bool>&
visited)
649 SYSTEM_LOG <<
"[GraphDocument] AutoLayout: Cycle detected at node ID=" << nodeId.
value << std::endl;
664 if (
config.direction == LayoutDirection::TopToBottom)
677 for (
size_t i = 0;
i <
node->children.size(); ++
i)
694 if (
node->children.empty())
715 if (
node->decoratorChild.value != 0)
719 node->decoratorChild,
ComponentTypeID GetComponentTypeID_Static()
Document class for managing node graphs.
json ToJson() const
Serialize blackboard to JSON.
Main document class for a node graph.
bool UpdateNode(NodeId nodeId, const NodeData &newData)
Update an existing node's data.
bool DeleteNode(NodeId id)
Delete a node from the graph.
float AutoLayoutNode(NodeId nodeId, const AutoLayoutConfig &config, float startX, float startY, int depth, std::map< NodeId, bool > &visited)
Helper to recursively layout a node and its children.
bool AutoLayout(const AutoLayoutConfig &config)
Automatically layout nodes in a hierarchical arrangement.
bool UpdateNodeParameters(NodeId id, const std::map< std::string, std::string > ¶ms)
Update node parameters.
LinkId ConnectPins(PinId fromPin, PinId toPin)
Connect two pins with a link.
bool HasCyclesHelper(NodeId nodeId, std::vector< NodeId > &visited, std::vector< NodeId > &recursionStack) const
LinkData * GetLink(LinkId id)
Get a link by ID.
json ToJson() const
Convert graph to JSON format (v2 schema)
BlackboardSystem m_blackboard
bool DisconnectLink(LinkId id)
Disconnect a link.
std::vector< LinkData > m_links
static GraphDocument FromJson(const json &j)
Create graph from JSON.
NodeAnnotationsManager m_nodeAnnotations
NodeId CreateNode(const std::string &nodeType, Vector2 pos)
Create a new node in the graph.
NodeData * GetNode(NodeId id)
Get a node by ID.
bool UpdateNodePosition(NodeId id, Vector2 newPos)
Update node position.
bool HasCycles() const
Check if the graph has cycles.
bool ValidateGraph(std::string &errorMessage) const
Validate the graph structure.
std::vector< NodeData > m_nodes
json ToJson() const
Serialize all annotations to JSON.
std::string GetString(const json &j, const std::string &key, const std::string &defaultValue="")
Safely get a string value from JSON.
uint32_t GetUInt(const json &j, const std::string &key, uint32_t defaultValue=0)
Safely get an unsigned integer value from JSON.
float GetFloat(const json &j, const std::string &key, float defaultValue=0.0f)
Safely get a float value from JSON.
< Provides AssetID and INVALID_ASSET_ID
std::string layoutDirection
std::vector< NodeId > selectedNodes