From dc6a9929b7d95bdc012983102884d4fb7e369331 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Tue, 12 Oct 2021 14:51:22 +0200 Subject: [PATCH] refactor touch and trigger handling to allow for touch controls --- .../openvr_overlay/OverlayInteraction.tscn | 5 +- .../OverlayInteractionRoot.tscn | 25 +++- ...verlayActivator.tscn => HandCollider.tscn} | 6 +- .../interaction/OverlayArea.tscn | 13 +- .../interaction/TouchCollider.tscn | 10 ++ .../interaction/overlay_cursor.gd | 14 ++- .../interaction/overlay_grab.gd | 14 +-- .../interaction/overlay_interaction.gd | 114 ++++++++++++------ src/addons/openvr_overlay/overlay_init.gd | 2 +- src/overlay_scripts/ui_demo.gd | 3 +- src/project.godot | 2 + 11 files changed, 145 insertions(+), 63 deletions(-) rename src/addons/openvr_overlay/interaction/{OverlayActivator.tscn => HandCollider.tscn} (64%) create mode 100644 src/addons/openvr_overlay/interaction/TouchCollider.tscn diff --git a/src/addons/openvr_overlay/OverlayInteraction.tscn b/src/addons/openvr_overlay/OverlayInteraction.tscn index ac39b58..5e5c959 100644 --- a/src/addons/openvr_overlay/OverlayInteraction.tscn +++ b/src/addons/openvr_overlay/OverlayInteraction.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://addons/openvr_overlay/interaction/overlay_interaction.gd" type="Script" id=1] +[ext_resource path="res://addons/openvr_overlay/interaction/OverlayArea.tscn" type="PackedScene" id=2] [node name="OverlayInteraction" type="Node"] script = ExtResource( 1 ) @@ -15,6 +16,8 @@ controller_id = 2 [node name="head" type="ARVRCamera" parent="VR"] visible = false +[node name="OverlayArea" parent="." instance=ExtResource( 2 )] + [connection signal="button_pressed" from="VR/left" to="." method="_on_LeftHand_button_pressed"] [connection signal="button_release" from="VR/left" to="." method="_on_LeftHand_button_release"] [connection signal="button_pressed" from="VR/right" to="." method="_on_RightHand_button_pressed"] diff --git a/src/addons/openvr_overlay/OverlayInteractionRoot.tscn b/src/addons/openvr_overlay/OverlayInteractionRoot.tscn index 69cefca..b756ce6 100644 --- a/src/addons/openvr_overlay/OverlayInteractionRoot.tscn +++ b/src/addons/openvr_overlay/OverlayInteractionRoot.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://addons/openvr_overlay/interaction/OverlayActivator.tscn" type="PackedScene" id=1] +[ext_resource path="res://addons/openvr_overlay/interaction/HandCollider.tscn" type="PackedScene" id=1] +[ext_resource path="res://addons/openvr_overlay/interaction/TouchCollider.tscn" type="PackedScene" id=2] [node name="OverlayInteractionRoot" type="Node"] @@ -8,16 +9,32 @@ [node name="left" type="ARVRController" parent="VR"] -[node name="OverlayActivator" parent="VR/left" instance=ExtResource( 1 )] +[node name="HandCollider" parent="VR/left" groups=[ +"left", +] instance=ExtResource( 1 )] collision_layer = 4 collision_mask = 4 +[node name="TouchCollider" parent="VR/left" groups=[ +"left", +] instance=ExtResource( 2 )] +collision_layer = 16 +collision_mask = 16 + [node name="right" type="ARVRController" parent="VR"] controller_id = 2 -[node name="OverlayActivator" parent="VR/right" instance=ExtResource( 1 )] +[node name="HandCollider" parent="VR/right" groups=[ +"right", +] instance=ExtResource( 1 )] collision_layer = 2 collision_mask = 2 +[node name="TouchCollider" parent="VR/right" groups=[ +"right", +] instance=ExtResource( 2 )] +collision_layer = 8 +collision_mask = 8 + [node name="head" type="ARVRCamera" parent="VR"] visible = false diff --git a/src/addons/openvr_overlay/interaction/OverlayActivator.tscn b/src/addons/openvr_overlay/interaction/HandCollider.tscn similarity index 64% rename from src/addons/openvr_overlay/interaction/OverlayActivator.tscn rename to src/addons/openvr_overlay/interaction/HandCollider.tscn index b891437..f9f3f09 100644 --- a/src/addons/openvr_overlay/interaction/OverlayActivator.tscn +++ b/src/addons/openvr_overlay/interaction/HandCollider.tscn @@ -2,11 +2,9 @@ [sub_resource type="SphereShape" id=1] margin = 0.001 -radius = 0.01 +radius = 0.03 -[node name="OverlayActivator" type="StaticBody" groups=[ -"OverlayActivator", -]] +[node name="HandCollider" type="StaticBody"] [node name="Collision" type="CollisionShape" parent="."] shape = SubResource( 1 ) diff --git a/src/addons/openvr_overlay/interaction/OverlayArea.tscn b/src/addons/openvr_overlay/interaction/OverlayArea.tscn index f45c2da..3e3f11b 100644 --- a/src/addons/openvr_overlay/interaction/OverlayArea.tscn +++ b/src/addons/openvr_overlay/interaction/OverlayArea.tscn @@ -4,9 +4,18 @@ resource_local_to_scene = true extents = Vector3( 0.2, 0.2, 0.01 ) -[node name="OverlayArea" type="Area"] +[node name="OverlayArea" type="Spatial"] + +[node name="AreaNear" type="Area" parent="."] collision_layer = 0 collision_mask = 6 -[node name="CollisionShape" type="CollisionShape" parent="."] +[node name="CollisionShape" type="CollisionShape" parent="AreaNear"] +shape = SubResource( 1 ) + +[node name="AreaTouch" type="Area" parent="."] +collision_layer = 0 +collision_mask = 24 + +[node name="CollisionShape" type="CollisionShape" parent="AreaTouch"] shape = SubResource( 1 ) diff --git a/src/addons/openvr_overlay/interaction/TouchCollider.tscn b/src/addons/openvr_overlay/interaction/TouchCollider.tscn new file mode 100644 index 0000000..a68a6de --- /dev/null +++ b/src/addons/openvr_overlay/interaction/TouchCollider.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=2 format=2] + +[sub_resource type="SphereShape" id=1] +margin = 0.001 +radius = 0.0 + +[node name="TouchCollider" type="StaticBody"] + +[node name="Collision" type="CollisionShape" parent="."] +shape = SubResource( 1 ) diff --git a/src/addons/openvr_overlay/interaction/overlay_cursor.gd b/src/addons/openvr_overlay/interaction/overlay_cursor.gd index 98104d5..bcdeddd 100644 --- a/src/addons/openvr_overlay/interaction/overlay_cursor.gd +++ b/src/addons/openvr_overlay/interaction/overlay_cursor.gd @@ -23,11 +23,17 @@ func _process(_delta: float) -> void: #get canvas position of active controller func get_canvas_pos() -> Vector2: - if not _i.active_controller: + var active + if _i.state.right.near: + active = "right" + elif _i.state.left.near: + active = "left" + else: return Vector2(-1000, 1000) # offscreen + #if not (_i.state.right.near or _i.state.left.near): var controller_local_pos = _i._overlay_area.global_transform.xform_inv(\ - _i.tracker_nodes[_i.active_controller].translation) + _i.tracker_nodes[active].translation) var pos = Vector2(controller_local_pos.x, controller_local_pos.y) var overlay_size = Vector2(2048, 2048) @@ -61,10 +67,10 @@ func _send_click_event(state: bool): viewport.input(click_event) -func _trigger_on(): +func _trigger_on(controller): _send_click_event(true) -func _trigger_off(): +func _trigger_off(controller): _send_click_event(false) diff --git a/src/addons/openvr_overlay/interaction/overlay_grab.gd b/src/addons/openvr_overlay/interaction/overlay_grab.gd index 6a67447..b2edefd 100644 --- a/src/addons/openvr_overlay/interaction/overlay_grab.gd +++ b/src/addons/openvr_overlay/interaction/overlay_grab.gd @@ -22,18 +22,18 @@ func _ready() -> void: get_parent().connect("trigger_off", self, "_trigger_off") -func _trigger_on(): +func _trigger_on(controller): if Settings.s.grab_mode or _interaction.grab_mode: - begin_move() + begin_move(controller) -func _trigger_off(): +func _trigger_off(_controller): finish_move() -func begin_move(): - if not _interaction.active_controller: - print("Could not begin moving overlay, no controller is touching overlay. <", _overlay.name, ">") +func begin_move(controller="right"): + if not _interaction.state[controller].near: + print("Could not begin moving overlay, " + controller + " controller is not touching overlay. <", _overlay.name, ">") return if is_moving: return @@ -41,7 +41,7 @@ func begin_move(): _interaction.pause_triggers = true # store current states to revert after move _pre_move_target = _overlay.current_target - _mover_hand_name = _interaction.active_controller + _mover_hand_name = controller _mover_hand_offsets = _overlay.get_offset(_mover_hand_name) # calculate offsets from active controller to overlay diff --git a/src/addons/openvr_overlay/interaction/overlay_interaction.gd b/src/addons/openvr_overlay/interaction/overlay_interaction.gd index 8a0b888..836db92 100644 --- a/src/addons/openvr_overlay/interaction/overlay_interaction.gd +++ b/src/addons/openvr_overlay/interaction/overlay_interaction.gd @@ -1,22 +1,37 @@ extends Node -signal touch_on # a controller entered -signal touch_off # a controller exited -signal trigger_on # trigger pushed while touching -signal trigger_off# trigger released -var touch_state := false -var trigger_state := false +signal near_on # a controller entered the near area (enable cursor and/or touch visualiser) +signal near_off # a controller exited +signal touch_on +signal touch_off +signal trigger_on # trigger pushed while touching +signal trigger_off # trigger released + var grab_mode := false setget set_grab_mode -# controller that currently has the trigger down -var active_controller := "" # reference to the area node thats used for touch -var _overlay_area = preload("res://addons/openvr_overlay/interaction/OverlayArea.tscn").instance() +var _overlay_area: Spatial# = preload("res://addons/openvr_overlay/interaction/OverlayArea.tscn").instance() var _right_is_activator := false # this hand has a collider on it to trigger things on the overlay var _left_is_activator := false -var pause_triggers := false # disable triggers updating +var pause_triggers := false # disable triggers updating (used by grab module) + +var state := { + "right": { + "active": false, + "near": false, + "touch": false, + "trigger": false, + }, + "left": { + "active": false, + "near": false, + "touch": false, + "trigger": false, + }, +} + onready var tracker_nodes = { "head": $VR/head, @@ -27,9 +42,12 @@ onready var tracker_nodes = { func _ready() -> void: - add_child(_overlay_area) - _overlay_area.connect("body_entered", self, "_on_OverlayArea_entered") - _overlay_area.connect("body_exited", self, "_on_OverlayArea_exited") + #add_child(_overlay_area) + _overlay_area = $OverlayArea + _overlay_area.get_node("AreaNear").connect("body_entered", self, "_on_Near_entered") + _overlay_area.get_node("AreaNear").connect("body_exited", self, "_on_Near_exited") + _overlay_area.get_node("AreaTouch").connect("body_entered", self, "_on_Touch_entered") + _overlay_area.get_node("AreaTouch").connect("body_exited", self, "_on_Touch_exited") get_parent().connect("width_changed", self, "_update_width") get_parent().connect("offset_changed", self, "_update_offset") @@ -45,37 +63,57 @@ func _ready() -> void: func _trigger_on(controller): - if touch_state: - active_controller = controller - trigger_state = true - emit_signal("trigger_on") + if state[controller].near: + state[controller].trigger = true + emit_signal("trigger_on", controller) -func _trigger_off(): - trigger_state = false - emit_signal("trigger_off") +func _trigger_off(controller): + state[controller].trigger = false + emit_signal("trigger_off", controller) -func _on_OverlayArea_entered(body: Node) -> void: +func _on_Near_entered(body: Node) -> void: if pause_triggers or !get_parent().overlay_visible: return - touch_state = true - active_controller = body.get_parent().name + var hand = body.get_groups()[0] + state[hand].near = true + update_selection() + emit_signal("near_on") + + +func _on_Near_exited(body: Node) -> void: + if pause_triggers or !get_parent().overlay_visible: + return + var hand = body.get_groups()[0] + state[hand].near = false + + update_selection() + emit_signal("near_off") + + +func _on_Touch_entered(body: Node) -> void: + if pause_triggers or !get_parent().overlay_visible: + return + var hand = body.get_groups()[0] + state[hand].touch = true update_selection() emit_signal("touch_on") -func _on_OverlayArea_exited(body: Node) -> void: +func _on_Touch_exited(body: Node) -> void: if pause_triggers or !get_parent().overlay_visible: return - active_controller = "" - touch_state = false + var hand = body.get_groups()[0] + state[hand].touch = false + update_selection() emit_signal("touch_off") func update_selection(): - var sel = touch_state and (Settings.s.grab_mode or grab_mode) + var sel = (Settings.s.grab_mode or grab_mode) + sel = sel and (state.right.near or state.left.near) get_parent().get_node("OverlayViewport/Selected").visible = sel @@ -87,7 +125,7 @@ func set_grab_mode(state: bool) -> void: func _update_width(): var ratio = OverlayInit.ovr_interface.get_render_targetsize() var extents = get_parent().width_meters * 0.5 - _overlay_area.get_child(0).shape.set_extents(Vector3(extents, extents * ratio.y/ratio.x, 0.05)) + _overlay_area.get_node("AreaNear/CollisionShape").shape.set_extents(Vector3(extents, extents * ratio.y/ratio.x, 0.05)) func _update_offset(): @@ -101,11 +139,11 @@ func _update_target(): _overlay_area.get_parent().remove_child(_overlay_area) tracker_nodes[t].add_child(_overlay_area) - _left_is_activator = t != "left" - _right_is_activator = t != "right" + state.right.active = t != "right" + state.left.active = t != "left" # make area only detect colliders of a different hand - _overlay_area.collision_mask = int(t!="right")*2 # detect right hand - _overlay_area.collision_mask += int(t!="left")*4 # detect left hand + _overlay_area.get_node("AreaNear").collision_mask = int(t!="right")*2 # detect right hand + _overlay_area.get_node("AreaNear").collision_mask += int(t!="left")*4 # detect left hand func _update_modules(): @@ -133,20 +171,20 @@ func _update_modules(): func _on_RightHand_button_pressed(button: int) -> void: - if button == JOY_VR_TRIGGER and _right_is_activator: + if button == JOY_VR_TRIGGER and state.right.active: _trigger_on("right") func _on_RightHand_button_release(button: int) -> void: - if button == JOY_VR_TRIGGER and active_controller == "right": - _trigger_off() + if button == JOY_VR_TRIGGER and state.right.trigger: + _trigger_off("right") func _on_LeftHand_button_pressed(button: int) -> void: - if button == JOY_VR_TRIGGER and _left_is_activator: + if button == JOY_VR_TRIGGER and state.left.active: _trigger_on("left") func _on_LeftHand_button_release(button: int) -> void: - if button == JOY_VR_TRIGGER and active_controller == "left": - _trigger_off() + if button == JOY_VR_TRIGGER and state.left.trigger: + _trigger_off("left") diff --git a/src/addons/openvr_overlay/overlay_init.gd b/src/addons/openvr_overlay/overlay_init.gd index fb351a2..7423c5a 100644 --- a/src/addons/openvr_overlay/overlay_init.gd +++ b/src/addons/openvr_overlay/overlay_init.gd @@ -6,6 +6,7 @@ const OVERLAY_PROPERTIES_DEFAULT = { "allow_hide": true, # "interaction": true, "has_cursor": false, + "has_touch": false, "has_grab": true, } @@ -21,7 +22,6 @@ var trackers = { func _init() -> void: # OS.window_minimized = true - ovr_config = preload("res://addons/godot-openvr/OpenVRConfig.gdns").new() ovr_config.set_application_type(2) # Set to OVERLAY MODE = 2, NORMAL MODE = 1 ovr_config.set_tracking_universe(1) # Set to SEATED MODE = 0, STANDING MODE = 1, RAW MODE = 2 diff --git a/src/overlay_scripts/ui_demo.gd b/src/overlay_scripts/ui_demo.gd index c19c53a..bf9b441 100644 --- a/src/overlay_scripts/ui_demo.gd +++ b/src/overlay_scripts/ui_demo.gd @@ -2,6 +2,7 @@ extends Control const OVERLAY_PROPERTIES = { "has_cursor": true, + "has_touch": true, } var ihandler @@ -11,8 +12,6 @@ var oinst func _ready() -> void: oinst = get_viewport().get_parent() ihandler = get_viewport().get_node("../OverlayInteraction/OverlayGrab") - #if not oinst.add_cursor: - # oinst.add_cursor() for t in oinst.TARGETS: $OptionButton.add_item(t) $OptionButton.selected = oinst.TARGETS.find(oinst.target) diff --git a/src/project.godot b/src/project.godot index 73e1eb1..8f394de 100644 --- a/src/project.godot +++ b/src/project.godot @@ -44,6 +44,8 @@ singletons=[ "res://addons/godot-openvr/godot_openvr.gdnlib" ] 3d_physics/layer_2="right_hand" 3d_physics/layer_3="left_hand" +3d_physics/layer_4="right_touch" +3d_physics/layer_5="left_touch" [physics]