Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
BTNodePalette.cpp
Go to the documentation of this file.
1/**
2 * @file BTNodePalette.cpp
3 * @brief Implementation of BTNodePalette
4 * @author Olympe Engine
5 * @date 2026-02-18
6 *
7 * @details
8 * Unified Color Architecture: Uses centralized NodeStyleRegistry as single source of truth
9 * for all node colors across canvas and palette. All specific BT types (BT_CanSetTarget,
10 * BT_CheckBlackboardValue, etc.) map to generic NodeType categories (BT_Condition, BT_Action)
11 * via StringToNodeType(), ensuring 100% color consistency.
12 */
13
14#include "BTNodePalette.h"
15#include "BTNodeRegistry.h"
16#include "../../BlueprintEditor/NodeStyleRegistry.h"
17#include "../../BlueprintEditor/BTNodeGraphManager.h"
18#include "../../third_party/imgui/imgui.h"
19#include <cstring>
20
21namespace Olympe {
22namespace AI {
23
25 : m_isDragging(false)
26{
27 std::memset(m_searchFilter, 0, sizeof(m_searchFilter));
28}
29
31 // Render palette content directly (don't wrap in BeginChild - already in a tab)
32 // Renders search filter and categorized node buttons for drag-drop
33
34 // Search filter
35 ImGui::InputText("Search##BTSearch", m_searchFilter, sizeof(m_searchFilter));
36 ImGui::Separator();
37
38 // Render by category using CollapsingHeaders
43 }
44
45void BTNodePalette::RenderCategory(const std::string& categoryName, BTNodeCategory category) {
46 if (ImGui::CollapsingHeader(categoryName.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
48 auto nodeTypes = registry.GetNodeTypesByCategory(category);
49
50 for (auto typeIt = nodeTypes.begin(); typeIt != nodeTypes.end(); ++typeIt) {
51 const std::string& typeName = *typeIt;
52
53 // Apply search filter
54 if (m_searchFilter[0] != '\0') {
55 const BTNodeTypeInfo* typeInfo = registry.GetNodeTypeInfo(typeName);
56 if (typeInfo != nullptr) {
57 // Check if search term is in display name
59 std::string searchLower = m_searchFilter;
60
61 // Simple case-insensitive search (ASCII only)
62 for (size_t i = 0; i < displayNameLower.length(); ++i) {
63 if (displayNameLower[i] >= 'A' && displayNameLower[i] <= 'Z') {
64 displayNameLower[i] = displayNameLower[i] + ('a' - 'A');
65 }
66 }
67 for (size_t i = 0; i < searchLower.length(); ++i) {
68 if (searchLower[i] >= 'A' && searchLower[i] <= 'Z') {
69 searchLower[i] = searchLower[i] + ('a' - 'A');
70 }
71 }
72
73 if (displayNameLower.find(searchLower) == std::string::npos) {
74 continue; // Skip this node
75 }
76 }
77 }
78
79 RenderNodeButton(typeName);
80 }
81 }
82}
83
84void BTNodePalette::RenderNodeButton(const std::string& typeName) {
86 const BTNodeTypeInfo* typeInfo = registry.GetNodeTypeInfo(typeName);
87
88 if (typeInfo == nullptr) {
89 return;
90 }
91
92 ImGui::PushID(typeName.c_str());
93
94 // ====== UNIFIED COLOR SYSTEM (SINGLE SOURCE OF TRUTH) ======
95 // Convert specific BT registry type name to generic NodeType category
96 // This ensures all Conditions display PURPLE, all Actions ORANGE, etc.
97 NodeType nodeType = StringToNodeType(typeName);
98
99 // Get style from CENTRALIZED NodeStyleRegistry (used by BOTH canvas and palette)
101
102 // Convert style color from ImU32 to ImVec4
103 float r = static_cast<float>((style.headerColor >> 0) & 0xFF) / 255.0f;
104 float g = static_cast<float>((style.headerColor >> 8) & 0xFF) / 255.0f;
105 float b = static_cast<float>((style.headerColor >> 16) & 0xFF) / 255.0f;
106 float a = static_cast<float>((style.headerColor >> 24) & 0xFF) / 255.0f;
107
108 ImVec4 buttonColor(r, g, b, a);
109 ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
110
111 // Create button label with icon and display name
112 std::string label = typeInfo->icon + " " + typeInfo->displayName;
113
114 if (ImGui::Button(label.c_str(), ImVec2(-1.0f, 0.0f))) {
115 // Button clicked but not necessarily dragging yet
116 m_draggedNodeType = typeName;
117 m_isDragging = true;
118 }
119
120 // Drag-drop source setup (modified from EntityPrefab pattern)
121 if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
122 {
123 // Store node type name in payload
124 m_draggedNodeType = typeName;
125 ImGui::SetDragDropPayload("BT_NODE_TYPE", typeName.c_str(), typeName.length() + 1);
126
127 // Show preview during drag
128 ImGui::Text("Creating: %s", typeInfo->displayName.c_str());
129
130 ImGui::EndDragDropSource();
131 }
132
133 // Tooltip on hover
134 if (ImGui::IsItemHovered()) {
135 ImGui::BeginTooltip();
136 ImGui::Text("%s", typeInfo->description.c_str());
137
138 // Show parameters if any
139 if (!typeInfo->parameterNames.empty()) {
140 ImGui::Separator();
141 ImGui::Text("Parameters:");
142 for (auto paramIt = typeInfo->parameterNames.begin();
143 paramIt != typeInfo->parameterNames.end();
144 ++paramIt) {
145 ImGui::BulletText("%s", paramIt->c_str());
146 }
147 }
148
149 // Show child constraints
150 if (typeInfo->minChildren >= 0 || typeInfo->maxChildren >= 0) {
151 ImGui::Separator();
152 if (typeInfo->minChildren >= 0 && typeInfo->maxChildren >= 0) {
153 if (typeInfo->minChildren == typeInfo->maxChildren) {
154 ImGui::Text("Children: exactly %d", typeInfo->minChildren);
155 } else {
156 ImGui::Text("Children: %d to %d", typeInfo->minChildren, typeInfo->maxChildren);
157 }
158 } else if (typeInfo->minChildren >= 0) {
159 ImGui::Text("Children: at least %d", typeInfo->minChildren);
160 } else {
161 ImGui::Text("Children: at most %d", typeInfo->maxChildren);
162 }
163 }
164
165 ImGui::EndTooltip();
166 }
167
168 ImGui::PopStyleColor();
169 ImGui::PopID();
170 }
171
172} // namespace AI
173} // namespace Olympe
ImGui palette for dragging BT nodes.
Registry of all Behavior Tree node types for AIGraphPlugin_BT.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
void RenderCategory(const std::string &categoryName, BTNodeCategory category)
Render a category section.
void RenderNodeButton(const std::string &typeName)
Render a single node button.
void Render(bool *isOpen)
Render the palette window.
static BTNodeRegistry & Get()
Get singleton instance.
const NodeStyle & GetStyle(NodeType type) const
Returns the style for the given node type.
static NodeStyleRegistry & Get()
Returns the singleton instance.
BTNodeCategory
Categories of behavior tree nodes.
@ Action
Leaf execution nodes (Wait, Move, Attack, etc.)
@ Composite
Flow control nodes (Selector, Sequence, Parallel)
@ Decorator
Modifiers (Inverter, Repeater, Cooldown, etc.)
@ Condition
Boolean checks (HasTarget, InRange, etc.)
< Provides AssetID and INVALID_ASSET_ID
NodeType StringToNodeType(const std::string &str)
Metadata for a behavior tree node type.
std::string displayName
Human-readable name (e.g., "Selector")
Visual descriptor for a single node type.
ImU32 headerColor
Title-bar background colour (ImNodes TitleBar colour slot).