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.find(action_set) == -1) { |
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.find(p_action_set) == -1) { |
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::set_interaction_profiles(Array p_interaction_profiles) { |
111 | interaction_profiles.clear(); |
112 | |
113 | for (int i = 0; i < p_interaction_profiles.size(); i++) { |
114 | Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profiles[i]; |
115 | if (interaction_profile.is_valid() && interaction_profiles.find(interaction_profile) == -1) { |
116 | interaction_profiles.push_back(interaction_profile); |
117 | } |
118 | } |
119 | } |
120 | |
121 | Array OpenXRActionMap::get_interaction_profiles() const { |
122 | return interaction_profiles; |
123 | } |
124 | |
125 | int OpenXRActionMap::get_interaction_profile_count() const { |
126 | return interaction_profiles.size(); |
127 | } |
128 | |
129 | Ref<OpenXRInteractionProfile> OpenXRActionMap::find_interaction_profile(String p_path) const { |
130 | for (int i = 0; i < interaction_profiles.size(); i++) { |
131 | Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i]; |
132 | if (interaction_profile->get_interaction_profile_path() == p_path) { |
133 | return interaction_profile; |
134 | } |
135 | } |
136 | |
137 | return Ref<OpenXRInteractionProfile>(); |
138 | } |
139 | |
140 | Ref<OpenXRInteractionProfile> OpenXRActionMap::get_interaction_profile(int p_idx) const { |
141 | ERR_FAIL_INDEX_V(p_idx, interaction_profiles.size(), Ref<OpenXRInteractionProfile>()); |
142 | |
143 | return interaction_profiles[p_idx]; |
144 | } |
145 | |
146 | void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) { |
147 | ERR_FAIL_COND(p_interaction_profile.is_null()); |
148 | |
149 | if (interaction_profiles.find(p_interaction_profile) == -1) { |
150 | interaction_profiles.push_back(p_interaction_profile); |
151 | emit_changed(); |
152 | } |
153 | } |
154 | |
155 | void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) { |
156 | int idx = interaction_profiles.find(p_interaction_profile); |
157 | if (idx != -1) { |
158 | interaction_profiles.remove_at(idx); |
159 | emit_changed(); |
160 | } |
161 | } |
162 | |
163 | void OpenXRActionMap::create_default_action_sets() { |
164 | // Note: |
165 | // - if you make changes here make sure to delete your default_action_map.tres file of it will load an old version. |
166 | // - our palm pose is only available if the relevant extension is supported, |
167 | // 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. |
168 | // - the same applies for interaction profiles that are only supported if the relevant extension is supported. |
169 | |
170 | // Create our Godot action set |
171 | Ref<OpenXRActionSet> action_set = OpenXRActionSet::new_action_set("godot" , "Godot action set" ); |
172 | add_action_set(action_set); |
173 | |
174 | // Create our actions |
175 | Ref<OpenXRAction> trigger = action_set->add_new_action("trigger" , "Trigger" , OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right" ); |
176 | Ref<OpenXRAction> trigger_click = action_set->add_new_action("trigger_click" , "Trigger click" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
177 | Ref<OpenXRAction> trigger_touch = action_set->add_new_action("trigger_touch" , "Trigger touching" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
178 | Ref<OpenXRAction> grip = action_set->add_new_action("grip" , "Grip" , OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right" ); |
179 | Ref<OpenXRAction> grip_click = action_set->add_new_action("grip_click" , "Grip click" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
180 | Ref<OpenXRAction> grip_touch = action_set->add_new_action("grip_touch" , "Grip touching" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
181 | Ref<OpenXRAction> grip_force = action_set->add_new_action("grip_force" , "Grip force" , OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right" ); |
182 | Ref<OpenXRAction> primary = action_set->add_new_action("primary" , "Primary joystick/thumbstick/trackpad" , OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right" ); |
183 | 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" ); |
184 | 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" ); |
185 | Ref<OpenXRAction> secondary = action_set->add_new_action("secondary" , "Secondary joystick/thumbstick/trackpad" , OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right" ); |
186 | 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" ); |
187 | 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" ); |
188 | Ref<OpenXRAction> = action_set->add_new_action("menu_button" , "Menu button" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
189 | Ref<OpenXRAction> select_button = action_set->add_new_action("select_button" , "Select button" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
190 | Ref<OpenXRAction> ax_button = action_set->add_new_action("ax_button" , "A/X button" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
191 | Ref<OpenXRAction> ax_touch = action_set->add_new_action("ax_touch" , "A/X touching" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
192 | Ref<OpenXRAction> by_button = action_set->add_new_action("by_button" , "B/Y button" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
193 | Ref<OpenXRAction> by_touch = action_set->add_new_action("by_touch" , "B/Y touching" , OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right" ); |
194 | Ref<OpenXRAction> default_pose = action_set->add_new_action("default_pose" , "Default pose" , OpenXRAction::OPENXR_ACTION_POSE, |
195 | "/user/hand/left," |
196 | "/user/hand/right," |
197 | // "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one |
198 | "/user/vive_tracker_htcx/role/left_foot," |
199 | "/user/vive_tracker_htcx/role/right_foot," |
200 | "/user/vive_tracker_htcx/role/left_shoulder," |
201 | "/user/vive_tracker_htcx/role/right_shoulder," |
202 | "/user/vive_tracker_htcx/role/left_elbow," |
203 | "/user/vive_tracker_htcx/role/right_elbow," |
204 | "/user/vive_tracker_htcx/role/left_knee," |
205 | "/user/vive_tracker_htcx/role/right_knee," |
206 | "/user/vive_tracker_htcx/role/waist," |
207 | "/user/vive_tracker_htcx/role/chest," |
208 | "/user/vive_tracker_htcx/role/camera," |
209 | "/user/vive_tracker_htcx/role/keyboard" ); |
210 | Ref<OpenXRAction> aim_pose = action_set->add_new_action("aim_pose" , "Aim pose" , OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right" ); |
211 | Ref<OpenXRAction> grip_pose = action_set->add_new_action("grip_pose" , "Grip pose" , OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right" ); |
212 | Ref<OpenXRAction> palm_pose = action_set->add_new_action("palm_pose" , "Palm pose" , OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right" ); |
213 | Ref<OpenXRAction> haptic = action_set->add_new_action("haptic" , "Haptic" , OpenXRAction::OPENXR_ACTION_HAPTIC, |
214 | "/user/hand/left," |
215 | "/user/hand/right," |
216 | // "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one |
217 | "/user/vive_tracker_htcx/role/left_foot," |
218 | "/user/vive_tracker_htcx/role/right_foot," |
219 | "/user/vive_tracker_htcx/role/left_shoulder," |
220 | "/user/vive_tracker_htcx/role/right_shoulder," |
221 | "/user/vive_tracker_htcx/role/left_elbow," |
222 | "/user/vive_tracker_htcx/role/right_elbow," |
223 | "/user/vive_tracker_htcx/role/left_knee," |
224 | "/user/vive_tracker_htcx/role/right_knee," |
225 | "/user/vive_tracker_htcx/role/waist," |
226 | "/user/vive_tracker_htcx/role/chest," |
227 | "/user/vive_tracker_htcx/role/camera," |
228 | "/user/vive_tracker_htcx/role/keyboard" ); |
229 | |
230 | // Create our interaction profiles |
231 | Ref<OpenXRInteractionProfile> profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/khr/simple_controller" ); |
232 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
233 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
234 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
235 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
236 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click" ); |
237 | profile->add_new_binding(select_button, "/user/hand/left/input/select/click,/user/hand/right/input/select/click" ); |
238 | // generic has no support for triggers, grip, A/B buttons, nor joystick/trackpad inputs |
239 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
240 | add_interaction_profile(profile); |
241 | |
242 | // Create our Vive controller profile |
243 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_controller" ); |
244 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
245 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
246 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
247 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
248 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click" ); |
249 | profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click" ); |
250 | // wmr controller has no a/b/x/y buttons |
251 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
252 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click" ); |
253 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); // OpenXR will convert bool to float |
254 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
255 | // primary on our vive controller is our trackpad |
256 | profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad" ); |
257 | profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click" ); |
258 | profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch" ); |
259 | // vive controllers have no secondary input |
260 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
261 | add_interaction_profile(profile); |
262 | |
263 | // Create our WMR controller profile |
264 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/microsoft/motion_controller" ); |
265 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
266 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
267 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
268 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
269 | // wmr controllers have no select button we can use |
270 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click" ); |
271 | // wmr controller has no a/b/x/y buttons |
272 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
273 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); // OpenXR will convert float to bool |
274 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); // OpenXR will convert bool to float |
275 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
276 | // primary on our wmr controller is our thumbstick, no touch |
277 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
278 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
279 | // secondary on our wmr controller is our trackpad |
280 | profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad" ); |
281 | profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click" ); |
282 | profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch" ); |
283 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
284 | add_interaction_profile(profile); |
285 | |
286 | // Create our Meta touch controller profile |
287 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller" ); |
288 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
289 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
290 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
291 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
292 | // touch controllers have no select button we can use |
293 | 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 |
294 | 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 |
295 | profile->add_new_binding(ax_touch, "/user/hand/left/input/x/touch,/user/hand/right/input/a/touch" ); |
296 | 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 |
297 | profile->add_new_binding(by_touch, "/user/hand/left/input/y/touch,/user/hand/right/input/b/touch" ); |
298 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
299 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); // should be converted to boolean |
300 | profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch" ); |
301 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); // should be converted to boolean |
302 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); |
303 | // primary on our touch controller is our thumbstick |
304 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
305 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
306 | profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch" ); |
307 | // touch controller has no secondary input |
308 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
309 | add_interaction_profile(profile); |
310 | |
311 | // Create our Pico 4 controller profile. |
312 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/bytedance/pico4_controller" ); |
313 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
314 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
315 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
316 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
317 | profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click" ); // system click may not be available |
318 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click" ); |
319 | 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 |
320 | profile->add_new_binding(ax_touch, "/user/hand/left/input/x/touch,/user/hand/right/input/a/touch" ); |
321 | 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 |
322 | profile->add_new_binding(by_touch, "/user/hand/left/input/y/touch,/user/hand/right/input/b/touch" ); |
323 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
324 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); // should be converted to boolean |
325 | profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch" ); |
326 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); // should be converted to boolean |
327 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); |
328 | // primary on our pico controller is our thumbstick |
329 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
330 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
331 | profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch" ); |
332 | // pico controller has no secondary input |
333 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
334 | add_interaction_profile(profile); |
335 | |
336 | // Create our Valve index controller profile |
337 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/valve/index_controller" ); |
338 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
339 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
340 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
341 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
342 | // index controllers have no select button we can use |
343 | profile->add_new_binding(menu_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click" ); |
344 | profile->add_new_binding(ax_button, "/user/hand/left/input/a/click,/user/hand/right/input/a/click" ); // a on both controllers |
345 | profile->add_new_binding(ax_touch, "/user/hand/left/input/a/touch,/user/hand/right/input/a/touch" ); |
346 | profile->add_new_binding(by_button, "/user/hand/left/input/b/click,/user/hand/right/input/b/click" ); // b on both controllers |
347 | profile->add_new_binding(by_touch, "/user/hand/left/input/b/touch,/user/hand/right/input/b/touch" ); |
348 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
349 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click" ); |
350 | profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch" ); |
351 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); |
352 | 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 |
353 | 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 |
354 | // primary on our index controller is our thumbstick |
355 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
356 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
357 | profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch" ); |
358 | // secondary on our index controller is our trackpad |
359 | profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad" ); |
360 | 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... |
361 | profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch" ); |
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 HP MR controller profile |
366 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_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 | // hpmr controllers have no select button we can use |
372 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click" ); |
373 | // hpmr controllers only register click, not touch, on our a/b/x/y buttons |
374 | 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 |
375 | 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 |
376 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
377 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
378 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); |
379 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value" ); |
380 | // primary on our hpmr controller is our thumbstick |
381 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
382 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
383 | // No secondary on our hpmr controller |
384 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
385 | add_interaction_profile(profile); |
386 | |
387 | // Create our Samsung Odyssey controller profile, |
388 | // Note that this controller is only identified specifically on WMR, on SteamVR this is identified as a normal WMR controller. |
389 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/samsung/odyssey_controller" ); |
390 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
391 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
392 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
393 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
394 | // Odyssey controllers have no select button we can use |
395 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click" ); |
396 | // Odyssey controller has no a/b/x/y buttons |
397 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
398 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
399 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
400 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
401 | // primary on our Odyssey controller is our thumbstick, no touch |
402 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
403 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
404 | // secondary on our Odyssey controller is our trackpad |
405 | profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad" ); |
406 | profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click" ); |
407 | profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch" ); |
408 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
409 | add_interaction_profile(profile); |
410 | |
411 | // Create our Vive Cosmos controller |
412 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_cosmos_controller" ); |
413 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
414 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
415 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
416 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
417 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click" ); |
418 | profile->add_new_binding(select_button, "/user/hand/right/input/system/click" ); // we'll map system to select |
419 | 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 |
420 | 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 |
421 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
422 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click" ); |
423 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
424 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
425 | // primary on our Cosmos controller is our thumbstick |
426 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
427 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
428 | profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch" ); |
429 | // No secondary on our cosmos controller |
430 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
431 | add_interaction_profile(profile); |
432 | |
433 | // Create our Vive Focus 3 controller |
434 | // Note, Vive Focus 3 currently is not yet supported as a stand alone device |
435 | // however HTC currently has a beta OpenXR runtime in testing we may support in the near future |
436 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_focus3_controller" ); |
437 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
438 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
439 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
440 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
441 | profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click" ); |
442 | profile->add_new_binding(select_button, "/user/hand/right/input/system/click" ); // we'll map system to select |
443 | 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 |
444 | 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 |
445 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
446 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click" ); |
447 | profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch" ); |
448 | profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
449 | profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click" ); |
450 | // primary on our Focus 3 controller is our thumbstick |
451 | profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick" ); |
452 | profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click" ); |
453 | profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch" ); |
454 | // We only have a thumb rest |
455 | profile->add_new_binding(secondary_touch, "/user/hand/left/input/thumbrest/touch,/user/hand/right/input/thumbrest/touch" ); |
456 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
457 | add_interaction_profile(profile); |
458 | |
459 | // Create our Huawei controller |
460 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/huawei/controller" ); |
461 | profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
462 | profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose" ); |
463 | profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose" ); |
464 | profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose" ); |
465 | profile->add_new_binding(menu_button, "/user/hand/left/input/home/click,/user/hand/right/input/home/click" ); |
466 | profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value" ); |
467 | profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click" ); |
468 | // primary on our Huawei controller is our trackpad |
469 | profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad" ); |
470 | profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click" ); |
471 | profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch" ); |
472 | profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic" ); |
473 | add_interaction_profile(profile); |
474 | |
475 | // Create our HTC Vive tracker profile |
476 | profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_tracker_htcx" ); |
477 | profile->add_new_binding(default_pose, |
478 | // "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose," <-- getting errors on this one |
479 | "/user/vive_tracker_htcx/role/left_foot/input/grip/pose," |
480 | "/user/vive_tracker_htcx/role/right_foot/input/grip/pose," |
481 | "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose," |
482 | "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose," |
483 | "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose," |
484 | "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose," |
485 | "/user/vive_tracker_htcx/role/left_knee/input/grip/pose," |
486 | "/user/vive_tracker_htcx/role/right_knee/input/grip/pose," |
487 | "/user/vive_tracker_htcx/role/waist/input/grip/pose," |
488 | "/user/vive_tracker_htcx/role/chest/input/grip/pose," |
489 | "/user/vive_tracker_htcx/role/camera/input/grip/pose," |
490 | "/user/vive_tracker_htcx/role/keyboard/input/grip/pose" ); |
491 | profile->add_new_binding(haptic, |
492 | // "/user/vive_tracker_htcx/role/handheld_object/output/haptic," <-- getting errors on this one |
493 | "/user/vive_tracker_htcx/role/left_foot/output/haptic," |
494 | "/user/vive_tracker_htcx/role/right_foot/output/haptic," |
495 | "/user/vive_tracker_htcx/role/left_shoulder/output/haptic," |
496 | "/user/vive_tracker_htcx/role/right_shoulder/output/haptic," |
497 | "/user/vive_tracker_htcx/role/left_elbow/output/haptic," |
498 | "/user/vive_tracker_htcx/role/right_elbow/output/haptic," |
499 | "/user/vive_tracker_htcx/role/left_knee/output/haptic," |
500 | "/user/vive_tracker_htcx/role/right_knee/output/haptic," |
501 | "/user/vive_tracker_htcx/role/waist/output/haptic," |
502 | "/user/vive_tracker_htcx/role/chest/output/haptic," |
503 | "/user/vive_tracker_htcx/role/camera/output/haptic," |
504 | "/user/vive_tracker_htcx/role/keyboard/output/haptic" ); |
505 | add_interaction_profile(profile); |
506 | } |
507 | |
508 | void OpenXRActionMap::create_editor_action_sets() { |
509 | // TODO implement |
510 | } |
511 | |
512 | Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const { |
513 | PackedStringArray paths = p_path.split("/" , false); |
514 | ERR_FAIL_COND_V(paths.size() != 2, Ref<OpenXRAction>()); |
515 | |
516 | Ref<OpenXRActionSet> action_set = find_action_set(paths[0]); |
517 | if (action_set.is_valid()) { |
518 | return action_set->get_action(paths[1]); |
519 | } |
520 | |
521 | return Ref<OpenXRAction>(); |
522 | } |
523 | |
524 | void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interaction_profiles) { |
525 | Ref<OpenXRAction> action = get_action(p_path); |
526 | if (action.is_valid()) { |
527 | for (int i = 0; i < interaction_profiles.size(); i++) { |
528 | Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i]; |
529 | |
530 | if (p_remove_interaction_profiles) { |
531 | // Remove any bindings for this action |
532 | interaction_profile->remove_binding_for_action(action); |
533 | } else { |
534 | ERR_FAIL_COND(interaction_profile->has_binding_for_action(action)); |
535 | } |
536 | } |
537 | |
538 | OpenXRActionSet *action_set = action->get_action_set(); |
539 | if (action_set != nullptr) { |
540 | // Remove the action from this action set |
541 | action_set->remove_action(action); |
542 | } |
543 | } |
544 | } |
545 | |
546 | PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) { |
547 | PackedStringArray arr; |
548 | |
549 | for (int i = 0; i < interaction_profiles.size(); i++) { |
550 | Ref<OpenXRInteractionProfile> ip = interaction_profiles[i]; |
551 | const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path()); |
552 | |
553 | if (profile != nullptr) { |
554 | for (int j = 0; j < ip->get_binding_count(); j++) { |
555 | Ref<OpenXRIPBinding> binding = ip->get_binding(j); |
556 | if (binding->get_action() == p_action) { |
557 | PackedStringArray paths = binding->get_paths(); |
558 | |
559 | for (int k = 0; k < paths.size(); k++) { |
560 | const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(paths[k]); |
561 | if (io_path != nullptr) { |
562 | String top_path = io_path->top_level_path; |
563 | |
564 | if (!arr.has(top_path)) { |
565 | arr.push_back(top_path); |
566 | } |
567 | } |
568 | } |
569 | } |
570 | } |
571 | } |
572 | } |
573 | |
574 | // print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr); |
575 | |
576 | return arr; |
577 | } |
578 | |
579 | OpenXRActionMap::~OpenXRActionMap() { |
580 | action_sets.clear(); |
581 | interaction_profiles.clear(); |
582 | } |
583 | |