Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
NodeConditionsEditModal.h
Go to the documentation of this file.
1/**
2 * @file NodeConditionsEditModal.h
3 * @brief Dedicated modal dialog for editing a NodeBranch's condition list (Phase 24-REFONTE).
4 * @author Olympe Engine
5 * @date 2026-03-17
6 *
7 * @details
8 * NodeConditionsEditModal provides a modal overlay to add, remove, reorder, and
9 * configure the logical operators of a NodeBranch's ConditionPreset references.
10 * It is separate from NodeConditionsPanel so that the Properties panel remains
11 * READ-ONLY (view only), while all edits are confirmed in one atomic Apply step.
12 *
13 * Usage:
14 * @code
15 * NodeConditionsEditModal modal(registry);
16 *
17 * // When user clicks "Edit Conditions" in the Properties panel:
18 * modal.Open(node.conditionRefs);
19 *
20 * // In render loop:
21 * modal.Render();
22 * if (modal.IsConfirmed()) {
23 * node.conditionRefs = modal.GetConditionRefs();
24 * modal.Close();
25 * }
26 * @endcode
27 *
28 * The modal works on a COPY of the node's condition refs. On "Apply" it marks
29 * itself as confirmed; on "Cancel" the copy is discarded.
30 *
31 * C++14 compliant — no std::optional, structured bindings, std::filesystem.
32 */
33
34#pragma once
35
36#include <string>
37#include <vector>
38#include <functional>
39
40#include "../ConditionPreset/ConditionPreset.h"
41#include "../../BlueprintEditor/ConditionRef.h" // Phase 24: For operand data
42#include "../ConditionPreset/ConditionPresetRegistry.h"
43#include "../ConditionPreset/NodeConditionRef.h"
44#include "../../TaskSystem/LocalBlackboard.h"
45
46namespace Olympe {
47
48/**
49 * @class NodeConditionsEditModal
50 * @brief Modal dialog for adding, removing, and reordering conditions on a node.
51 *
52 * @details
53 * The modal contains:
54 * - A scrollable list of current conditions, each with:
55 * - Logical operator dropdown (And / Or; first entry is always fixed).
56 * - Preset selector dropdown (from global registry).
57 * - Delete [X] button.
58 * - Move Up / Move Down buttons.
59 * - An "Add Condition" button (opens preset picker inline).
60 * - Apply and Cancel buttons at the bottom.
61 */
63public:
64
65 /**
66 * @brief Constructs the modal bound to a global preset registry.
67 * @param registry Global ConditionPresetRegistry (must outlive this modal).
68 */
70
72
73 // Non-copyable
76
77 // -----------------------------------------------------------------------
78 // Visibility / lifecycle
79 // -----------------------------------------------------------------------
80
81 /**
82 * @brief Returns true if the modal is currently open.
83 */
84 bool IsOpen() const { return m_isOpen; }
85
86 /**
87 * @brief Opens the modal, loading the given condition refs for editing.
88 *
89 * Resets the confirmed flag and takes a COPY of the refs to edit.
90 *
91 * @param currentRefs Condition refs from the selected node.
92 */
93 void Open(const std::vector<NodeConditionRef>& currentRefs,
94 const std::vector<ConditionRef>& operandRefs = std::vector<ConditionRef>());
95
96 /**
97 * @brief Closes the modal without confirming changes.
98 */
99 void Close();
100
101 /**
102 * @brief Returns true if the user clicked "Apply" and the modal was closed.
103 *
104 * Reset by Open().
105 */
106 bool IsConfirmed() const { return m_isConfirmed; }
107
108 // -----------------------------------------------------------------------
109 // Result
110 // -----------------------------------------------------------------------
111
112 /**
113 * @brief Returns the edited condition ref list.
114 *
115 * Only meaningful when IsConfirmed() is true.
116 */
117 const std::vector<NodeConditionRef>& GetConditionRefs() const;
118
119 /**
120 * @brief Returns the edited operand ref list (Phase 24).
121 *
122 * Only meaningful when IsConfirmed() is true.
123 */
124 const std::vector<ConditionRef>& GetConditionOperandRefs() const;
125
126 // -----------------------------------------------------------------------
127 // Condition management (testable without ImGui)
128 // -----------------------------------------------------------------------
129
130 /**
131 * @brief Returns the number of conditions in the working copy.
132 */
133 size_t GetConditionCount() const;
134
135 /**
136 * @brief Appends a new condition for the given preset to the working copy.
137 *
138 * The logicalOp defaults to And (Start for the first condition).
139 * @param presetID UUID of the preset to add.
140 */
141 void AddCondition(const std::string& presetID);
142
143 /**
144 * @brief Removes the condition at the given index from the working copy.
145 * @param index Zero-based index.
146 */
147 void RemoveCondition(size_t index);
148
149 /**
150 * @brief Sets the logical operator for the condition at the given index.
151 *
152 * Index 0 is always forced to LogicalOp::Start.
153 * @param index Zero-based index.
154 * @param op Desired operator (And or Or).
155 */
156 void SetLogicalOp(size_t index, LogicalOp op);
157
158 /**
159 * @brief Moves the condition at `index` one position earlier (swap with index-1).
160 *
161 * No-op when index == 0.
162 * @param index Zero-based index.
163 */
164 void MoveConditionUp(size_t index);
165
166 /**
167 * @brief Moves the condition at `index` one position later (swap with index+1).
168 *
169 * No-op when index is the last element.
170 * @param index Zero-based index.
171 */
172 void MoveConditionDown(size_t index);
173
174 /**
175 * @brief Programmatically confirms the modal (equivalent to clicking Apply).
176 *
177 * Marks the modal as confirmed and closes it. Always succeeds.
178 * Fires the OnApply callback (if set) before closing.
179 */
180 void Confirm();
181
182 // -----------------------------------------------------------------------
183 // Callbacks
184 // -----------------------------------------------------------------------
185
186 /**
187 * @brief Optional callback fired when the user clicks "Apply" (Confirm).
188 *
189 * Set this before opening the modal. The callback is invoked from within
190 * Confirm() after m_isConfirmed is set but before Close() is called,
191 * allowing the host to read GetConditionRefs() synchronously.
192 *
193 * Example:
194 * @code
195 * modal.OnApply = [&]() {
196 * node.conditionRefs = modal.GetConditionRefs();
197 * pinManager.RegeneratePinsFromConditions(node.conditionRefs);
198 * };
199 * @endcode
200 */
201 std::function<void()> OnApply;
202
203 // -----------------------------------------------------------------------
204 // Phase 24 Global Blackboard Integration
205 // -----------------------------------------------------------------------
206
207 /**
208 * @brief Sets the list of local variables for combo population.
209 * @param localVars Vector of local blackboard entries.
210 */
211 void SetLocalVariables(const std::vector<BlackboardEntry>& localVars)
212 {
214 }
215
216 // -----------------------------------------------------------------------
217 // Dropdown helper
218 // -----------------------------------------------------------------------
219
220 /**
221 * @brief Sets the search filter for the "Add Condition" preset picker.
222 * @param filter Substring filter (empty = show all).
223 */
224 void SetDropdownFilter(const std::string& filter);
225
226 /**
227 * @brief Returns the current dropdown filter string.
228 */
229 const std::string& GetDropdownFilter() const { return m_dropdownFilter; }
230
231 /**
232 * @brief Returns presets matching the current dropdown filter.
233 */
234 std::vector<ConditionPreset> GetFilteredPresetsForDropdown() const;
235
236 // -----------------------------------------------------------------------
237 // Rendering (ImGui — guarded by OLYMPE_HEADLESS in tests)
238 // -----------------------------------------------------------------------
239
240 /**
241 * @brief Renders the modal dialog using ImGui.
242 *
243 * Must be called once per frame from the host's render loop.
244 * No-op when !IsOpen().
245 */
246 void Render();
247
248private:
249
250 // -----------------------------------------------------------------------
251 // ImGui rendering helpers
252 // -----------------------------------------------------------------------
253
254 void RenderConditionRow(size_t index, const NodeConditionRef& ref);
256 void RenderFooterButtons();
257
258 // -----------------------------------------------------------------------
259 // Internal helpers
260 // -----------------------------------------------------------------------
261
262 /** Ensures the first condition's logicalOp is always Start. */
263 void NormalizeLogicalOps();
264
265 // -----------------------------------------------------------------------
266 // State
267 // -----------------------------------------------------------------------
268
269 ConditionPresetRegistry& m_registry; ///< Shared global registry
270 std::vector<NodeConditionRef> m_workingCopy; ///< Editable in-progress copy
271 std::vector<ConditionRef> m_workingCopyOperandRefs; ///< Phase 24: Operand data
272 bool m_isOpen = false;
273 bool m_isConfirmed = false;
274
275 std::string m_dropdownFilter; ///< Preset-picker search filter
276 bool m_pickerOpen = false; ///< Whether the add-preset picker is open
277 std::vector<BlackboardEntry> m_localVariables; ///< Phase 24: Local variables for combo
278};
279
280} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Manages the global pool of ConditionPreset objects.
Modal dialog for adding, removing, and reordering conditions on a node.
std::string m_dropdownFilter
Preset-picker search filter.
std::vector< BlackboardEntry > m_localVariables
Phase 24: Local variables for combo.
bool IsConfirmed() const
Returns true if the user clicked "Apply" and the modal was closed.
std::vector< ConditionRef > m_workingCopyOperandRefs
Phase 24: Operand data.
bool m_pickerOpen
Whether the add-preset picker is open.
std::function< void()> OnApply
Optional callback fired when the user clicks "Apply" (Confirm).
void AddCondition(const std::string &presetID)
Appends a new condition for the given preset to the working copy.
NodeConditionsEditModal(const NodeConditionsEditModal &)=delete
void RemoveCondition(size_t index)
Removes the condition at the given index from the working copy.
void RenderConditionRow(size_t index, const NodeConditionRef &ref)
NodeConditionsEditModal & operator=(const NodeConditionsEditModal &)=delete
std::vector< NodeConditionRef > m_workingCopy
Editable in-progress copy.
const std::vector< NodeConditionRef > & GetConditionRefs() const
Returns the edited condition ref list.
size_t GetConditionCount() const
Returns the number of conditions in the working copy.
void NormalizeLogicalOps()
Ensures the first condition's logicalOp is always Start.
const std::vector< ConditionRef > & GetConditionOperandRefs() const
Returns the edited operand ref list (Phase 24).
void Render()
Renders the modal dialog using ImGui.
void Confirm()
Programmatically confirms the modal (equivalent to clicking Apply).
const std::string & GetDropdownFilter() const
Returns the current dropdown filter string.
void SetDropdownFilter(const std::string &filter)
Sets the search filter for the "Add Condition" preset picker.
std::vector< ConditionPreset > GetFilteredPresetsForDropdown() const
Returns presets matching the current dropdown filter.
void MoveConditionUp(size_t index)
Moves the condition at index one position earlier (swap with index-1).
void Open(const std::vector< NodeConditionRef > &currentRefs, const std::vector< ConditionRef > &operandRefs=std::vector< ConditionRef >())
Opens the modal, loading the given condition refs for editing.
void MoveConditionDown(size_t index)
Moves the condition at index one position later (swap with index+1).
ConditionPresetRegistry & m_registry
Shared global registry.
void Close()
Closes the modal without confirming changes.
bool IsOpen() const
Returns true if the modal is currently open.
void SetLogicalOp(size_t index, LogicalOp op)
Sets the logical operator for the condition at the given index.
void SetLocalVariables(const std::vector< BlackboardEntry > &localVars)
Sets the list of local variables for combo population.
< Provides AssetID and INVALID_ASSET_ID
LogicalOp
How this condition is combined with the one preceding it.
One entry in a NodeBranch's conditions list.