Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
Renderer.h
Go to the documentation of this file.
1#pragma once
2
3#include "NodeGraphShared.h"
4#include "../AI/BehaviorTree.h"
5#include "../BlueprintEditor/NodeStyleRegistry.h"
6#include <unordered_set>
7#include <algorithm>
8#include <iostream>
9#include <string>
10
11namespace Olympe
12{
13 namespace NodeGraphShared
14 {
16 {
17 switch (t)
18 {
27 default: return NodeType::BT_Action;
28 }
29 }
30
31 // Map from BT Registry node type name to NodeType (for new node types)
33 {
34 // Composites
35 if (registryName == "BT_Selector") return NodeType::BT_Selector;
36 if (registryName == "BT_Sequence") return NodeType::BT_Sequence;
37 if (registryName == "BT_Parallel") return NodeType::BT_Parallel;
38 if (registryName == "BT_RandomSelector") return NodeType::BT_RandomSelector;
39 if (registryName == "BT_ParallelThreshold") return NodeType::BT_ParallelThreshold;
40
41 // Conditions
42 if (registryName.find("Condition") != std::string::npos ||
43 registryName.find("Check") != std::string::npos ||
44 registryName.find("Has") != std::string::npos ||
45 registryName.find("Is") != std::string::npos ||
46 registryName.find("Can") != std::string::npos)
48
49 // Decorators
50 if (registryName == "BT_Inverter") return NodeType::BT_Inverter;
51 if (registryName == "BT_Monitor") return NodeType::BT_Monitor;
52 if (registryName == "BT_Repeater") return NodeType::BT_Repeater;
53 if (registryName == "BT_UntilSuccess") return NodeType::BT_UntilSuccess;
54 if (registryName == "BT_UntilFailure") return NodeType::BT_UntilFailure;
55 if (registryName == "BT_Cooldown") return NodeType::BT_Cooldown;
56
57 // Entry Points
58 if (registryName == "BT_Root") return NodeType::BT_Root;
59 if (registryName == "BT_OnEvent") return NodeType::BT_OnEvent;
60
61 // Utilities
62 if (registryName == "BT_SendMessage") return NodeType::BT_SendMessage;
63 if (registryName == "BT_SubGraph") return NodeType::BT_SubGraph;
64
65 // Default to Action
67 }
68
69 inline void RenderNodeVisual(int nodeId, const std::string& title, NodeType editorType,
70 float posX, float posY, float width, float height,
71 bool isCurrentNode, float currentZoom, float pulseTimer,
72 float pinRadius, float pinOutline, float pinHeaderHeight,
73 std::unordered_set<uint32_t>& positionedNodes)
74 {
75 if (positionedNodes.find(nodeId) == positionedNodes.end())
76 {
77 ImNodes::SetNodeGridSpacePos(nodeId, ImVec2(posX, posY));
78 positionedNodes.insert(nodeId);
79 }
80
82
83 ImNodes::BeginNode(nodeId);
84 ImNodes::BeginNodeTitleBar();
86 ImNodes::EndNodeTitleBar();
87
88 ImNodes::PushColorStyle(ImNodesCol_Pin, IM_COL32(0,0,0,0));
89 ImNodes::PushColorStyle(ImNodesCol_PinHovered, IM_COL32(0,0,0,0));
90 ImNodes::BeginInputAttribute(nodeId * 10000);
91 ImGui::TextUnformatted("In");
92 ImNodes::EndInputAttribute();
93 ImNodes::PopColorStyle(); ImNodes::PopColorStyle();
94
95 ImGui::TextDisabled(" ");
96 ImGui::Text("Type: %s", NodeTypeToString(editorType));
97 ImGui::Text("ID: %d", nodeId);
98
99 ImNodes::PushColorStyle(ImNodesCol_Pin, IM_COL32(0,0,0,0));
100 ImNodes::PushColorStyle(ImNodesCol_PinHovered, IM_COL32(0,0,0,0));
101 ImNodes::BeginOutputAttribute(nodeId * 10000 + 1);
102 ImGui::TextUnformatted("Out");
103 ImNodes::EndOutputAttribute();
104 ImNodes::PopColorStyle(); ImNodes::PopColorStyle();
105
106 if (isCurrentNode)
107 {
108 ImU32 highlightColor = IM_COL32(255, 200, 50, 180);
109 ImNodes::PushColorStyle(ImNodesCol_NodeOutline, highlightColor);
110 }
111
112 ImNodes::EndNode();
113
114 if (isCurrentNode)
115 ImNodes::PopColorStyle();
116
117 ImDrawList* drawList = ImGui::GetWindowDrawList();
118 if (drawList)
119 {
120 ImVec2 inputCenter = ComputePinCenterScreen(nodeId, nullptr, false, ImNodes::GetStyle().PinOffset, pinHeaderHeight, currentZoom);
121 ImVec2 outputCenter = ComputePinCenterScreen(nodeId, nullptr, true, ImNodes::GetStyle().PinOffset, pinHeaderHeight, currentZoom);
122 ImU32 fill = IM_COL32(66,133,244,255);
123 ImU32 outline = IM_COL32(40,40,40,255);
126 }
127 }
128
129 inline void RenderBTNode(const BTNode* node, const BTNodeLayout* layout, bool isCurrentNode,
130 float currentZoom, float pulseTimer, const BTConfig& config,
131 std::unordered_set<uint32_t>& positionedNodes)
132 {
133 if (!node || !layout) return;
134 RenderNodeVisual(static_cast<int>(node->id), node->name, MapBTToEditor(node->type),
135 layout->position.x, layout->position.y, layout->width, layout->height,
137 static_cast<float>(config.pinRadius), static_cast<float>(config.pinOutlineThickness), static_cast<float>(config.pinHeaderHeight),
139 }
140
142 {
143 if (!tree) return;
144 ImDrawList* drawList = ImGui::GetWindowDrawList();
145 if (!drawList) return;
146
147 for (const auto& node : tree->nodes)
148 {
149 if (node.type == BTNodeType::Selector || node.type == BTNodeType::Sequence)
150 {
151 for (uint32_t childId : node.childIds)
152 {
153 ImVec2 pPos = ImNodes::GetNodeScreenSpacePos(static_cast<int>(node.id));
154 ImVec2 pDim = ImNodes::GetNodeDimensions(static_cast<int>(node.id));
155 ImVec2 cPos = ImNodes::GetNodeScreenSpacePos(static_cast<int>(childId));
156 ImVec2 cDim = ImNodes::GetNodeDimensions(static_cast<int>(childId));
157
158 const float po = ImNodes::GetStyle().PinOffset;
159 ImVec2 p1(pPos.x + pDim.x - po, pPos.y + pDim.y * 0.5f);
160 ImVec2 p4(cPos.x + po, cPos.y + cDim.y * 0.5f);
161
162 float curve = std::max(50.0f, std::abs(p4.x - p1.x) * 0.4f);
163 ImVec2 p2(p1.x + curve, p1.y);
164 ImVec2 p3(p4.x - curve, p4.y);
165
166 ImU32 col = IM_COL32(100, 160, 240, 255);
167 drawList->AddBezierCubic(p1, p2, p3, p4, col, 3.0f);
168 }
169 }
170 else if ((node.type == BTNodeType::Inverter || node.type == BTNodeType::Repeater) && node.decoratorChildId != 0)
171 {
172 ImVec2 pPos = ImNodes::GetNodeScreenSpacePos(static_cast<int>(node.id));
173 ImVec2 pDim = ImNodes::GetNodeDimensions(static_cast<int>(node.id));
174 ImVec2 cPos = ImNodes::GetNodeScreenSpacePos(static_cast<int>(node.decoratorChildId));
175 ImVec2 cDim = ImNodes::GetNodeDimensions(static_cast<int>(node.decoratorChildId));
176
177 const float po = ImNodes::GetStyle().PinOffset;
178 ImVec2 p1(pPos.x + pDim.x - po, pPos.y + pDim.y * 0.5f);
179 ImVec2 p4(cPos.x + po, cPos.y + cDim.y * 0.5f);
180
181 float curve = std::max(50.0f, std::abs(p4.x - p1.x) * 0.4f);
182 ImVec2 p2(p1.x + curve, p1.y);
183 ImVec2 p3(p4.x - curve, p4.y);
184
185 ImU32 col = IM_COL32(100, 160, 240, 255);
186 drawList->AddBezierCubic(p1, p2, p3, p4, col, 3.0f);
187 }
188 }
189 }
190
191 }
192}
BTNodeType
Behavior tree node types.
@ Action
Leaf node - performs an action.
@ Selector
OR node - succeeds if any child succeeds.
@ OnEvent
Phase 38b: OnEvent root - event-driven entry point (orange, event-triggered)
@ Sequence
AND node - succeeds if all children succeed.
@ Inverter
Decorator - inverts child result.
@ Condition
Leaf node - checks a condition.
@ Repeater
Decorator - repeats child N times.
@ Root
Phase 38b: Root node - entry point of behavior tree (green, fixed position)
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
const NodeStyle & GetStyle(NodeType type) const
Returns the style for the given node type.
static NodeStyleRegistry & Get()
Returns the singleton instance.
void DrawPinCircle(ImDrawList *drawList, const ImVec2 &center, float radius, ImU32 fillColor, ImU32 outlineColor, float outlineThickness)
void RenderBTNodeConnections(const BehaviorTreeAsset *tree, uint32_t activeNodeId)
Definition Renderer.h:141
void RenderNodeHeader(int nodeId, const NodeStyle &style, const char *icon, const std::string &title, bool isCurrentNode, float pulseTimer)
void RenderBTNode(const BTNode *node, const BTNodeLayout *layout, bool isCurrentNode, float currentZoom, float pulseTimer, const BTConfig &config, std::unordered_set< uint32_t > &positionedNodes)
Definition Renderer.h:129
ImVec2 ComputePinCenterScreen(int nodeId, const BTNodeLayout *layout, bool isOutput, float pinOffset, float headerPx, float currentZoom)
Compute the screen-space center position of a pin.
void RenderNodeVisual(int nodeId, const std::string &title, NodeType editorType, float posX, float posY, float width, float height, bool isCurrentNode, float currentZoom, float pulseTimer, float pinRadius, float pinOutline, float pinHeaderHeight, std::unordered_set< uint32_t > &positionedNodes)
Definition Renderer.h:69
static NodeType MapBTToEditor(BTNodeType t)
NodeType MapBTRegistryNameToEditor(const std::string &registryName)
Definition Renderer.h:32
< Provides AssetID and INVALID_ASSET_ID
@ BT_OnEvent
Phase 38b: Event-driven root (green, event-triggered)
@ BT_SubGraph
Phase 8: references a subgraph by UUID (BehaviorTree)
@ BT_Root
Phase 38b: Root entry point (green, fixed position)
const char * NodeTypeToString(NodeType type)
Represents a single node in a behavior tree.
Layout information for a single behavior tree node.
Visual descriptor for a single node type.
const char * icon
Short ASCII icon displayed before the node title (no emoji/extended chars).