diff --git a/README.md b/README.md
index 311b37a..c299d53 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,14 @@ $ ./make build && ./make tests
> NOTE #1: to rebundle the THREE/AFRAME javascripts during dev run `./make build js`
> NOTE #2: to regenerate the parser in various languages (via haxe), run `./make build parser`
+# Godot (>=v4.3.1)
+
+```
+$ ./make install godot # this installs the godot-xr-tools addon
+```
+
+> NOTE: the godot project is in [src/xrfragment/godot](./src/xrfragment/godot) (open the folder in godot)
+
# Credits
diff --git a/example/godot/.gitattributes b/example/godot/.gitattributes
new file mode 100644
index 0000000..8ad74f7
--- /dev/null
+++ b/example/godot/.gitattributes
@@ -0,0 +1,2 @@
+# Normalize EOL for all files that Git considers text files.
+* text=auto eol=lf
diff --git a/example/godot/.gitignore b/example/godot/.gitignore
new file mode 100644
index 0000000..4709183
--- /dev/null
+++ b/example/godot/.gitignore
@@ -0,0 +1,2 @@
+# Godot 4+ specific ignores
+.godot/
diff --git a/example/godot/dist/webxr/USE_GODOT_EDITOR_TO_EXPORT.txt b/example/godot/dist/webxr/USE_GODOT_EDITOR_TO_EXPORT.txt
new file mode 100644
index 0000000..e69de29
diff --git a/example/godot/export_presets.cfg b/example/godot/export_presets.cfg
new file mode 100644
index 0000000..4b96790
--- /dev/null
+++ b/example/godot/export_presets.cfg
@@ -0,0 +1,43 @@
+[preset.0]
+
+name="Web"
+platform="Web"
+runnable=true
+dedicated_server=false
+custom_features=""
+export_filter="all_resources"
+include_filter=""
+exclude_filter=""
+export_path="dist/webxr/index.html"
+encryption_include_filters=""
+encryption_exclude_filters=""
+encrypt_pck=false
+encrypt_directory=false
+
+[preset.0.options]
+
+custom_template/debug=""
+custom_template/release=""
+variant/extensions_support=false
+variant/thread_support=true
+vram_texture_compression/for_desktop=true
+vram_texture_compression/for_mobile=true
+html/export_icon=true
+html/custom_html_shell=""
+html/head_include=""
+html/canvas_resize_policy=2
+html/focus_canvas_on_start=true
+html/experimental_virtual_keyboard=false
+progressive_web_app/enabled=false
+progressive_web_app/offline_page=""
+progressive_web_app/display=1
+progressive_web_app/orientation=0
+progressive_web_app/icon_144x144=""
+progressive_web_app/icon_180x180=""
+progressive_web_app/icon_512x512=""
+progressive_web_app/background_color=Color(0, 0, 0, 1)
diff --git a/example/godot/icon.svg b/example/godot/icon.svg
new file mode 100644
index 0000000..b370ceb
--- /dev/null
+++ b/example/godot/icon.svg
@@ -0,0 +1 @@
+
diff --git a/example/godot/icon.svg.import b/example/godot/icon.svg.import
new file mode 100644
index 0000000..ea9156e
--- /dev/null
+++ b/example/godot/icon.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ckn6pn505bam5"
+path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.svg"
+dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/example/godot/index.glb b/example/godot/index.glb
new file mode 120000
index 0000000..0675c21
--- /dev/null
+++ b/example/godot/index.glb
@@ -0,0 +1 @@
+../assets/index.glb
\ No newline at end of file
diff --git a/example/godot/main.gd b/example/godot/main.gd
new file mode 100644
index 0000000..d1cbff4
--- /dev/null
+++ b/example/godot/main.gd
@@ -0,0 +1,14 @@
+extends Node3D
+
+var xr_interface: XRInterface
+
+func _ready():
+ # Import MyClass
+ const XRF = preload("res://xrfragment.gd")
+ var xrf = XRF.new()
+ add_child(xrf)
+ print( xrf.parseURL("https://foo.com/?foo#flop=bar&fap=fop") )
+ print( xrf.parseURL("https://foo.com/flop.html?foo#flop=bar&fap=fop") )
+ xrf.load("https://xrfragment.org/index.glb")
+
+
diff --git a/example/godot/main.tscn b/example/godot/main.tscn
new file mode 100644
index 0000000..67b5fe2
--- /dev/null
+++ b/example/godot/main.tscn
@@ -0,0 +1,47 @@
+[gd_scene load_steps=8 format=3 uid="uid://cgjxim2x47n6g"]
+
+[ext_resource type="Script" path="res://main.gd" id="1_oabt8"]
+[ext_resource type="PackedScene" uid="uid://bq86r4yll8po" path="res://addons/godot-xr-tools/hands/scenes/lowpoly/left_fullglove_low.tscn" id="2_nv01r"]
+[ext_resource type="PackedScene" uid="uid://bl2nuu3qhlb5k" path="res://addons/godot-xr-tools/functions/movement_direct.tscn" id="3_xxgqa"]
+[ext_resource type="PackedScene" uid="uid://xqimcf20s2jp" path="res://addons/godot-xr-tools/hands/scenes/lowpoly/right_fullglove_low.tscn" id="4_i4b8r"]
+[ext_resource type="PackedScene" uid="uid://b6bk2pj8vbj28" path="res://addons/godot-xr-tools/functions/movement_turn.tscn" id="5_pyrq4"]
+[ext_resource type="PackedScene" uid="uid://diyu06cw06syv" path="res://addons/godot-xr-tools/player/player_body.tscn" id="6_kfmth"]
+[ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="8_htpay"]
+
+[node name="Main" type="Node3D"]
+script = ExtResource("1_oabt8")
+
+[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
+transform = Transform3D(-0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, 0.75, -0.433013, 0, 0, 0)
+shadow_enabled = true
+
+[node name="XROrigin3D" type="XROrigin3D" parent="."]
+
+[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 0)
+
+[node name="LeftHand" type="XRController3D" parent="XROrigin3D"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, 0)
+tracker = &"left_hand"
+
+[node name="LeftHand" parent="XROrigin3D/LeftHand" instance=ExtResource("2_nv01r")]
+
+[node name="MovementDirect" parent="XROrigin3D/LeftHand" instance=ExtResource("3_xxgqa")]
+strafe = true
+input_action = "thumbstick"
+
+[node name="RightHand" type="XRController3D" parent="XROrigin3D"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, 0)
+tracker = &"right_hand"
+
+[node name="RightHand" parent="XROrigin3D/RightHand" instance=ExtResource("4_i4b8r")]
+
+[node name="MovementDirect" parent="XROrigin3D/RightHand" instance=ExtResource("3_xxgqa")]
+input_action = "thumbstick"
+
+[node name="MovementTurn" parent="XROrigin3D/RightHand" instance=ExtResource("5_pyrq4")]
+input_action = "thumbstick"
+
+[node name="PlayerBody" parent="XROrigin3D" instance=ExtResource("6_kfmth")]
+
+[node name="StartXR" parent="." instance=ExtResource("8_htpay")]
diff --git a/example/godot/openxr_action_map.tres b/example/godot/openxr_action_map.tres
new file mode 100644
index 0000000..60aa8e6
--- /dev/null
+++ b/example/godot/openxr_action_map.tres
@@ -0,0 +1,885 @@
+[gd_resource type="OpenXRActionMap" load_steps=210 format=3 uid="uid://dsj24l7qnotcy"]
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_p1qbu"]
+resource_name = "trigger"
+localized_name = "Trigger"
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_h1q76"]
+resource_name = "trigger_click"
+localized_name = "Trigger click"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_40uyl"]
+resource_name = "trigger_touch"
+localized_name = "Trigger touching"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_fi72f"]
+resource_name = "grip"
+localized_name = "Grip"
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_txhvr"]
+resource_name = "grip_click"
+localized_name = "Grip click"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_jx75s"]
+resource_name = "grip_force"
+localized_name = "Grip force"
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_ukvk2"]
+resource_name = "primary"
+localized_name = "Primary joystick/thumbstick/trackpad"
+action_type = 2
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_6dqlo"]
+resource_name = "primary_click"
+localized_name = "Primary joystick/thumbstick/trackpad click"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_vyrot"]
+resource_name = "primary_touch"
+localized_name = "Primary joystick/thumbstick/trackpad touching"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_mavp1"]
+resource_name = "secondary"
+localized_name = "Secondary joystick/thumbstick/trackpad"
+action_type = 2
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_0tp8j"]
+resource_name = "secondary_click"
+localized_name = "Secondary joystick/thumbstick/trackpad click"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_doiqt"]
+resource_name = "secondary_touch"
+localized_name = "Secondary joystick/thumbstick/trackpad touching"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_w7yf6"]
+resource_name = "menu_button"
+localized_name = "Menu button"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_wgxqk"]
+resource_name = "select_button"
+localized_name = "Select button"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_pnd64"]
+resource_name = "ax_button"
+localized_name = "A/X button"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_do38y"]
+resource_name = "ax_touch"
+localized_name = "A/X touching"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_uwjrj"]
+resource_name = "by_button"
+localized_name = "B/Y button"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_shsmx"]
+resource_name = "by_touch"
+localized_name = "B/Y touching"
+action_type = 0
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_7fi81"]
+resource_name = "default_pose"
+localized_name = "Default pose"
+action_type = 3
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard", "/user/eyes_ext")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_ft0mk"]
+resource_name = "aim_pose"
+localized_name = "Aim pose"
+action_type = 3
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_itk60"]
+resource_name = "grip_pose"
+localized_name = "Grip pose"
+action_type = 3
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_fi2yi"]
+resource_name = "palm_pose"
+localized_name = "Palm pose"
+action_type = 3
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
+
+[sub_resource type="OpenXRAction" id="OpenXRAction_ks6w8"]
+resource_name = "haptic"
+localized_name = "Haptic"
+action_type = 4
+toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard")
+
+[sub_resource type="OpenXRActionSet" id="OpenXRActionSet_0o34d"]
+resource_name = "godot"
+localized_name = "Godot action set"
+actions = [SubResource("OpenXRAction_p1qbu"), SubResource("OpenXRAction_h1q76"), SubResource("OpenXRAction_40uyl"), SubResource("OpenXRAction_fi72f"), SubResource("OpenXRAction_txhvr"), SubResource("OpenXRAction_jx75s"), SubResource("OpenXRAction_ukvk2"), SubResource("OpenXRAction_6dqlo"), SubResource("OpenXRAction_vyrot"), SubResource("OpenXRAction_mavp1"), SubResource("OpenXRAction_0tp8j"), SubResource("OpenXRAction_doiqt"), SubResource("OpenXRAction_w7yf6"), SubResource("OpenXRAction_wgxqk"), SubResource("OpenXRAction_pnd64"), SubResource("OpenXRAction_do38y"), SubResource("OpenXRAction_uwjrj"), SubResource("OpenXRAction_shsmx"), SubResource("OpenXRAction_7fi81"), SubResource("OpenXRAction_ft0mk"), SubResource("OpenXRAction_itk60"), SubResource("OpenXRAction_fi2yi"), SubResource("OpenXRAction_ks6w8")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k5fcj"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ey06d"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1oumt"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rjohw"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fl58m"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bm1u6"]
+action = SubResource("OpenXRAction_wgxqk")
+paths = PackedStringArray("/user/hand/left/input/select/click", "/user/hand/right/input/select/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4xtk0"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_iyv21"]
+interaction_profile_path = "/interaction_profiles/khr/simple_controller"
+bindings = [SubResource("OpenXRIPBinding_k5fcj"), SubResource("OpenXRIPBinding_ey06d"), SubResource("OpenXRIPBinding_1oumt"), SubResource("OpenXRIPBinding_rjohw"), SubResource("OpenXRIPBinding_fl58m"), SubResource("OpenXRIPBinding_bm1u6"), SubResource("OpenXRIPBinding_4xtk0")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_a1bbd"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jygrk"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ytxa7"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jq563"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rucv7"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_574s5"]
+action = SubResource("OpenXRAction_wgxqk")
+paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_abvxo"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_44kn7"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mlnp3"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xkx17"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rdhyh"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4yn8i"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ns68t"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5am2b"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_jyjt5"]
+interaction_profile_path = "/interaction_profiles/htc/vive_controller"
+bindings = [SubResource("OpenXRIPBinding_a1bbd"), SubResource("OpenXRIPBinding_jygrk"), SubResource("OpenXRIPBinding_ytxa7"), SubResource("OpenXRIPBinding_jq563"), SubResource("OpenXRIPBinding_rucv7"), SubResource("OpenXRIPBinding_574s5"), SubResource("OpenXRIPBinding_abvxo"), SubResource("OpenXRIPBinding_44kn7"), SubResource("OpenXRIPBinding_mlnp3"), SubResource("OpenXRIPBinding_xkx17"), SubResource("OpenXRIPBinding_rdhyh"), SubResource("OpenXRIPBinding_4yn8i"), SubResource("OpenXRIPBinding_ns68t"), SubResource("OpenXRIPBinding_5am2b")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_spkfk"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cc1ht"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_300ah"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6olt8"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nmird"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ntp2l"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2qefk"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_m1qhd"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6o3ow"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_u2bvt"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qksqt"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fgkr4"]
+action = SubResource("OpenXRAction_mavp1")
+paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_441qa"]
+action = SubResource("OpenXRAction_0tp8j")
+paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dmu24"]
+action = SubResource("OpenXRAction_doiqt")
+paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ttkyt"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_jlls3"]
+interaction_profile_path = "/interaction_profiles/microsoft/motion_controller"
+bindings = [SubResource("OpenXRIPBinding_spkfk"), SubResource("OpenXRIPBinding_cc1ht"), SubResource("OpenXRIPBinding_300ah"), SubResource("OpenXRIPBinding_6olt8"), SubResource("OpenXRIPBinding_nmird"), SubResource("OpenXRIPBinding_ntp2l"), SubResource("OpenXRIPBinding_2qefk"), SubResource("OpenXRIPBinding_m1qhd"), SubResource("OpenXRIPBinding_6o3ow"), SubResource("OpenXRIPBinding_u2bvt"), SubResource("OpenXRIPBinding_qksqt"), SubResource("OpenXRIPBinding_fgkr4"), SubResource("OpenXRIPBinding_441qa"), SubResource("OpenXRIPBinding_dmu24"), SubResource("OpenXRIPBinding_ttkyt")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0aylh"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4ftgx"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1cj81"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fwdkc"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d31r8"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_64nbn"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_js0u8"]
+action = SubResource("OpenXRAction_do38y")
+paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v5te4"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yt2f7"]
+action = SubResource("OpenXRAction_shsmx")
+paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n1a64"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_p1odw"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_imvcy"]
+action = SubResource("OpenXRAction_40uyl")
+paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uem2u"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_16xmt"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hj2qy"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kdl7p"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7o3u7"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qvxpc"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_272e4"]
+interaction_profile_path = "/interaction_profiles/oculus/touch_controller"
+bindings = [SubResource("OpenXRIPBinding_0aylh"), SubResource("OpenXRIPBinding_4ftgx"), SubResource("OpenXRIPBinding_1cj81"), SubResource("OpenXRIPBinding_fwdkc"), SubResource("OpenXRIPBinding_d31r8"), SubResource("OpenXRIPBinding_64nbn"), SubResource("OpenXRIPBinding_js0u8"), SubResource("OpenXRIPBinding_v5te4"), SubResource("OpenXRIPBinding_yt2f7"), SubResource("OpenXRIPBinding_n1a64"), SubResource("OpenXRIPBinding_p1odw"), SubResource("OpenXRIPBinding_imvcy"), SubResource("OpenXRIPBinding_uem2u"), SubResource("OpenXRIPBinding_16xmt"), SubResource("OpenXRIPBinding_hj2qy"), SubResource("OpenXRIPBinding_kdl7p"), SubResource("OpenXRIPBinding_7o3u7"), SubResource("OpenXRIPBinding_qvxpc")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7d8kg"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pdpqc"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vrx1l"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_exs0w"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sc1qa"]
+action = SubResource("OpenXRAction_wgxqk")
+paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4450r"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_is30e"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kbg0k"]
+action = SubResource("OpenXRAction_do38y")
+paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ink3t"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_03gqq"]
+action = SubResource("OpenXRAction_shsmx")
+paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t6po4"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t064u"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5ppsb"]
+action = SubResource("OpenXRAction_40uyl")
+paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e6ahd"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nsv78"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jcp55"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3ols2"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5fk30"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fitxy"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_t5wvy"]
+interaction_profile_path = "/interaction_profiles/bytedance/pico4_controller"
+bindings = [SubResource("OpenXRIPBinding_7d8kg"), SubResource("OpenXRIPBinding_pdpqc"), SubResource("OpenXRIPBinding_vrx1l"), SubResource("OpenXRIPBinding_exs0w"), SubResource("OpenXRIPBinding_sc1qa"), SubResource("OpenXRIPBinding_4450r"), SubResource("OpenXRIPBinding_is30e"), SubResource("OpenXRIPBinding_kbg0k"), SubResource("OpenXRIPBinding_ink3t"), SubResource("OpenXRIPBinding_03gqq"), SubResource("OpenXRIPBinding_t6po4"), SubResource("OpenXRIPBinding_t064u"), SubResource("OpenXRIPBinding_5ppsb"), SubResource("OpenXRIPBinding_e6ahd"), SubResource("OpenXRIPBinding_nsv78"), SubResource("OpenXRIPBinding_jcp55"), SubResource("OpenXRIPBinding_3ols2"), SubResource("OpenXRIPBinding_5fk30"), SubResource("OpenXRIPBinding_fitxy")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yfah0"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r81sm"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jnxl5"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ggi8y"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gyvyi"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ydsle"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/a/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x7dm0"]
+action = SubResource("OpenXRAction_do38y")
+paths = PackedStringArray("/user/hand/left/input/a/touch", "/user/hand/right/input/a/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dy53c"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/b/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qiayg"]
+action = SubResource("OpenXRAction_shsmx")
+paths = PackedStringArray("/user/hand/left/input/b/touch", "/user/hand/right/input/b/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_p1t5k"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5j67o"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gr8j7"]
+action = SubResource("OpenXRAction_40uyl")
+paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_spqqg"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l7kv6"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b1vi2"]
+action = SubResource("OpenXRAction_jx75s")
+paths = PackedStringArray("/user/hand/left/input/squeeze/force", "/user/hand/right/input/squeeze/force")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jkrbd"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2th34"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jmeka"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gfsia"]
+action = SubResource("OpenXRAction_mavp1")
+paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j8prd"]
+action = SubResource("OpenXRAction_0tp8j")
+paths = PackedStringArray("/user/hand/left/input/trackpad/force", "/user/hand/right/input/trackpad/force")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4vquj"]
+action = SubResource("OpenXRAction_doiqt")
+paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4hbrf"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_qc6pb"]
+interaction_profile_path = "/interaction_profiles/valve/index_controller"
+bindings = [SubResource("OpenXRIPBinding_yfah0"), SubResource("OpenXRIPBinding_r81sm"), SubResource("OpenXRIPBinding_jnxl5"), SubResource("OpenXRIPBinding_ggi8y"), SubResource("OpenXRIPBinding_gyvyi"), SubResource("OpenXRIPBinding_ydsle"), SubResource("OpenXRIPBinding_x7dm0"), SubResource("OpenXRIPBinding_dy53c"), SubResource("OpenXRIPBinding_qiayg"), SubResource("OpenXRIPBinding_p1t5k"), SubResource("OpenXRIPBinding_5j67o"), SubResource("OpenXRIPBinding_gr8j7"), SubResource("OpenXRIPBinding_spqqg"), SubResource("OpenXRIPBinding_l7kv6"), SubResource("OpenXRIPBinding_b1vi2"), SubResource("OpenXRIPBinding_jkrbd"), SubResource("OpenXRIPBinding_2th34"), SubResource("OpenXRIPBinding_jmeka"), SubResource("OpenXRIPBinding_gfsia"), SubResource("OpenXRIPBinding_j8prd"), SubResource("OpenXRIPBinding_4vquj"), SubResource("OpenXRIPBinding_4hbrf")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bmlpa"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l7u44"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cc2t1"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_f6okh"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xjlsb"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3pfvl"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i1xfm"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r2wyp"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6vane"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yah5k"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1drk4"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5k8hr"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4jbot"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4lb7a"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_tlptw"]
+interaction_profile_path = "/interaction_profiles/hp/mixed_reality_controller"
+bindings = [SubResource("OpenXRIPBinding_bmlpa"), SubResource("OpenXRIPBinding_l7u44"), SubResource("OpenXRIPBinding_cc2t1"), SubResource("OpenXRIPBinding_f6okh"), SubResource("OpenXRIPBinding_xjlsb"), SubResource("OpenXRIPBinding_3pfvl"), SubResource("OpenXRIPBinding_i1xfm"), SubResource("OpenXRIPBinding_r2wyp"), SubResource("OpenXRIPBinding_6vane"), SubResource("OpenXRIPBinding_yah5k"), SubResource("OpenXRIPBinding_1drk4"), SubResource("OpenXRIPBinding_5k8hr"), SubResource("OpenXRIPBinding_4jbot"), SubResource("OpenXRIPBinding_4lb7a")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ffiu3"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cs63x"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lex3e"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pueu6"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t641s"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kkww7"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gsx12"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bv52h"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bwcsr"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_chf2t"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_82lhq"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fqj0f"]
+action = SubResource("OpenXRAction_mavp1")
+paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2evvu"]
+action = SubResource("OpenXRAction_0tp8j")
+paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gt5qs"]
+action = SubResource("OpenXRAction_doiqt")
+paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_45ux7"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ifqou"]
+interaction_profile_path = "/interaction_profiles/samsung/odyssey_controller"
+bindings = [SubResource("OpenXRIPBinding_ffiu3"), SubResource("OpenXRIPBinding_cs63x"), SubResource("OpenXRIPBinding_lex3e"), SubResource("OpenXRIPBinding_pueu6"), SubResource("OpenXRIPBinding_t641s"), SubResource("OpenXRIPBinding_kkww7"), SubResource("OpenXRIPBinding_gsx12"), SubResource("OpenXRIPBinding_bv52h"), SubResource("OpenXRIPBinding_bwcsr"), SubResource("OpenXRIPBinding_chf2t"), SubResource("OpenXRIPBinding_82lhq"), SubResource("OpenXRIPBinding_fqj0f"), SubResource("OpenXRIPBinding_2evvu"), SubResource("OpenXRIPBinding_gt5qs"), SubResource("OpenXRIPBinding_45ux7")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h4qcu"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lw1j0"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wiafw"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d2xjr"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cxr63"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fjggq"]
+action = SubResource("OpenXRAction_wgxqk")
+paths = PackedStringArray("/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cm6vh"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dx68f"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uyw0x"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h3xr1"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_05yod"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c43jn"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xlqlb"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c27oe"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fqi1x"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ifotl"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_vq5vi"]
+interaction_profile_path = "/interaction_profiles/htc/vive_cosmos_controller"
+bindings = [SubResource("OpenXRIPBinding_h4qcu"), SubResource("OpenXRIPBinding_lw1j0"), SubResource("OpenXRIPBinding_wiafw"), SubResource("OpenXRIPBinding_d2xjr"), SubResource("OpenXRIPBinding_cxr63"), SubResource("OpenXRIPBinding_fjggq"), SubResource("OpenXRIPBinding_cm6vh"), SubResource("OpenXRIPBinding_dx68f"), SubResource("OpenXRIPBinding_uyw0x"), SubResource("OpenXRIPBinding_h3xr1"), SubResource("OpenXRIPBinding_05yod"), SubResource("OpenXRIPBinding_c43jn"), SubResource("OpenXRIPBinding_xlqlb"), SubResource("OpenXRIPBinding_c27oe"), SubResource("OpenXRIPBinding_fqi1x"), SubResource("OpenXRIPBinding_ifotl")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e01yu"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_232it"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_642ln"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ryfrm"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j4rhg"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/menu/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fdi6k"]
+action = SubResource("OpenXRAction_wgxqk")
+paths = PackedStringArray("/user/hand/right/input/system/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ec5dv"]
+action = SubResource("OpenXRAction_pnd64")
+paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ac8c6"]
+action = SubResource("OpenXRAction_uwjrj")
+paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ovu4a"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i14pk"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ixdk0"]
+action = SubResource("OpenXRAction_40uyl")
+paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_355ex"]
+action = SubResource("OpenXRAction_fi72f")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_80df3"]
+action = SubResource("OpenXRAction_txhvr")
+paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_138lw"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ti78g"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c2f8l"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mrsyu"]
+action = SubResource("OpenXRAction_doiqt")
+paths = PackedStringArray("/user/hand/left/input/thumbrest/touch", "/user/hand/right/input/thumbrest/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7ufh4"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_mapo7"]
+interaction_profile_path = "/interaction_profiles/htc/vive_focus3_controller"
+bindings = [SubResource("OpenXRIPBinding_e01yu"), SubResource("OpenXRIPBinding_232it"), SubResource("OpenXRIPBinding_642ln"), SubResource("OpenXRIPBinding_ryfrm"), SubResource("OpenXRIPBinding_j4rhg"), SubResource("OpenXRIPBinding_fdi6k"), SubResource("OpenXRIPBinding_ec5dv"), SubResource("OpenXRIPBinding_ac8c6"), SubResource("OpenXRIPBinding_ovu4a"), SubResource("OpenXRIPBinding_i14pk"), SubResource("OpenXRIPBinding_ixdk0"), SubResource("OpenXRIPBinding_355ex"), SubResource("OpenXRIPBinding_80df3"), SubResource("OpenXRIPBinding_138lw"), SubResource("OpenXRIPBinding_ti78g"), SubResource("OpenXRIPBinding_c2f8l"), SubResource("OpenXRIPBinding_mrsyu"), SubResource("OpenXRIPBinding_7ufh4")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nuiab"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3afjt"]
+action = SubResource("OpenXRAction_ft0mk")
+paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wg7tk"]
+action = SubResource("OpenXRAction_itk60")
+paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3gya4"]
+action = SubResource("OpenXRAction_fi2yi")
+paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nresw"]
+action = SubResource("OpenXRAction_w7yf6")
+paths = PackedStringArray("/user/hand/left/input/home/click", "/user/hand/right/input/home/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gih0u"]
+action = SubResource("OpenXRAction_p1qbu")
+paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_voccd"]
+action = SubResource("OpenXRAction_h1q76")
+paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1tf0b"]
+action = SubResource("OpenXRAction_ukvk2")
+paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fvi1f"]
+action = SubResource("OpenXRAction_6dqlo")
+paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y7qt8"]
+action = SubResource("OpenXRAction_vyrot")
+paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qdakj"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_1ueyw"]
+interaction_profile_path = "/interaction_profiles/huawei/controller"
+bindings = [SubResource("OpenXRIPBinding_nuiab"), SubResource("OpenXRIPBinding_3afjt"), SubResource("OpenXRIPBinding_wg7tk"), SubResource("OpenXRIPBinding_3gya4"), SubResource("OpenXRIPBinding_nresw"), SubResource("OpenXRIPBinding_gih0u"), SubResource("OpenXRIPBinding_voccd"), SubResource("OpenXRIPBinding_1tf0b"), SubResource("OpenXRIPBinding_fvi1f"), SubResource("OpenXRIPBinding_y7qt8"), SubResource("OpenXRIPBinding_qdakj")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nusr4"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/vive_tracker_htcx/role/left_foot/input/grip/pose", "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", "/user/vive_tracker_htcx/role/waist/input/grip/pose", "/user/vive_tracker_htcx/role/chest/input/grip/pose", "/user/vive_tracker_htcx/role/camera/input/grip/pose", "/user/vive_tracker_htcx/role/keyboard/input/grip/pose")
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gkfwb"]
+action = SubResource("OpenXRAction_ks6w8")
+paths = PackedStringArray("/user/vive_tracker_htcx/role/left_foot/output/haptic", "/user/vive_tracker_htcx/role/right_foot/output/haptic", "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", "/user/vive_tracker_htcx/role/left_elbow/output/haptic", "/user/vive_tracker_htcx/role/right_elbow/output/haptic", "/user/vive_tracker_htcx/role/left_knee/output/haptic", "/user/vive_tracker_htcx/role/right_knee/output/haptic", "/user/vive_tracker_htcx/role/waist/output/haptic", "/user/vive_tracker_htcx/role/chest/output/haptic", "/user/vive_tracker_htcx/role/camera/output/haptic", "/user/vive_tracker_htcx/role/keyboard/output/haptic")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_5qbto"]
+interaction_profile_path = "/interaction_profiles/htc/vive_tracker_htcx"
+bindings = [SubResource("OpenXRIPBinding_nusr4"), SubResource("OpenXRIPBinding_gkfwb")]
+
+[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hhjas"]
+action = SubResource("OpenXRAction_7fi81")
+paths = PackedStringArray("/user/eyes_ext/input/gaze_ext/pose")
+
+[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ska4h"]
+interaction_profile_path = "/interaction_profiles/ext/eye_gaze_interaction"
+bindings = [SubResource("OpenXRIPBinding_hhjas")]
+
+[resource]
+action_sets = [SubResource("OpenXRActionSet_0o34d")]
+interaction_profiles = [SubResource("OpenXRInteractionProfile_iyv21"), SubResource("OpenXRInteractionProfile_jyjt5"), SubResource("OpenXRInteractionProfile_jlls3"), SubResource("OpenXRInteractionProfile_272e4"), SubResource("OpenXRInteractionProfile_t5wvy"), SubResource("OpenXRInteractionProfile_qc6pb"), SubResource("OpenXRInteractionProfile_tlptw"), SubResource("OpenXRInteractionProfile_ifqou"), SubResource("OpenXRInteractionProfile_vq5vi"), SubResource("OpenXRInteractionProfile_mapo7"), SubResource("OpenXRInteractionProfile_1ueyw"), SubResource("OpenXRInteractionProfile_5qbto"), SubResource("OpenXRInteractionProfile_ska4h")]
diff --git a/example/godot/project.godot b/example/godot/project.godot
new file mode 100644
index 0000000..b1195af
--- /dev/null
+++ b/example/godot/project.godot
@@ -0,0 +1,37 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+; [section] ; section goes between []
+; param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="XRF browser"
+run/main_scene="res://main.tscn"
+config/features=PackedStringArray("4.3", "GL Compatibility")
+config/icon="res://icon.svg"
+
+[autoload]
+
+XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd"
+
+[editor_plugins]
+
+enabled=PackedStringArray("res://addons/godot-xr-tools/plugin.cfg")
+
+[rendering]
+
+renderer/rendering_method="gl_compatibility"
+renderer/rendering_method.mobile="gl_compatibility"
+textures/vram_compression/import_etc2_astc=true
+
+[xr]
+
+openxr/enabled=true
+openxr/foveation_level=3
+openxr/foveation_dynamic=true
+shaders/enabled=true
diff --git a/example/godot/xrfragment.gd b/example/godot/xrfragment.gd
new file mode 120000
index 0000000..cb55d13
--- /dev/null
+++ b/example/godot/xrfragment.gd
@@ -0,0 +1 @@
+../../src/xrfragment/xrfragment.gd
\ No newline at end of file
diff --git a/make b/make
index 78c3ea1..36ea4d1 100755
--- a/make
+++ b/make
@@ -27,10 +27,14 @@ install(){
}
godot(){
- # GoDot support
- haxelib git gdscript https://github.com/SomeRanDev/reflaxe.GDScript nightly
- #haxelib git godot-api-generator https://github.com/SomeRanDev/Haxe-GodotBindingsGenerator
- #haxelib run godot-api-generator
+ test -d src/xrfragment/godot/addons || mkdir src/xrfragment/godot/addons
+ test -d src/xrfragment/godot/addons/godot-xr-tools || {
+ cd src/xrfragment/godot
+ wget "https://github.com/GodotVR/godot-xr-tools/releases/download/4.3.1/godot-xr-tools.zip"
+ unzip godot-xr-tools.zip
+ mv godot-xr-tools/addons/godot-xr-tools addons/.
+ rm -rf godot-xr-tools*
+ }
}
test -z $1 && general
diff --git a/src/xrfragment/xrfragment.gd b/src/xrfragment/xrfragment.gd
new file mode 100644
index 0000000..5bbe66c
--- /dev/null
+++ b/src/xrfragment/xrfragment.gd
@@ -0,0 +1,221 @@
+extends Node
+
+class_name XRF
+
+var rootScene
+var isModelLoading = false
+
+# Called when the node enters the scene tree for the first time.
+func _ready():
+ pass # Replace with function body.
+
+
+# Called every frame. 'delta' is the elapsed time since the previous frame.
+func _process(delta):
+ pass
+
+####################################################################################################
+# URI Related functions
+####################################################################################################
+
+func parseURL(url: String) -> Dictionary:
+ var URI = {}
+
+ # Split URL by '://' to get protocol and the rest of the URL
+ var parts = url.split("://")
+ if parts.size() > 1:
+ URI["protocol"] = parts[0]
+ url = parts[1]
+ else:
+ URI["protocol"] = "http" # Default to http if protocol is missing
+
+ # Split URL by '/' to separate domain, path, and file
+ parts = url.split("/")
+ URI["domain"] = parts[0]
+ if parts.size() > 1:
+ var path_and_file = parts[1]
+ var path_and_file_parts = path_and_file.split("/")
+ if path_and_file_parts.size() > 1:
+ URI["path"] = path_and_file_parts
+ var file = path_and_file_parts.pop_back()
+ URI["path"] = path_and_file_parts.join("/")
+ else:
+ URI["path"] = path_and_file
+
+ # Check if there's a query string
+ if url.find("?") != -1:
+ parts = url.split("?")
+ URI["path"] = parts[0]
+ var args = parts[1]
+ if args.find("#"):
+ args = args.split("#")[0]
+ URI["query"] = parseArgs(args)
+ else:
+ URI["query"] = {}
+
+ # Check if there's a fragment
+ if url.find("#") != -1:
+ parts = url.split("#")
+ URI["fragment"] = parseArgs(parts[1])
+ else:
+ URI["fragment"] = {}
+
+ return URI
+
+func parseArgs(fragment: String) -> Dictionary:
+ var ARG = {}
+
+ # Split fragment by '&' to separate items
+ var items = fragment.split("&")
+
+ for item in items:
+ # Split item by '=' to separate key and value
+ var key_value = item.split("=")
+ if key_value.size() > 1:
+ ARG[key_value[0]] = key_value[1]
+ else:
+ ARG[key_value[0]] = ""
+
+ return ARG
+
+####################################################################################################
+# Model Related functions
+####################################################################################################
+
+# Download model by HTTP and run `downloadModelSuccess` if OK
+func load(url):
+ print("loading "+url)
+ var http_request = HTTPRequest.new()
+ add_child(http_request)
+ http_request.request_completed.connect(downloadModelSuccess)
+
+ var error = http_request.request(url)
+ if error != OK:
+ push_error("An error occurred in the HTTP request.")
+
+
+
+func placeModelToEditorScene(model):
+ add_child(model)
+ #model.translate(Vector3(0.0, 0.0, -1.0))
+ print("model added")
+
+func downloadModelSuccess(result, response_code, headers, body):
+ # TODO: here different parsing functions should be called
+ # based on the filetype (glb,gltf,ade,obj e.g.)
+ loadModelFromBufferByGLTFDocument(body)
+
+func loadModelFromBufferByGLTFDocument(body):
+ print("loadModelFromBuffer")
+ var doc = GLTFDocument.new()
+ var state = GLTFState.new()
+ #state.set_handle_binary_image(GLTFState.HANDLE_BINARY_EMBED_AS_BASISU) # Fixed in new Godot version (4.3 as I see) https://github.com/godotengine/godot/blob/17e7f85c06366b427e5068c5b3e2940e27ff5f1d/scene/resources/portable_compressed_texture.cpp#L116
+
+ var error = doc.append_from_buffer(body, "", state)
+ if error == OK:
+ #var glb_importer_model: GLTFMesh = state.get_meshes()[0]
+ #var glb_importer_model_mesh: ImporterMesh = glb_importer_model.get_mesh()
+ var scene = doc.generate_scene(state)
+ scene.set_meta("json",state.json)
+ #var ok:Error = _parseExtras(state)
+ traverse(scene, evalNode)
+ self.placeModelToEditorScene(scene)
+
+ else:
+ print("Couldn't load glTF scene (error code: %s)." % error_string(error))
+
+func evalNode(node:Node):
+ print(node.name)
+ #if node.has_meta("extras"):
+ # print(node.get_meta("extras",""))
+
+func traverse(node, f:Callable ):
+ for N in node.get_children():
+ if N.get_child_count() > 0:
+ f.call(N)
+ self.traverse(N,f)
+ else:
+ f.call(N)
+
+func _parseExtras(state: GLTFState) -> Error:
+ print( state.json.keys() )
+
+ # Add metadata to materials
+ var materials_json : Array = state.json.get("materials", [])
+ var materials : Array[Material] = state.get_materials()
+ for i in materials_json.size():
+ if materials_json[i].has("extras"):
+ materials[i].set_meta("extras", materials_json[i]["extras"])
+
+ # Add metadata to ImporterMeshes
+ var meshes_json : Array = state.json.get("meshes", [])
+ var meshes : Array[GLTFMesh] = state.get_meshes()
+ for i in meshes_json.size():
+ if meshes_json[i].has("extras"):
+ meshes[i].mesh.set_meta("extras", meshes_json[i]["extras"])
+
+ # Add metadata to nodes
+ var nodes_json : Array = state.json.get("nodes", [])
+ for i in nodes_json.size():
+ var node = state.get_scene_node(i)
+ if !node:
+ continue
+ if nodes_json[i].has("extras"):
+ # Handle special case
+ if node is ImporterMeshInstance3D:
+ # ImporterMeshInstance3D nodes will be converted later to either
+ # MeshInstance3D or StaticBody3D and metadata will be lost
+ # A sibling is created preserving the metadata. It can be later
+ # merged back in using a EditorScenePostImport script
+ var metadata_node = Node.new()
+ metadata_node.set_meta("extras", nodes_json[i]["extras"])
+
+ # Meshes are also ImporterMeshes that will be later converted either
+ # to ArrayMesh or some form of collision shape.
+ # We'll save it as another metadata item. If the mesh is reused we'll
+ # have duplicated info but at least it will always be accurate
+ if node.mesh and node.mesh.has_meta("extras"):
+ metadata_node.set_meta("mesh_extras", node.mesh.get_meta("extras"))
+
+ # Well add it as sibling so metadata node always follows the actual metadata owner
+ node.add_sibling(metadata_node)
+ # Make sure owner is set otherwise it won't get serialized to disk
+ metadata_node.owner = node.owner
+ # Add a suffix to the generated name so it's easy to find
+ metadata_node.name += "_meta"
+ # In all other cases just set_meta
+ else:
+ node.set_meta("extras", nodes_json[i]["extras"])
+
+ ## now we merge extras to the scene
+ #var verbose_output = []
+ #var nodes : Array[Node] = scene.find_children("*" + "_meta", "Node")
+ #verbose_output.append_array(["Metadata nodes:", nodes])
+ #for node in nodes:
+ #var extras = node.get_meta("extras")
+ #if !extras:
+ #verbose_output.append("Node %s contains no 'extras' metadata" % node)
+ #continue
+ #var parent = node.get_parent()
+ #if !parent:
+ #verbose_output.append("Node %s has no parent" % node)
+ #continue
+ #var idx_original = node.get_index() - 1
+ #if idx_original < 0 or parent.get_child_count() <= idx_original:
+ #verbose_output.append("Original node index %s is out of bounds. Parent child count: %s" % [idx_original, parent.get_child_count()])
+ #continue
+ #var original = node.get_parent().get_child(idx_original)
+ #if original:
+ #verbose_output.append("Setting extras metadata for %s" % original)
+ #original.set_meta("extras", extras)
+ #if node.has_meta("mesh_extras"):
+ #if original is MeshInstance3D and original.mesh:
+ #verbose_output.append("Setting extras metadata for mesh %s" % original.mesh)
+ #original.mesh.set_meta("extras", node.get_meta("mesh_extras"))
+ #else:
+ #verbose_output.append("Metadata node %s has 'mesh_extras' but original %s has no mesh, preserving as 'mesh_extras'" % [node, original])
+ #original.set_meta("mesh_extras", node.get_meta("mesh_extras"))
+ #else:
+ #verbose_output.append("Original node not found for %s" % node)
+ #node.queue_free()
+ return OK