VR-Engage  2.2
Loading...
Searching...
No Matches
actionMenuElement.h
Go to the documentation of this file.
1/******************************************************************************
2** Copyright (c) 2025 MAK Technologies
3** All rights reserved.
4******************************************************************************/
5
6//! \file actionMenuElement.h
7//! \brief Defines the menu element classes for interactive menus
8//!
9//! This file contains the DtMenuElement class which represents individual
10//! entries in menus used throughout VR-Engage. It also includes observer classes
11//! that dynamically generate menu elements based on attribute changes.
12
13#pragma once
14
16
17#include "vreUtil/attribute.h"
18
19#include <vector>
20#include <string>
21
22namespace makVre
23{
24class DtMenuManager;
25class DtMenuCursor;
26class DtMenu;
27class DtInitTable;
28class DtMenuAttributeListObserver;
29
30//! \brief Menu element class for interactive menus
31//!
32//! DtMenuElement represents a single selectable item in a menu. It can represent
33//! an action to be executed, or a submenu to be displayed. Each element has a label
34//! that is shown to the user, and attributes that control its behavior, such as
35//! an action to be taken when selected, display conditions, and visual properties.
36//!
37//! Menu elements can be dynamically enabled or disabled based on conditions defined
38//! in the player attribute store, allowing for context-sensitive menu options.
40{
41public:
42 //! \brief Types of menu elements
43 //!
44 //! Defines the behavior of the menu element when selected.
46 {
47 ACTION, //!< Performs an action when selected
48 MENU //!< Opens a submenu when selected
49 };
50
51 //! \brief Constructor for a menu element
52 //! \param label Text displayed for this menu element
53 //! \param action Action identifier to execute when selected
54 //! \param param Parameter to pass with the action
55 //! \param displayConditions List of conditions that determine when this element is enabled
56 //! \param openMenuOnDisplayConditionMet Whether to automatically open a submenu when conditions are met
57 //! \param hasSubMenu Whether this element has a submenu
58 //! \param cursor Cursor name to display when this element is selected
59 //! \param valueMapping List of values for variable substitution
60 //! \param isValid Whether this element is valid and can be displayed
61 //!
62 //! Creates a new menu element with the specified properties. The element's type
63 //! (ACTION or MENU) is determined automatically based on the action parameter.
64 //! If action is "selectMenu", the type will be MENU, otherwise ACTION.
65 DtMenuElement(const std::string& label, const std::string& action, const std::string& param = "",
66 const std::vector<std::pair<std::string, bool>>& displayConditions = std::vector<std::pair<std::string, bool>>(),
67 bool openMenuOnDisplayConditionMet = false, bool hasSubMenu = false, const std::string& cursor = "",
68 std::vector<std::string> valueMapping = std::vector<std::string>(), bool isValid = true);
69
70 //! \brief Virtual destructor
71 //!
72 //! Cleans up resources used by the menu element and disconnects from attribute callbacks.
73 virtual ~DtMenuElement();
74
75 //! \brief Sets the parent menu for this element
76 //! \param menu Pointer to the parent menu
77 //!
78 //! Associates this element with a menu and sets up attribute callbacks for
79 //! dynamic state tracking. When the parent menu is set, the element will look for
80 //! relevant state attributes in the player attribute store and connect to them.
81 virtual void setMenu(DtMenu* menu);
82
83 //! \brief Gets the element type
84 //! \return Type of this menu element (ACTION or MENU)
85 //!
86 //! Retrieves the type of this menu element, which determines its behavior
87 //! when selected (performing an action or opening a submenu).
88 virtual ElementType type() { return myType; }
89
90 //! \brief Sets the element's selected state
91 //! \param select True to select this element, false to deselect it
92 //!
93 //! Called when the selection state of this element changes. When an element
94 //! is selected, it updates the active cursor to match its specified cursor.
95 virtual void setSelected(bool select);
96
97 //! \brief Checks if this element is currently enabled
98 //! \return True if enabled, false if disabled
99 //!
100 //! Determines whether this menu element is currently enabled based on its
101 //! display conditions. Disabled elements cannot be selected and may be
102 //! visually grayed out or hidden depending on the menu implementation.
103 virtual bool isEnabled();
104
105 //! \brief Gets the previous enabled state
106 //! \return True if previously enabled, false otherwise
107 //!
108 //! Returns the previously cached enabled state of the element.
109 //! Used to detect changes in enabled state for updating menus.
110 virtual bool previouslyEnabled() { return myPreviouslyEnabled; }
111
112 //! \brief Checks if the menu should open automatically when conditions are met
113 //! \return True if menu should open automatically, false otherwise
114 //!
115 //! If true and if this menu item has display conditions, open the item's menu
116 //! when the conditions become true. Useful for context-sensitive actions like
117 //! open a nearby door when you walk up to it.
119
120 //! \brief Sets the label text for this menu element
121 //! \param newLabel The new label text
122 //!
123 //! Updates the text that is displayed for this menu element.
124 virtual void setLabel(const std::string& newLabel) { myLabel = newLabel; }
125
126 //! \brief Gets the label for this menu element
127 //! \return Label text with any variables resolved
128 //!
129 //! Retrieves the display text for this menu element, resolving any
130 //! variable references in the process. Variables are replaced with
131 //! values from the player attribute store.
132 virtual std::string label();
133
134 //! \brief Gets the action identifier
135 //! \return Reference to the action string
136 //!
137 //! Returns the action identifier that will be executed when this element is selected.
138 virtual const std::string& action() { return myAction; }
139
140 //! \brief Sets the action identifier
141 //! \param newAction The new action string
142 //!
143 //! Updates the action that will be executed when this element is selected.
144 virtual void setAction(const std::string& newAction) { myAction = newAction; }
145
146 //! \brief Gets the action parameter
147 //! \return Reference to the parameter string
148 //!
149 //! Returns the parameter that will be passed with the action when executed.
150 virtual const std::string& parameter() { return myParameter; }
151
152 //! \brief Sets the action parameter
153 //! \param newParam The new parameter string
154 //!
155 //! Updates the parameter that will be passed with the action when executed.
156 virtual void setParameter(const std::string& newParam) { myParameter = newParam; }
157
158 //! \brief Gets the decorator text
159 //! \return Decorator text with variables resolved
160 //!
161 //! Retrieves additional text displayed alongside the label, such as
162 //! a current value or state information. This may include resolved
163 //! variable references to show dynamic information.
164 virtual std::string decoratorText();
165
166 //! \brief Checks if this element has a submenu
167 //! \return True if element has a submenu, false otherwise
168 //!
169 //! Determines whether selecting this element will open a submenu.
170 virtual bool hasSubMenu() const { return myHasSubMenu; }
171
172 //! \brief Sets whether this element has a submenu
173 //! \param val True if element should have a submenu, false otherwise
174 //!
175 //! Updates whether selecting this element will open a submenu.
176 virtual void setHasSubMenu(bool val) { myHasSubMenu = val; }
177
178 //! \brief Sets the cursor for this element
179 //! \param cursor Name of the cursor to display when selected
180 //!
181 //! Updates the cursor that will be shown when this element is selected.
182 virtual void setCursor(const std::string& cursor);
183
184 //! \brief Gets the cursor name
185 //! \return Reference to the cursor name string
186 //!
187 //! Returns the name of the cursor to display when this element is selected.
188 virtual const std::string& cursor() { return myCursor; }
189
190 //! \brief Gets the value mapping list
191 //! \return Reference to the value mapping vector
192 //!
193 //! Returns the list of values used for substituting variables in labels and parameters.
194 virtual const std::vector<std::string>& valueMapping() { return myValueMapping; }
195
196 //! \brief Checks if this element is valid
197 //! \return True if valid, false otherwise
198 //!
199 //! Determines whether this element is valid and should be displayed.
200 //! Invalid elements are excluded from menus entirely.
201 virtual bool isValid() const { return myIsValid; };
202
203 //! \brief Sets the validity of this element
204 //! \param val True to mark as valid, false to mark as invalid
205 //!
206 //! Updates whether this element is valid and should be displayed.
207 virtual void setIsValid(bool val) { myIsValid = val; };
208
209 //! \brief Executes this element's action
210 //!
211 //! Performs the action associated with this menu element. For ACTION type elements,
212 //! this creates and sends a MenuActionMessage with the element's action and parameter.
213 //! For MENU type elements, this creates and sends a MenuSetStateMessage to show
214 //! the specified submenu and closes the current menu.
215 virtual void doAction();
216
217 //! \brief Creates a menu element from configuration data
218 //! \param config Configuration table containing element properties
219 //! \return Newly created menu element, or NULL if creation failed
220 //!
221 //! Factory method that creates a menu element from a configuration table.
222 //! This is used when loading menu definitions from files or dynamic sources.
224
225 //! \brief Resets the element's state
226 //!
227 //! Disconnects all attribute callbacks and clears state attributes.
228 //! Called during cleanup or when the element needs to be completely reset.
229 virtual void reset();
230
231protected:
232 //! \brief Resolves variables in a string with values from attributes
233 //! \param str String containing variables to resolve
234 //! \return String with variables replaced by their values
235 //!
236 //! Processes a string and replaces variable references (marked with $)
237 //! with values from the player attribute store. This is used to create
238 //! dynamic labels and parameters based on current state.
239 std::string resolveVars(const std::string& str);
240
241 //! \brief Handles attribute change notifications
242 //! \param attribute The attribute that changed
243 //!
244 //! Called when an attribute this element is monitoring changes. Triggers
245 //! an update of the parent menu to reflect the changed state.
247
248 //! \brief Finds a state attribute referenced in a string
249 //! \param str String potentially containing a state attribute reference
250 //! \return Name of the referenced state attribute, or empty string if none
251 //!
252 //! Parses a string to find embedded state attribute references.
253 //! These references can be used to create labels or parameters that
254 //! dynamically reflect the current state.
255 std::string findStateAttribute(const std::string& str);
256
257 //! \brief Checks whether this element should be enabled
258 //! \return True if all display conditions are satisfied, false otherwise
259 //!
260 //! Evaluates all display conditions for this element to determine if it
261 //! should be enabled. Each condition refers to a boolean attribute in the
262 //! player attribute store, optionally inverted.
264
265 //! \brief Configuration data for this element
267
268 //! \brief Parent menu containing this element
270
271 //! \brief Type of element (ACTION or MENU)
273
274 //! \brief List of display conditions for this element
275 //!
276 //! Each pair contains the name of a boolean state attribute and a flag
277 //! indicating whether the condition should be inverted. The element is
278 //! enabled only when all conditions are satisfied.
279 std::vector<std::pair<std::string, bool>> myDisplayConditions;
280
281 //! \brief Label text displayed for this element
282 std::string myLabel;
283
284 //! \brief Action identifier executed when selected
285 std::string myAction;
286
287 //! \brief Parameter passed with the action
288 std::string myParameter;
289
290 //! \brief Cursor name to display when selected
291 std::string myCursor;
292
293 //! \brief Handle to a state attribute for dynamic content
295
296 //! \brief List of values for variable substitution
297 std::vector<std::string> myValueMapping;
298
299 //! \brief Callback for attribute change notifications
301
302 //! \brief Whether this element has a submenu
304
305 //! \brief Whether this element is valid and should be displayed
307
308 //! \brief Previously cached enabled state
310
311 //! \brief Whether to open submenu automatically when conditions are met
313
314 //! \brief Friend classes that need access to internals
316};
317
318//! \brief Generates menu elements from a list of attributes
319//!
320//! DtMenuAttributeListObserver monitors a list attribute in the player attribute
321//! store and generates a menu element for each item in the list. This is used to
322//! create dynamic menus where the available options depend on the current state,
323//! such as a list of available weapons or targets.
325{
326public:
327 //! \brief Constructor
328 //! \param menu Pointer to the menu to populate with elements
329 //! \param state Attribute handle to the player attribute store
330 //! \param attributeName Name of the attribute to observe
331 //! \param prototype Prototype menu element to clone for each generated element
332 //!
333 //! Creates a new instance that will monitor the specified attribute and
334 //! generate menu elements using the prototype element as a template.
335 //!
336 //! A new menu element is generated for each item in the attribute list.
337 //! If the attribute is a vector of strings, the keyword "$EACH" in the
338 //! prototype's label and param fields is replaced with the string.
339 //! If the attribute is a map of key/value string pairs, the keyword "$KEY"
340 //! in the prototype's label and param fields is replaced with the key, and
341 //! the keyword "$VALUE" is replaced with the associated sting value.
342
344 DtMenu* menu, DtAttributeHandle state, const std::string& attributeName, DtMenuElement* prototype);
345
346 //! \brief Virtual destructor
347 //!
348 //! Ensures proper cleanup of derived observer classes.
350
351protected:
352 //! \brief Handles attribute change notifications
353 //! \param attribute The attribute that changed
354 //!
355 //! Called when the observed list attribute changes. Regenerates the menu elements
356 //! based on the new list content, removing old elements and creating new ones as needed.
357 virtual void handleAttributeChanged(const DtAttributeHandle& attribute);
358
359 //! \brief Replaces a key with a value in a string
360 //! \param string Source string to search
361 //! \param key Key to find and replace
362 //! \param value Value to substitute for the key
363 //! \return String with all instances of the key replaced by the value
364 //!
365 //! Utility method for substituting a specific key with a value in a string.
366 //! Used for generating dynamic element labels and parameters from templates.
367 static std::string replaceEach(const std::string& string, std::string const& key, std::string const& value);
368
369 //! \brief Creates a new menu element from the prototype
370 //! \param label Label string for the new menu element
371 //! \param param Param string for the new menu element
372 //!
373 //! Instantiates a new DtMenuElement using the prototype template and the
374 //! given label and param strings and adds the new element to the menu.
375 virtual void createMenuElement(const std::string& label, const std::string& param);
376
377 //! \brief Menu to populate with generated elements
379
380 //! \brief Attribute handle to the player attribute store
382
383 //! \brief Callback for attribute change notifications
385
386 //! \brief Prototype element to clone for each generated element
388
389 //! \brief List of elements generated by this observer
390 std::vector<DtMenuElement*> myElements;
391};
392
393} // namespace makVre
Provides attribute handling system for hierarchical data storage and manipulation.
Scoped attribute change callback wrapper.
Definition attributeCallback.h:86
Handle class for safe access to attributes.
Definition attributeHandle.h:30
Table-based access to Lua state for configuration data.
Definition initializer.h:38
virtual void handleAttributeChanged(const DtAttributeHandle &attribute)
Handles attribute change notifications.
static std::string replaceEach(const std::string &string, std::string const &key, std::string const &value)
Replaces a key with a value in a string.
DtMenuElement * myPrototype
Prototype element to clone for each generated element.
Definition actionMenuElement.h:387
virtual ~DtMenuAttributeObserver()
Virtual destructor.
DtMenu * myMenu
Menu to populate with generated elements.
Definition actionMenuElement.h:378
virtual void createMenuElement(const std::string &label, const std::string &param)
Creates a new menu element from the prototype.
DtAttributeHandle myState
Attribute handle to the player attribute store.
Definition actionMenuElement.h:381
std::vector< DtMenuElement * > myElements
List of elements generated by this observer.
Definition actionMenuElement.h:390
DtMenuAttributeObserver(DtMenu *menu, DtAttributeHandle state, const std::string &attributeName, DtMenuElement *prototype)
Constructor.
DtAttributeChangeCallback myChangeCallback
Callback for attribute change notifications.
Definition actionMenuElement.h:384
Class for managing menu cursor visualization.
Definition actionMenuManager.h:60
Menu element class for interactive menus.
Definition actionMenuElement.h:40
bool myOpenMenuOnDisplayConditionMet
Whether to open submenu automatically when conditions are met.
Definition actionMenuElement.h:312
bool myHasSubMenu
Whether this element has a submenu.
Definition actionMenuElement.h:303
virtual void reset()
Resets the element's state.
virtual const std::string & action()
Gets the action identifier.
Definition actionMenuElement.h:138
virtual const std::vector< std::string > & valueMapping()
Gets the value mapping list.
Definition actionMenuElement.h:194
virtual std::string label()
Gets the label for this menu element.
std::string myLabel
Label text displayed for this element.
Definition actionMenuElement.h:282
std::string myCursor
Cursor name to display when selected.
Definition actionMenuElement.h:291
std::vector< std::string > myValueMapping
List of values for variable substitution.
Definition actionMenuElement.h:297
DtInitTable * myConfig
Configuration data for this element.
Definition actionMenuElement.h:266
virtual const std::string & cursor()
Gets the cursor name.
Definition actionMenuElement.h:188
virtual std::string decoratorText()
Gets the decorator text.
virtual void setParameter(const std::string &newParam)
Sets the action parameter.
Definition actionMenuElement.h:156
std::vector< std::pair< std::string, bool > > myDisplayConditions
List of display conditions for this element.
Definition actionMenuElement.h:279
friend class DtMenuAttributeObserver
Friend classes that need access to internals.
Definition actionMenuElement.h:315
virtual bool isEnabled()
Checks if this element is currently enabled.
bool myIsValid
Whether this element is valid and should be displayed.
Definition actionMenuElement.h:306
DtMenu * myMenu
Parent menu containing this element.
Definition actionMenuElement.h:269
virtual bool openMenuOnDisplayConditionMet()
Checks if the menu should open automatically when conditions are met.
Definition actionMenuElement.h:118
virtual void setAction(const std::string &newAction)
Sets the action identifier.
Definition actionMenuElement.h:144
std::string myAction
Action identifier executed when selected.
Definition actionMenuElement.h:285
bool myPreviouslyEnabled
Previously cached enabled state.
Definition actionMenuElement.h:309
bool checkEnabled()
Checks whether this element should be enabled.
virtual bool isValid() const
Checks if this element is valid.
Definition actionMenuElement.h:201
ElementType
Types of menu elements.
Definition actionMenuElement.h:46
@ ACTION
Performs an action when selected.
Definition actionMenuElement.h:47
@ MENU
Opens a submenu when selected.
Definition actionMenuElement.h:48
virtual void setSelected(bool select)
Sets the element's selected state.
virtual ~DtMenuElement()
Virtual destructor.
virtual void setMenu(DtMenu *menu)
Sets the parent menu for this element.
static DtMenuElement * create(DtInitTable &config)
Creates a menu element from configuration data.
DtAttributeHandle myStateAttribute
Handle to a state attribute for dynamic content.
Definition actionMenuElement.h:294
virtual ElementType type()
Gets the element type.
Definition actionMenuElement.h:88
virtual void setIsValid(bool val)
Sets the validity of this element.
Definition actionMenuElement.h:207
DtAttributeChangeCallback myAttributeCallback
Callback for attribute change notifications.
Definition actionMenuElement.h:300
virtual bool previouslyEnabled()
Gets the previous enabled state.
Definition actionMenuElement.h:110
std::string myParameter
Parameter passed with the action.
Definition actionMenuElement.h:288
virtual void setLabel(const std::string &newLabel)
Sets the label text for this menu element.
Definition actionMenuElement.h:124
DtMenuElement(const std::string &label, const std::string &action, const std::string &param="", const std::vector< std::pair< std::string, bool > > &displayConditions=std::vector< std::pair< std::string, bool > >(), bool openMenuOnDisplayConditionMet=false, bool hasSubMenu=false, const std::string &cursor="", std::vector< std::string > valueMapping=std::vector< std::string >(), bool isValid=true)
Constructor for a menu element.
virtual const std::string & parameter()
Gets the action parameter.
Definition actionMenuElement.h:150
virtual void setHasSubMenu(bool val)
Sets whether this element has a submenu.
Definition actionMenuElement.h:176
virtual void doAction()
Executes this element's action.
virtual bool hasSubMenu() const
Checks if this element has a submenu.
Definition actionMenuElement.h:170
virtual void setCursor(const std::string &cursor)
Sets the cursor for this element.
void handleAttributeChanged(const DtAttributeHandle &attribute)
Handles attribute change notifications.
std::string findStateAttribute(const std::string &str)
Finds a state attribute referenced in a string.
ElementType myType
Type of element (ACTION or MENU)
Definition actionMenuElement.h:272
std::string resolveVars(const std::string &str)
Resolves variables in a string with values from attributes.
Core class for all interactive menus in VR-Engage.
Definition actionMenu.h:67
Central manager for all menus in VR-Engage.
Definition actionMenuManager.h:111
Defines export macros for the VR-Engage Player Station library.
#define PLAYERSTATION_DLL
Definition export.h:24
Include export definitions for this library.
Definition glsVreMessageUtil.h:49