Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
NodeSearchPanel.h
Go to the documentation of this file.
1/**
2 * @file NodeSearchPanel.h
3 * @brief Quick node-add search panel with fuzzy matching (Phase 9).
4 * @author Olympe Engine
5 * @date 2026-03-09
6 *
7 * @details
8 * NodeSearchPanel provides a floating search panel that the user can open
9 * with the Space key. It performs fuzzy scoring against a catalogue of
10 * available node types and reports the user's choice via a callback.
11 *
12 * The implementation has no ImGui dependency — it is a pure data layer.
13 * UI code calls OpenSearch(), UpdateQuery(), and reads GetResults().
14 * When the user accepts a result, it calls ConfirmSelection() which
15 * fires the OnNodeAdd callback.
16 *
17 * C++14 compliant — no std::optional, structured bindings, std::filesystem.
18 */
19
20#pragma once
21
22#include <functional>
23#include <string>
24#include <vector>
25
26namespace Olympe {
27
28// ============================================================================
29// Supporting types
30// ============================================================================
31
32/**
33 * @struct NodeSearchResult
34 * @brief A single search result entry from the panel.
35 */
36struct NodeSearchResult {
37 std::string name; ///< Display name of the node type
38 std::string category; ///< Category label (e.g. "ControlFlow")
39 std::string description; ///< Short human-readable description
40 std::string nodeType; ///< Internal type key (e.g. "Sequence")
41 float relevanceScore; ///< Higher = better match
42};
43
44// ============================================================================
45// NodeSearchPanel
46// ============================================================================
47
48/**
49 * @class NodeSearchPanel
50 * @brief Singleton fuzzy-search panel for adding nodes to the graph.
51 *
52 * Typical usage:
53 * @code
54 * auto& sp = NodeSearchPanel::Get();
55 * sp.SetNodeAddCallback([](const std::string& type, float x, float y) {
56 * graph.AddNode(type, x, y);
57 * });
58 *
59 * // On Space key:
60 * sp.OpenSearch(mouseX, mouseY);
61 *
62 * // Each frame the panel is open:
63 * sp.UpdateQuery(currentSearchText);
64 * for (const auto& r : sp.GetResults())
65 * // ... render result ...
66 *
67 * // On Enter / double-click:
68 * sp.ConfirmSelection(selectedIndex);
69 * @endcode
70 */
72public:
73
74 // -----------------------------------------------------------------------
75 // Singleton access
76 // -----------------------------------------------------------------------
77
78 /** @brief Returns the single shared instance. */
79 static NodeSearchPanel& Get();
80
81 // -----------------------------------------------------------------------
82 // Open / close
83 // -----------------------------------------------------------------------
84
85 /**
86 * @brief Opens the search panel at the given graph-space position.
87 * @param posX Spawn X for the new node (graph space).
88 * @param posY Spawn Y for the new node (graph space).
89 */
90 void OpenSearch(float posX, float posY);
91
92 /** @brief Closes the search panel and clears the query. */
93 void CloseSearch();
94
95 /** @brief Returns true if the panel is currently visible. */
96 bool IsOpen() const;
97
98 // -----------------------------------------------------------------------
99 // Search
100 // -----------------------------------------------------------------------
101
102 /**
103 * @brief Recomputes the result list for the given query string.
104 * Call this every frame (or whenever the query changes).
105 */
106 void UpdateQuery(const std::string& query);
107
108 /**
109 * @brief Returns the current result list sorted by relevance (best first).
110 */
111 const std::vector<NodeSearchResult>& GetResults() const;
112
113 // -----------------------------------------------------------------------
114 // Selection
115 // -----------------------------------------------------------------------
116
117 /**
118 * @brief Fires the OnNodeAdd callback for the result at @p index and
119 * closes the panel. No-op if @p index is out of range.
120 */
121 void ConfirmSelection(int index);
122
123 /**
124 * @brief Returns the index of the currently highlighted result (-1 = none).
125 */
126 int GetSelectedIndex() const;
127
128 /**
129 * @brief Moves the selection up by one step (wraps around).
130 */
131 void SelectPrevious();
132
133 /**
134 * @brief Moves the selection down by one step (wraps around).
135 */
136 void SelectNext();
137
138 // -----------------------------------------------------------------------
139 // Callback
140 // -----------------------------------------------------------------------
141
142 /**
143 * @brief Registers the callback that fires when the user confirms a node.
144 *
145 * @param callback Signature: void(nodeType, spawnX, spawnY)
146 */
147 void SetNodeAddCallback(std::function<void(const std::string&, float, float)> callback);
148
149 // -----------------------------------------------------------------------
150 // Spawn position
151 // -----------------------------------------------------------------------
152
153 /** @brief Returns the X coordinate where the new node should be spawned. */
154 float GetSpawnX() const;
155
156 /** @brief Returns the Y coordinate where the new node should be spawned. */
157 float GetSpawnY() const;
158
159private:
160
162
163 void InitNodeCatalogue();
164
165 /// Compute a [0..1] relevance score; returns 0 if there is no match.
166 static float ComputeScore(const std::string& query,
167 const std::string& candidate);
168
172 std::vector<NodeSearchResult> m_Catalogue; ///< Full unfiltered catalogue
173 std::vector<NodeSearchResult> m_Results; ///< Current filtered/sorted results
175 std::function<void(const std::string&, float, float)> m_OnNodeAdd;
176};
177
178} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Singleton fuzzy-search panel for adding nodes to the graph.
int GetSelectedIndex() const
Returns the index of the currently highlighted result (-1 = none).
void SelectNext()
Moves the selection down by one step (wraps around).
void UpdateQuery(const std::string &query)
Recomputes the result list for the given query string.
bool IsOpen() const
Returns true if the panel is currently visible.
void SelectPrevious()
Moves the selection up by one step (wraps around).
std::vector< NodeSearchResult > m_Results
Current filtered/sorted results.
float GetSpawnX() const
Returns the X coordinate where the new node should be spawned.
std::function< void(const std::string &, float, float)> m_OnNodeAdd
void ConfirmSelection(int index)
Fires the OnNodeAdd callback for the result at index and closes the panel.
const std::vector< NodeSearchResult > & GetResults() const
Returns the current result list sorted by relevance (best first).
void OpenSearch(float posX, float posY)
Opens the search panel at the given graph-space position.
std::vector< NodeSearchResult > m_Catalogue
Full unfiltered catalogue.
void CloseSearch()
Closes the search panel and clears the query.
float GetSpawnY() const
Returns the Y coordinate where the new node should be spawned.
static float ComputeScore(const std::string &query, const std::string &candidate)
Compute a [0..1] relevance score; returns 0 if there is no match.
static NodeSearchPanel & Get()
Returns the single shared instance.
void SetNodeAddCallback(std::function< void(const std::string &, float, float)> callback)
Registers the callback that fires when the user confirms a node.
< Provides AssetID and INVALID_ASSET_ID
std::string category
Category label (e.g. "ControlFlow")
std::string name
Display name of the node type.
std::string nodeType
Internal type key (e.g. "Sequence")
std::string description
Short human-readable description.
float relevanceScore
Higher = better match.