Compare commits
60 commits
Author | SHA1 | Date | |
---|---|---|---|
b1098a13ec | |||
7edd005bb7 | |||
9f0b811d24 | |||
f892d4892b | |||
e6e003ca51 | |||
d83deb8721 | |||
8725763124 | |||
be9ceeef9c | |||
24ad04e262 | |||
899a3dce3d | |||
710b418970 | |||
23b37778b1 | |||
aaeed533da | |||
ef744db9ae | |||
2bac6afcdc | |||
08cb7dc283 | |||
9eea2a7c28 | |||
97fd916a87 | |||
e1944bcc25 | |||
20bf94d7ab | |||
dc6a9929b7 | |||
a073c19e9c | |||
b673410e70 | |||
f081a963a4 | |||
43d3ce3e16 | |||
a284c87792 | |||
b1eb8eb9d8 | |||
|
588f361f52 | ||
3a6d0469e5 | |||
73d9d9b88b | |||
284cfa3c2f | |||
774d678bd7 | |||
5fc14a3def | |||
bf3908de5c | |||
727e559396 | |||
01c11ffd32 | |||
b15c00f5f0 | |||
386465e8d9 | |||
078cd11e5e | |||
2ff72e5023 | |||
a0e6e932e4 | |||
d05880187a | |||
e0c7def52d | |||
f0b0bc84b5 | |||
2fefd5a03b | |||
9a5e58351f | |||
dd28bdcb54 | |||
f22efdea0a | |||
721c518bc3 | |||
eda8c8c06c | |||
0ad307d194 | |||
92feff4892 | |||
6f79709af5 | |||
7dd5a544ab | |||
64a51bdd7e | |||
|
80512957cc | ||
4a89de6af9 | |||
381be25af0 | |||
74f7caed5d | |||
8d21c4f424 |
|
@ -11,3 +11,6 @@ A cross-platform SteamVR overlay application that aims to have many useful tools
|
|||
* Click `add` and then `add selected programs`
|
||||
* You should now be able to start it from steam (favourite it for easier access)
|
||||
|
||||
## Usage
|
||||
At the moment all interacions are done with the trigger buttons, this will use steamvr actions and be configurable in the future.
|
||||
|
||||
|
|
35
docs/README.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# WIP documentation
|
||||
|
||||
## Hierarchy
|
||||
|
||||
```
|
||||
OverlayManager
|
||||
- MyOverlayInstance
|
||||
- [...]
|
||||
- OverlayViewport
|
||||
- Container
|
||||
- MyOverlay
|
||||
- [...]
|
||||
- OverlayInteraction
|
||||
- VR
|
||||
- [colliders for vr trackers etc]
|
||||
- Grabbable
|
||||
- Clickable
|
||||
- Touchable
|
||||
|
||||
```
|
||||
|
||||
|
||||
## overlay interaction types
|
||||
Each overlay instance has a OverlayInteraction node, which spawns the different interaction modules depending on what is defined in the OVERLAY_PROPERTIES.
|
||||
|
||||
The modules/interaction types are:
|
||||
- Grabbable
|
||||
- Touchable
|
||||
- Clickable
|
||||
|
||||
These modules connect signals from different places to the interaction manager (`OverlayInteraction`)
|
||||
Touchable connects collision signals to mouse inputs (potentially logic between to help prevent double presses)
|
||||
Clickable connects vr button signals to mouse inputs
|
||||
Grabbable connects vr button signals to grab logic, while telling the interaction manager to pause normal interaction
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="Main" type="Node"]
|
|
@ -1,5 +0,0 @@
|
|||
The resources here are taken from: `Steam\steamapps\common\SteamVR\resources\rendermodels\vr_glove\`
|
||||
|
||||
To save space in the repository only the slim models are included while the texture maps have been taken from the full versions.
|
||||
|
||||
See `../scenes/ovr_left_hand.tscn` and `../scenes/ovr_right_hand.tscn` for implementation details
|
|
@ -1,36 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path.s3tc="res://.import/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.stex"
|
||||
path.etc2="res://.import/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.etc2.stex"
|
||||
metadata={
|
||||
"imported_formats": [ "s3tc", "etc2" ],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/godot-openvr/meshes/hands_albedo.png"
|
||||
dest_files=[ "res://.import/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.s3tc.stex", "res://.import/hands_albedo.png-149a10baba7906560a9f9eab8fadf1d8.etc2.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=true
|
||||
flags/filter=true
|
||||
flags/mipmaps=true
|
||||
flags/anisotropic=false
|
||||
flags/srgb=1
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
Before Width: | Height: | Size: 29 MiB |
|
@ -1,36 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path.s3tc="res://.import/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.stex"
|
||||
path.etc2="res://.import/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.etc2.stex"
|
||||
metadata={
|
||||
"imported_formats": [ "s3tc", "etc2" ],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/godot-openvr/meshes/hands_normal.png"
|
||||
dest_files=[ "res://.import/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.s3tc.stex", "res://.import/hands_normal.png-eab7a86e959f13e1294e8f67904a8873.etc2.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=1
|
||||
flags/repeat=true
|
||||
flags/filter=true
|
||||
flags/mipmaps=true
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
|
@ -1,42 +0,0 @@
|
|||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://addons/godot-openvr/meshes/vr_glove_left_model_slim.glb" type="PackedScene" id=1]
|
||||
[ext_resource path="res://addons/godot-openvr/meshes/models_hands_vr_glove_vmat.material" type="Material" id=2]
|
||||
[ext_resource path="res://addons/godot-openvr/OpenVRPose.gdns" type="Script" id=3]
|
||||
[ext_resource path="res://addons/godot-openvr/OpenVRSkeleton.gdns" type="Script" id=4]
|
||||
|
||||
[node name="ovr_left_hand" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 3 )
|
||||
action = "/actions/godot/in/left_hand"
|
||||
|
||||
[node name="Skeleton" parent="RootNode" index="0"]
|
||||
bones/5/bound_children = [ NodePath("Thumb") ]
|
||||
bones/10/bound_children = [ NodePath("Index") ]
|
||||
bones/15/bound_children = [ NodePath("Middle") ]
|
||||
bones/20/bound_children = [ NodePath("Ring") ]
|
||||
bones/25/bound_children = [ NodePath("Pinky") ]
|
||||
script = ExtResource( 4 )
|
||||
action = "/actions/godot/in/left_hand"
|
||||
|
||||
[node name="vr_glove_left_slim" parent="RootNode/Skeleton" index="0"]
|
||||
material/0 = ExtResource( 2 )
|
||||
|
||||
[node name="Thumb" type="BoneAttachment" parent="RootNode/Skeleton" index="1"]
|
||||
transform = Transform( -0.347509, 0.0284256, 0.937246, -0.13095, -0.991217, -0.0184906, 0.928488, -0.129158, 0.348178, -0.0498674, 0.056092, 0.112777 )
|
||||
bone_name = "finger_thumb_l_end"
|
||||
|
||||
[node name="Index" type="BoneAttachment" parent="RootNode/Skeleton" index="2"]
|
||||
transform = Transform( -0.717079, -0.669965, 0.19221, -0.076153, -0.19881, -0.977075, 0.69282, -0.715277, 0.0915429, -0.0345977, 0.0355404, 0.164767 )
|
||||
bone_name = "finger_index_l_end"
|
||||
|
||||
[node name="Middle" type="BoneAttachment" parent="RootNode/Skeleton" index="3"]
|
||||
transform = Transform( -0.755126, -0.650532, 0.0812012, -0.0513261, -0.064817, -0.996576, 0.653568, -0.756708, 0.0155557, -0.0321126, 0.00654218, 0.171613 )
|
||||
bone_name = "finger_middle_l_end"
|
||||
|
||||
[node name="Ring" type="BoneAttachment" parent="RootNode/Skeleton" index="4"]
|
||||
transform = Transform( -0.749612, -0.661178, -0.0304372, -0.0961052, 0.154228, -0.98335, 0.654864, -0.734206, -0.179154, -0.0346831, -0.0253934, 0.156924 )
|
||||
bone_name = "finger_ring_l_end"
|
||||
|
||||
[node name="Pinky" type="BoneAttachment" parent="RootNode/Skeleton" index="5"]
|
||||
transform = Transform( -0.615435, -0.749373, -0.244295, -0.0354297, 0.335934, -0.941219, 0.787391, -0.570604, -0.233296, -0.0270969, -0.0462902, 0.133467 )
|
||||
bone_name = "finger_pinky_l_end"
|
|
@ -1,42 +0,0 @@
|
|||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://addons/godot-openvr/meshes/vr_glove_right_model_slim.glb" type="PackedScene" id=1]
|
||||
[ext_resource path="res://addons/godot-openvr/meshes/models_hands_vr_glove_vmat.material" type="Material" id=2]
|
||||
[ext_resource path="res://addons/godot-openvr/OpenVRPose.gdns" type="Script" id=3]
|
||||
[ext_resource path="res://addons/godot-openvr/OpenVRSkeleton.gdns" type="Script" id=4]
|
||||
|
||||
[node name="ovr_right_hand" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 3 )
|
||||
action = "/actions/godot/in/right_hand"
|
||||
|
||||
[node name="Skeleton" parent="RootNode" index="0"]
|
||||
bones/5/bound_children = [ NodePath("Thumb") ]
|
||||
bones/10/bound_children = [ NodePath("Index") ]
|
||||
bones/15/bound_children = [ NodePath("Middle") ]
|
||||
bones/20/bound_children = [ NodePath("Ring") ]
|
||||
bones/25/bound_children = [ NodePath("Pinky") ]
|
||||
script = ExtResource( 4 )
|
||||
action = "/actions/godot/in/right_hand"
|
||||
|
||||
[node name="vr_glove_right_slim" parent="RootNode/Skeleton" index="0"]
|
||||
material/0 = ExtResource( 2 )
|
||||
|
||||
[node name="Thumb" type="BoneAttachment" parent="RootNode/Skeleton" index="1"]
|
||||
transform = Transform( -0.347509, 0.0284256, 0.937246, 0.130949, 0.991217, 0.0184906, -0.928488, 0.129158, -0.348179, 0.0498674, 0.0560921, 0.112777 )
|
||||
bone_name = "finger_thumb_r_end"
|
||||
|
||||
[node name="Index" type="BoneAttachment" parent="RootNode/Skeleton" index="2"]
|
||||
transform = Transform( -0.717079, -0.669965, 0.19221, 0.0761528, 0.19881, 0.977075, -0.69282, 0.715277, -0.0915429, 0.0345977, 0.0355405, 0.164767 )
|
||||
bone_name = "finger_index_r_end"
|
||||
|
||||
[node name="Middle" type="BoneAttachment" parent="RootNode/Skeleton" index="3"]
|
||||
transform = Transform( -0.755126, -0.650532, 0.0812013, 0.0513261, 0.064817, 0.996577, -0.653568, 0.756708, -0.0155557, 0.0321126, 0.00654219, 0.171613 )
|
||||
bone_name = "finger_middle_r_end"
|
||||
|
||||
[node name="Ring" type="BoneAttachment" parent="RootNode/Skeleton" index="4"]
|
||||
transform = Transform( -0.749612, -0.661178, -0.0304372, 0.0961052, -0.154228, 0.98335, -0.654864, 0.734206, 0.179154, 0.0346831, -0.0253934, 0.156924 )
|
||||
bone_name = "finger_ring_r_end"
|
||||
|
||||
[node name="Pinky" type="BoneAttachment" parent="RootNode/Skeleton" index="5"]
|
||||
transform = Transform( -0.615435, -0.749373, -0.244295, 0.0354297, -0.335934, 0.941219, -0.787391, 0.570604, 0.233296, 0.0270969, -0.0462902, 0.133467 )
|
||||
bone_name = "finger_pinky_r_end"
|
|
@ -1,6 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/overlay_cursor.gd" type="Script" id=1]
|
||||
|
||||
[node name="OverlayCursor" type="Node"]
|
||||
script = ExtResource( 1 )
|
|
@ -1,6 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/overlay_grab.gd" type="Script" id=1]
|
||||
|
||||
[node name="OverlayGrab" type="Node"]
|
||||
script = ExtResource( 1 )
|
|
@ -1,10 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="BoxShape" id=1]
|
||||
resource_local_to_scene = true
|
||||
extents = Vector3( 0.2, 0.2, 0.01 )
|
||||
|
||||
[node name="OverlayArea" type="Area"]
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="."]
|
||||
shape = SubResource( 1 )
|
|
@ -1,56 +0,0 @@
|
|||
extends Node
|
||||
|
||||
|
||||
var cursor_node = preload("res://addons/openvr_overlay/interaction/Cursor.tscn").instance()
|
||||
onready var viewport: Viewport = get_node("../../OverlayViewport")
|
||||
onready var _i = get_parent()
|
||||
|
||||
func _ready() -> void:
|
||||
viewport.add_child(cursor_node)
|
||||
get_parent().connect("trigger_on", self, "_trigger_on")
|
||||
get_parent().connect("trigger_off", self, "_trigger_off")
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
_update_cursor()
|
||||
|
||||
|
||||
#get canvas position of active controller
|
||||
func get_canvas_pos() -> Vector2:
|
||||
if not _i.active_controller:
|
||||
return Vector2(-1000, 1000) # offscreen
|
||||
|
||||
var controller_local_pos = _i._overlay_area.global_transform.xform_inv(\
|
||||
_i.tracker_nodes[_i.active_controller].translation)
|
||||
var pos = Vector2(controller_local_pos.x, controller_local_pos.y)
|
||||
|
||||
# var overlay_size = OverlayInit.ovr_interface.get_render_targetsize()
|
||||
var overlay_size = Vector2(2048, 2048)
|
||||
# scale to pixels
|
||||
pos *= overlay_size.x
|
||||
pos /= _i.get_parent().width_meters
|
||||
# adjust to center
|
||||
pos.y *= -1
|
||||
pos += overlay_size * 0.5
|
||||
return pos
|
||||
|
||||
|
||||
func _update_cursor():
|
||||
cursor_node.rect_position = get_canvas_pos()
|
||||
|
||||
|
||||
func _send_click_event(state: bool):
|
||||
var click_event = InputEventMouseButton.new()
|
||||
click_event.position = get_canvas_pos()
|
||||
click_event.pressed = state
|
||||
click_event.button_index = 1
|
||||
viewport.input(click_event)
|
||||
|
||||
|
||||
func _trigger_on():
|
||||
_send_click_event(true)
|
||||
|
||||
|
||||
func _trigger_off():
|
||||
_send_click_event(false)
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
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
|
||||
var grab_mode := false
|
||||
|
||||
# controller that currently 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 _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
|
||||
|
||||
onready var tracker_nodes = {
|
||||
"head": $VR/head,
|
||||
"left": $VR/left,
|
||||
"right": $VR/right,
|
||||
"world": $VR
|
||||
}
|
||||
|
||||
|
||||
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")
|
||||
|
||||
get_parent().connect("width_changed", self, "_update_width")
|
||||
get_parent().connect("offset_changed", self, "_update_offset")
|
||||
get_parent().connect("target_changed", self, "_update_target")
|
||||
|
||||
_update_width()
|
||||
_update_offset()
|
||||
_update_target()
|
||||
|
||||
|
||||
func _trigger_on(controller):
|
||||
if touch_state:
|
||||
active_controller = controller
|
||||
trigger_state = true
|
||||
emit_signal("trigger_on")
|
||||
|
||||
|
||||
func _trigger_off():
|
||||
trigger_state = false
|
||||
emit_signal("trigger_off")
|
||||
|
||||
|
||||
func _on_OverlayArea_entered(body: Node) -> void:
|
||||
if body.get_node("../../..") != self or pause_triggers or !get_parent().overlay_visible:
|
||||
return
|
||||
touch_state = true
|
||||
active_controller = body.get_parent().name
|
||||
get_parent().get_node("OverlayViewport/Selected").visible = Settings.s.grab_mode or grab_mode
|
||||
emit_signal("touch_on")
|
||||
|
||||
|
||||
func _on_OverlayArea_exited(body: Node) -> void:
|
||||
if body.get_node("../../..") != self or pause_triggers or !get_parent().overlay_visible:
|
||||
return
|
||||
# TODO revert to other controller if both were touching (edge case)
|
||||
active_controller = ""
|
||||
touch_state = false
|
||||
get_parent().get_node("OverlayViewport/Selected").visible = false
|
||||
emit_signal("touch_off")
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
func _update_offset():
|
||||
_overlay_area.translation = get_parent().translation
|
||||
_overlay_area.rotation = get_parent().rotation
|
||||
|
||||
|
||||
func _update_target():
|
||||
# reparent _overlay_area
|
||||
_overlay_area.get_parent().remove_child(_overlay_area)
|
||||
tracker_nodes[get_parent().current_target].add_child(_overlay_area)
|
||||
|
||||
_left_is_activator = get_parent().current_target != "left"
|
||||
_right_is_activator = get_parent().current_target != "right"
|
||||
# toggle appropriate colliders
|
||||
$VR/left/OverlayActivator/Collision.disabled = !_left_is_activator
|
||||
$VR/right/OverlayActivator/Collision.disabled = !_right_is_activator
|
||||
|
||||
|
||||
func _on_RightHand_button_pressed(button: int) -> void:
|
||||
if button == JOY_VR_TRIGGER and _right_is_activator:
|
||||
_trigger_on("right")
|
||||
|
||||
|
||||
func _on_RightHand_button_release(button: int) -> void:
|
||||
if button == JOY_VR_TRIGGER and active_controller == "right":
|
||||
_trigger_off()
|
||||
|
||||
|
||||
func _on_LeftHand_button_pressed(button: int) -> void:
|
||||
if button == JOY_VR_TRIGGER and _left_is_activator:
|
||||
_trigger_on("left")
|
||||
|
||||
|
||||
func _on_LeftHand_button_release(button: int) -> void:
|
||||
if button == JOY_VR_TRIGGER and active_controller == "left":
|
||||
_trigger_off()
|
|
@ -1,12 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/settings-manager/settings.gd" type="Script" id=1]
|
||||
|
||||
[node name="Settings" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="AutosaveTimer" type="Timer" parent="."]
|
||||
wait_time = 300.0
|
||||
autostart = true
|
||||
|
||||
[connection signal="timeout" from="AutosaveTimer" to="." method="_on_AutosaveTimer_timeout"]
|
|
@ -1 +0,0 @@
|
|||
<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#e0e0e0" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 1.002946 -1043.3636)" width="6.1027" x="-741.53003" y="741.08002"/></svg>
|
Before Width: | Height: | Size: 265 B |
|
@ -1 +0,0 @@
|
|||
<svg height="16" viewBox="0 0 4.2333333 4.2333333" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.5875 0c-.28858 0-.52917.24059-.52917.52917v.61132c-.085589-.051-.18113-.0891-.28525-.0853-.34849.0127-.5952.37346-.48059.70278l.26355.79066c.048664.14623.15979.24805.29249.30644l-.60927.40669c-.13121.0845-.22102.22389-.24133.3633-.020312.13941.017471.26985.087333.37465s.17614.19045.31264.22532c.13634.0348.29946.006.42788-.0827h.0005159l1.0852-.72348.26097.52192c.11682.23391.39274.34829.64079.26561l.79375-.26458-.00775.003c.15105-.0454.27732-.15615.33486-.2863.057538-.13015.055144-.26773.014986-.38809-.03156-.0946-.10972-.1687-.19275-.23617.069099-.0546.1445-.10364.18035-.19325.051761-.12941.045257-.29292-.02377-.43098l-.26459-.52946c-.089407-.17933-.27348-.29308-.47335-.29305h-.1111c.052029-.0817.1111-.16214.1111-.26458v-.79375c0-.28858-.24059-.52917-.52917-.52917z"/><path d="m1.5875.26458c-.14658 0-.26458.118-.26458.26459v.79375c0 .14658.118.26458.26458.26458h.26458v.262a.26461.26461 0 0 0 -.083716.0165l-.5426.18086-.18087-.5426a.26461.26461 0 0 0 -.262-.18448.26461.26461 0 0 0 -.2403.3514l.26458.79375a.26461.26461 0 0 0 .33486.16743l.44545-.14831v.16174c0 .0108.00495.02.0062.0305l-1.2113.80771a.26461.26461 0 1 0 .29352.44028l1.3379-.89194.39532.79014a.26461.26461 0 0 0 .32039.1328l.79375-.26458a.26461.26461 0 1 0 -.16743-.50175l-.57619.19172-.25787-.51625c.072998-.047.12402-.12495.12402-.21859v-.26458h.36587l.1912.38292a.26461.26461 0 1 0 .47336-.23668l-.26458-.52916a.26461.26461 0 0 0 -.23668-.14625h-.79375v-.26458h.26458c.14658 0 .26458-.118.26458-.26458v-.79375c0-.14659-.118-.26459-.26458-.26459zm0 .52917h.26458v.52917h-.26458z" fill="#fff" fill-opacity=".99608"/></svg>
|
Before Width: | Height: | Size: 1.7 KiB |
|
@ -1,32 +0,0 @@
|
|||
extends Control
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
OverlayManager.connect("added_overlay", self, "_add_overlay_to_list")
|
||||
OverlayManager.connect("removed_overlay", self, "_remove_overlay_from_list")
|
||||
for o in Settings.s.overlays:
|
||||
if o != "MainOverlay":
|
||||
_add_overlay_to_list(o)
|
||||
$VSplitContainer/Control/Overlays.visible = false
|
||||
|
||||
|
||||
func _add_overlay_to_list(name):
|
||||
var new = preload("res://ui/ListOverlayItem.tscn").instance()
|
||||
new.overlay_name = name
|
||||
$VSplitContainer/Control/Overlays.add_child(new)
|
||||
|
||||
func _remove_overlay_from_list(name):
|
||||
$VSplitContainer/Control/Overlays.get_node(name).queue_free()
|
||||
|
||||
|
||||
func _on_GrabMode_toggled(state: bool) -> void:
|
||||
Settings.s.grab_mode = state
|
||||
|
||||
|
||||
func _on_ShowOverlays_toggled(state: bool) -> void:
|
||||
$VSplitContainer/Control/Overlays.visible = state
|
||||
|
||||
|
||||
func _on_AddOverlay_pressed() -> void:
|
||||
$VSplitContainer/Control/AddMenu.visible = !$VSplitContainer/Control/AddMenu.visible
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://ui/add_menu.gd" type="Script" id=1]
|
||||
|
||||
[node name="AddMenu" type="PanelContainer"]
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_top = -78.0
|
||||
margin_right = 78.0
|
||||
grow_vertical = 0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
margin_left = 7.0
|
||||
margin_top = 7.0
|
||||
margin_right = 71.0
|
||||
margin_bottom = 71.0
|
||||
custom_constants/margin_right = 32
|
||||
custom_constants/margin_top = 32
|
||||
custom_constants/margin_left = 32
|
||||
custom_constants/margin_bottom = 32
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
margin_left = 32.0
|
||||
margin_top = 32.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
alignment = 2
|
|
@ -1,6 +0,0 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="Button" type="Button"]
|
||||
margin_top = 1950.0
|
||||
margin_right = 1970.0
|
||||
margin_bottom = 1970.0
|
|
@ -1,81 +0,0 @@
|
|||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://overlay_scripts/main_menu.gd" type="Script" id=1]
|
||||
[ext_resource path="res://styles/menu.theme" type="Theme" id=2]
|
||||
[ext_resource path="res://ui/AddMenu.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://icons/add.svg" type="Texture" id=4]
|
||||
[ext_resource path="res://icons/move.svg" type="Texture" id=5]
|
||||
[ext_resource path="res://icons/list.svg" type="Texture" id=6]
|
||||
[ext_resource path="res://ui/ListOverlayItem.tscn" type="PackedScene" id=7]
|
||||
|
||||
[node name="MainOverlay" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
theme = ExtResource( 2 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VSplitContainer" type="VSplitContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Control" type="Control" parent="VSplitContainer"]
|
||||
margin_right = 2048.0
|
||||
margin_bottom = 1845.0
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Overlays" type="VBoxContainer" parent="VSplitContainer/Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_vertical = 3
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ListOverlayItem" parent="VSplitContainer/Control/Overlays" instance=ExtResource( 7 )]
|
||||
margin_top = 1622.0
|
||||
margin_bottom = 1845.0
|
||||
overlay_name = "MainOverlay"
|
||||
|
||||
[node name="AddMenu" parent="VSplitContainer/Control" instance=ExtResource( 3 )]
|
||||
visible = false
|
||||
|
||||
[node name="MainBar" type="HBoxContainer" parent="VSplitContainer"]
|
||||
margin_top = 1857.0
|
||||
margin_right = 2048.0
|
||||
margin_bottom = 2048.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ShowOverlays" type="Button" parent="VSplitContainer/MainBar"]
|
||||
margin_right = 176.0
|
||||
margin_bottom = 191.0
|
||||
focus_mode = 0
|
||||
toggle_mode = true
|
||||
icon = ExtResource( 6 )
|
||||
|
||||
[node name="GrabMode" type="Button" parent="VSplitContainer/MainBar"]
|
||||
margin_left = 180.0
|
||||
margin_right = 356.0
|
||||
margin_bottom = 191.0
|
||||
focus_mode = 0
|
||||
toggle_mode = true
|
||||
icon = ExtResource( 5 )
|
||||
|
||||
[node name="AddOverlay" type="Button" parent="VSplitContainer/MainBar"]
|
||||
margin_left = 360.0
|
||||
margin_right = 536.0
|
||||
margin_bottom = 191.0
|
||||
focus_mode = 0
|
||||
icon = ExtResource( 4 )
|
||||
|
||||
[connection signal="toggled" from="VSplitContainer/MainBar/ShowOverlays" to="." method="_on_ShowOverlays_toggled"]
|
||||
[connection signal="toggled" from="VSplitContainer/MainBar/GrabMode" to="." method="_on_GrabMode_toggled"]
|
||||
[connection signal="pressed" from="VSplitContainer/MainBar/AddOverlay" to="." method="_on_AddOverlay_pressed"]
|
|
@ -1,36 +0,0 @@
|
|||
extends Control
|
||||
|
||||
|
||||
var types: Array
|
||||
|
||||
func _ready() -> void:
|
||||
visible = false
|
||||
types = get_overlay_types()
|
||||
for t in types:
|
||||
var btn = preload("res://ui/AddOverlayButton.tscn").instance()
|
||||
btn.text = t
|
||||
btn.connect("pressed", self, "add_overlay", [t])
|
||||
$MarginContainer/VBoxContainer.add_child(btn)
|
||||
|
||||
|
||||
func add_overlay(type):
|
||||
OverlayManager.add_overlay(type, type + " " + str(randi()%1000))
|
||||
visible = false
|
||||
|
||||
|
||||
func get_overlay_types(path := "res://overlays/"):
|
||||
var found = []
|
||||
var dir = Directory.new()
|
||||
if dir.open(path) == OK:
|
||||
dir.list_dir_begin(true)
|
||||
var file_name = dir.get_next()
|
||||
while file_name != "":
|
||||
if dir.current_is_dir():
|
||||
# TODO make recursive, must include folder as prefix for type
|
||||
pass
|
||||
else:
|
||||
found.append(file_name.split(".")[0])
|
||||
file_name = dir.get_next()
|
||||
else:
|
||||
print("An error occurred when trying to access the path ", path)
|
||||
return found
|
6
src/Main.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="Main" type="Node"]
|
||||
__meta__ = {
|
||||
"_editor_description_": "Everything is loaded using autoloads so this scene is just a dummy"
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://ui/MainOverlay.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://addons/openvr_overlay/OverlayInstance.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://OverlaySettingsSync.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://overlay_manager.gd" type="Script" id=4]
|
||||
|
||||
[node name="OverlayManager" type="Node"]
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="MainOverlay" parent="." instance=ExtResource( 2 )]
|
||||
overlay_scene = ExtResource( 1 )
|
||||
add_cursor = true
|
||||
|
||||
[node name="OverlaySettingsSync" parent="MainOverlay" instance=ExtResource( 3 )]
|
12
src/OverlaySettingsSync.tscn
Normal file
|
@ -0,0 +1,12 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://overlay_settings_sync.gd" type="Script" id=1]
|
||||
|
||||
[node name="OverlaySettingsSync" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="SyncTimer" type="Timer" parent="."]
|
||||
wait_time = 0.2
|
||||
autostart = true
|
||||
|
||||
[connection signal="timeout" from="SyncTimer" to="." method="_on_SyncTimer_timeout"]
|
6
src/addons/gdvk/GDVK.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/gdvk/gdvk.gdns" type="Script" id=1]
|
||||
|
||||
[node name="GDVK" type="Node"]
|
||||
script = ExtResource( 1 )
|
BIN
ovr-utils/addons/godot-openvr/meshes/hands_albedo.png → src/addons/gdvk/bin/win64/libgdvk.dll
Normal file → Executable file
Before Width: | Height: | Size: 21 MiB After Width: | Height: | Size: 19 MiB |
BIN
src/addons/gdvk/bin/x11/libgdvk.so
Executable file
17
src/addons/gdvk/gdvk.gdnlib
Normal file
|
@ -0,0 +1,17 @@
|
|||
[general]
|
||||
|
||||
singleton=false
|
||||
load_once=true
|
||||
symbol_prefix="gdvk_"
|
||||
reloadable=true
|
||||
|
||||
[entry]
|
||||
|
||||
X11.64="res://addons/gdvk/bin/x11/libgdvk.so"
|
||||
Windows.64="res://addons/gdvk/bin/win64/libgdvk.dll"
|
||||
|
||||
[dependencies]
|
||||
|
||||
X11.64=[ ]
|
||||
Windows.64=[ ]
|
||||
OSX.64=[ ]
|
8
src/addons/gdvk/gdvk.gdns
Normal file
|
@ -0,0 +1,8 @@
|
|||
[gd_resource type="NativeScript" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/gdvk/gdvk.gdnlib" type="GDNativeLibrary" id=1]
|
||||
|
||||
[resource]
|
||||
resource_name = "gdvk"
|
||||
class_name = "GDVK"
|
||||
library = ExtResource( 1 )
|
10
src/addons/gdvk/gdvk_plugin.gd
Normal file
|
@ -0,0 +1,10 @@
|
|||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
add_autoload_singleton("GDVK", "res://addons/gdvk/GDVK.tscn")
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
remove_autoload_singleton("GDVK")
|
9
src/addons/gdvk/plugin.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
[plugin]
|
||||
|
||||
name="GDVK"
|
||||
description="Godot virtual keyboard plugin
|
||||
|
||||
see https://github.com/CrispyPin/gdvk"
|
||||
author="CrispyPin"
|
||||
version="0.1.0"
|
||||
script="gdvk_plugin.gd"
|
BIN
src/addons/godot-openvr/bin/win64/libgodot_openvr.dll
Normal file
BIN
src/addons/godot-openvr/bin/x11/libgodot_openvr.so
Executable file
BIN
src/addons/godot-openvr/bin/x11/libopenvr_api.so
Normal file
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -1,6 +1,7 @@
|
|||
[gd_scene load_steps=5 format=2]
|
||||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/overlay_instance.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/openvr_overlay/OverlayInteraction.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://addons/godot-openvr/OpenVROverlay.gdns" type="Script" id=3]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
|
@ -21,7 +22,6 @@ script = ExtResource( 1 )
|
|||
[node name="OverlayViewport" type="Viewport" parent="."]
|
||||
size = Vector2( 2048, 2048 )
|
||||
transparent_bg = true
|
||||
handle_input_locally = false
|
||||
hdr = false
|
||||
disable_3d = true
|
||||
usage = 0
|
||||
|
@ -57,17 +57,12 @@ shadow_atlas_quad_3 = 0
|
|||
script = ExtResource( 3 )
|
||||
overlay_width_in_meters = 0.4
|
||||
|
||||
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VROverlayViewport"]
|
||||
[node name="TextureRect" type="TextureRect" parent="VROverlayViewport"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="VROverlayViewport/AspectRatioContainer"]
|
||||
margin_right = 100.0
|
||||
margin_bottom = 100.0
|
||||
texture = SubResource( 2 )
|
||||
expand = true
|
||||
stretch_mode = 5
|
||||
flip_v = true
|
||||
|
||||
[node name="OverlayInteraction" parent="." instance=ExtResource( 2 )]
|
|
@ -1,7 +1,7 @@
|
|||
[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/OverlayActivator.tscn" type="PackedScene" id=6]
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/OverlayArea.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="OverlayInteraction" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
@ -10,16 +10,14 @@ script = ExtResource( 1 )
|
|||
|
||||
[node name="left" type="ARVRController" parent="VR"]
|
||||
|
||||
[node name="OverlayActivator" parent="VR/left" instance=ExtResource( 6 )]
|
||||
|
||||
[node name="right" type="ARVRController" parent="VR"]
|
||||
controller_id = 2
|
||||
|
||||
[node name="OverlayActivator" parent="VR/right" instance=ExtResource( 6 )]
|
||||
|
||||
[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"]
|
25
src/addons/openvr_overlay/OverlayInteractionRoot.tscn
Normal file
|
@ -0,0 +1,25 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/HandCollider.tscn" type="PackedScene" id=1]
|
||||
|
||||
[node name="OverlayInteractionRoot" type="Node"]
|
||||
|
||||
[node name="VR" type="ARVROrigin" parent="."]
|
||||
|
||||
[node name="left" type="ARVRController" parent="VR"]
|
||||
|
||||
[node name="HandCollider" parent="VR/left" groups=[
|
||||
"left",
|
||||
] instance=ExtResource( 1 )]
|
||||
collision_layer = 20
|
||||
|
||||
[node name="right" type="ARVRController" parent="VR"]
|
||||
controller_id = 2
|
||||
|
||||
[node name="HandCollider" parent="VR/right" groups=[
|
||||
"right",
|
||||
] instance=ExtResource( 1 )]
|
||||
collision_layer = 10
|
||||
|
||||
[node name="head" type="ARVRCamera" parent="VR"]
|
||||
visible = false
|
|
@ -4,7 +4,10 @@
|
|||
margin = 0.001
|
||||
radius = 0.01
|
||||
|
||||
[node name="OverlayActivator" type="StaticBody"]
|
||||
[node name="HandCollider" type="Area"]
|
||||
monitoring = false
|
||||
collision_layer = 30
|
||||
collision_mask = 0
|
||||
|
||||
[node name="Collision" type="CollisionShape" parent="."]
|
||||
shape = SubResource( 1 )
|
27
src/addons/openvr_overlay/interaction/OverlayArea.tscn
Normal file
|
@ -0,0 +1,27 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[sub_resource type="BoxShape" id=1]
|
||||
resource_local_to_scene = true
|
||||
extents = Vector3( 0.2, 0.2, 0.1 )
|
||||
|
||||
[sub_resource type="BoxShape" id=2]
|
||||
resource_local_to_scene = true
|
||||
extents = Vector3( 0.2, 0.2, 0.01 )
|
||||
|
||||
[node name="OverlayArea" type="Spatial"]
|
||||
|
||||
[node name="AreaNear" type="Area" parent="."]
|
||||
monitorable = false
|
||||
collision_layer = 0
|
||||
collision_mask = 6
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="AreaNear"]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="AreaTouch" type="Area" parent="."]
|
||||
monitorable = false
|
||||
collision_layer = 0
|
||||
collision_mask = 24
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="AreaTouch"]
|
||||
shape = SubResource( 2 )
|
Before Width: | Height: | Size: 90 B After Width: | Height: | Size: 90 B |
6
src/addons/openvr_overlay/interaction/mod/Clickable.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/mod/clickable.gd" type="Script" id=1]
|
||||
|
||||
[node name="Clickable" type="Node"]
|
||||
script = ExtResource( 1 )
|
6
src/addons/openvr_overlay/interaction/mod/Grabbable.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/mod/grabbable.gd" type="Script" id=1]
|
||||
|
||||
[node name="Grabbable" type="Node"]
|
||||
script = ExtResource( 1 )
|
7
src/addons/openvr_overlay/interaction/mod/Touchable.tscn
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/openvr_overlay/interaction/mod/clickable.gd" type="Script" id=1]
|
||||
|
||||
[node name="Touchable" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
is_touch = true
|
109
src/addons/openvr_overlay/interaction/mod/clickable.gd
Normal file
|
@ -0,0 +1,109 @@
|
|||
extends Node
|
||||
|
||||
export var is_touch := false
|
||||
|
||||
onready var viewport: Viewport = get_node("../../OverlayViewport")
|
||||
onready var _i = get_parent()
|
||||
|
||||
var cursor_pos := {
|
||||
"right": Vector2(),
|
||||
"left": Vector2(),
|
||||
}
|
||||
var prev_pos := {
|
||||
"right": Vector2(),
|
||||
"left": Vector2(),
|
||||
}
|
||||
var click := {
|
||||
"right": false,
|
||||
"left": false,
|
||||
}
|
||||
var active_side := ""
|
||||
|
||||
var cursor_nodes := {
|
||||
"right": preload("res://addons/openvr_overlay/interaction/Cursor.tscn").instance(),
|
||||
"left": preload("res://addons/openvr_overlay/interaction/Cursor.tscn").instance(),
|
||||
}
|
||||
|
||||
func _ready() -> void:
|
||||
viewport.add_child(cursor_nodes.right)
|
||||
viewport.add_child(cursor_nodes.left)
|
||||
if is_touch:
|
||||
get_parent().connect("touch_on", self, "_trigger_on")
|
||||
get_parent().connect("touch_off", self, "_trigger_off")
|
||||
else:
|
||||
get_parent().connect("trigger_on", self, "_trigger_on")
|
||||
get_parent().connect("trigger_off", self, "_trigger_off")
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
cursor_pos.right = get_canvas_pos("right")
|
||||
cursor_pos.left = get_canvas_pos("left")
|
||||
_update_cursors()
|
||||
# _send_move_event()
|
||||
prev_pos = cursor_pos.duplicate(true)
|
||||
|
||||
|
||||
|
||||
# get canvas position of controller
|
||||
func get_canvas_pos(controller) -> Vector2:
|
||||
var controller_local_pos = _i._overlay_area.global_transform.xform_inv(\
|
||||
_i.tracker_nodes[controller].translation)
|
||||
var pos = Vector2(controller_local_pos.x, controller_local_pos.y)
|
||||
|
||||
var overlay_size = Vector2(2048, 2048)
|
||||
# scale to pixels
|
||||
pos *= overlay_size.x
|
||||
pos /= _i.get_parent().width_meters
|
||||
# adjust to center
|
||||
pos.y *= -1
|
||||
pos += overlay_size * 0.5
|
||||
return pos
|
||||
|
||||
|
||||
func _update_cursors():
|
||||
cursor_nodes.right.visible = _i.state.right.near
|
||||
cursor_nodes.left.visible = _i.state.left.near
|
||||
cursor_nodes.right.rect_position = cursor_pos.right
|
||||
cursor_nodes.left.rect_position = cursor_pos.left
|
||||
|
||||
|
||||
func _send_move_event():
|
||||
if not active_side:
|
||||
return# only send move events while a cursor is held down
|
||||
|
||||
var event = InputEventMouseMotion.new()
|
||||
event.position = prev_pos[active_side]
|
||||
event.relative = cursor_pos[active_side] - prev_pos[active_side]
|
||||
event.speed = event.relative
|
||||
viewport.input(event)
|
||||
|
||||
|
||||
func _send_click_event(state: bool, controller: String):
|
||||
if click[controller] == state:
|
||||
return # already in that state
|
||||
click[controller] = state
|
||||
_update_active_side()
|
||||
var click_event = InputEventMouseButton.new()
|
||||
click_event.position = cursor_pos[controller]
|
||||
click_event.pressed = state
|
||||
click_event.button_index = 1
|
||||
viewport.input(click_event)
|
||||
# print("SENT EVENT ", click_event.position, " -- ", click_event.pressed)
|
||||
|
||||
|
||||
func _trigger_on(controller):
|
||||
if click.right or click.left:
|
||||
return
|
||||
_send_click_event(true, controller)
|
||||
|
||||
|
||||
func _trigger_off(controller):
|
||||
_send_click_event(false, controller)
|
||||
|
||||
func _update_active_side() -> void:
|
||||
if click.right:
|
||||
active_side = "right"
|
||||
elif click.left:
|
||||
active_side = "left"
|
||||
else:
|
||||
active_side = ""
|
|
@ -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
|
||||
|
@ -73,7 +73,6 @@ func finish_move():
|
|||
|
||||
# revert target
|
||||
_overlay.update_current_target()
|
||||
_overlay.save_settings()
|
||||
|
||||
_interaction._update_target()
|
||||
_interaction.pause_triggers = false
|
188
src/addons/openvr_overlay/interaction/overlay_interaction.gd
Normal file
|
@ -0,0 +1,188 @@
|
|||
extends Node
|
||||
|
||||
|
||||
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
|
||||
|
||||
# reference to the area node thats used for touch
|
||||
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 (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,
|
||||
"left": $VR/left,
|
||||
"right": $VR/right,
|
||||
"world": $VR
|
||||
}
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_overlay_area = $OverlayArea
|
||||
_overlay_area.get_node("AreaNear"). connect("area_entered", self, "_on_Near_entered")
|
||||
_overlay_area.get_node("AreaNear"). connect("area_exited", self, "_on_Near_exited")
|
||||
_overlay_area.get_node("AreaTouch").connect("area_entered", self, "_on_Touch_entered")
|
||||
_overlay_area.get_node("AreaTouch").connect("area_exited", self, "_on_Touch_exited")
|
||||
|
||||
get_parent().connect("width_changed", self, "_update_width")
|
||||
get_parent().connect("offset_changed", self, "_update_offset")
|
||||
get_parent().connect("target_changed", self, "_update_target")
|
||||
|
||||
OverlayManager.connect("grab_mode_changed", self, "update_selection")
|
||||
|
||||
call_deferred("_update_width")
|
||||
call_deferred("_update_offset")
|
||||
call_deferred("_update_target")
|
||||
|
||||
|
||||
func _trigger_on(controller):
|
||||
if state[controller].near:
|
||||
state[controller].trigger = true
|
||||
# print("TRIGGER ON ", controller)
|
||||
emit_signal("trigger_on", controller)
|
||||
|
||||
|
||||
func _trigger_off(controller):
|
||||
state[controller].trigger = false
|
||||
# print("TRIGGER OFF ", controller)
|
||||
emit_signal("trigger_off", controller)
|
||||
|
||||
|
||||
func _on_Near_entered(body: Node) -> void:
|
||||
if pause_triggers or !get_parent().overlay_visible:
|
||||
return
|
||||
var hand = body.get_groups()[0]
|
||||
state[hand].near = true
|
||||
update_selection()
|
||||
# print("NEAR ON ", hand)
|
||||
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
|
||||
|
||||
# print("NEAR OFF ", hand)
|
||||
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()
|
||||
# print("TOUCH ON ", hand)
|
||||
emit_signal("touch_on", hand)
|
||||
|
||||
|
||||
func _on_Touch_exited(body: Node) -> void:
|
||||
if pause_triggers or !get_parent().overlay_visible:
|
||||
return
|
||||
var hand = body.get_groups()[0]
|
||||
state[hand].touch = false
|
||||
update_selection()
|
||||
# print("TOUCH OFF ", hand)
|
||||
emit_signal("touch_off", hand)
|
||||
|
||||
|
||||
func update_selection():
|
||||
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
|
||||
|
||||
|
||||
func set_grab_mode(state: bool) -> void:
|
||||
grab_mode = state
|
||||
update_selection()
|
||||
|
||||
|
||||
func _update_width():
|
||||
var ratio = OverlayInit.ovr_interface.get_render_targetsize()
|
||||
var extents = get_parent().width_meters * 0.5
|
||||
_overlay_area.get_node("AreaNear/CollisionShape").shape.set_extents(
|
||||
Vector3(extents, extents * ratio.y/ratio.x, 0.1))
|
||||
_overlay_area.get_node("AreaTouch/CollisionShape").shape.set_extents(
|
||||
Vector3(extents, extents * ratio.y/ratio.x, 0.01))
|
||||
|
||||
|
||||
func _update_offset():
|
||||
_overlay_area.translation = get_parent().translation
|
||||
_overlay_area.rotation = get_parent().rotation
|
||||
|
||||
|
||||
func _update_target():
|
||||
var t = get_parent().current_target
|
||||
# reparent _overlay_area
|
||||
_overlay_area.get_parent().remove_child(_overlay_area)
|
||||
tracker_nodes[t].add_child(_overlay_area)
|
||||
|
||||
state.right.active = t != "right"
|
||||
state.left.active = t != "left"
|
||||
# make area only detect colliders of a different 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
|
||||
_overlay_area.get_node("AreaNear").collision_mask = int(t!="right")*8 # detect right hand
|
||||
_overlay_area.get_node("AreaNear").collision_mask += int(t!="left")*16 # detect left hand
|
||||
|
||||
|
||||
# called by overlay_instance after properties are loaded and before overlay scene enters the tree
|
||||
func spawn_modules():
|
||||
if get_parent().get_property("grabbable"):
|
||||
var module = preload("res://addons/openvr_overlay/interaction/mod/Grabbable.tscn")
|
||||
add_child(module.instance())
|
||||
|
||||
if get_parent().get_property("clickable"):
|
||||
var module = preload("res://addons/openvr_overlay/interaction/mod/Clickable.tscn")
|
||||
add_child(module.instance())
|
||||
|
||||
if get_parent().get_property("touchable"):
|
||||
var module = preload("res://addons/openvr_overlay/interaction/mod/Touchable.tscn")
|
||||
add_child(module.instance())
|
||||
|
||||
|
||||
func _on_RightHand_button_pressed(button: int) -> void:
|
||||
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 state.right.trigger:
|
||||
_trigger_off("right")
|
||||
|
||||
|
||||
func _on_LeftHand_button_pressed(button: int) -> void:
|
||||
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 state.left.trigger:
|
||||
_trigger_off("left")
|
|
@ -4,7 +4,9 @@ extends EditorPlugin
|
|||
|
||||
func _enter_tree() -> void:
|
||||
add_autoload_singleton("OverlayInit", "res://addons/openvr_overlay/overlay_init.gd")
|
||||
add_autoload_singleton("OverlayInteractionRoot", "res://addons/openvr_overlay/OverlayInteractionRoot.tscn")
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
remove_autoload_singleton("OverlayInit")
|
||||
remove_autoload_singleton("OverlayInteractionRoot")
|
|
@ -1,5 +1,14 @@
|
|||
extends Node
|
||||
|
||||
|
||||
const OVERLAY_PROPERTIES_DEFAULT = {
|
||||
"allow_delete": true,
|
||||
"allow_hide": true,
|
||||
"clickable": false,
|
||||
"touchable": false,
|
||||
"grabbable": true,
|
||||
}
|
||||
|
||||
var ovr_interface: ARVRInterface
|
||||
var ovr_config := preload("res://addons/godot-openvr/OpenVRConfig.gdns").new()
|
||||
|
||||
|
@ -11,9 +20,7 @@ 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_application_type(2) # Set to OVERLAY MODE
|
||||
ovr_config.set_tracking_universe(1) # Set to SEATED MODE = 0, STANDING MODE = 1, RAW MODE = 2
|
||||
|
||||
# Find the OpenVR interface and initialise it
|
||||
|
@ -23,9 +30,14 @@ func _init() -> void:
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
OS.window_size = Vector2(16, 16)
|
||||
OS.window_position = Vector2(32, 32)
|
||||
OS.window_minimized = true
|
||||
|
||||
ARVRServer.connect("tracker_added", self, "_tracker_added")
|
||||
ARVRServer.connect("tracker_removed", self, "_tracker_removed")
|
||||
update_hand_ids()
|
||||
#Input.set_use_accumulated_input(true)
|
||||
|
||||
|
||||
func _tracker_added(tracker_name: String, type: int, id: int):
|
|
@ -1,22 +1,23 @@
|
|||
extends Spatial
|
||||
|
||||
#signal path_changed
|
||||
signal overlay_visible_changed
|
||||
signal width_changed
|
||||
signal offset_changed
|
||||
signal alpha_changed
|
||||
signal target_changed
|
||||
signal overlay_visibility_changed
|
||||
signal fallback_changed
|
||||
signal offset_changed
|
||||
|
||||
const TARGETS = ["head", "left", "right", "world"]
|
||||
export (String, "head", "left", "right", "world") var target = "left" setget set_target
|
||||
|
||||
export var overlay_scene: PackedScene = \
|
||||
preload("res://addons/openvr_overlay/MissingOverlay.tscn") setget set_overlay_scene
|
||||
export var width_meters := 0.4 setget set_width_in_meters
|
||||
export var add_grabbing := true # add grabbing module
|
||||
export var add_cursor := false # add cursor module
|
||||
export var alpha := 1.0 setget set_alpha
|
||||
|
||||
|
||||
var _tracker_id := 0
|
||||
var _offsets:Dictionary = {
|
||||
"head": {"pos": Vector3(0, 0, -0.5), "rot": Quat()},
|
||||
"head": {"pos": Vector3(0, 0, -0.35), "rot": Quat()},
|
||||
"left": {"pos": Vector3(), "rot": Quat()},
|
||||
"right": {"pos": Vector3(), "rot": Quat()},
|
||||
"world": {"pos": Vector3(0,1,0), "rot": Quat()},
|
||||
|
@ -27,12 +28,17 @@ var current_target: String = "world" setget _set_current_target
|
|||
var fallback = ["left", "right", "head"] # TODO setget that updates tracking (not important)
|
||||
var interaction_handler: Node
|
||||
var overlay_visible := true setget set_overlay_visible
|
||||
var type := "main"
|
||||
var path : String = "res://special_overlays/MainOverlay.tscn"# setget set_path
|
||||
var path_invalid := false
|
||||
var OVERLAY_PROPERTIES: Dictionary # defined in overlay root script (optional)
|
||||
|
||||
onready var container = $OverlayViewport/Container
|
||||
var overlay_scene: Node
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
container = $OverlayViewport/Container
|
||||
load_overlay()
|
||||
current_target = target
|
||||
|
||||
ARVRServer.connect("tracker_added", self, "_tracker_changed")
|
||||
|
@ -41,64 +47,27 @@ func _ready() -> void:
|
|||
$VROverlayViewport.size = OverlayInit.ovr_interface.get_render_targetsize()
|
||||
set_notify_transform(true)
|
||||
|
||||
load_settings()
|
||||
if add_cursor or add_grabbing:
|
||||
interaction_handler = load("res://addons/openvr_overlay/OverlayInteraction.tscn").instance()
|
||||
add_child(interaction_handler)
|
||||
if add_cursor:
|
||||
add_cursor()
|
||||
if add_grabbing:
|
||||
add_grab()
|
||||
|
||||
if overlay_scene:
|
||||
container.add_child(overlay_scene.instance())
|
||||
|
||||
update_tracker_id()
|
||||
call_deferred("update_offset")
|
||||
|
||||
func load_overlay() -> void:
|
||||
path_invalid = false
|
||||
|
||||
func add_cursor():
|
||||
interaction_handler.add_child(load("res://addons/openvr_overlay/OverlayCursor.tscn").instance())
|
||||
|
||||
|
||||
func add_grab():
|
||||
interaction_handler.add_child(load("res://addons/openvr_overlay/OverlayGrab.tscn").instance())
|
||||
|
||||
|
||||
func load_settings():
|
||||
if Settings.s.overlays.has(name):
|
||||
var loaded = Settings.s.overlays[name]
|
||||
if loaded.has("fallback"):
|
||||
fallback = loaded.fallback
|
||||
set_target(loaded.target)
|
||||
|
||||
set_width_in_meters(loaded.width)
|
||||
|
||||
for t_key in loaded.offsets:
|
||||
var t_offset = loaded.offsets[t_key]
|
||||
_offsets[t_key].pos = t_offset.pos
|
||||
_offsets[t_key].rot = t_offset.rot
|
||||
update_offset()
|
||||
if loaded.has("visible"):
|
||||
set_overlay_visible(loaded.visible)
|
||||
var packed_overlay = load(path)
|
||||
if not packed_overlay:
|
||||
path_invalid = true
|
||||
overlay_scene = load("res://special_overlays/UnknownType.tscn").instance()
|
||||
else:
|
||||
save_settings()
|
||||
overlay_scene = packed_overlay.instance()
|
||||
|
||||
if overlay_scene.get("OVERLAY_PROPERTIES") != null:
|
||||
OVERLAY_PROPERTIES = overlay_scene.OVERLAY_PROPERTIES
|
||||
|
||||
func save_settings():
|
||||
if not Settings.s.overlays.has(name):
|
||||
Settings.s.overlays[name] = {}
|
||||
Settings.s.overlays[name].target = target
|
||||
Settings.s.overlays[name].width = width_meters
|
||||
Settings.s.overlays[name].fallback = fallback
|
||||
Settings.s.overlays[name].type = type
|
||||
|
||||
if not Settings.s.overlays[name].has("offsets"):
|
||||
Settings.s.overlays[name]["offsets"] = {}
|
||||
for t_key in TARGETS:
|
||||
Settings.s.overlays[name].offsets[t_key] = _offsets[t_key]
|
||||
|
||||
Settings.save_settings()
|
||||
$OverlayInteraction.spawn_modules()
|
||||
|
||||
if container.get_child_count() > 0:
|
||||
container.get_child(0).queue_free()
|
||||
container.add_child(overlay_scene)
|
||||
|
||||
func update_tracker_id():
|
||||
_tracker_id = -1
|
||||
|
@ -112,7 +81,7 @@ func update_tracker_id():
|
|||
|
||||
if _tracker_id == -1:
|
||||
# could not find controller, fallback
|
||||
print("Missing controller ", current_target, " ", target, " ", fallback, " - ", name)
|
||||
# print("Missing controller ", current_target, " ", target, " ", fallback, " - ", name)
|
||||
_tracker_id = 63 # highest tracker id (unused, at origin)
|
||||
|
||||
|
||||
|
@ -143,9 +112,7 @@ func update_current_target():
|
|||
func set_overlay_visible(state: bool):
|
||||
overlay_visible = state
|
||||
$VROverlayViewport.overlay_visible = state
|
||||
Settings.s.overlays[name].visible = state
|
||||
emit_signal("overlay_visibility_changed", state)
|
||||
save_settings()
|
||||
emit_signal("overlay_visible_changed", state)
|
||||
|
||||
|
||||
func _tracker_changed(tracker_name: String, type: int, id: int):
|
||||
|
@ -182,13 +149,10 @@ func set_width_in_meters(width: float) -> void:
|
|||
emit_signal("width_changed")
|
||||
|
||||
|
||||
func set_overlay_scene(scene: PackedScene) -> void:
|
||||
overlay_scene = scene
|
||||
if not container:
|
||||
return
|
||||
if container.get_child_count() > 0:
|
||||
container.get_child(0).queue_free()
|
||||
container.add_child(overlay_scene.instance())
|
||||
func set_alpha(val: float):
|
||||
alpha = val
|
||||
$VROverlayViewport/TextureRect.modulate.a = val
|
||||
emit_signal("alpha_changed")
|
||||
|
||||
|
||||
func reset_offset() -> void:
|
||||
|
@ -197,10 +161,15 @@ func reset_offset() -> void:
|
|||
if current_target == "head":
|
||||
_offsets[current_target].pos.z = -0.5
|
||||
update_offset()
|
||||
save_settings()
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_TRANSFORM_CHANGED:
|
||||
update_offset()
|
||||
emit_signal("offset_changed")
|
||||
|
||||
|
||||
func get_property(p_name: String):
|
||||
if OVERLAY_PROPERTIES.has(p_name):
|
||||
return OVERLAY_PROPERTIES[p_name]
|
||||
|
||||
return OverlayInit.OVERLAY_PROPERTIES_DEFAULT[p_name]
|