refactor touch and trigger handling to allow for touch controls

This commit is contained in:
Crispy 2021-10-12 14:51:22 +02:00
parent a073c19e9c
commit dc6a9929b7
11 changed files with 145 additions and 63 deletions

View file

@ -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/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"] [node name="OverlayInteraction" type="Node"]
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -15,6 +16,8 @@ controller_id = 2
[node name="head" type="ARVRCamera" parent="VR"] [node name="head" type="ARVRCamera" parent="VR"]
visible = false 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_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_release" from="VR/left" to="." method="_on_LeftHand_button_release"]
[connection signal="button_pressed" from="VR/right" to="." method="_on_RightHand_button_pressed"] [connection signal="button_pressed" from="VR/right" to="." method="_on_RightHand_button_pressed"]

View file

@ -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"] [node name="OverlayInteractionRoot" type="Node"]
@ -8,16 +9,32 @@
[node name="left" type="ARVRController" parent="VR"] [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_layer = 4
collision_mask = 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"] [node name="right" type="ARVRController" parent="VR"]
controller_id = 2 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_layer = 2
collision_mask = 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"] [node name="head" type="ARVRCamera" parent="VR"]
visible = false visible = false

View file

@ -2,11 +2,9 @@
[sub_resource type="SphereShape" id=1] [sub_resource type="SphereShape" id=1]
margin = 0.001 margin = 0.001
radius = 0.01 radius = 0.03
[node name="OverlayActivator" type="StaticBody" groups=[ [node name="HandCollider" type="StaticBody"]
"OverlayActivator",
]]
[node name="Collision" type="CollisionShape" parent="."] [node name="Collision" type="CollisionShape" parent="."]
shape = SubResource( 1 ) shape = SubResource( 1 )

View file

@ -4,9 +4,18 @@
resource_local_to_scene = true resource_local_to_scene = true
extents = Vector3( 0.2, 0.2, 0.01 ) 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_layer = 0
collision_mask = 6 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 ) shape = SubResource( 1 )

View file

@ -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 )

View file

@ -23,11 +23,17 @@ func _process(_delta: float) -> void:
#get canvas position of active controller #get canvas position of active controller
func get_canvas_pos() -> Vector2: 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 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(\ 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 pos = Vector2(controller_local_pos.x, controller_local_pos.y)
var overlay_size = Vector2(2048, 2048) var overlay_size = Vector2(2048, 2048)
@ -61,10 +67,10 @@ func _send_click_event(state: bool):
viewport.input(click_event) viewport.input(click_event)
func _trigger_on(): func _trigger_on(controller):
_send_click_event(true) _send_click_event(true)
func _trigger_off(): func _trigger_off(controller):
_send_click_event(false) _send_click_event(false)

View file

@ -22,18 +22,18 @@ func _ready() -> void:
get_parent().connect("trigger_off", self, "_trigger_off") get_parent().connect("trigger_off", self, "_trigger_off")
func _trigger_on(): func _trigger_on(controller):
if Settings.s.grab_mode or _interaction.grab_mode: if Settings.s.grab_mode or _interaction.grab_mode:
begin_move() begin_move(controller)
func _trigger_off(): func _trigger_off(_controller):
finish_move() finish_move()
func begin_move(): func begin_move(controller="right"):
if not _interaction.active_controller: if not _interaction.state[controller].near:
print("Could not begin moving overlay, no controller is touching overlay. <", _overlay.name, ">") print("Could not begin moving overlay, " + controller + " controller is not touching overlay. <", _overlay.name, ">")
return return
if is_moving: if is_moving:
return return
@ -41,7 +41,7 @@ func begin_move():
_interaction.pause_triggers = true _interaction.pause_triggers = true
# store current states to revert after move # store current states to revert after move
_pre_move_target = _overlay.current_target _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) _mover_hand_offsets = _overlay.get_offset(_mover_hand_name)
# calculate offsets from active controller to overlay # calculate offsets from active controller to overlay

View file

