diff --git a/README.md b/README.md
index 5ad28bf..d2043a8 100644
--- a/README.md
+++ b/README.md
@@ -27,34 +27,24 @@ Scons should be run from an environment that has the Microsoft x64 development t
> `scons example target=[template_debug | template_release]` Copy build products to the `example\addons\tilt-five\bin`
-## Basic usage
-
-- Open the project in the examples directory
-- Run the default scene
-
## Starting with a new project
To use this plugin in your own project:
-- Copy the add on into your project
+- Copy the `addons/tiltfive` folder into your project
- Open Project->Project Settings
- - On the Autoload tab add `res://addons/tiltfive/T5Interface.gd`
-- Create a main scene and add a T5Manager node
+ - Click on the Plugins tab
+ - Make sure the Tilt Five plugin is enabled
+ - You may need to restart Godot
+- In the main scene add a T5Manager node
+- In the main scene add a T5Gameboard node
+- On the T5Manager node set the start location to the T5Gameboard node
+- Add lights and other items to your scene
-See example project for futher details.
+Running should now show your scene on the Tilt Five system
## Dependencies
- Uses the godot-cpp headers
- Uses the Tilt Five NDK
-## TODO
-
-- API for tangible camera on the glasses
-- Better docs
-- Examples
-
-
-## Acknowledgments
-This was written by referring a lot to [GodotVR](https://github.com/GodotVR) code and reading
-[Godot's](https://github.com/godotengine/godot) source code.
diff --git a/example/T5Glasses.tscn b/example/T5Glasses.tscn
index b81a343..6c219b9 100644
--- a/example/T5Glasses.tscn
+++ b/example/T5Glasses.tscn
@@ -34,7 +34,6 @@ albedo_color = Color(0.862745, 0, 0.0235294, 1)
[node name="T5Glasses" instance=ExtResource("1_uq4nw")]
[node name="Origin" parent="." index="0"]
-gameboard_scale = 16.0
script = ExtResource("1_qprko")
[node name="T5-glasses" parent="Origin/Camera" index="0" instance=ExtResource("3_xuir6")]
diff --git a/example/XROrigin3D.gd b/example/XROrigin3D.gd
index bce8903..8df7e5b 100644
--- a/example/XROrigin3D.gd
+++ b/example/XROrigin3D.gd
@@ -2,10 +2,7 @@ extends T5Origin3D
var elapsed = 0.0
-func _init():
- print(gameboard_scale)
-
func _process(delta):
elapsed += delta
- position.x = sin(elapsed) * 1
+ position.y = sin(elapsed) * 1
diff --git a/example/addons/tiltfive/T5Interface.gd b/example/addons/tiltfive/T5Interface.gd
index cb1b539..4899246 100644
--- a/example/addons/tiltfive/T5Interface.gd
+++ b/example/addons/tiltfive/T5Interface.gd
@@ -1,4 +1,3 @@
-@tool
extends Node
## This script should be configured as an autoload script.
@@ -12,50 +11,140 @@ extends Node
## in editor. This will allow the Godot editor to request
## action information from the interface.
-var tilt_five_xr_interface: TiltFiveXRInterface
+const T5ManagerBase = preload("res://addons/tiltfive/T5ManagerBase.gd")
-func get_tilt_five_xr_interface() -> TiltFiveXRInterface:
- return tilt_five_xr_interface
+enum GameboardType {
+ LE = TiltFiveXRInterface.LE_GAMEBOARD,
+ XE = TiltFiveXRInterface.XE_GAMEBOARD,
+ XE_Raised = TiltFiveXRInterface.XE_RAISED_GAMEBOARD,
+ Unknown = TiltFiveXRInterface.NO_GAMEBOARD_SET
+}
-func _define_project_setting(
- p_name : String,
- p_type : int,
- p_hint : int = PROPERTY_HINT_NONE,
- p_hint_string : String = "",
- p_default_val = "") -> void:
- # p_default_val can be any type!!
+# State of a set of glasses.
+class GlassesState:
+ var available := false
+ var attempting_to_reserve := false
+ var reserved := false
+ var glasses_scene : Node
+ var gameboard_type := GameboardType.Unknown
+ func can_attempt_to_reserve():
+ return available and (not attempting_to_reserve) and (not reserved)
+
+# Dictionary maps glasses_id -> GlassesState
+var glasses_dict: Dictionary
- if !ProjectSettings.has_setting(p_name):
- ProjectSettings.set_setting(p_name, p_default_val)
+var tilt_five_xr_interface: TiltFiveXRInterface
- var property_info : Dictionary = {
- "name" : p_name,
- "type" : p_type,
- "hint" : p_hint,
- "hint_string" : p_hint_string
- }
+var t5_manager : T5ManagerBase:
+ set(value):
+ t5_manager = value
- ProjectSettings.add_property_info(property_info)
- ProjectSettings.set_as_basic(p_name, true)
- ProjectSettings.set_initial_value(p_name, p_default_val)
+func get_tilt_five_xr_interface() -> TiltFiveXRInterface:
+ return tilt_five_xr_interface
+
+func get_setting_or_default(name : String, default):
+ var val = ProjectSettings.get_setting_with_override(name)
+ if not val:
+ val = default
+ return val
# Called when the manager is loaded and added to our scene
func _enter_tree():
- _define_project_setting("xr/tilt_five/application_id", TYPE_STRING, PROPERTY_HINT_NONE, "", "my.game.com")
- _define_project_setting("xr/tilt_five/application_version", TYPE_STRING, PROPERTY_HINT_NONE, "", "0.1.0")
- _define_project_setting("xr/tilt_five/default_display_name", TYPE_STRING, PROPERTY_HINT_NONE, "", "Game: Player One")
-
tilt_five_xr_interface = TiltFiveXRInterface.new();
if tilt_five_xr_interface:
- tilt_five_xr_interface.application_id = ProjectSettings.get_setting_with_override("xr/tilt_five/application_id")
- tilt_five_xr_interface.application_version = ProjectSettings.get_setting_with_override("xr/tilt_five/application_version")
+ tilt_five_xr_interface.application_id = T5ProjectSettings.application_id
+ tilt_five_xr_interface.application_version = T5ProjectSettings.application_version
XRServer.add_interface(tilt_five_xr_interface)
+ tilt_five_xr_interface.glasses_event.connect(_on_glasses_event)
func _exit_tree():
if tilt_five_xr_interface:
+ tilt_five_xr_interface.glasses_event.disconnect(_on_glasses_event)
if tilt_five_xr_interface.is_initialized():
tilt_five_xr_interface.uninitialize()
-
+
XRServer.remove_interface(tilt_five_xr_interface)
tilt_five_xr_interface = null
+
+func _ready():
+ if not t5_manager:
+ push_error("T5Manager is not set in T5Interface")
+ return
+ if !tilt_five_xr_interface.is_initialized():
+ tilt_five_xr_interface.initialize()
+
+func _start_display(glasses_id : StringName, glasses_scene : Node):
+ var viewport := t5_manager.get_glasses_scene_viewport(glasses_scene)
+ var xr_origin := t5_manager.get_glasses_scene_origin(glasses_scene)
+ tilt_five_xr_interface.start_display(glasses_id, viewport, xr_origin)
+ var t5_camera := t5_manager.get_glasses_scene_camera(glasses_scene)
+ if t5_camera:
+ t5_camera.tracker = "/user/%s/head" % glasses_id
+ for idx in range(4):
+ var controller = t5_manager.get_glasses_scene_wand(glasses_scene, idx)
+ if not controller: break
+ controller.tracker = "/user/%s/wand_%d" % [glasses_id, idx + 1]
+
+func _process_glasses():
+ for glasses_id in glasses_dict:
+ var glasses_state = glasses_dict.get(glasses_id) as GlassesState
+ if glasses_state.can_attempt_to_reserve() and t5_manager.should_use_glasses(glasses_id):
+ glasses_state.attempting_to_reserve = true
+ tilt_five_xr_interface.reserve_glasses(glasses_id, t5_manager.get_glasses_display_name(glasses_id))
+
+func _on_glasses_event(glasses_id, event_num):
+ var glasses_state = glasses_dict.get(glasses_id) as GlassesState
+ if not glasses_state:
+ glasses_state = GlassesState.new()
+ glasses_dict[glasses_id] = glasses_state
+ match event_num:
+ TiltFiveXRInterface.E_AVAILABLE:
+ print_verbose(glasses_id, " E_AVAILABLE")
+ glasses_state.available = true
+ _process_glasses()
+
+ TiltFiveXRInterface.E_UNAVAILABLE:
+ print_verbose(glasses_id, " E_UNAVAILABLE")
+ glasses_state.available = false
+ if glasses_state.attempting_to_reserve:
+ glasses_state.attempting_to_reserve = false
+ _process_glasses()
+
+ TiltFiveXRInterface.E_RESERVED:
+ print_verbose(glasses_id, " E_RESERVED")
+ glasses_state.reserved = true
+ glasses_state.attempting_to_reserve = false
+
+ var glasses_scene = t5_manager.create_glasses_scene(glasses_id)
+
+ # instance our scene
+ if glasses_scene:
+ glasses_state.glasses_scene = glasses_scene
+ _start_display(glasses_id, glasses_scene)
+ else:
+ tilt_five_xr_interface.release_glasses(glasses_id)
+
+ TiltFiveXRInterface.E_DROPPED:
+ print_verbose(glasses_id, " E_DROPPED")
+ glasses_state.reserved = false
+
+ var glasses_scene = glasses_state.glasses_scene
+ if glasses_scene:
+ tilt_five_xr_interface.stop_display(glasses_id)
+ glasses_state.glasses_scene = null
+ t5_manager.release_glasses_scene(glasses_scene)
+
+ TiltFiveXRInterface.E_TRACKING:
+ var gbt = tilt_five_xr_interface.get_gameboard_type(glasses_id)
+ if glasses_state.gameboard_type != gbt:
+ glasses_state.gameboard_type = gbt
+ if glasses_state.glasses_scene:
+ t5_manager.set_glasses_scene_gameboard_type(glasses_state.glasses_scene, glasses_state.gameboard_type)
+ print_verbose(glasses_id, " E_TRACKING, Gameboard size = ", tilt_five_xr_interface.get_gameboard_extents(gbt))
+
+ TiltFiveXRInterface.E_NOT_TRACKING:
+ print_verbose(glasses_id, " E_NOT_TRACKING")
+
+ _:
+ print_verbose(glasses_id, " - unknown event: ", event_num)
diff --git a/example/addons/tiltfive/T5Manager.gd b/example/addons/tiltfive/T5Manager.gd
index b8c45aa..18e57fa 100644
--- a/example/addons/tiltfive/T5Manager.gd
+++ b/example/addons/tiltfive/T5Manager.gd
@@ -1,162 +1,65 @@
-class_name T5Manager extends Node
-
-## The T5Manager node should be added to your
-## main scene and will manage when glasses
-## and wands are detected.
+@icon("res://addons/tiltfive/assets/glasses.svg")
+class_name T5Manager extends "res://addons/tiltfive/T5ManagerBase.gd"
+## Create a instance of an XR rig for each pair of Tilt Five glasses
##
+## This node will create an instance of the T5GlassesBase or derived scene
+## for each pair of Tilt Five glasses that are found. The glasses
+## scene is an XR rig with an SubViewport, T5Origin, Camera, and wand.
+## If the glasses scene is not specified then T5GlassesBase.tscn is used.
+##
## This should be persistent.
-signal glasses_available(glasses_id : String)
-signal glasses_reserved(glasses_id : String)
-signal glasses_dropped(glasses_id : String)
+## Signal when the glasses scene is added to the main scene
+signal glasses_scene_was_added(glasses : T5GlassesBase)
+
+## Signal when the glasses scene is removed from the main scene
+signal glasses_scene_will_be_removed(glasses : T5GlassesBase)
const xr_origin_node := ^"Origin"
const xr_camera_node := ^"Origin/Camera"
-const wand_node_list := [^"Origin/Wand_1", ^"Origin/Wand_2", ^"Origin/Wand_3", ^"Origin/Wand_4"]
+const wand_node_list := [^"Origin/Wand_1", ^"Origin/Wand_2"]
-var tilt_five_xr_interface: TiltFiveXRInterface
-
-@export var automatically_start : bool = true
+## [PackedScene] that will instanced for a pair of Tilt Five glasses. Defaults to T5GlassesBase.tscn
@export var glasses_scene : PackedScene = preload("res://addons/tiltfive/scenes/T5GlassesBase.tscn")
-var reserved_glasses: Dictionary
+## A [T5Gameboard] node in the scene that will be used to set the location and content scale of the
+## [T5Origin] in the glasses scene
+@export var start_location : T5Gameboard
# We'll add our glasses scenes as children of this node
var glasses_node: Node3D
-# Called when the manager is loaded and added to our scene
-func _enter_tree():
- tilt_five_xr_interface = T5Interface.get_tilt_five_xr_interface()
-
- if tilt_five_xr_interface:
- tilt_five_xr_interface.service_event.connect(on_service_event)
- tilt_five_xr_interface.glasses_event.connect(on_glasses_event)
-
-# Called when the manager is removed
-func _exit_tree():
- if tilt_five_xr_interface:
- tilt_five_xr_interface.glasses_event.disconnect(on_glasses_event)
- tilt_five_xr_interface.service_event.disconnect(on_service_event)
-
- tilt_five_xr_interface = null
-
-# Called when our scene is fully setup
-func _ready():
- # Create a node on our parent under which we create our glasses scenes
+func _ready():
glasses_node = Node3D.new()
glasses_node.name = "TiltFiveGlasses"
get_parent().add_child.call_deferred(glasses_node)
- if not tilt_five_xr_interface:
- return
-
- if automatically_start and !tilt_five_xr_interface.is_initialized():
- tilt_five_xr_interface.initialize()
-
-func start_service() -> bool:
- if not tilt_five_xr_interface:
- return false
-
- return tilt_five_xr_interface.initialize()
-
-func has_reserved_glasses() -> bool:
- for glasses in reserved_glasses:
- if reserved_glasses[glasses]:
- return true
- return false
-
-func reserve_glasses(glasses_id : StringName, display_name := "") -> void:
- if not reserved_glasses.has(glasses_id):
- print_verbose("Warning: Tilt Five glasses id ", glasses_id, " does not exist")
- return
- if reserved_glasses[glasses_id]:
- print_verbose("Warning: Tilt Five glasses ", glasses_id, " already reserved")
- return
- if display_name.length() == 0:
- display_name = ProjectSettings.get_setting_with_override("xr/tilt_five/default_display_name")
- tilt_five_xr_interface.reserve_glasses(glasses_id, display_name)
-
-func start_display(glasses_id : StringName, viewport : SubViewport):
- var xr_origin = viewport.get_node(xr_origin_node)
- tilt_five_xr_interface.start_display(glasses_id, viewport, xr_origin)
- var t5_camera := viewport.get_node_or_null(xr_camera_node) as T5Camera3D
- if t5_camera:
- t5_camera.tracker = "/user/%s/head" % glasses_id
- for idx in 4:
- var controller = viewport.get_node_or_null(wand_node_list[idx]) as T5Controller3D
- if controller:
- controller.tracker = "/user/%s/wand_%d" % [glasses_id, idx + 1]
-
-func node_name_from_glasses_id(glasses_id: String) -> String:
- return "Glasses_" + glasses_id.replace("-", "_")
-
-func on_service_event(event_num):
- match event_num:
- TiltFiveXRInterface.E_SERVICE_T5_UNAVAILABLE:
- print("Tilt Five service is unavailable")
- TiltFiveXRInterface.E_SERVICE_T5_INCOMPATIBLE_VERSION:
- print("Tilt Five service has an incompatible version")
- TiltFiveXRInterface.E_SERVICE_RUNNING:
- print("Tilt Five service is running")
- TiltFiveXRInterface.E_SERVICE_STOPPED:
- print("Tilt Five service has stopped")
-
-func on_glasses_event(glasses_id, event_num):
- match event_num:
- TiltFiveXRInterface.E_GLASSES_AVAILABLE:
- print_verbose(glasses_id, " E_GLASSES_AVAILABLE")
- if not reserved_glasses.has(glasses_id):
- reserved_glasses[glasses_id] = false
-
- # If we're managing our glasses scene, reserve our glasses
- if glasses_scene:
- reserve_glasses(glasses_id)
-
- # Let others who are interested know
- glasses_available.emit(glasses_id)
-
- TiltFiveXRInterface.E_GLASSES_UNAVAILABLE:
- print_verbose(glasses_id, " E_GLASSES_UNAVAILABLE")
-
- # Let others who are interested know
- reserved_glasses.erase(glasses_id)
-
- TiltFiveXRInterface.E_GLASSES_RESERVED:
- print_verbose(glasses_id, " E_GLASSES_RESERVED")
-
- reserved_glasses[glasses_id] = true
-
- # If we're managing our glasses scene, instance our scene
- if glasses_scene:
- var gview = glasses_scene.instantiate()
- gview.name = node_name_from_glasses_id(glasses_id)
- glasses_node.add_child(gview)
- start_display(glasses_id, gview)
-
- # Let others who are interested know
- glasses_reserved.emit(glasses_id)
-
- TiltFiveXRInterface.E_GLASSES_DROPPED:
- print_verbose(glasses_id, " E_GLASSES_DROPPED")
-
- var node_name = node_name_from_glasses_id(glasses_id)
- var gview = glasses_node.get_node_or_null(node_name)
- if gview:
- tilt_five_xr_interface.stop_display(glasses_id)
- glasses_node.remove_child(gview)
- gview.queue_free()
-
- if reserved_glasses.get(glasses_id, false):
- reserved_glasses[glasses_id] = false
- glasses_dropped.emit(glasses_id)
-
- TiltFiveXRInterface.E_GLASSES_TRACKING:
- var gbt = tilt_five_xr_interface.get_gameboard_type(glasses_id)
- print_verbose(glasses_id, " E_GLASSES_TRACKING, Gameboard size = ", tilt_five_xr_interface.get_gameboard_extents(gbt))
-
- TiltFiveXRInterface.E_GLASSES_NOT_TRACKING:
- print_verbose(glasses_id, " E_GLASSES_NOT_TRACKING")
-
- _:
- print_verbose(glasses_id, " - unknown event: ", event_num)
-
+func create_glasses_scene(glasses_id : String) -> Node:
+ var gview = glasses_scene.instantiate()
+ glasses_node.add_child(gview)
+ if start_location:
+ var origin := get_glasses_scene_origin(gview)
+ origin.transform = start_location.transform
+ origin.gameboard_scale = start_location.content_scale
+ glasses_scene_was_added.emit(gview)
+ return gview
+
+func release_glasses_scene(glasses_scene : Node) -> void:
+ glasses_scene_will_be_removed.emit(glasses_scene)
+ glasses_node.remove_child(glasses_scene)
+ glasses_scene.queue_free()
+
+func get_glasses_scene_viewport(glasses_scene : Node) -> SubViewport:
+ return glasses_scene as SubViewport
+
+func get_glasses_scene_origin(glasses_scene : Node) -> T5Origin3D:
+ return glasses_scene.get_node(xr_origin_node)
+
+func get_glasses_scene_camera(glasses_scene : Node) -> Camera3D:
+ return glasses_scene.get_node(xr_camera_node)
+
+func get_glasses_scene_wand(glasses_scene : Node, wand_num : int) -> T5Controller3D:
+ if wand_num < wand_node_list.size():
+ return glasses_scene.get_node_or_null(wand_node_list[wand_num]) as T5Controller3D
+ return null
+
diff --git a/example/addons/tiltfive/T5ManagerBase.gd b/example/addons/tiltfive/T5ManagerBase.gd
new file mode 100644
index 0000000..d08abe7
--- /dev/null
+++ b/example/addons/tiltfive/T5ManagerBase.gd
@@ -0,0 +1,73 @@
+extends Node
+## Base class for all T5Managers. Should not be used directly.
+##
+## Classes derived from T5ManagerBase implement these functions
+## to customize the process of connecting the XR rigs in the scene
+## to the Tilt Five glasses hardware that is found.
+##
+## These functions must be overridden
+##
+## create_glasses_scene
+## release_glasses_scene
+## get_glasses_scene_viewport
+## get_glasses_scene_origin
+## get_glasses_scene_camera
+## get_glasses_scene_wand
+##
+## The derived node should be persistent.
+
+# Called when the manager is loaded and added to our scene
+func _enter_tree():
+ T5Interface.t5_manager = self
+
+# Called when the manager is removed
+func _exit_tree():
+ T5Interface.t5_manager = null
+
+## Invoked by the T5Interface to find out if the glasses should be used in
+## game
+func should_use_glasses(glasses_id : String) -> bool:
+ return true
+
+## Invoked by the T5Interface to get the display name to be assigned to
+## the glasses. This is the name that shows up in the Tilt Five control
+## panel
+func get_glasses_display_name(glasses_id : String) -> String:
+ return T5ProjectSettings.default_display_name
+
+## Invoked by the T5Interface to get the XR rig scene to be associated with
+## tilt five glasses. This scene should contain a SubViewport -> T5Origin -> Camera3D and T5Controller3D(s)
+func create_glasses_scene(glasses_id : String) -> Node:
+ push_error("create_glasses_scene not implemented in T5ManagerBase derived class")
+ return null
+
+## Invoked by the T5Interface if the Tilt Five glasses become unavailable
+func release_glasses_scene(glasses_scene : Node) -> void:
+ push_error("release_glasses_scene not implemented in T5ManagerBase derived class")
+
+## Invoked by the T5Interface to get the SubViewport of the XR rig
+func get_glasses_scene_viewport(glasses_scene : Node) -> SubViewport:
+ push_error("get_glasses_scene_viewport not implemented in T5ManagerBase derived class")
+ return null
+
+## Invoked by the T5Interface to get the T5Origin3D of the XR rig
+func get_glasses_scene_origin(glasses_scene : Node) -> T5Origin3D:
+ push_error("get_glasses_scene_origin not implemented in T5ManagerBase derived class")
+ return null
+
+## Invoked by the T5Interface to get the Camera3D of the XR rig
+func get_glasses_scene_camera(glasses_scene : Node) -> Camera3D:
+ push_error("get_glasses_scene_camera not implemented in T5ManagerBase derived class")
+ return null
+
+## Invoked by the T5Interface to get a T5Controller3D from the XR rig. Although the default rig
+## has only one wand two may be paired to a headset.
+func get_glasses_scene_wand(glasses_scene : Node, wand_num : int) -> T5Controller3D:
+ push_error("get_glasses_scene_wand not implemented in T5ManagerBase derived class")
+ return null
+
+## Invoked by the T5Interface to set the gameboard type the Tilt Fiave glasses detected
+func set_glasses_scene_gameboard_type(glasses_scene : Node, gameboard_type : T5Interface.GameboardType) -> void:
+ pass
+
+
diff --git a/example/addons/tiltfive/T5ProjectSettings.gd b/example/addons/tiltfive/T5ProjectSettings.gd
new file mode 100644
index 0000000..34cae21
--- /dev/null
+++ b/example/addons/tiltfive/T5ProjectSettings.gd
@@ -0,0 +1,48 @@
+class_name T5ProjectSettings extends RefCounted
+
+static var _initialized := false
+
+static func _define_project_setting(
+ p_name : String,
+ p_type : int,
+ p_hint : int = PROPERTY_HINT_NONE,
+ p_hint_string : String = "",
+ p_default_val = "") -> void:
+ # p_default_val can be any type!!
+
+ if !ProjectSettings.has_setting(p_name):
+ ProjectSettings.set_setting(p_name, p_default_val)
+
+ var property_info : Dictionary = {
+ "name" : p_name,
+ "type" : p_type,
+ "hint" : p_hint,
+ "hint_string" : p_hint_string
+ }
+
+ ProjectSettings.add_property_info(property_info)
+ ProjectSettings.set_as_basic(p_name, true)
+ ProjectSettings.set_initial_value(p_name, p_default_val)
+
+static func setup_properties():
+ if not _initialized:
+ _define_project_setting("xr/tilt_five/application_id", TYPE_STRING, PROPERTY_HINT_NONE, "", "my.game.com")
+ _define_project_setting("xr/tilt_five/application_version", TYPE_STRING, PROPERTY_HINT_NONE, "", "0.1.0")
+ _define_project_setting("xr/tilt_five/default_display_name", TYPE_STRING, PROPERTY_HINT_NONE, "", "Game: Player One")
+ _initialized = true
+
+static var application_id : String:
+ get:
+ setup_properties()
+ return ProjectSettings.get_setting_with_override("xr/tilt_five/application_id")
+
+static var application_version : String:
+ get:
+ setup_properties()
+ return ProjectSettings.get_setting_with_override("xr/tilt_five/application_version")
+
+static var default_display_name : String:
+ get:
+ setup_properties()
+ return ProjectSettings.get_setting_with_override("xr/tilt_five/default_display_name")
+
diff --git a/example/addons/tiltfive/T5_Icon_RGB.svg.import b/example/addons/tiltfive/T5_Icon_RGB.svg.import
new file mode 100644
index 0000000..09ced77
--- /dev/null
+++ b/example/addons/tiltfive/T5_Icon_RGB.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://jql7sxvwys6l"
+path="res://.godot/imported/T5_Icon_RGB.svg-913fc980ffc72ff335b087b54f0a0888.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/tiltfive/T5_Icon_RGB.svg"
+dest_files=["res://.godot/imported/T5_Icon_RGB.svg-913fc980ffc72ff335b087b54f0a0888.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/addons/tiltfive/assets/T5_border.glb b/example/addons/tiltfive/assets/T5_border.glb
new file mode 100644
index 0000000..f630e65
Binary files /dev/null and b/example/addons/tiltfive/assets/T5_border.glb differ
diff --git a/example/addons/tiltfive/assets/T5_border.glb.import b/example/addons/tiltfive/assets/T5_border.glb.import
new file mode 100644
index 0000000..ec70317
--- /dev/null
+++ b/example/addons/tiltfive/assets/T5_border.glb.import
@@ -0,0 +1,39 @@
+[remap]
+
+importer="scene"
+importer_version=1
+type="PackedScene"
+uid="uid://s3wiiyeuos30"
+path="res://.godot/imported/T5_border.glb-c296b67b5e5121f576eaa5a4e3abd8d7.scn"
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/T5_border.glb"
+dest_files=["res://.godot/imported/T5_border.glb-c296b67b5e5121f576eaa5a4e3abd8d7.scn"]
+
+[params]
+
+nodes/root_type="Node3D"
+nodes/root_name="Scene Root"
+nodes/apply_root_scale=true
+nodes/root_scale=1.0
+meshes/ensure_tangents=true
+meshes/generate_lods=true
+meshes/create_shadow_meshes=true
+meshes/light_baking=1
+meshes/lightmap_texel_size=0.2
+skins/use_named_skins=true
+animation/import=true
+animation/fps=30
+animation/trimming=false
+animation/remove_immutable_tracks=true
+import_script/path=""
+_subresources={
+"materials": {
+"Boarder Material": {
+"use_external/enabled": true,
+"use_external/path": "res://addons/tiltfive/assets/materials/T5BorderMat.tres"
+}
+}
+}
+gltf/embedded_image_handling=0
diff --git a/example/addons/tiltfive/assets/T5_border_XE.glb b/example/addons/tiltfive/assets/T5_border_XE.glb
new file mode 100644
index 0000000..f10e074
Binary files /dev/null and b/example/addons/tiltfive/assets/T5_border_XE.glb differ
diff --git a/example/addons/tiltfive/assets/T5_border_XE.glb.import b/example/addons/tiltfive/assets/T5_border_XE.glb.import
new file mode 100644
index 0000000..285d74f
--- /dev/null
+++ b/example/addons/tiltfive/assets/T5_border_XE.glb.import
@@ -0,0 +1,39 @@
+[remap]
+
+importer="scene"
+importer_version=1
+type="PackedScene"
+uid="uid://bvi54sixhguyl"
+path="res://.godot/imported/T5_border_XE.glb-8ae44d3d0d11e4f9febaa25582a4baec.scn"
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/T5_border_XE.glb"
+dest_files=["res://.godot/imported/T5_border_XE.glb-8ae44d3d0d11e4f9febaa25582a4baec.scn"]
+
+[params]
+
+nodes/root_type="Node3D"
+nodes/root_name="Scene Root"
+nodes/apply_root_scale=true
+nodes/root_scale=1.0
+meshes/ensure_tangents=true
+meshes/generate_lods=true
+meshes/create_shadow_meshes=true
+meshes/light_baking=1
+meshes/lightmap_texel_size=0.2
+skins/use_named_skins=true
+animation/import=true
+animation/fps=30
+animation/trimming=false
+animation/remove_immutable_tracks=true
+import_script/path=""
+_subresources={
+"materials": {
+"Border Material": {
+"use_external/enabled": true,
+"use_external/path": "res://addons/tiltfive/assets/materials/T5BorderMat.tres"
+}
+}
+}
+gltf/embedded_image_handling=0
diff --git a/example/addons/tiltfive/assets/T5_border_XE_raised.glb b/example/addons/tiltfive/assets/T5_border_XE_raised.glb
new file mode 100644
index 0000000..9f8392d
Binary files /dev/null and b/example/addons/tiltfive/assets/T5_border_XE_raised.glb differ
diff --git a/example/addons/tiltfive/assets/T5_border_XE_raised.glb.import b/example/addons/tiltfive/assets/T5_border_XE_raised.glb.import
new file mode 100644
index 0000000..25a8715
--- /dev/null
+++ b/example/addons/tiltfive/assets/T5_border_XE_raised.glb.import
@@ -0,0 +1,39 @@
+[remap]
+
+importer="scene"
+importer_version=1
+type="PackedScene"
+uid="uid://cnjvy4x25r3ae"
+path="res://.godot/imported/T5_border_XE_raised.glb-b835c3500317b519c096a0e5b7317a31.scn"
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/T5_border_XE_raised.glb"
+dest_files=["res://.godot/imported/T5_border_XE_raised.glb-b835c3500317b519c096a0e5b7317a31.scn"]
+
+[params]
+
+nodes/root_type="Node3D"
+nodes/root_name="Scene Root"
+nodes/apply_root_scale=true
+nodes/root_scale=1.0
+meshes/ensure_tangents=true
+meshes/generate_lods=true
+meshes/create_shadow_meshes=true
+meshes/light_baking=1
+meshes/lightmap_texel_size=0.2
+skins/use_named_skins=true
+animation/import=true
+animation/fps=30
+animation/trimming=false
+animation/remove_immutable_tracks=true
+import_script/path=""
+_subresources={
+"materials": {
+"Border Material": {
+"use_external/enabled": true,
+"use_external/path": "res://addons/tiltfive/assets/materials/T5BorderMat.tres"
+}
+}
+}
+gltf/embedded_image_handling=0
diff --git a/example/addons/tiltfive/assets/board.svg b/example/addons/tiltfive/assets/board.svg
new file mode 100644
index 0000000..98a3139
--- /dev/null
+++ b/example/addons/tiltfive/assets/board.svg
@@ -0,0 +1,50 @@
+
+
+
+
diff --git a/example/addons/tiltfive/assets/board.svg.import b/example/addons/tiltfive/assets/board.svg.import
new file mode 100644
index 0000000..131f8eb
--- /dev/null
+++ b/example/addons/tiltfive/assets/board.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d1k4sti7mydwh"
+path="res://.godot/imported/board.svg-ece10245621dedc440b30e3a84647ba9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/board.svg"
+dest_files=["res://.godot/imported/board.svg-ece10245621dedc440b30e3a84647ba9.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/addons/tiltfive/assets/glasses.svg b/example/addons/tiltfive/assets/glasses.svg
new file mode 100644
index 0000000..d127c68
--- /dev/null
+++ b/example/addons/tiltfive/assets/glasses.svg
@@ -0,0 +1,69 @@
+
+
+
+
diff --git a/example/addons/tiltfive/assets/glasses.svg.import b/example/addons/tiltfive/assets/glasses.svg.import
new file mode 100644
index 0000000..fd92c68
--- /dev/null
+++ b/example/addons/tiltfive/assets/glasses.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://63xpi03wffd8"
+path="res://.godot/imported/glasses.svg-065e492e0e832aaa5619ccaad95c9012.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/glasses.svg"
+dest_files=["res://.godot/imported/glasses.svg-065e492e0e832aaa5619ccaad95c9012.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/addons/tiltfive/assets/materials/T5BorderMat.tres b/example/addons/tiltfive/assets/materials/T5BorderMat.tres
new file mode 100644
index 0000000..9cdce6d
--- /dev/null
+++ b/example/addons/tiltfive/assets/materials/T5BorderMat.tres
@@ -0,0 +1,6 @@
+[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://df4vk6rpxs784"]
+
+[ext_resource type="Texture2D" uid="uid://b42436tkvdjtj" path="res://addons/tiltfive/assets/materials/T5_border_tex.png" id="1_d1o3y"]
+
+[resource]
+albedo_texture = ExtResource("1_d1o3y")
diff --git a/example/addons/tiltfive/assets/materials/T5_border_tex.png b/example/addons/tiltfive/assets/materials/T5_border_tex.png
new file mode 100644
index 0000000..9e2ff18
Binary files /dev/null and b/example/addons/tiltfive/assets/materials/T5_border_tex.png differ
diff --git a/example/addons/tiltfive/assets/materials/T5_border_tex.png.import b/example/addons/tiltfive/assets/materials/T5_border_tex.png.import
new file mode 100644
index 0000000..9a22f78
--- /dev/null
+++ b/example/addons/tiltfive/assets/materials/T5_border_tex.png.import
@@ -0,0 +1,36 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b42436tkvdjtj"
+path.s3tc="res://.godot/imported/T5_border_tex.png-f817ec4f59697917c96dd8c9cdc0b494.s3tc.ctex"
+metadata={
+"imported_formats": ["s3tc_bptc"],
+"vram_texture": true
+}
+generator_parameters={}
+
+[deps]
+
+source_file="res://addons/tiltfive/assets/materials/T5_border_tex.png"
+dest_files=["res://.godot/imported/T5_border_tex.png-f817ec4f59697917c96dd8c9cdc0b494.s3tc.ctex"]
+
+[params]
+
+compress/mode=2
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=true
+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=0
diff --git a/example/addons/tiltfive/plugin.cfg b/example/addons/tiltfive/plugin.cfg
new file mode 100644
index 0000000..661a0b3
--- /dev/null
+++ b/example/addons/tiltfive/plugin.cfg
@@ -0,0 +1,7 @@
+[plugin]
+
+name="Tilt Five"
+description="Support for the Tilt Five XR headset"
+author="Patrick Down"
+version="1.0.0"
+script="plugin.gd"
diff --git a/example/addons/tiltfive/plugin.gd b/example/addons/tiltfive/plugin.gd
new file mode 100644
index 0000000..942637c
--- /dev/null
+++ b/example/addons/tiltfive/plugin.gd
@@ -0,0 +1,23 @@
+@tool
+extends EditorPlugin
+
+static var _initialized := false
+
+func _setup():
+ if not _initialized:
+ #add_custom_type("T5Manager", "Node", preload("res://addons/tiltfive/T5Manager.gd"), preload("res://addons/tiltfive/assets/glasses.svg"))
+ add_autoload_singleton("T5Interface", "res://addons/tiltfive/T5Interface.gd")
+ _initialized = true
+
+func _enter_tree():
+ T5ProjectSettings.setup_properties()
+ _setup()
+
+func _enable_plugin():
+ _setup()
+
+func _disable_plugin():
+ if _initialized:
+ #remove_custom_type("T5Manager")
+ remove_autoload_singleton("T5Interface")
+
diff --git a/example/addons/tiltfive/scenes/T5GlassesBase.gd b/example/addons/tiltfive/scenes/T5GlassesBase.gd
index 9726117..cfeb497 100644
--- a/example/addons/tiltfive/scenes/T5GlassesBase.gd
+++ b/example/addons/tiltfive/scenes/T5GlassesBase.gd
@@ -1,4 +1,4 @@
-extends SubViewport
+class_name T5GlassesBase extends SubViewport
@onready var wand = $Origin/Wand_1
diff --git a/example/addons/tiltfive/scenes/T5GlassesBase.tscn b/example/addons/tiltfive/scenes/T5GlassesBase.tscn
index 2fff38b..5da1db5 100644
--- a/example/addons/tiltfive/scenes/T5GlassesBase.tscn
+++ b/example/addons/tiltfive/scenes/T5GlassesBase.tscn
@@ -1,11 +1,11 @@
[gd_scene load_steps=2 format=3 uid="uid://je0clrdu7o76"]
-[ext_resource type="Script" path="res://addons/tiltfive/scenes/T5GlassesBase.gd" id="1_ra3f6"]
+[ext_resource type="Script" path="res://addons/tiltfive/scenes/T5GlassesBase.gd" id="1_tymyw"]
[node name="T5GlassesBase" type="SubViewport"]
size = Vector2i(2, 2)
render_target_update_mode = 0
-script = ExtResource("1_ra3f6")
+script = ExtResource("1_tymyw")
[node name="Origin" type="T5Origin3D" parent="."]
diff --git a/example/addons/tiltfive/tiltfive.gdextension b/example/addons/tiltfive/tiltfive.gdextension
index fb10e68..4277612 100644
--- a/example/addons/tiltfive/tiltfive.gdextension
+++ b/example/addons/tiltfive/tiltfive.gdextension
@@ -3,6 +3,9 @@
entry_symbol = "tiltfive_library_init"
compatibility_minimum = "4.1.0"
+[icons]
+T5Gameboard = "res://addons/tiltfive/assets/board.svg"
+
[libraries]
windows.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_debug.x86_64.dll"
diff --git a/example/main.gd b/example/main.gd
index ea4a90d..880e6ec 100644
--- a/example/main.gd
+++ b/example/main.gd
@@ -1,2 +1,7 @@
extends Node3D
+func _on_t5_manager_glasses_scene_was_added(glasses):
+ print("Scene ", glasses.name, " added")
+
+func _on_t5_manager_glasses_scene_will_be_removed(glasses):
+ print("Scene ", glasses.name, " removed")
diff --git a/example/main.tscn b/example/main.tscn
index 2cfdf95..19c9256 100644
--- a/example/main.tscn
+++ b/example/main.tscn
@@ -1,9 +1,9 @@
[gd_scene load_steps=17 format=3 uid="uid://ckbe6draoen0x"]
-[ext_resource type="Script" path="res://main.gd" id="1_ptcg0"]
+[ext_resource type="Script" path="res://main.gd" id="1_xvgge"]
[ext_resource type="Script" path="res://addons/tiltfive/T5Manager.gd" id="2_dibvp"]
+[ext_resource type="PackedScene" uid="uid://dl3mv76qkuscf" path="res://T5Glasses.tscn" id="3_i6xar"]
[ext_resource type="Script" path="res://addons/tiltfive/scenes/helpers/SelectableBody.gd" id="3_jespo"]
-[ext_resource type="PackedScene" uid="uid://dl3mv76qkuscf" path="res://T5Glasses.tscn" id="3_xx6p7"]
[ext_resource type="Material" uid="uid://blq3i2qbhoyum" path="res://addons/tiltfive/materials/highlight_overlay_material.tres" id="5_cq8r1"]
[sub_resource type="BoxMesh" id="BoxMesh_gbwc2"]
@@ -35,11 +35,15 @@ albedo_color = Color(0.862745, 0, 0.0235294, 1)
albedo_color = Color(0.741176, 0, 0.686275, 1)
[node name="Main" type="Node3D"]
-script = ExtResource("1_ptcg0")
+script = ExtResource("1_xvgge")
-[node name="T5Manager" type="Node" parent="."]
+[node name="T5Manager" type="Node" parent="." node_paths=PackedStringArray("start_location")]
script = ExtResource("2_dibvp")
-glasses_scene = ExtResource("3_xx6p7")
+glasses_scene = ExtResource("3_i6xar")
+start_location = NodePath("../T5Gameboard")
+
+[node name="T5Gameboard" type="T5Gameboard" parent="."]
+content_scale = 16.0
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.952497, -0.0534809, 0.299816, -0.283211, 0.206458, 0.936572, -0.111988, -0.976993, 0.181504, 2.31774, 1.62798, 0)
diff --git a/example/openxr_action_map.tres b/example/openxr_action_map.tres
deleted file mode 100644
index 49e8894..0000000
--- a/example/openxr_action_map.tres
+++ /dev/null
@@ -1,826 +0,0 @@
-[gd_resource type="OpenXRActionMap" load_steps=195 format=3 uid="uid://cjxvj4v2q54a5"]
-
-[sub_resource type="OpenXRAction" id="OpenXRAction_qhy06"]
-resource_name = "trigger"
-localized_name = "Trigger"
-toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
-
-[sub_resource type="OpenXRAction" id="OpenXRAction_2vwe0"]
-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_gpqeh"]
-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_473o0"]
-resource_name = "grip"
-localized_name = "Grip"
-toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
-
-[sub_resource type="OpenXRAction" id="OpenXRAction_8qgll"]
-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_kmk80"]
-resource_name = "grip_touch"
-localized_name = "Grip touching"
-action_type = 0
-toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
-
-[sub_resource type="OpenXRAction" id="OpenXRAction_rhxy5"]
-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_sxg5f"]
-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_3rri5"]
-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_53byk"]
-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_bkd5n"]
-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_mkk7a"]
-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_4uh4f"]
-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_83w55"]
-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_0sqj6"]
-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_3tdc8"]
-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_tblbd"]
-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_fayqd"]
-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_mj02j"]
-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")
-
-[sub_resource type="OpenXRAction" id="OpenXRAction_x4afo"]
-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_ffdsq"]
-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_80sg0"]
-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_5os4r"]
-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_dlwup"]
-resource_name = "godot"
-localized_name = "Godot action set"
-actions = [SubResource("OpenXRAction_qhy06"), SubResource("OpenXRAction_2vwe0"), SubResource("OpenXRAction_gpqeh"), SubResource("OpenXRAction_473o0"), SubResource("OpenXRAction_8qgll"), SubResource("OpenXRAction_kmk80"), SubResource("OpenXRAction_rhxy5"), SubResource("OpenXRAction_sxg5f"), SubResource("OpenXRAction_3rri5"), SubResource("OpenXRAction_53byk"), SubResource("OpenXRAction_bkd5n"), SubResource("OpenXRAction_mkk7a"), SubResource("OpenXRAction_4uh4f"), SubResource("OpenXRAction_83w55"), SubResource("OpenXRAction_0sqj6"), SubResource("OpenXRAction_3tdc8"), SubResource("OpenXRAction_tblbd"), SubResource("OpenXRAction_fayqd"), SubResource("OpenXRAction_mj02j"), SubResource("OpenXRAction_x4afo"), SubResource("OpenXRAction_ffdsq"), SubResource("OpenXRAction_80sg0"), SubResource("OpenXRAction_5os4r")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_im411"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wdvxs"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cahdc"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_voxcd"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rh512"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v45m1"]
-action = SubResource("OpenXRAction_83w55")
-paths = PackedStringArray("/user/hand/left/input/select/click", "/user/hand/right/input/select/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gpprf"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_n4f80"]
-interaction_profile_path = "/interaction_profiles/khr/simple_controller"
-bindings = [SubResource("OpenXRIPBinding_im411"), SubResource("OpenXRIPBinding_wdvxs"), SubResource("OpenXRIPBinding_cahdc"), SubResource("OpenXRIPBinding_voxcd"), SubResource("OpenXRIPBinding_rh512"), SubResource("OpenXRIPBinding_v45m1"), SubResource("OpenXRIPBinding_gpprf")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kpvac"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8kp18"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bxlun"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_se4e1"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lnjyf"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5sqy5"]
-action = SubResource("OpenXRAction_83w55")
-paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qs7ua"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_q86v7"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cnyj6"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jlsfx"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2wfqp"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gf5ct"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fpm1i"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xyyt2"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_om27o"]
-interaction_profile_path = "/interaction_profiles/htc/vive_controller"
-bindings = [SubResource("OpenXRIPBinding_kpvac"), SubResource("OpenXRIPBinding_8kp18"), SubResource("OpenXRIPBinding_bxlun"), SubResource("OpenXRIPBinding_se4e1"), SubResource("OpenXRIPBinding_lnjyf"), SubResource("OpenXRIPBinding_5sqy5"), SubResource("OpenXRIPBinding_qs7ua"), SubResource("OpenXRIPBinding_q86v7"), SubResource("OpenXRIPBinding_cnyj6"), SubResource("OpenXRIPBinding_jlsfx"), SubResource("OpenXRIPBinding_2wfqp"), SubResource("OpenXRIPBinding_gf5ct"), SubResource("OpenXRIPBinding_fpm1i"), SubResource("OpenXRIPBinding_xyyt2")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8bitt"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4jso0"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jt3hh"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0kdv5"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3ueik"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sdi8m"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3s0mv"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k1tdu"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bf5r6"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2fqvs"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_id70d"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kuadv"]
-action = SubResource("OpenXRAction_53byk")
-paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vc3mt"]
-action = SubResource("OpenXRAction_bkd5n")
-paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v06u4"]
-action = SubResource("OpenXRAction_mkk7a")
-paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n3wd8"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_tk604"]
-interaction_profile_path = "/interaction_profiles/microsoft/motion_controller"
-bindings = [SubResource("OpenXRIPBinding_8bitt"), SubResource("OpenXRIPBinding_4jso0"), SubResource("OpenXRIPBinding_jt3hh"), SubResource("OpenXRIPBinding_0kdv5"), SubResource("OpenXRIPBinding_3ueik"), SubResource("OpenXRIPBinding_sdi8m"), SubResource("OpenXRIPBinding_3s0mv"), SubResource("OpenXRIPBinding_k1tdu"), SubResource("OpenXRIPBinding_bf5r6"), SubResource("OpenXRIPBinding_2fqvs"), SubResource("OpenXRIPBinding_id70d"), SubResource("OpenXRIPBinding_kuadv"), SubResource("OpenXRIPBinding_vc3mt"), SubResource("OpenXRIPBinding_v06u4"), SubResource("OpenXRIPBinding_n3wd8")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mqkht"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s7gwf"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d44wu"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2xbfe"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yrexh"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_co5wb"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_svkea"]
-action = SubResource("OpenXRAction_3tdc8")
-paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tqkga"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_36qfl"]
-action = SubResource("OpenXRAction_fayqd")
-paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5fhs4"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jgdy4"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tl1gn"]
-action = SubResource("OpenXRAction_gpqeh")
-paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_afswg"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tv4sh"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v3n7r"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3cy0f"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y5rl5"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nlre4"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_kc40e"]
-interaction_profile_path = "/interaction_profiles/oculus/touch_controller"
-bindings = [SubResource("OpenXRIPBinding_mqkht"), SubResource("OpenXRIPBinding_s7gwf"), SubResource("OpenXRIPBinding_d44wu"), SubResource("OpenXRIPBinding_2xbfe"), SubResource("OpenXRIPBinding_yrexh"), SubResource("OpenXRIPBinding_co5wb"), SubResource("OpenXRIPBinding_svkea"), SubResource("OpenXRIPBinding_tqkga"), SubResource("OpenXRIPBinding_36qfl"), SubResource("OpenXRIPBinding_5fhs4"), SubResource("OpenXRIPBinding_jgdy4"), SubResource("OpenXRIPBinding_tl1gn"), SubResource("OpenXRIPBinding_afswg"), SubResource("OpenXRIPBinding_tv4sh"), SubResource("OpenXRIPBinding_v3n7r"), SubResource("OpenXRIPBinding_3cy0f"), SubResource("OpenXRIPBinding_y5rl5"), SubResource("OpenXRIPBinding_nlre4")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_52qkv"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jrcjr"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3lqo4"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_q6f46"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xbac3"]
-action = SubResource("OpenXRAction_83w55")
-paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ugijx"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/back/click", "/user/hand/right/input/back/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c6e0h"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_if48k"]
-action = SubResource("OpenXRAction_3tdc8")
-paths = PackedStringArray("/user/hand/left/input/x/touch", "/user/hand/right/input/a/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t12aj"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_as3e6"]
-action = SubResource("OpenXRAction_fayqd")
-paths = PackedStringArray("/user/hand/left/input/y/touch", "/user/hand/right/input/b/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g834v"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fosu3"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kfw8l"]
-action = SubResource("OpenXRAction_gpqeh")
-paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_741bj"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_224bn"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dpx87"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gr54n"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mjqra"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uunaw"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ammxl"]
-interaction_profile_path = "/interaction_profiles/pico/neo3_controller"
-bindings = [SubResource("OpenXRIPBinding_52qkv"), SubResource("OpenXRIPBinding_jrcjr"), SubResource("OpenXRIPBinding_3lqo4"), SubResource("OpenXRIPBinding_q6f46"), SubResource("OpenXRIPBinding_xbac3"), SubResource("OpenXRIPBinding_ugijx"), SubResource("OpenXRIPBinding_c6e0h"), SubResource("OpenXRIPBinding_if48k"), SubResource("OpenXRIPBinding_t12aj"), SubResource("OpenXRIPBinding_as3e6"), SubResource("OpenXRIPBinding_g834v"), SubResource("OpenXRIPBinding_fosu3"), SubResource("OpenXRIPBinding_kfw8l"), SubResource("OpenXRIPBinding_741bj"), SubResource("OpenXRIPBinding_224bn"), SubResource("OpenXRIPBinding_dpx87"), SubResource("OpenXRIPBinding_gr54n"), SubResource("OpenXRIPBinding_mjqra"), SubResource("OpenXRIPBinding_uunaw")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s0c47"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2rykr"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3apyd"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ec4nm"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_teed4"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/system/click", "/user/hand/right/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c1jsm"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/a/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i31ov"]
-action = SubResource("OpenXRAction_3tdc8")
-paths = PackedStringArray("/user/hand/left/input/a/touch", "/user/hand/right/input/a/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_a5dot"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/b/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sy7to"]
-action = SubResource("OpenXRAction_fayqd")
-paths = PackedStringArray("/user/hand/left/input/b/touch", "/user/hand/right/input/b/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7onrj"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_75ykv"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0l2lu"]
-action = SubResource("OpenXRAction_gpqeh")
-paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n0kql"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pxnyh"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wlbel"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_k58ue"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i5msy"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rhs2g"]
-action = SubResource("OpenXRAction_53byk")
-paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xrpmw"]
-action = SubResource("OpenXRAction_bkd5n")
-paths = PackedStringArray("/user/hand/left/input/trackpad/force", "/user/hand/right/input/trackpad/force")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5qr1b"]
-action = SubResource("OpenXRAction_mkk7a")
-paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5pkjy"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_6eyyg"]
-interaction_profile_path = "/interaction_profiles/valve/index_controller"
-bindings = [SubResource("OpenXRIPBinding_s0c47"), SubResource("OpenXRIPBinding_2rykr"), SubResource("OpenXRIPBinding_3apyd"), SubResource("OpenXRIPBinding_ec4nm"), SubResource("OpenXRIPBinding_teed4"), SubResource("OpenXRIPBinding_c1jsm"), SubResource("OpenXRIPBinding_i31ov"), SubResource("OpenXRIPBinding_a5dot"), SubResource("OpenXRIPBinding_sy7to"), SubResource("OpenXRIPBinding_7onrj"), SubResource("OpenXRIPBinding_75ykv"), SubResource("OpenXRIPBinding_0l2lu"), SubResource("OpenXRIPBinding_n0kql"), SubResource("OpenXRIPBinding_pxnyh"), SubResource("OpenXRIPBinding_wlbel"), SubResource("OpenXRIPBinding_k58ue"), SubResource("OpenXRIPBinding_i5msy"), SubResource("OpenXRIPBinding_rhs2g"), SubResource("OpenXRIPBinding_xrpmw"), SubResource("OpenXRIPBinding_5qr1b"), SubResource("OpenXRIPBinding_5pkjy")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gokds"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pofwu"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b1pba"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l18yv"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3uw3r"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3a84h"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fqe4s"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ddk7k"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gl8l7"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pn00s"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kw4aa"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_03m8e"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ekghp"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lbcu8"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_kxooo"]
-interaction_profile_path = "/interaction_profiles/hp/mixed_reality_controller"
-bindings = [SubResource("OpenXRIPBinding_gokds"), SubResource("OpenXRIPBinding_pofwu"), SubResource("OpenXRIPBinding_b1pba"), SubResource("OpenXRIPBinding_l18yv"), SubResource("OpenXRIPBinding_3uw3r"), SubResource("OpenXRIPBinding_3a84h"), SubResource("OpenXRIPBinding_fqe4s"), SubResource("OpenXRIPBinding_ddk7k"), SubResource("OpenXRIPBinding_gl8l7"), SubResource("OpenXRIPBinding_pn00s"), SubResource("OpenXRIPBinding_kw4aa"), SubResource("OpenXRIPBinding_03m8e"), SubResource("OpenXRIPBinding_ekghp"), SubResource("OpenXRIPBinding_lbcu8")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nxupw"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t4825"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3y4i7"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ea251"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jhak1"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click", "/user/hand/right/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mg6go"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pu8tu"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jvgch"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tae7d"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t2ie6"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7cage"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ofsd6"]
-action = SubResource("OpenXRAction_53byk")
-paths = PackedStringArray("/user/hand/left/input/trackpad", "/user/hand/right/input/trackpad")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cdtpu"]
-action = SubResource("OpenXRAction_bkd5n")
-paths = PackedStringArray("/user/hand/left/input/trackpad/click", "/user/hand/right/input/trackpad/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dtyxn"]
-action = SubResource("OpenXRAction_mkk7a")
-paths = PackedStringArray("/user/hand/left/input/trackpad/touch", "/user/hand/right/input/trackpad/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yid6j"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_wy3t2"]
-interaction_profile_path = "/interaction_profiles/samsung/odyssey_controller"
-bindings = [SubResource("OpenXRIPBinding_nxupw"), SubResource("OpenXRIPBinding_t4825"), SubResource("OpenXRIPBinding_3y4i7"), SubResource("OpenXRIPBinding_ea251"), SubResource("OpenXRIPBinding_jhak1"), SubResource("OpenXRIPBinding_mg6go"), SubResource("OpenXRIPBinding_pu8tu"), SubResource("OpenXRIPBinding_jvgch"), SubResource("OpenXRIPBinding_tae7d"), SubResource("OpenXRIPBinding_t2ie6"), SubResource("OpenXRIPBinding_7cage"), SubResource("OpenXRIPBinding_ofsd6"), SubResource("OpenXRIPBinding_cdtpu"), SubResource("OpenXRIPBinding_dtyxn"), SubResource("OpenXRIPBinding_yid6j")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_30ohe"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mo2cy"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_88il2"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hgr0c"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_53clm"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_krxa6"]
-action = SubResource("OpenXRAction_83w55")
-paths = PackedStringArray("/user/hand/left/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rwig7"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_scly6"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0xc3c"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kilck"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vcgs0"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hdvvr"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_83wki"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c02p5"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g2rpc"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lul31"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_maqsl"]
-interaction_profile_path = "/interaction_profiles/htc/vive_cosmos_controller"
-bindings = [SubResource("OpenXRIPBinding_30ohe"), SubResource("OpenXRIPBinding_mo2cy"), SubResource("OpenXRIPBinding_88il2"), SubResource("OpenXRIPBinding_hgr0c"), SubResource("OpenXRIPBinding_53clm"), SubResource("OpenXRIPBinding_krxa6"), SubResource("OpenXRIPBinding_rwig7"), SubResource("OpenXRIPBinding_scly6"), SubResource("OpenXRIPBinding_0xc3c"), SubResource("OpenXRIPBinding_kilck"), SubResource("OpenXRIPBinding_vcgs0"), SubResource("OpenXRIPBinding_hdvvr"), SubResource("OpenXRIPBinding_83wki"), SubResource("OpenXRIPBinding_c02p5"), SubResource("OpenXRIPBinding_g2rpc"), SubResource("OpenXRIPBinding_lul31")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jfxms"]
-action = SubResource("OpenXRAction_mj02j")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b52tt"]
-action = SubResource("OpenXRAction_x4afo")
-paths = PackedStringArray("/user/hand/left/input/aim/pose", "/user/hand/right/input/aim/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2p8m5"]
-action = SubResource("OpenXRAction_ffdsq")
-paths = PackedStringArray("/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vsjur"]
-action = SubResource("OpenXRAction_80sg0")
-paths = PackedStringArray("/user/hand/left/input/palm_ext/pose", "/user/hand/right/input/palm_ext/pose")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bfbcv"]
-action = SubResource("OpenXRAction_4uh4f")
-paths = PackedStringArray("/user/hand/left/input/menu/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qswlg"]
-action = SubResource("OpenXRAction_83w55")
-paths = PackedStringArray("/user/hand/left/input/system/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i3jtx"]
-action = SubResource("OpenXRAction_0sqj6")
-paths = PackedStringArray("/user/hand/left/input/x/click", "/user/hand/right/input/a/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_80khm"]
-action = SubResource("OpenXRAction_tblbd")
-paths = PackedStringArray("/user/hand/left/input/y/click", "/user/hand/right/input/b/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yabtl"]
-action = SubResource("OpenXRAction_qhy06")
-paths = PackedStringArray("/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qk0dp"]
-action = SubResource("OpenXRAction_2vwe0")
-paths = PackedStringArray("/user/hand/left/input/trigger/click", "/user/hand/right/input/trigger/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l8guq"]
-action = SubResource("OpenXRAction_gpqeh")
-paths = PackedStringArray("/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jlokn"]
-action = SubResource("OpenXRAction_473o0")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fy7c1"]
-action = SubResource("OpenXRAction_8qgll")
-paths = PackedStringArray("/user/hand/left/input/squeeze/click", "/user/hand/right/input/squeeze/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2c4pk"]
-action = SubResource("OpenXRAction_rhxy5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick", "/user/hand/right/input/thumbstick")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_41pcr"]
-action = SubResource("OpenXRAction_sxg5f")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mjifc"]
-action = SubResource("OpenXRAction_3rri5")
-paths = PackedStringArray("/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j3ms0"]
-action = SubResource("OpenXRAction_mkk7a")
-paths = PackedStringArray("/user/hand/left/input/thumbrest/touch", "/user/hand/right/input/thumbrest/touch")
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nsg5c"]
-action = SubResource("OpenXRAction_5os4r")
-paths = PackedStringArray("/user/hand/left/output/haptic", "/user/hand/right/output/haptic")
-
-[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_qqead"]
-interaction_profile_path = "/interaction_profiles/htc/vive_focus3_controller"
-bindings = [SubResource("OpenXRIPBinding_jfxms"), SubResource("OpenXRIPBinding_b52tt"), SubResource("OpenXRIPBinding_2p8m5"), SubResource("OpenXRIPBinding_vsjur"), SubResource("OpenXRIPBinding_bfbcv"), SubResource("OpenXRIPBinding_qswlg"), SubResource("OpenXRIPBinding_i3jtx"), SubResource("OpenXRIPBinding_80khm"), SubResource("OpenXRIPBinding_yabtl"), SubResource("OpenXRIPBinding_qk0dp"), SubResource("OpenXRIPBinding_l8guq"), SubResource("OpenXRIPBinding_jlokn"), SubResource("OpenXRIPBinding_fy7c1"), SubResource("OpenXRIPBinding_2c4pk"), SubResource("OpenXRIPBinding_41pcr"), SubResource("OpenXRIPBinding_mjifc"), SubResource("OpenXRIPBinding_j3ms0"), SubResource("OpenXRIPBinding_nsg5c")]
-
-[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vkj8f"]
-action = SubResource("OpenXRAction_mj02j")
-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_ci8gc"]
-action = SubResource("OpenXRAction_5os4r")
-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_bsacy"]
-interaction_profile_path = "/interaction_profiles/htc/vive_tracker_htcx"
-bindings = [SubResource("OpenXRIPBinding_vkj8f"), SubResource("OpenXRIPBinding_ci8gc")]
-
-[resource]
-action_sets = [SubResource("OpenXRActionSet_dlwup")]
-interaction_profiles = [SubResource("OpenXRInteractionProfile_n4f80"), SubResource("OpenXRInteractionProfile_om27o"), SubResource("OpenXRInteractionProfile_tk604"), SubResource("OpenXRInteractionProfile_kc40e"), SubResource("OpenXRInteractionProfile_ammxl"), SubResource("OpenXRInteractionProfile_6eyyg"), SubResource("OpenXRInteractionProfile_kxooo"), SubResource("OpenXRInteractionProfile_wy3t2"), SubResource("OpenXRInteractionProfile_maqsl"), SubResource("OpenXRInteractionProfile_qqead"), SubResource("OpenXRInteractionProfile_bsacy")]
diff --git a/example/project.godot b/example/project.godot
index ea8978a..a59171d 100644
--- a/example/project.godot
+++ b/example/project.godot
@@ -20,6 +20,10 @@ config/icon="res://icon.png"
T5Interface="*res://addons/tiltfive/T5Interface.gd"
+[editor_plugins]
+
+enabled=PackedStringArray("res://addons/tiltfive/plugin.cfg")
+
[input]
trigger={
diff --git a/extension/src/GodotT5Service.cpp b/extension/src/GodotT5Service.cpp
index ae4f487..26b2334 100644
--- a/extension/src/GodotT5Service.cpp
+++ b/extension/src/GodotT5Service.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
using godot::Variant;
@@ -90,18 +91,15 @@ void GodotT5Logger::log_warning(const char* message, const char* func_name, cons
}
void GodotT5Logger::log_string(const char* message) {
- Variant msg = message;
- UtilityFunctions::print(msg);
+ Variant v_msg = message;
+ UtilityFunctions::print_verbose(v_msg);
}
-
GodotT5Service::Ptr GodotT5ObjectRegistry::service() {
-
- assert(_instance);
- return std::static_pointer_cast(ObjectRegistry::service());
+ assert(_instance);
+ return std::static_pointer_cast(ObjectRegistry::service());
}
-
T5Integration::T5Service::Ptr GodotT5ObjectRegistry::get_service() {
GodotT5Service::Ptr service;
if (_service.expired()) {
@@ -127,15 +125,15 @@ T5Integration::T5Math::Ptr GodotT5ObjectRegistry::get_math() {
}
T5Integration::Logger::Ptr GodotT5ObjectRegistry::get_logger() {
- GodotT5Logger::Ptr logger;
- if (_logger.expired()) {
- logger = std::make_shared();
- _logger = logger;
- }
- else {
- logger = std::static_pointer_cast(_logger.lock());
- }
- return logger;
+ GodotT5Logger::Ptr logger;
+ if (_logger.expired()) {
+ logger = std::make_shared();
+ _logger = logger;
+ }
+ else {
+ logger = std::static_pointer_cast(_logger.lock());
+ }
+ return logger;
}
}
\ No newline at end of file
diff --git a/extension/src/T5Gameboard.cpp b/extension/src/T5Gameboard.cpp
new file mode 100644
index 0000000..ca957f3
--- /dev/null
+++ b/extension/src/T5Gameboard.cpp
@@ -0,0 +1,188 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+using godot::ClassDB;
+using godot::D_METHOD;
+using godot::PropertyInfo;
+using godot::Variant;
+using godot::Callable;
+using godot::Object;
+using godot::UtilityFunctions;
+using godot::ResourceLoader;
+using godot::PackedScene;
+using godot::SceneTree;
+using godot::Vector3;
+using godot::Engine;
+
+const char le_name[] = "LE";
+const char xe_name[] = "XE";
+const char raised_xe_name[] = "Raised XE";
+
+void T5Gameboard::set_content_scale(float scale) {
+ content_scale = scale;
+ set_board_state();
+}
+
+float T5Gameboard::get_content_scale() const{
+ return content_scale;
+}
+
+void T5Gameboard::set_gameboard_type(String gb_type) {
+ if(gb_type == le_name) {
+ gameboard_type = TiltFiveXRInterface::LE_GAMEBOARD;
+ }
+ else if(gb_type == xe_name) {
+ gameboard_type = TiltFiveXRInterface::XE_GAMEBOARD;
+ }
+ else if(gb_type == raised_xe_name) {
+ gameboard_type = TiltFiveXRInterface::XE_RAISED_GAMEBOARD;
+ }
+ else {
+ gameboard_type = TiltFiveXRInterface::NO_GAMEBOARD_SET;
+ }
+ set_board_state();
+
+}
+
+String T5Gameboard::get_gameboard_type() const{
+ switch (gameboard_type)
+ {
+ case TiltFiveXRInterface::LE_GAMEBOARD:
+ return le_name;
+ case TiltFiveXRInterface::XE_GAMEBOARD:
+ return xe_name;
+ case TiltFiveXRInterface::XE_RAISED_GAMEBOARD:
+ return raised_xe_name;
+ default:
+ break;
+ }
+ return "Unknown";
+}
+
+void T5Gameboard::set_show_at_runtime(bool show) {
+ show_at_runtime = show;
+ set_board_state();
+}
+
+bool T5Gameboard::get_show_at_runtime() const {
+ return show_at_runtime;
+}
+
+void T5Gameboard::set_layer_mask(uint32_t p_mask) {
+ layers = p_mask;
+ set_board_state();
+}
+
+uint32_t T5Gameboard::get_layer_mask() const {
+ return layers;
+}
+
+void T5Gameboard::set_layer_mask_value(int p_layer_number, bool p_value) {
+ ERR_FAIL_COND_MSG(p_layer_number < 1, "Render layer number must be between 1 and 20 inclusive.");
+ ERR_FAIL_COND_MSG(p_layer_number > 20, "Render layer number must be between 1 and 20 inclusive.");
+ uint32_t mask = get_layer_mask();
+ if (p_value) {
+ mask |= 1 << (p_layer_number - 1);
+ } else {
+ mask &= ~(1 << (p_layer_number - 1));
+ }
+ set_layer_mask(mask);
+}
+
+bool T5Gameboard::get_layer_mask_value(int p_layer_number) const {
+ ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Render layer number must be between 1 and 20 inclusive.");
+ ERR_FAIL_COND_V_MSG(p_layer_number > 20, false, "Render layer number must be between 1 and 20 inclusive.");
+ return layers & (1 << (p_layer_number - 1));
+}
+
+
+T5Gameboard::T5Gameboard(){
+
+}
+
+T5Gameboard::~T5Gameboard(){
+
+}
+
+Node3D* T5Gameboard::add_scene(String path) {
+ Ref scene = ResourceLoader::get_singleton()->load(path, "PackedScene");
+ ERR_FAIL_COND_V_MSG(scene.is_null(), nullptr, godot::vformat("Failed to load: %s", path));
+
+ auto node = scene->instantiate();
+ auto node_3d = Object::cast_to(node);
+ if(!node_3d) {
+ node->queue_free();
+ ERR_FAIL_V_MSG(nullptr, godot::vformat("Not Node3D: %s", path));
+ }
+ if(node_3d->get_child_count() == 0 || node->get_child(0)->get_class() != "MeshInstance3D") {
+ node->queue_free();
+ ERR_FAIL_V_MSG(nullptr, godot::vformat("Not Node3D and MeshInstance3D: %s", path));
+ }
+
+ add_child(node_3d);
+ return node_3d;
+}
+
+void T5Gameboard::set_board_state() {
+
+ bool show_board = show_at_runtime || Engine::get_singleton()->is_editor_hint();
+ if(le_node) {
+ le_node->set_scale(Vector3(content_scale, content_scale, content_scale));
+ le_node->set_visible(gameboard_type == TiltFiveXRInterface::LE_GAMEBOARD && show_board);
+ auto mesh_inst = Object::cast_to(le_node->get_child(0));
+ mesh_inst->set_layer_mask(layers);
+ }
+ if(xe_node) {
+ xe_node->set_scale(Vector3(content_scale, content_scale, content_scale));
+ xe_node->set_visible(gameboard_type == TiltFiveXRInterface::XE_GAMEBOARD && show_board);
+ auto mesh_inst = Object::cast_to(le_node->get_child(0));
+ mesh_inst->set_layer_mask(layers);
+ }
+ if(raised_xe_node) {
+ raised_xe_node->set_scale(Vector3(content_scale, content_scale, content_scale));
+ raised_xe_node->set_visible(gameboard_type == TiltFiveXRInterface::XE_RAISED_GAMEBOARD && show_board);
+ auto mesh_inst = Object::cast_to(le_node->get_child(0));
+ mesh_inst->set_layer_mask(layers);
+ }
+}
+
+void T5Gameboard::_ready() {
+ le_node = add_scene("res://addons/tiltfive/assets/T5_border.glb");
+ xe_node = add_scene("res://addons/tiltfive/assets/T5_border_XE.glb");
+ raised_xe_node = add_scene("res://addons/tiltfive/assets/T5_border_XE_raised.glb");
+ set_board_state();
+}
+
+void T5Gameboard::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_content_scale", "scale"), &T5Gameboard::set_content_scale);
+ ClassDB::bind_method(D_METHOD("get_content_scale"), &T5Gameboard::get_content_scale);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale", godot::PROPERTY_HINT_RANGE, "0.001, 1000.0, or_greater, hide_slider"), "set_content_scale", "get_content_scale");
+
+ ClassDB::bind_method(D_METHOD("set_gameboard_type", "gameboard_type"), &T5Gameboard::set_gameboard_type);
+ ClassDB::bind_method(D_METHOD("get_gameboard_type"), &T5Gameboard::get_gameboard_type);
+
+ auto hint = godot::vformat("%s,%s,%s", le_name, xe_name, raised_xe_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "gameboard_type", godot::PROPERTY_HINT_ENUM, hint), "set_gameboard_type", "get_gameboard_type");
+
+ ClassDB::bind_method(D_METHOD("set_show_at_runtime", "show"), &T5Gameboard::set_show_at_runtime);
+ ClassDB::bind_method(D_METHOD("get_show_at_runtime"), &T5Gameboard::get_show_at_runtime);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_at_runtime", godot::PROPERTY_HINT_NONE), "set_show_at_runtime", "get_show_at_runtime");
+
+ ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &T5Gameboard::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"), &T5Gameboard::get_layer_mask);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", godot::PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
+
+ ClassDB::bind_method(D_METHOD("set_layer_mask_value", "layer_number", "value"), &T5Gameboard::set_layer_mask_value);
+ ClassDB::bind_method(D_METHOD("get_layer_mask_value", "layer_number"), &T5Gameboard::get_layer_mask_value);
+
+};
+
+
\ No newline at end of file
diff --git a/extension/src/T5Gameboard.h b/extension/src/T5Gameboard.h
new file mode 100644
index 0000000..690d07f
--- /dev/null
+++ b/extension/src/T5Gameboard.h
@@ -0,0 +1,64 @@
+#ifndef T5_GAMEBOARD_H
+#define T5_GAMEBOARD_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using godot::Ref;
+using godot::String;
+using godot::StringName;
+using godot::VisualInstance3D;
+
+class T5Gameboard : public Node3D {
+ GDCLASS(T5Gameboard, Node3D);
+
+public:
+
+ void _ready() override;
+
+ void set_content_scale(float scale);
+ float get_content_scale() const;
+
+ void set_gameboard_type(String gbtype);
+ String get_gameboard_type() const;
+
+ void set_show_at_runtime(bool show);
+ bool get_show_at_runtime() const;
+
+ void set_layer_mask(uint32_t p_mask);
+ uint32_t get_layer_mask() const;
+
+ void set_layer_mask_value(int p_layer_number, bool p_enable);
+ bool get_layer_mask_value(int p_layer_number) const;
+
+
+ T5Gameboard();
+ ~T5Gameboard();
+
+protected:
+
+ static void _bind_methods();
+
+private:
+ Node3D* add_scene(String path);
+ void set_board_state();
+
+ float content_scale = 1.0;
+ TiltFiveXRInterface::GameBoardType gameboard_type = TiltFiveXRInterface::GameBoardType::LE_GAMEBOARD;
+ bool show_at_runtime = false;
+ uint32_t layers = 1;
+
+ Node3D* le_node = nullptr;
+ Node3D* xe_node = nullptr;
+ Node3D* raised_xe_node = nullptr;
+};
+
+
+
+
+#endif // T5_GAMEBOARD_H
\ No newline at end of file
diff --git a/extension/src/register_types.cpp b/extension/src/register_types.cpp
index 2e5906e..b144529 100644
--- a/extension/src/register_types.cpp
+++ b/extension/src/register_types.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -21,6 +22,8 @@ void initialize_tiltfive_types(ModuleInitializationLevel p_level)
ClassDB::register_class();
ClassDB::register_class();
ClassDB::register_class();
+ ClassDB::register_class();
+
}