Ocean
ActionSet.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_PLATFORM_OPENXR_ACTION_SET_H
9 #define META_OCEAN_PLATFORM_OPENXR_ACTION_SET_H
10 
13 
14 #include "ocean/base/Lock.h"
15 
16 namespace Ocean
17 {
18 
19 namespace Platform
20 {
21 
22 namespace OpenXR
23 {
24 
25 // Foward declaration.
26 class ActionSet;
27 
28 /**
29  * Definition of a shared pointer holding an ActionSet object.
30  * @see ActionSet.
31  * @ingroup platformopenxr
32  */
33 typedef std::shared_ptr<ActionSet> SharedActionSet;
34 
35 /**
36  * Definition of a vector holding ActionSet objects.
37  * @see ActinoSet
38  * @ingroup platformopenxr
39  */
40 typedef std::vector<ActionSet> ActionSets;
41 
42 /**
43  * Definition of a vector holding a SharedActionSet object.
44  * @see SharedActionSet.
45  * @ingroup platformopenxr
46  */
47 typedef std::vector<SharedActionSet> SharedActionSets;
48 
49 /**
50  * This class implements a wrapper for an OpenXR action set.
51  * @ingroup platformopenxr
52  */
53 class OCEAN_PLATFORM_OPENXR_EXPORT ActionSet final
54 {
55  public:
56 
57  /**
58  * Definition of an id for an action.
59  */
60  typedef uint32_t ActionId;
61 
62  /**
63  * Definition of an unordered map mapping action ids to XrAction objects.
64  */
65  typedef std::unordered_map<ActionId, XrAction> ActionIdMap;
66 
67  /**
68  * Definition of a vector holding strings.
69  */
70  typedef std::vector<std::string> Paths;
71 
72  /// An invalid action id.
73  static constexpr ActionId invalidActionId_ = ActionId(-1);
74 
75  protected:
76 
77  /**
78  * Definition of a vector holding XrActionSuggestedBinding objects.
79  */
80  typedef std::vector<XrActionSuggestedBinding> XrActionSuggestedBindings;
81 
82  public:
83 
84  /**
85  * Default constructor.
86  */
87  ActionSet() noexcept = default;
88 
89  /**
90  * Move constructor.
91  * @param actionSet The action set to be moved
92  */
93  inline ActionSet(ActionSet&& actionSet) noexcept;
94 
95  /**
96  * Destructs this action set and releases all resources.
97  */
99 
100  /**
101  * Initializes the action set.
102  * @param xrInstance The OpenXR instance for which the action set will be created, must be valid
103  * @param name The action set's name, must be valid
104  * @param description The action set's description, must be valid
105  * @param priority The action set's priority, with range [0, infinity)
106  * @return True, if succeeded
107  */
108  bool initialize(const XrInstance& xrInstance, const std::string& name, const std::string& description, const uint32_t priority = 0u);
109 
110  /**
111  * Creates a new action.
112  * In case an external managed id is provided, the id must be unique and must not be associated with an existing id already.
113  * @param xrActionType The type of the action to be created, must be valid
114  * @param name The name of the action, must be valid
115  * @param description The description of the action, must be valid
116  * @param actionId The id of the action, an explicit (externally managed id), or invalidActionId_ to use an internally managed id
117  * @return The id of the created action, invalidActionId_ if the action could not be created
118  */
119  ActionId createAction(const XrActionType xrActionType, const std::string& name, const std::string& description, const ActionId actionId = invalidActionId_);
120 
121  /**
122  * Creates a new action.
123  * In case an external managed id is provided, the id must be unique and must not be associated with an existing id already.
124  * @param xrActionType The type of the action to be created, must be valid
125  * @param name The name of the action, must be valid
126  * @param description The description of the action, must be valid
127  * @param subactionPaths Optional sub-action paths
128  * @param actionId The id of the action, an explicit (externally managed id), or invalidActionId_ to use an internally managed id
129  * @return The id of the created action, invalidActionId_ if the action could not be created
130  */
131  ActionId createAction(const XrActionType xrActionType, const std::string& name, const std::string& description, const Paths& subactionPaths, const ActionId actionId = invalidActionId_);
132 
133  /**
134  * Creates a new action.
135  * In case an external managed id is provided, the id must be unique and must not be associated with an existing id already.
136  * @param xrActionType The type of the action to be created, must be valid
137  * @param name The name of the action, must be valid
138  * @param description The description of the action, must be valid
139  * @param xrSubactionPaths Optional sub-action paths
140  * @param actionId The id of the action, an explicit (externally managed id), or invalidActionId_ to use an internally managed id
141  * @return The id of the created action, invalidActionId_ if the action could not be created
142  */
143  ActionId createAction(const XrActionType xrActionType, const std::string& name, const std::string& description, const XrPaths& xrSubactionPaths, const ActionId actionId = invalidActionId_);
144 
145  /**
146  * Creates a new action and directly adds an action binding.
147  * In case an external managed id is provided, the id must be unique and must not be associated with an existing id already.
148  * @param xrActionType The type of the action to be created, must be valid
149  * @param name The name of the action, must be valid
150  * @param description The description of the action, must be valid
151  * @param path The OpenXR path to which the action will be bound, must be valid
152  * @param actionId The id of the action, an explicit (externally managed id), or invalidActionId_ to use an internally managed id
153  * @return The id of the created action, invalidActionId_ if the action could not be created
154  */
155  inline ActionId createActionWithBinding(const XrActionType xrActionType, const std::string& name, const std::string& description, const std::string& path, const ActionId actionId = invalidActionId_);
156 
157  /**
158  * Adds an action binding.
159  * @param actionId The id of the action to bind, must be valid
160  * @param path The OpenXR path to which the action will be bound, must be valid
161  * @return True, if succeeded
162  */
163  bool addActionBinding(const ActionId actionId, const std::string& path);
164 
165  /**
166  * Adds an action binding.
167  * @param actionId The id of the action to bind, must be valid
168  * @param xrPath The OpenXR path to which the action will be bound, must be valid
169  * @return True, if succeeded
170  */
171  bool addActionBinding(const ActionId actionId, const XrPath& xrPath);
172 
173  /**
174  * Suggests the actions of this set as binding.
175  * @param xrInstance The OpenXR instance for which the action set will be created, must be valid
176  * @param interactionProfile The interaction profile to be used, must be valid
177  * @return True, if succeeded
178  * @see actionBindingsSuggested().
179  */
180  inline bool suggestActionBindings(const XrInstance& xrInstance, const std::string& interactionProfile);
181 
182  /**
183  * Suggests the actions of this set as binding.
184  * @param xrInstance The OpenXR instance for which the action set will be created, must be valid
185  * @param xrInteractionProfilePath The interaction profile to be used, must be valid
186  * @return True, if succeeded
187  * @see actionBindingsSuggested().
188  */
189  bool suggestActionBindings(const XrInstance& xrInstance, const XrPath& xrInteractionProfilePath);
190 
191  /**
192  * Returns an action of this set.
193  * @param actionId The id of the action, must be valid
194  * @return The requested action, XR_NULL_HANDLE if unknown
195  */
196  XrAction action(const ActionId actionId) const;
197 
198  /**
199  * Determines the state of an action.
200  * @param xrSession The session to which the action belongs (is synchronized), must be valid
201  * @param actionId The id of the action, must be valid
202  * @param state The resulting state
203  * @return True, if succeeded
204  * @tparam T The data type of the state, either 'XrActionStateBoolean', 'xrGetActionStateFloat', 'XrActionStateVector2f', or 'xrGetActionStatePose'
205  */
206  template <typename T>
207  bool actionState(const XrSession& xrSession, const ActionId actionId, T& state) const;
208 
209  /**
210  * Explicitly releases the action set and all associated actions and resources.
211  * @see initialize().
212  */
213  void release();
214 
215  /**
216  * Returns true whether the actions have been set as applicated-suggested bindings.
217  * @return True, if so
218  * @see suggestActionBindings().
219  */
220  bool actionBindingsSuggested() const;
221 
222  /**
223  * Returns whether this object holds a valid OpenXR action set.
224  * @return True, if so
225  * @see initialize().
226  */
227  bool isValid() const;
228 
229  /**
230  * Returns the wrapped OpenXR action set.
231  * @return The actual action set, nullptr if not initialized
232  * @see isValid().
233  */
234  inline operator XrActionSet() const;
235 
236  /**
237  * Returns whether this object holds a valid OpenXR action set.
238  * @return True, if so
239  * @see isValid().
240  */
241  explicit inline operator bool() const;
242 
243  /**
244  * Move operator.
245  * @param actionSet The action set object to be moved
246  * @return The reference to this object
247  */
248  ActionSet& operator=(ActionSet&& actionSet) noexcept;
249 
250  /**
251  * Determines the state of an action.
252  * @param xrSession The session to which the action belongs (is synchronized), must be valid
253  * @param xrAction The action for which the state will be returned, must be valid
254  * @param state The resulting state
255  * @return True, if succeeded
256  * @tparam T The data type of the state, either 'XrActionStateBoolean', 'xrGetActionStateFloat', 'XrActionStateVector2f', or 'xrGetActionStatePose'
257  */
258  template <typename T>
259  static bool actionState(const XrSession& xrSession, const XrAction& xrAction, T& state);
260 
261  protected:
262 
263  /**
264  * Disabled copy constructor.
265  */
266  ActionSet(const ActionSet&) = delete;
267 
268  /**
269  * Disabled assign operator.
270  * @return The reference to this object
271  */
272  ActionSet& operator=(const ActionSet&) = delete;
273 
274  protected:
275 
276  /// The OpenXR instance associated with this action set.
277  XrInstance xrInstance_ = XR_NULL_HANDLE;
278 
279  /// The action OpenXR action set.
280  XrActionSet xrActionSet_ = XR_NULL_HANDLE;
281 
282  /// The actions of this action set.
283  ActionIdMap actionIdMap_;
284 
285  /// The counter of unique action ids.
286  ActionId actionIdCounter_ = 0u;
287 
288  /// The XrActionSuggestedBindings of this action set.
289  XrActionSuggestedBindings xrActionSuggestedBindings_;
290 
291  /// True, if the actions have been set as applicated-suggested bindings.
292  bool actionBindingsSuggested_ = false;
293 
294  /// The action set's lock.
295  mutable Lock lock_;
296 };
297 
298 inline ActionSet::ActionSet(ActionSet&& actionSet) noexcept
299 {
300  *this = std::move(actionSet);
301 }
302 
303 inline ActionSet::ActionId ActionSet::createActionWithBinding(const XrActionType xrActionType, const std::string& name, const std::string& description, const std::string& path, const ActionId actionId)
304 {
305  const ActionId id = createAction(xrActionType, name, description, actionId);
306  ocean_assert(id != invalidActionId_);
307 
308  if (id != invalidActionId_ && addActionBinding(id, path))
309  {
310  return id;
311  }
312 
313  return invalidActionId_;
314 }
315 
316 inline bool ActionSet::suggestActionBindings(const XrInstance& xrInstance, const std::string& interactionProfile)
317 {
318  ocean_assert(xrInstance != XR_NULL_HANDLE);
319  ocean_assert(!interactionProfile.empty());
320 
321  return suggestActionBindings(xrInstance, Utilities::translatePath(xrInstance, interactionProfile));
322 }
323 
324 template <typename T>
325 bool ActionSet::actionState(const XrSession& xrSession, const ActionId actionId, T& state) const
326 {
327  ocean_assert(xrSession != XR_NULL_HANDLE);
328  ocean_assert(actionId != invalidActionId_);
329 
330  const ScopedLock scopedLock(lock_);
331 
332  const ActionIdMap::const_iterator iAction = actionIdMap_.find(actionId);
333 
334  if (iAction == actionIdMap_.cend())
335  {
336  ocean_assert(false && "Unknown action id");
337  return false;
338  }
339 
340  return actionState<T>(xrSession, iAction->second, state);
341 }
342 
343 template <>
344 inline bool ActionSet::actionState(const XrSession& xrSession, const XrAction& xrAction, XrActionStateBoolean& state)
345 {
346  ocean_assert(xrSession != XR_NULL_HANDLE);
347  ocean_assert(xrAction != XR_NULL_HANDLE);
348 
349  state = XrActionStateBoolean{XR_TYPE_ACTION_STATE_BOOLEAN};
350 
351  XrActionStateGetInfo xrActionStateGetInfo{XR_TYPE_ACTION_STATE_GET_INFO};
352  xrActionStateGetInfo.action = xrAction;
353 
354  const XrResult xrResult = xrGetActionStateBoolean(xrSession, &xrActionStateGetInfo, &state);
355  ocean_assert(xrResult == XR_SUCCESS);
356 
357  return xrResult == XR_SUCCESS;
358 }
359 
360 template <>
361 inline bool ActionSet::actionState(const XrSession& xrSession, const XrAction& xrAction, XrActionStateFloat& state)
362 {
363  ocean_assert(xrSession != XR_NULL_HANDLE);
364  ocean_assert(xrAction != XR_NULL_HANDLE);
365 
366  state = XrActionStateFloat{XR_TYPE_ACTION_STATE_FLOAT};
367 
368  XrActionStateGetInfo xrActionStateGetInfo{XR_TYPE_ACTION_STATE_GET_INFO};
369  xrActionStateGetInfo.action = xrAction;
370 
371  const XrResult xrResult = xrGetActionStateFloat(xrSession, &xrActionStateGetInfo, &state);
372  ocean_assert(xrResult == XR_SUCCESS);
373 
374  return xrResult == XR_SUCCESS;
375 }
376 
377 template <>
378 inline bool ActionSet::actionState(const XrSession& xrSession, const XrAction& xrAction, XrActionStateVector2f& state)
379 {
380  ocean_assert(xrSession != XR_NULL_HANDLE);
381  ocean_assert(xrAction != XR_NULL_HANDLE);
382 
383  state = XrActionStateVector2f{XR_TYPE_ACTION_STATE_VECTOR2F};
384 
385  XrActionStateGetInfo xrActionStateGetInfo{XR_TYPE_ACTION_STATE_GET_INFO};
386  xrActionStateGetInfo.action = xrAction;
387 
388  const XrResult xrResult = xrGetActionStateVector2f(xrSession, &xrActionStateGetInfo, &state);
389  ocean_assert(xrResult == XR_SUCCESS);
390 
391  return xrResult == XR_SUCCESS;
392 }
393 
394 template <>
395 inline bool ActionSet::actionState(const XrSession& xrSession, const XrAction& xrAction, XrActionStatePose& state)
396 {
397  ocean_assert(xrSession != XR_NULL_HANDLE);
398  ocean_assert(xrAction != XR_NULL_HANDLE);
399 
400  state = XrActionStatePose{XR_TYPE_ACTION_STATE_POSE};
401 
402  XrActionStateGetInfo xrActionStateGetInfo{XR_TYPE_ACTION_STATE_GET_INFO};
403  xrActionStateGetInfo.action = xrAction;
404 
405  const XrResult xrResult = xrGetActionStatePose(xrSession, &xrActionStateGetInfo, &state);
406  ocean_assert(xrResult == XR_SUCCESS);
407 
408  return xrResult == XR_SUCCESS;
409 }
410 
411 inline ActionSet::operator XrActionSet() const
412 {
413  const ScopedLock scopedLock(lock_);
414 
415  return xrActionSet_;
416 }
417 
418 inline ActionSet::operator bool() const
419 {
420  return isValid();
421 }
422 
423 }
424 
425 }
426 
427 }
428 
429 #endif // META_OCEAN_PLATFORM_OPENXR_ACTION_SET_H
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a wrapper for an OpenXR action set.
Definition: ActionSet.h:54
ActionSet() noexcept=default
Default constructor.
ActionId createActionWithBinding(const XrActionType xrActionType, const std::string &name, const std::string &description, const std::string &path, const ActionId actionId=invalidActionId_)
Creates a new action and directly adds an action binding.
Definition: ActionSet.h:303
bool actionState(const XrSession &xrSession, const ActionId actionId, T &state) const
Determines the state of an action.
Definition: ActionSet.h:325
std::vector< XrActionSuggestedBinding > XrActionSuggestedBindings
Definition of a vector holding XrActionSuggestedBinding objects.
Definition: ActionSet.h:80
bool suggestActionBindings(const XrInstance &xrInstance, const std::string &interactionProfile)
Suggests the actions of this set as binding.
Definition: ActionSet.h:316
uint32_t ActionId
Definition of an id for an action.
Definition: ActionSet.h:60
std::vector< std::string > Paths
Definition of a vector holding strings.
Definition: ActionSet.h:70
std::unordered_map< ActionId, XrAction > ActionIdMap
Definition of an unordered map mapping action ids to XrAction objects.
Definition: ActionSet.h:65
static std::string translatePath(const XrInstance &xrInstance, const XrPath &xrPath)
Converts an OpenXR path to a string.
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
void release(T *object)
This functions allows to release a DirectShow object if it does exist.
Definition: DSObject.h:266
std::vector< SharedActionSet > SharedActionSets
Definition of a vector holding a SharedActionSet object.
Definition: ActionSet.h:47
std::vector< ActionSet > ActionSets
Definition of a vector holding ActionSet objects.
Definition: ActionSet.h:40
std::shared_ptr< ActionSet > SharedActionSet
Definition of a shared pointer holding an ActionSet object.
Definition: ActionSet.h:26
std::vector< XrPath > XrPaths
Definition of a vector holding OpenXR XrPath objects.
Definition: openxr/OpenXR.h:113
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15