Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/openxr/action_map/openxr_action_map.cpp
10278 views
1
/**************************************************************************/
2
/* openxr_action_map.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "openxr_action_map.h"
32
33
void OpenXRActionMap::_bind_methods() {
34
ClassDB::bind_method(D_METHOD("set_action_sets", "action_sets"), &OpenXRActionMap::set_action_sets);
35
ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRActionMap::get_action_sets);
36
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "action_sets", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRActionSet", PROPERTY_USAGE_NO_EDITOR), "set_action_sets", "get_action_sets");
37
38
ClassDB::bind_method(D_METHOD("get_action_set_count"), &OpenXRActionMap::get_action_set_count);
39
ClassDB::bind_method(D_METHOD("find_action_set", "name"), &OpenXRActionMap::find_action_set);
40
ClassDB::bind_method(D_METHOD("get_action_set", "idx"), &OpenXRActionMap::get_action_set);
41
ClassDB::bind_method(D_METHOD("add_action_set", "action_set"), &OpenXRActionMap::add_action_set);
42
ClassDB::bind_method(D_METHOD("remove_action_set", "action_set"), &OpenXRActionMap::remove_action_set);
43
44
ClassDB::bind_method(D_METHOD("set_interaction_profiles", "interaction_profiles"), &OpenXRActionMap::set_interaction_profiles);
45
ClassDB::bind_method(D_METHOD("get_interaction_profiles"), &OpenXRActionMap::get_interaction_profiles);
46
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "interaction_profiles", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRInteractionProfile", PROPERTY_USAGE_NO_EDITOR), "set_interaction_profiles", "get_interaction_profiles");
47
48
ClassDB::bind_method(D_METHOD("get_interaction_profile_count"), &OpenXRActionMap::get_interaction_profile_count);
49
ClassDB::bind_method(D_METHOD("find_interaction_profile", "name"), &OpenXRActionMap::find_interaction_profile);
50
ClassDB::bind_method(D_METHOD("get_interaction_profile", "idx"), &OpenXRActionMap::get_interaction_profile);
51
ClassDB::bind_method(D_METHOD("add_interaction_profile", "interaction_profile"), &OpenXRActionMap::add_interaction_profile);
52
ClassDB::bind_method(D_METHOD("remove_interaction_profile", "interaction_profile"), &OpenXRActionMap::remove_interaction_profile);
53
54
ClassDB::bind_method(D_METHOD("create_default_action_sets"), &OpenXRActionMap::create_default_action_sets);
55
}
56
57
void OpenXRActionMap::set_action_sets(Array p_action_sets) {
58
action_sets.clear();
59
60
for (int i = 0; i < p_action_sets.size(); i++) {
61
Ref<OpenXRActionSet> action_set = p_action_sets[i];
62
if (action_set.is_valid() && !action_sets.has(action_set)) {
63
action_sets.push_back(action_set);
64
}
65
}
66
}
67
68
Array OpenXRActionMap::get_action_sets() const {
69
return action_sets;
70
}
71
72
int OpenXRActionMap::get_action_set_count() const {
73
return action_sets.size();
74
}
75
76
Ref<OpenXRActionSet> OpenXRActionMap::find_action_set(String p_name) const {
77
for (int i = 0; i < action_sets.size(); i++) {
78
Ref<OpenXRActionSet> action_set = action_sets[i];
79
if (action_set->get_name() == p_name) {
80
return action_set;
81
}
82
}
83
84
return Ref<OpenXRActionSet>();
85
}
86
87
Ref<OpenXRActionSet> OpenXRActionMap::get_action_set(int p_idx) const {
88
ERR_FAIL_INDEX_V(p_idx, action_sets.size(), Ref<OpenXRActionSet>());
89
90
return action_sets[p_idx];
91
}
92
93
void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) {
94
ERR_FAIL_COND(p_action_set.is_null());
95
96
if (!action_sets.has(p_action_set)) {
97
action_sets.push_back(p_action_set);
98
emit_changed();
99
}
100
}
101
102
void OpenXRActionMap::remove_action_set(Ref<OpenXRActionSet> p_action_set) {
103
int idx = action_sets.find(p_action_set);
104
if (idx != -1) {
105
action_sets.remove_at(idx);
106
emit_changed();
107
}
108
}
109
110
void OpenXRActionMap::clear_interaction_profiles() {
111
if (interaction_profiles.is_empty()) {
112
return;
113
}
114
115
// Interaction profiles held within our action map set should be released and destroyed but just in case they are still used some where else.
116
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
117
interaction_profile->action_map = nullptr;
118
}
119
interaction_profiles.clear();
120
emit_changed();
121
}
122
123
void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) {
124
clear_interaction_profiles();
125
126
for (const Variant &interaction_profile : p_interaction_profiles) {
127
// Add them anew so we verify our interaction profile pointer.
128
add_interaction_profile(interaction_profile);
129
}
130
}
131
132
Array OpenXRActionMap::get_interaction_profiles() const {
133
return interaction_profiles;
134
}
135
136
int OpenXRActionMap::get_interaction_profile_count() const {
137
return interaction_profiles.size();
138
}
139
140
Ref<OpenXRInteractionProfile> OpenXRActionMap::find_interaction_profile(String p_path) const {
141
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
142
if (interaction_profile->get_interaction_profile_path() == p_path) {
143
return interaction_profile;
144
}
145
}
146
147
return Ref<OpenXRInteractionProfile>();
148
}
149
150
Ref<OpenXRInteractionProfile> OpenXRActionMap::get_interaction_profile(int p_idx) const {
151
ERR_FAIL_INDEX_V(p_idx, interaction_profiles.size(), Ref<OpenXRInteractionProfile>());
152
153
return interaction_profiles[p_idx];
154
}
155
156
void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
157
ERR_FAIL_COND(p_interaction_profile.is_null());
158
159
if (!interaction_profiles.has(p_interaction_profile)) {
160
if (p_interaction_profile->action_map && p_interaction_profile->action_map != this) {
161
// Interaction profiles should only relate to our action map.
162
p_interaction_profile->action_map->remove_interaction_profile(p_interaction_profile);
163
}
164
165
p_interaction_profile->action_map = this;
166
167
interaction_profiles.push_back(p_interaction_profile);
168
emit_changed();
169
}
170
}
171
172
void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
173
int idx = interaction_profiles.find(p_interaction_profile);
174
if (idx != -1) {
175
interaction_profiles.remove_at(idx);
176
177
ERR_FAIL_COND_MSG(p_interaction_profile->action_map != this, "Removing interaction profile that belongs to this action map but had incorrect action map pointer."); // This should never happen!
178
p_interaction_profile->action_map = nullptr;
179
180
emit_changed();
181
}
182
}
183
184
void OpenXRActionMap::create_default_action_sets() {
185
// Note:
186
// - if you make changes here make sure to delete your default_action_map.tres file of it will load an old version.
187
// - our palm pose is only available if the relevant extension is supported,
188
// we still want it to be part of our action map as we may deploy the same game to platforms that do and don't support it.
189
// - the same applies for interaction profiles that are only supported if the relevant extension is supported.
190
191
// Create our Godot action set.
192
Ref<OpenXRActionSet> action_set = OpenXRActionSet::new_action_set("godot", "Godot action set");
193
add_action_set(action_set);
194
195
// Create our actions.
196
Ref<OpenXRAction> trigger = action_set->add_new_action("trigger", "Trigger", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
197
Ref<OpenXRAction> trigger_click = action_set->add_new_action("trigger_click", "Trigger click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
198
Ref<OpenXRAction> trigger_touch = action_set->add_new_action("trigger_touch", "Trigger touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
199
Ref<OpenXRAction> grip = action_set->add_new_action("grip", "Grip", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
200
Ref<OpenXRAction> grip_click = action_set->add_new_action("grip_click", "Grip click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
201
Ref<OpenXRAction> grip_force = action_set->add_new_action("grip_force", "Grip force", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
202
Ref<OpenXRAction> primary = action_set->add_new_action("primary", "Primary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
203
Ref<OpenXRAction> primary_click = action_set->add_new_action("primary_click", "Primary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
204
Ref<OpenXRAction> primary_touch = action_set->add_new_action("primary_touch", "Primary joystick/thumbstick/trackpad touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
205
Ref<OpenXRAction> secondary = action_set->add_new_action("secondary", "Secondary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
206
Ref<OpenXRAction> secondary_click = action_set->add_new_action("secondary_click", "Secondary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
207
Ref<OpenXRAction> secondary_touch = action_set->add_new_action("secondary_touch", "Secondary joystick/thumbstick/trackpad touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
208
Ref<OpenXRAction> menu_button = action_set->add_new_action("menu_button", "Menu button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
209
Ref<OpenXRAction> select_button = action_set->add_new_action("select_button", "Select button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
210
Ref<OpenXRAction> ax_button = action_set->add_new_action("ax_button", "A/X button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
211
Ref<OpenXRAction> ax_touch = action_set->add_new_action("ax_touch", "A/X touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
212
Ref<OpenXRAction> by_button = action_set->add_new_action("by_button", "B/Y button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
213
Ref<OpenXRAction> by_touch = action_set->add_new_action("by_touch", "B/Y touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
214
Ref<OpenXRAction> default_pose = action_set->add_new_action("default_pose", "Default pose", OpenXRAction::OPENXR_ACTION_POSE,
215
"/user/hand/left,"
216
"/user/hand/right,"
217
// "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one.
218
"/user/vive_tracker_htcx/role/left_foot,"
219
"/user/vive_tracker_htcx/role/right_foot,"
220
"/user/vive_tracker_htcx/role/left_shoulder,"
221
"/user/vive_tracker_htcx/role/right_shoulder,"
222
"/user/vive_tracker_htcx/role/left_elbow,"
223
"/user/vive_tracker_htcx/role/right_elbow,"
224
"/user/vive_tracker_htcx/role/left_knee,"
225
"/user/vive_tracker_htcx/role/right_knee,"
226
"/user/vive_tracker_htcx/role/waist,"
227
"/user/vive_tracker_htcx/role/chest,"
228
"/user/vive_tracker_htcx/role/camera,"
229
"/user/vive_tracker_htcx/role/keyboard,"
230
"/user/vive_tracker_htcx/role/left_wrist,"
231
"/user/vive_tracker_htcx/role/right_wrist,"
232
"/user/vive_tracker_htcx/role/left_ankle,"
233
"/user/vive_tracker_htcx/role/right_ankle,"
234
"/user/eyes_ext");
235
Ref<OpenXRAction> aim_pose = action_set->add_new_action("aim_pose", "Aim pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
236
Ref<OpenXRAction> grip_pose = action_set->add_new_action("grip_pose", "Grip pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
237
Ref<OpenXRAction> palm_pose = action_set->add_new_action("palm_pose", "Palm pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
238
Ref<OpenXRAction> haptic = action_set->add_new_action("haptic", "Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC,
239
"/user/hand/left,"
240
"/user/hand/right,"
241
// "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one.
242
"/user/vive_tracker_htcx/role/left_foot,"
243
"/user/vive_tracker_htcx/role/right_foot,"
244
"/user/vive_tracker_htcx/role/left_shoulder,"
245
"/user/vive_tracker_htcx/role/right_shoulder,"
246
"/user/vive_tracker_htcx/role/left_elbow,"
247
"/user/vive_tracker_htcx/role/right_elbow,"
248
"/user/vive_tracker_htcx/role/left_knee,"
249
"/user/vive_tracker_htcx/role/right_knee,"
250
"/user/vive_tracker_htcx/role/waist,"
251
"/user/vive_tracker_htcx/role/chest,"
252
"/user/vive_tracker_htcx/role/camera,"
253
"/user/vive_tracker_htcx/role/keyboard,"
254
"/user/vive_tracker_htcx/role/left_wrist,"
255
"/user/vive_tracker_htcx/role/right_wrist,"
256
"/user/vive_tracker_htcx/role/left_ankle,"
257
"/user/vive_tracker_htcx/role/right_ankle");
258
259
// Create our interaction profiles.
260
Ref<OpenXRInteractionProfile> profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/khr/simple_controller");
261
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
262
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
263
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
264
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
265
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
266
profile->add_new_binding(select_button, "/user/hand/left/input/select/click,/user/hand/right/input/select/click");
267
// generic has no support for triggers, grip, A/B buttons, nor joystick/trackpad inputs.
268
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
269
add_interaction_profile(profile);
270
271
// Create our Vive controller profile.
272
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_controller");
273
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
274
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
275
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
276
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
277
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
278
profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click");
279
// wmr controller has no a/b/x/y buttons.
280
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
281
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
282
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click"); // OpenXR will convert bool to float.
283
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
284
// primary on our vive controller is our trackpad.
285
profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
286
profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
287
profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
288
// vive controllers have no secondary input.
289
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
290
add_interaction_profile(profile);
291
292
// Create our WMR controller profile.
293
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/microsoft/motion_controller");
294
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
295
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
296
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
297
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
298
// wmr controllers have no select button we can use.
299
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
300
// wmr controller has no a/b/x/y buttons.
301
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
302
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); // OpenXR will convert float to bool.
303
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click"); // OpenXR will convert bool to float.
304
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
305
// primary on our wmr controller is our thumbstick, no touch.
306
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
307
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
308
// secondary on our wmr controller is our trackpad.
309
profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
310
profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
311
profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
312
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
313
add_interaction_profile(profile);
314
315
// Create our Meta touch controller profile.
316
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller");
317
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
318
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
319
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
320
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
321
// touch controllers have no select button we can use.
322
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/system/click"); // right hand system click may not be available.
323
profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand.
324
profile->add_new_binding(ax_touch, "/user/hand/left/input/x/touch,/user/hand/right/input/a/touch");
325
profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand.
326
profile->add_new_binding(by_touch, "/user/hand/left/input/y/touch,/user/hand/right/input/b/touch");
327
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
328
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); // should be converted to boolean.
329
profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
330
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value"); // should be converted to boolean.
331
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
332
// primary on our touch controller is our thumbstick.
333
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
334
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
335
profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
336
// touch controller has no secondary input.
337
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
338
add_interaction_profile(profile);
339
340
// Create our Pico 4 controller profile.
341
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/bytedance/pico4_controller");
342
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
343
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
344
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
345
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
346
profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click"); // system click may not be available.
347
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
348
profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand.
349
profile->add_new_binding(ax_touch, "/user/hand/left/input/x/touch,/user/hand/right/input/a/touch");
350
profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand.
351
profile->add_new_binding(by_touch, "/user/hand/left/input/y/touch,/user/hand/right/input/b/touch");
352
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
353
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); // should be converted to boolean.
354
profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
355
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value"); // should be converted to boolean.
356
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
357
// primary on our pico controller is our thumbstick.
358
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
359
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
360
profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
361
// pico controller has no secondary input.
362
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
363
add_interaction_profile(profile);
364
365
// Create our Valve index controller profile.
366
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/valve/index_controller");
367
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
368
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
369
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
370
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
371
// index controllers have no select button we can use.
372
profile->add_new_binding(menu_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click");
373
profile->add_new_binding(ax_button, "/user/hand/left/input/a/click,/user/hand/right/input/a/click"); // a on both controllers.
374
profile->add_new_binding(ax_touch, "/user/hand/left/input/a/touch,/user/hand/right/input/a/touch");
375
profile->add_new_binding(by_button, "/user/hand/left/input/b/click,/user/hand/right/input/b/click"); // b on both controllers.
376
profile->add_new_binding(by_touch, "/user/hand/left/input/b/touch,/user/hand/right/input/b/touch");
377
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
378
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
379
profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
380
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
381
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value"); // this should do a float to bool conversion.
382
profile->add_new_binding(grip_force, "/user/hand/left/input/squeeze/force,/user/hand/right/input/squeeze/force"); // grip force seems to be unique to the Valve Index.
383
// primary on our index controller is our thumbstick.
384
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
385
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
386
profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
387
// secondary on our index controller is our trackpad.
388
profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
389
profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/force,/user/hand/right/input/trackpad/force"); // not sure if this will work but doesn't seem to support click...
390
profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
391
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
392
add_interaction_profile(profile);
393
394
// Create our HP MR controller profile.
395
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_controller");
396
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
397
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
398
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
399
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
400
// hpmr controllers have no select button we can use.
401
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
402
// hpmr controllers only register click, not touch, on our a/b/x/y buttons.
403
profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand.
404
profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand.
405
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
406
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
407
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
408
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
409
// primary on our hpmr controller is our thumbstick.
410
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
411
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
412
// No secondary on our hpmr controller.
413
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
414
add_interaction_profile(profile);
415
416
// Create our Samsung Odyssey controller profile,
417
// Note that this controller is only identified specifically on WMR, on SteamVR this is identified as a normal WMR controller.
418
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/samsung/odyssey_controller");
419
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
420
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
421
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
422
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
423
// Odyssey controllers have no select button we can use.
424
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
425
// Odyssey controller has no a/b/x/y buttons.
426
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
427
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
428
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
429
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
430
// primary on our Odyssey controller is our thumbstick, no touch.
431
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
432
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
433
// secondary on our Odyssey controller is our trackpad.
434
profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
435
profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
436
profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
437
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
438
add_interaction_profile(profile);
439
440
// Create our Vive Cosmos controller.
441
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_cosmos_controller");
442
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
443
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
444
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
445
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
446
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
447
profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select.
448
profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand.
449
profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand.
450
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
451
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
452
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
453
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
454
// primary on our Cosmos controller is our thumbstick.
455
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
456
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
457
profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
458
// No secondary on our cosmos controller.
459
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
460
add_interaction_profile(profile);
461
462
// Create our Vive Focus 3 controller.
463
// Note, Vive Focus 3 currently is not yet supported as a stand alone device
464
// however HTC currently has a beta OpenXR runtime in testing we may support in the near future.
465
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_focus3_controller");
466
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
467
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
468
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
469
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
470
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
471
profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select.
472
profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand.
473
profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand.
474
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
475
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
476
profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
477
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
478
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
479
// primary on our Focus 3 controller is our thumbstick.
480
profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
481
profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
482
profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
483
// We only have a thumb rest.
484
profile->add_new_binding(secondary_touch, "/user/hand/left/input/thumbrest/touch,/user/hand/right/input/thumbrest/touch");
485
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
486
add_interaction_profile(profile);
487
488
// Create our Huawei controller.
489
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/huawei/controller");
490
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
491
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
492
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
493
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
494
profile->add_new_binding(menu_button, "/user/hand/left/input/home/click,/user/hand/right/input/home/click");
495
profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
496
profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
497
// primary on our Huawei controller is our trackpad.
498
profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
499
profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
500
profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
501
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
502
add_interaction_profile(profile);
503
504
// Create our HTC Vive tracker profile.
505
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_tracker_htcx");
506
profile->add_new_binding(default_pose,
507
// "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose," <-- getting errors on this one.
508
"/user/vive_tracker_htcx/role/left_foot/input/grip/pose,"
509
"/user/vive_tracker_htcx/role/right_foot/input/grip/pose,"
510
"/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose,"
511
"/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose,"
512
"/user/vive_tracker_htcx/role/left_elbow/input/grip/pose,"
513
"/user/vive_tracker_htcx/role/right_elbow/input/grip/pose,"
514
"/user/vive_tracker_htcx/role/left_knee/input/grip/pose,"
515
"/user/vive_tracker_htcx/role/right_knee/input/grip/pose,"
516
"/user/vive_tracker_htcx/role/waist/input/grip/pose,"
517
"/user/vive_tracker_htcx/role/chest/input/grip/pose,"
518
"/user/vive_tracker_htcx/role/camera/input/grip/pose,"
519
"/user/vive_tracker_htcx/role/keyboard/input/grip/pose,"
520
"/user/vive_tracker_htcx/role/left_wrist/input/grip/pose,"
521
"/user/vive_tracker_htcx/role/right_wrist/input/grip/pose,"
522
"/user/vive_tracker_htcx/role/left_ankle/input/grip/pose,"
523
"/user/vive_tracker_htcx/role/right_ankle/input/grip/pose");
524
profile->add_new_binding(haptic,
525
// "/user/vive_tracker_htcx/role/handheld_object/output/haptic," <-- getting errors on this one.
526
"/user/vive_tracker_htcx/role/left_foot/output/haptic,"
527
"/user/vive_tracker_htcx/role/right_foot/output/haptic,"
528
"/user/vive_tracker_htcx/role/left_shoulder/output/haptic,"
529
"/user/vive_tracker_htcx/role/right_shoulder/output/haptic,"
530
"/user/vive_tracker_htcx/role/left_elbow/output/haptic,"
531
"/user/vive_tracker_htcx/role/right_elbow/output/haptic,"
532
"/user/vive_tracker_htcx/role/left_knee/output/haptic,"
533
"/user/vive_tracker_htcx/role/right_knee/output/haptic,"
534
"/user/vive_tracker_htcx/role/waist/output/haptic,"
535
"/user/vive_tracker_htcx/role/chest/output/haptic,"
536
"/user/vive_tracker_htcx/role/camera/output/haptic,"
537
"/user/vive_tracker_htcx/role/keyboard/output/haptic,"
538
"/user/vive_tracker_htcx/role/left_wrist/output/haptic,"
539
"/user/vive_tracker_htcx/role/right_wrist/output/haptic,"
540
"/user/vive_tracker_htcx/role/left_ankle/output/haptic,"
541
"/user/vive_tracker_htcx/role/right_ankle/output/haptic");
542
add_interaction_profile(profile);
543
544
// Create our eye gaze interaction profile.
545
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/ext/eye_gaze_interaction");
546
profile->add_new_binding(default_pose, "/user/eyes_ext/input/gaze_ext/pose");
547
add_interaction_profile(profile);
548
549
// Create our hand interaction profile.
550
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/ext/hand_interaction_ext");
551
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
552
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
553
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
554
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
555
556
// Use pinch as primary.
557
profile->add_new_binding(primary, "/user/hand/left/input/pinch_ext/value,/user/hand/right/input/pinch_ext/value");
558
profile->add_new_binding(primary_click, "/user/hand/left/input/pinch_ext/ready_ext,/user/hand/right/input/pinch_ext/ready_ext");
559
560
// Use activation as secondary.
561
profile->add_new_binding(secondary, "/user/hand/left/input/aim_activate_ext/value,/user/hand/right/input/aim_activate_ext/value");
562
profile->add_new_binding(secondary_click, "/user/hand/left/input/aim_activate_ext/ready_ext,/user/hand/right/input/aim_activate_ext/ready_ext");
563
564
// We link grasp to our grip.
565
profile->add_new_binding(grip, "/user/hand/left/input/grasp_ext/value,/user/hand/right/input/grasp_ext/value");
566
profile->add_new_binding(grip_click, "/user/hand/left/input/grasp_ext/ready_ext,/user/hand/right/input/grasp_ext/ready_ext");
567
add_interaction_profile(profile);
568
}
569
570
void OpenXRActionMap::create_editor_action_sets() {
571
// TODO implement
572
}
573
574
Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const {
575
PackedStringArray paths = p_path.split("/", false);
576
ERR_FAIL_COND_V(paths.size() != 2, Ref<OpenXRAction>());
577
578
Ref<OpenXRActionSet> action_set = find_action_set(paths[0]);
579
if (action_set.is_valid()) {
580
return action_set->get_action(paths[1]);
581
}
582
583
return Ref<OpenXRAction>();
584
}
585
586
void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interaction_profiles) {
587
Ref<OpenXRAction> action = get_action(p_path);
588
if (action.is_valid()) {
589
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
590
if (p_remove_interaction_profiles) {
591
// Remove any bindings for this action
592
interaction_profile->remove_binding_for_action(action);
593
} else {
594
ERR_FAIL_COND(interaction_profile->has_binding_for_action(action));
595
}
596
}
597
598
OpenXRActionSet *action_set = action->get_action_set();
599
if (action_set != nullptr) {
600
// Remove the action from this action set
601
action_set->remove_action(action);
602
}
603
}
604
}
605
606
PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) {
607
PackedStringArray arr;
608
609
for (Ref<OpenXRInteractionProfile> ip : interaction_profiles) {
610
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path());
611
612
if (profile != nullptr) {
613
Vector<Ref<OpenXRIPBinding>> bindings = ip->get_bindings_for_action(p_action);
614
for (const Ref<OpenXRIPBinding> &binding : bindings) {
615
String binding_path = binding->get_binding_path();
616
const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(binding_path);
617
if (io_path != nullptr) {
618
String top_path = io_path->top_level_path;
619
620
if (!arr.has(top_path)) {
621
arr.push_back(top_path);
622
}
623
}
624
}
625
}
626
}
627
628
// print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr);
629
630
return arr;
631
}
632
633
OpenXRActionMap::~OpenXRActionMap() {
634
action_sets.clear();
635
clear_interaction_profiles();
636
}
637
638