@ -1,22 +1,37 @@
extends Node 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 signal near_on # a controller entered the near area (enable cursor and/or touch visualiser)
var trigger_state := false 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 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 # 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 _right_is_activator := false # this hand has a collider on it to trigger things on the overlay
var _left_is_activator := false 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 = { onready var tracker_nodes = {
"head": $VR/head, "head": $VR/head,
@ -27,9 +42,12 @@ onready var tracker_nodes = {
func _ready() -> void: func _ready() -> void:
add_child(_overlay_area) #add_child(_overlay_area)
_overlay_area.connect("body_entered", self, "_on_OverlayArea_entered") _overlay_area = $OverlayArea
_overlay_area.connect("body_exited", self, "_on_OverlayArea_exited") _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("width_changed", self, "_update_width")
get_parent().connect("offset_changed", self, "_update_offset") get_parent().connect("offset_changed", self, "_update_offset")
@ -45,37 +63,57 @@ func _ready() -> void:
func _trigger_on(controller): func _trigger_on(controller):
if touch_state: if state[controller].near:
active_controller = controller state[controller].trigger = true
trigger_state = true emit_signal("trigger_on", controller)
emit_signal("trigger_on")
func _trigger_off(): func _trigger_off(controller):
trigger_state = false state[controller].trigger = false
emit_signal("trigger_off") 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: if pause_triggers or !get_parent().overlay_visible:
return return
touch_state = true var hand = body.get_groups()[0]
active_controller = body.get_parent().name 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() update_selection()
emit_signal("touch_on") 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: if pause_triggers or !get_parent().overlay_visible:
return return
active_controller = "" var hand = body.get_groups()[0]
touch_state = false state[hand].touch = false
update_selection() update_selection()
emit_signal("touch_off") emit_signal("touch_off")
func update_selection(): 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 get_parent().get_node("OverlayViewport/Selected").visible = sel
@ -87,7 +125,7 @@ func set_grab_mode(state: bool) -> void:
func _update_width(): func _update_width():
var ratio = OverlayInit.ovr_interface.get_render_targetsize() var ratio = OverlayInit.ovr_interface.get_render_targetsize()
var extents = get_parent().width_meters * 0.5 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(): func _update_offset():
@ -101,11 +139,11 @@ func _update_target():
_overlay_area.get_parent().remove_child(_overlay_area) _overlay_area.get_parent().remove_child(_overlay_area)
tracker_nodes[t].add_child(_overlay_area) tracker_nodes[t].add_child(_overlay_area)
_left_is_activator = t != "left" state.right.active = t != "right"
_right_is_activator = t != "right" state.left.active = t != "left"
# make area only detect colliders of a different hand # make area only detect colliders of a different hand
_overlay_area.collision_mask = int(t!="right")*2 # detect right hand _overlay_area.get_node("AreaNear").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!="left")*4 # detect left hand
func _update_modules(): func _update_modules():
@ -133,20 +171,20 @@ func _update_modules():
func _on_RightHand_button_pressed(button: int) -> void: 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") _trigger_on("right")
func _on_RightHand_button_release(button: int) -> void: func _on_RightHand_button_release(button: int) -> void:
if button == JOY_VR_TRIGGER and active_controller == "right": if button == JOY_VR_TRIGGER and state.right.trigger:
_trigger_off() _trigger_off("right")
func _on_LeftHand_button_pressed(button: int) -> void: 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") _trigger_on("left")
func _on_LeftHand_button_release(button: int) -> void: func _on_LeftHand_button_release(button: int) -> void:
if button == JOY_VR_TRIGGER and active_controller == "left": if button == JOY_VR_TRIGGER and state.left.trigger:
_trigger_off() _trigger_off("left")

View file

@ -6,6 +6,7 @@ const OVERLAY_PROPERTIES_DEFAULT = {
"allow_hide": true, "allow_hide": true,
# "interaction": true, # "interaction": true,
"has_cursor": false, "has_cursor": false,
"has_touch": false,
"has_grab": true, "has_grab": true,
} }
@ -21,7 +22,6 @@ var trackers = {
func _init() -> void: func _init() -> void:
# OS.window_minimized = true # 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_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 ovr_config.set_tracking_universe(1) # Set to SEATED MODE = 0, STANDING MODE = 1, RAW MODE = 2

View file

@ -2,6 +2,7 @@ extends Control
const OVERLAY_PROPERTIES = { const OVERLAY_PROPERTIES = {
"has_cursor": true, "has_cursor": true,
"has_touch": true,
} }
var ihandler var ihandler
@ -11,8 +12,6 @@ var oinst
func _ready() -> void: func _ready() -> void:
oinst = get_viewport().get_parent() oinst = get_viewport().get_parent()
ihandler = get_viewport().get_node("../OverlayInteraction/OverlayGrab") ihandler = get_viewport().get_node("../OverlayInteraction/OverlayGrab")
#if not oinst.add_cursor:
# oinst.add_cursor()
for t in oinst.TARGETS: for t in oinst.TARGETS:
$OptionButton.add_item(t) $OptionButton.add_item(t)
$OptionButton.selected = oinst.TARGETS.find(oinst.target) $OptionButton.selected = oinst.TARGETS.find(oinst.target)

View file

@ -44,6 +44,8 @@ singletons=[ "res://addons/godot-openvr/godot_openvr.gdnlib" ]
3d_physics/layer_2="right_hand" 3d_physics/layer_2="right_hand"
3d_physics/layer_3="left_hand" 3d_physics/layer_3="left_hand"
3d_physics/layer_4="right_touch"
3d_physics/layer_5="left_touch"
[physics] [physics]