Blender  V3.3
wm_xr_action.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
12 #include "BLI_listbase.h"
13 #include "BLI_math.h"
14 
15 #include "GHOST_C-api.h"
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "WM_api.h"
20 #include "WM_types.h"
21 
22 #include "wm_xr_intern.h"
23 
24 /* -------------------------------------------------------------------- */
31 static wmXrActionSet *action_set_create(const char *action_set_name)
32 {
33  wmXrActionSet *action_set = MEM_callocN(sizeof(*action_set), __func__);
34  action_set->name = MEM_mallocN(strlen(action_set_name) + 1, "XrActionSet_Name");
35  strcpy(action_set->name, action_set_name);
36 
37  return action_set;
38 }
39 
40 static void action_set_destroy(void *val)
41 {
42  wmXrActionSet *action_set = val;
43 
44  MEM_SAFE_FREE(action_set->name);
45 
46  BLI_freelistN(&action_set->active_modal_actions);
48 
49  MEM_freeN(action_set);
50 }
51 
52 static wmXrActionSet *action_set_find(wmXrData *xr, const char *action_set_name)
53 {
54  return GHOST_XrGetActionSetCustomdata(xr->runtime->context, action_set_name);
55 }
56 
57 static wmXrAction *action_create(const char *action_name,
59  const ListBase *user_paths,
61  IDProperty *op_properties,
62  const char *haptic_name,
63  const int64_t *haptic_duration,
64  const float *haptic_frequency,
65  const float *haptic_amplitude,
66  eXrOpFlag op_flag,
67  eXrActionFlag action_flag,
68  eXrHapticFlag haptic_flag)
69 {
70  wmXrAction *action = MEM_callocN(sizeof(*action), __func__);
71  action->name = MEM_mallocN(strlen(action_name) + 1, "XrAction_Name");
72  strcpy(action->name, action_name);
73  action->type = type;
74 
75  const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
76  unsigned int subaction_idx = 0;
77  action->count_subaction_paths = count;
78 
79  action->subaction_paths = MEM_mallocN(sizeof(*action->subaction_paths) * count,
80  "XrAction_SubactionPaths");
81  LISTBASE_FOREACH_INDEX (XrUserPath *, user_path, user_paths, subaction_idx) {
82  action->subaction_paths[subaction_idx] = MEM_mallocN(strlen(user_path->path) + 1,
83  "XrAction_SubactionPath");
84  strcpy(action->subaction_paths[subaction_idx], user_path->path);
85  }
86 
87  size_t size;
88  switch (type) {
89  case XR_BOOLEAN_INPUT:
90  size = sizeof(bool);
91  break;
92  case XR_FLOAT_INPUT:
93  size = sizeof(float);
94  break;
95  case XR_VECTOR2F_INPUT:
96  size = sizeof(float) * 2;
97  break;
98  case XR_POSE_INPUT:
99  size = sizeof(GHOST_XrPose);
100  break;
101  case XR_VIBRATION_OUTPUT:
102  return action;
103  }
104  action->states = MEM_calloc_arrayN(count, size, "XrAction_States");
105  action->states_prev = MEM_calloc_arrayN(count, size, "XrAction_StatesPrev");
106 
107  const bool is_float_action = ELEM(type, XR_FLOAT_INPUT, XR_VECTOR2F_INPUT);
108  const bool is_button_action = (is_float_action || type == XR_BOOLEAN_INPUT);
109  if (is_float_action) {
111  count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds");
112  }
113  if (is_button_action) {
114  action->axis_flags = MEM_calloc_arrayN(
115  count, sizeof(*action->axis_flags), "XrAction_AxisFlags");
116  }
117 
118  action->ot = ot;
119  action->op_properties = op_properties;
120 
121  if (haptic_name) {
122  BLI_assert(is_button_action);
123  action->haptic_name = MEM_mallocN(strlen(haptic_name) + 1, "XrAction_HapticName");
124  strcpy(action->haptic_name, haptic_name);
125  action->haptic_duration = *haptic_duration;
126  action->haptic_frequency = *haptic_frequency;
127  action->haptic_amplitude = *haptic_amplitude;
128  }
129 
130  action->op_flag = op_flag;
131  action->action_flag = action_flag;
132  action->haptic_flag = haptic_flag;
133 
134  return action;
135 }
136 
137 static void action_destroy(void *val)
138 {
139  wmXrAction *action = val;
140 
141  MEM_SAFE_FREE(action->name);
142 
143  char **subaction_paths = action->subaction_paths;
144  if (subaction_paths) {
145  for (unsigned int i = 0; i < action->count_subaction_paths; ++i) {
146  MEM_SAFE_FREE(subaction_paths[i]);
147  }
148  MEM_freeN(subaction_paths);
149  }
150 
151  MEM_SAFE_FREE(action->states);
152  MEM_SAFE_FREE(action->states_prev);
153 
155  MEM_SAFE_FREE(action->axis_flags);
156 
157  MEM_SAFE_FREE(action->haptic_name);
158 
159  MEM_freeN(action);
160 }
161 
162 static wmXrAction *action_find(wmXrData *xr, const char *action_set_name, const char *action_name)
163 {
164  return GHOST_XrGetActionCustomdata(xr->runtime->context, action_set_name, action_name);
165 }
166 
167 bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name)
168 {
169  if (action_set_find(xr, action_set_name)) {
170  return false;
171  }
172 
173  wmXrActionSet *action_set = action_set_create(action_set_name);
174 
175  GHOST_XrActionSetInfo info = {
176  .name = action_set_name,
177  .customdata_free_fn = action_set_destroy,
178  .customdata = action_set,
179  };
180 
181  if (!GHOST_XrCreateActionSet(xr->runtime->context, &info)) {
182  return false;
183  }
184 
185  return true;
186 }
187 
188 void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name)
189 {
190  wmXrActionSet *action_set = action_set_find(xr, action_set_name);
191  if (!action_set) {
192  return;
193  }
194 
195  wmXrSessionState *session_state = &xr->runtime->session_state;
196 
197  if (action_set == session_state->active_action_set) {
198  if (action_set->controller_grip_action || action_set->controller_aim_action) {
200  action_set->controller_grip_action = action_set->controller_aim_action = NULL;
201  }
202 
203  BLI_freelistN(&action_set->active_modal_actions);
204  BLI_freelistN(&action_set->active_haptic_actions);
205 
206  session_state->active_action_set = NULL;
207  }
208 
209  GHOST_XrDestroyActionSet(xr->runtime->context, action_set_name);
210 }
211 
213  const char *action_set_name,
214  const char *action_name,
216  const ListBase *user_paths,
218  IDProperty *op_properties,
219  const char *haptic_name,
220  const int64_t *haptic_duration,
221  const float *haptic_frequency,
222  const float *haptic_amplitude,
223  eXrOpFlag op_flag,
224  eXrActionFlag action_flag,
225  eXrHapticFlag haptic_flag)
226 {
227  if (action_find(xr, action_set_name, action_name)) {
228  return false;
229  }
230 
231  wmXrAction *action = action_create(action_name,
232  type,
233  user_paths,
234  ot,
235  op_properties,
236  haptic_name,
237  haptic_duration,
238  haptic_frequency,
239  haptic_amplitude,
240  op_flag,
241  action_flag,
242  haptic_flag);
243 
244  const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
245  unsigned int subaction_idx = 0;
246 
247  char **subaction_paths = MEM_calloc_arrayN(
248  count, sizeof(*subaction_paths), "XrAction_SubactionPathPointers");
249 
250  LISTBASE_FOREACH_INDEX (XrUserPath *, user_path, user_paths, subaction_idx) {
251  subaction_paths[subaction_idx] = (char *)user_path->path;
252  }
253 
254  GHOST_XrActionInfo info = {
255  .name = action_name,
256  .count_subaction_paths = count,
257  .subaction_paths = (const char **)subaction_paths,
258  .states = action->states,
259  .float_thresholds = action->float_thresholds,
260  .axis_flags = (int16_t *)action->axis_flags,
261  .customdata_free_fn = action_destroy,
262  .customdata = action,
263  };
264 
265  switch (type) {
266  case XR_BOOLEAN_INPUT:
267  info.type = GHOST_kXrActionTypeBooleanInput;
268  break;
269  case XR_FLOAT_INPUT:
270  info.type = GHOST_kXrActionTypeFloatInput;
271  break;
272  case XR_VECTOR2F_INPUT:
273  info.type = GHOST_kXrActionTypeVector2fInput;
274  break;
275  case XR_POSE_INPUT:
276  info.type = GHOST_kXrActionTypePoseInput;
277  break;
278  case XR_VIBRATION_OUTPUT:
279  info.type = GHOST_kXrActionTypeVibrationOutput;
280  break;
281  }
282 
283  const bool success = GHOST_XrCreateActions(xr->runtime->context, action_set_name, 1, &info);
284 
285  MEM_freeN(subaction_paths);
286 
287  return success;
288 }
289 
290 void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name)
291 {
292  wmXrActionSet *action_set = action_set_find(xr, action_set_name);
293  if (!action_set) {
294  return;
295  }
296 
297  wmXrAction *action = action_find(xr, action_set_name, action_name);
298  if (!action) {
299  return;
300  }
301 
302  if ((action_set->controller_grip_action &&
303  STREQ(action_set->controller_grip_action->name, action_name)) ||
304  (action_set->controller_aim_action &&
305  STREQ(action_set->controller_aim_action->name, action_name))) {
306  if (action_set == xr->runtime->session_state.active_action_set) {
308  }
309  action_set->controller_grip_action = action_set->controller_aim_action = NULL;
310  }
311 
312  LISTBASE_FOREACH (LinkData *, ld, &action_set->active_modal_actions) {
313  wmXrAction *active_modal_action = ld->data;
314  if (STREQ(active_modal_action->name, action_name)) {
315  BLI_freelinkN(&action_set->active_modal_actions, ld);
316  break;
317  }
318  }
319 
321  if (STREQ(ha->action->name, action_name)) {
322  BLI_freelinkN(&action_set->active_haptic_actions, ha);
323  }
324  }
325 
326  GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name);
327 }
328 
330  const char *action_set_name,
331  const char *action_name,
332  const char *profile_path,
333  const ListBase *user_paths,
334  const ListBase *component_paths,
335  const float *float_thresholds,
336  const eXrAxisFlag *axis_flags,
337  const struct wmXrPose *poses)
338 {
339  const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
340  BLI_assert(count == (unsigned int)BLI_listbase_count(component_paths));
341 
342  GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN(
343  count, sizeof(*binding_infos), "XrActionBinding_Infos");
344 
345  char **subaction_paths = MEM_calloc_arrayN(
346  count, sizeof(*subaction_paths), "XrActionBinding_SubactionPathPointers");
347 
348  for (unsigned int i = 0; i < count; ++i) {
349  GHOST_XrActionBindingInfo *binding_info = &binding_infos[i];
350  const XrUserPath *user_path = BLI_findlink(user_paths, i);
351  const XrComponentPath *component_path = BLI_findlink(component_paths, i);
352 
353  subaction_paths[i] = (char *)user_path->path;
354 
355  binding_info->component_path = component_path->path;
356  if (float_thresholds) {
357  binding_info->float_threshold = float_thresholds[i];
358  }
359  if (axis_flags) {
360  binding_info->axis_flag = axis_flags[i];
361  }
362  if (poses) {
363  copy_v3_v3(binding_info->pose.position, poses[i].position);
364  copy_qt_qt(binding_info->pose.orientation_quat, poses[i].orientation_quat);
365  }
366  }
367 
368  GHOST_XrActionProfileInfo profile_info = {
369  .action_name = action_name,
370  .profile_path = profile_path,
371  .count_subaction_paths = count,
372  .subaction_paths = (const char **)subaction_paths,
373  .bindings = binding_infos,
374  };
375 
376  const bool success = GHOST_XrCreateActionBindings(
377  xr->runtime->context, action_set_name, 1, &profile_info);
378 
379  MEM_freeN(subaction_paths);
380  MEM_freeN(binding_infos);
381 
382  return success;
383 }
384 
386  const char *action_set_name,
387  const char *action_name,
388  const char *profile_path)
389 {
390  GHOST_XrDestroyActionBindings(
391  xr->runtime->context, action_set_name, 1, &action_name, &profile_path);
392 }
393 
394 bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name, bool delayed)
395 {
396  wmXrActionSet *action_set = action_set_find(xr, action_set_name);
397  if (!action_set) {
398  return false;
399  }
400 
401  if (delayed) {
402  /* Save name to activate action set later, before next actions sync
403  * (see #wm_xr_session_actions_update()). */
404  strcpy(xr->runtime->session_state.active_action_set_next, action_set_name);
405  return true;
406  }
407 
408  {
409  /* Clear any active modal/haptic actions. */
410  wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set;
411  if (active_action_set) {
412  BLI_freelistN(&active_action_set->active_modal_actions);
413  BLI_freelistN(&active_action_set->active_haptic_actions);
414  }
415  }
416 
417  xr->runtime->session_state.active_action_set = action_set;
418 
419  if (action_set->controller_grip_action && action_set->controller_aim_action) {
421  action_set->controller_grip_action, action_set->controller_aim_action, xr);
422  }
423  else {
425  }
426 
427  return true;
428 }
429 
431  const char *action_set_name,
432  const char *grip_action_name,
433  const char *aim_action_name)
434 {
435  wmXrActionSet *action_set = action_set_find(xr, action_set_name);
436  if (!action_set) {
437  return false;
438  }
439 
440  wmXrAction *grip_action = action_find(xr, action_set_name, grip_action_name);
441  if (!grip_action) {
442  return false;
443  }
444 
445  wmXrAction *aim_action = action_find(xr, action_set_name, aim_action_name);
446  if (!aim_action) {
447  return false;
448  }
449 
450  /* Ensure consistent subaction paths. */
451  const unsigned int count = grip_action->count_subaction_paths;
452  if (count != aim_action->count_subaction_paths) {
453  return false;
454  }
455 
456  for (unsigned int i = 0; i < count; ++i) {
457  if (!STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i])) {
458  return false;
459  }
460  }
461 
462  action_set->controller_grip_action = grip_action;
463  action_set->controller_aim_action = aim_action;
464 
465  if (action_set == xr->runtime->session_state.active_action_set) {
466  wm_xr_session_controller_data_populate(grip_action, aim_action, xr);
467  }
468 
469  return true;
470 }
471 
473  const char *action_set_name,
474  const char *action_name,
475  const char *subaction_path,
476  wmXrActionState *r_state)
477 {
478  const wmXrAction *action = action_find((wmXrData *)xr, action_set_name, action_name);
479  if (!action) {
480  return false;
481  }
482 
483  r_state->type = (int)action->type;
484 
485  /* Find the action state corresponding to the subaction path. */
486  for (unsigned int i = 0; i < action->count_subaction_paths; ++i) {
487  if (STREQ(subaction_path, action->subaction_paths[i])) {
488  switch (action->type) {
489  case XR_BOOLEAN_INPUT:
490  r_state->state_boolean = ((bool *)action->states)[i];
491  break;
492  case XR_FLOAT_INPUT:
493  r_state->state_float = ((float *)action->states)[i];
494  break;
495  case XR_VECTOR2F_INPUT:
496  copy_v2_v2(r_state->state_vector2f, ((float(*)[2])action->states)[i]);
497  break;
498  case XR_POSE_INPUT: {
499  const GHOST_XrPose *pose = &((GHOST_XrPose *)action->states)[i];
500  copy_v3_v3(r_state->state_pose.position, pose->position);
501  copy_qt_qt(r_state->state_pose.orientation_quat, pose->orientation_quat);
502  break;
503  }
504  case XR_VIBRATION_OUTPUT:
506  break;
507  }
508  return true;
509  }
510  }
511 
512  return false;
513 }
514 
516  const char *action_set_name,
517  const char *action_name,
518  const char *subaction_path,
519  const int64_t *duration,
520  const float *frequency,
521  const float *amplitude)
522 {
523  return GHOST_XrApplyHapticAction(xr->runtime->context,
524  action_set_name,
525  action_name,
526  subaction_path,
527  duration,
528  frequency,
529  amplitude) ?
530  true :
531  false;
532 }
533 
535  const char *action_set_name,
536  const char *action_name,
537  const char *subaction_path)
538 {
539  GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name, subaction_path);
540 }
541  /* XR-Action API */
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
#define STREQ(a, b)
eXrOpFlag
Definition: DNA_xr_types.h:73
eXrAxisFlag
Definition: DNA_xr_types.h:100
eXrActionType
Definition: DNA_xr_types.h:64
@ XR_FLOAT_INPUT
Definition: DNA_xr_types.h:66
@ XR_BOOLEAN_INPUT
Definition: DNA_xr_types.h:65
@ XR_VECTOR2F_INPUT
Definition: DNA_xr_types.h:67
@ XR_POSE_INPUT
Definition: DNA_xr_types.h:68
@ XR_VIBRATION_OUTPUT
Definition: DNA_xr_types.h:69
eXrActionFlag
Definition: DNA_xr_types.h:79
eXrHapticFlag
Definition: DNA_xr_types.h:84
GHOST C-API function and type declarations.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
int count
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
signed short int16_t
Definition: stdint.h:76
__int64 int64_t
Definition: stdint.h:89
char path[192]
Definition: DNA_xr_types.h:127
char path[64]
Definition: DNA_xr_types.h:155
wmXrAction * controller_aim_action
Definition: wm_xr_intern.h:180
wmXrAction * controller_grip_action
Definition: wm_xr_intern.h:179
ListBase active_modal_actions
Definition: wm_xr_intern.h:183
ListBase active_haptic_actions
Definition: wm_xr_intern.h:185
eXrActionType type
Definition: wm_xr_intern.h:137
struct wmOperatorType * ot
Definition: wm_xr_intern.h:153
eXrAxisFlag * axis_flags
Definition: wm_xr_intern.h:147
void * states
Definition: wm_xr_intern.h:141
char * haptic_name
Definition: wm_xr_intern.h:157
unsigned int count_subaction_paths
Definition: wm_xr_intern.h:138
void * states_prev
Definition: wm_xr_intern.h:143
eXrOpFlag op_flag
Definition: wm_xr_intern.h:163
char * name
Definition: wm_xr_intern.h:136
float haptic_frequency
Definition: wm_xr_intern.h:159
int64_t haptic_duration
Definition: wm_xr_intern.h:158
eXrActionFlag action_flag
Definition: wm_xr_intern.h:164
char ** subaction_paths
Definition: wm_xr_intern.h:139
float * float_thresholds
Definition: wm_xr_intern.h:146
float haptic_amplitude
Definition: wm_xr_intern.h:160
eXrHapticFlag haptic_flag
Definition: wm_xr_intern.h:165
IDProperty * op_properties
Definition: wm_xr_intern.h:154
struct wmXrRuntimeData * runtime
GHOST_XrContextHandle context
Definition: wm_xr_intern.h:65
wmXrSessionState session_state
Definition: wm_xr_intern.h:75
char active_action_set_next[64]
Definition: wm_xr_intern.h:61
struct wmXrActionSet * active_action_set
Definition: wm_xr_intern.h:59
wmOperatorType * ot
Definition: wm_files.c:3479
static wmXrActionSet * action_set_find(wmXrData *xr, const char *action_set_name)
Definition: wm_xr_action.c:52
bool WM_xr_action_state_get(const wmXrData *xr, const char *action_set_name, const char *action_name, const char *subaction_path, wmXrActionState *r_state)
Definition: wm_xr_action.c:472
static wmXrAction * action_find(wmXrData *xr, const char *action_set_name, const char *action_name)
Definition: wm_xr_action.c:162
bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, const char *action_name, const char *profile_path, const ListBase *user_paths, const ListBase *component_paths, const float *float_thresholds, const eXrAxisFlag *axis_flags, const struct wmXrPose *poses)
Definition: wm_xr_action.c:329
static wmXrActionSet * action_set_create(const char *action_set_name)
Definition: wm_xr_action.c:31
void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name)
Definition: wm_xr_action.c:290
void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name, const char *subaction_path)
Definition: wm_xr_action.c:534
bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name)
Definition: wm_xr_action.c:167
void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, const char *action_name, const char *profile_path)
Definition: wm_xr_action.c:385
bool WM_xr_action_create(wmXrData *xr, const char *action_set_name, const char *action_name, eXrActionType type, const ListBase *user_paths, wmOperatorType *ot, IDProperty *op_properties, const char *haptic_name, const int64_t *haptic_duration, const float *haptic_frequency, const float *haptic_amplitude, eXrOpFlag op_flag, eXrActionFlag action_flag, eXrHapticFlag haptic_flag)
Definition: wm_xr_action.c:212
void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name)
Definition: wm_xr_action.c:188
bool WM_xr_controller_pose_actions_set(wmXrData *xr, const char *action_set_name, const char *grip_action_name, const char *aim_action_name)
Definition: wm_xr_action.c:430
static wmXrAction * action_create(const char *action_name, eXrActionType type, const ListBase *user_paths, wmOperatorType *ot, IDProperty *op_properties, const char *haptic_name, const int64_t *haptic_duration, const float *haptic_frequency, const float *haptic_amplitude, eXrOpFlag op_flag, eXrActionFlag action_flag, eXrHapticFlag haptic_flag)
Definition: wm_xr_action.c:57
static void action_set_destroy(void *val)
Definition: wm_xr_action.c:40
static void action_destroy(void *val)
Definition: wm_xr_action.c:137
bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, const char *subaction_path, const int64_t *duration, const float *frequency, const float *amplitude)
Definition: wm_xr_action.c:515
bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name, bool delayed)
Definition: wm_xr_action.c:394
void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, const wmXrAction *aim_action, wmXrData *xr)
void wm_xr_session_controller_data_clear(wmXrSessionState *state)