update interaction system

This commit is contained in:
Nitwel 2023-11-05 13:59:33 +01:00
parent 9ff35349a1
commit c240efa56f
5 changed files with 110 additions and 32 deletions

View File

@ -65,30 +65,29 @@ func watch_state(entity: String, callback: Callable[entity: Entity]) -> Callable
### Interaction Events ### Interaction Events
Each time a button is pressed on the primary controller, a raycast is done to be able to interact with devices or the UI. Each time a button is pressed on the primary controller, a ray-cast is done to be able to interact with devices or the UI.
**InteractionEvent** ```python
```js InteractionEvent {
{ "controller": XRController3D, # The controller that triggered the event
position: Vector3, "ray": RayCast3D, # The ray-cast that triggered the event
rotation: Vector3
} }
``` ```
| Function called | Args | Description | | Function called | Args | Description |
| -- | -- | -- | | -- | -- | -- |
| `_click` | `[event: InteractionEvent]` | The back trigger button has been pressed and released | | `_on_click` | `[event: InteractionEvent]` | The back trigger button has been pressed and released |
| `_dbl_click` | `[event: InteractionEvent]` | The back trigger button has been pressed and released twice in a row | | `_on_press_down` | `[event: InteractionEvent]` | The back trigger button has been pressed down |
| `_long_click` | `[event: InteractionEvent]` | The back trigger button has been pressed, then hold still for a short period, then released | | `_on_press_move` | `[event: InteractionEvent]` | The back trigger button has been moved while pressed down |
| `_press_down` | `[event: InteractionEvent]` | The back trigger button has been pressed down | | `_on_press_up` | `[event: InteractionEvent]` | The back trigger button has been released |
| `_press_move` | `[event: InteractionEvent]` | The back trigger button has been moved while pressed down | | `_on_grab_down` | `[event: InteractionEvent]` | The side grab button been pressed down |
| `_press_up` | `[event: InteractionEvent]` | The back trigger button has been released | | `_on_grab_move` | `[event: InteractionEvent]` | The side grab button been pressed down |
| `_grab_down` | `[event: InteractionEvent]` | The side grap button been pressed down | | `_on_grab_up` | `[event: InteractionEvent]` | The side grab button been released |
| `_grab_move` | `[event: InteractionEvent]` | The side grap button been pressed down | | `_on_ray_enter` | `[event: InteractionEvent]` | The ray-cast enters the the collision body |
| `_grab_up` | `[event: InteractionEvent]` | The side grap button been released | | `_on_ray_leave` | `[event: InteractionEvent]` | The ray-cast leaves the the collision body |
### Testing without a VR Headset ### Testing without a VR Headset
In order to test without a headset, press the run project (F5) button in Godot and ignore the prompt that OpenXR failed to start. In order to test without a headset, press the run project (F5) button in Godot and ignore the prompt that OpenXR failed to start.
To simulate the headset and controller movement, we're using the [XR Input Simulator](https://godotengine.org/asset-library/asset/1775) asset. To simulate the headset and controller movement, we're using the [XR Input Simulator](https://godotengine.org/asset-library/asset/1775) asset.
Click at the link to get a list of the supported controlls. Click at the link to get a list of the supported controls.

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=12 format=3 uid="uid://eecv28y6jxk4"] [gd_scene load_steps=13 format=3 uid="uid://eecv28y6jxk4"]
[ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"] [ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"]
[ext_resource type="Script" path="res://src/raycast.gd" id="1_tsqxc"] [ext_resource type="Script" path="res://src/raycast.gd" id="1_tsqxc"]
@ -7,6 +7,7 @@
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://scenes/menu.tscn" id="3_1tbp3"] [ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://scenes/menu.tscn" id="3_1tbp3"]
[ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"] [ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"]
[ext_resource type="Material" uid="uid://bf5ina366dwm6" path="res://assets/materials/sky.material" id="5_wgwf8"] [ext_resource type="Material" uid="uid://bf5ina366dwm6" path="res://assets/materials/sky.material" id="5_wgwf8"]
[ext_resource type="PackedScene" uid="uid://cscl5k7lhopj5" path="res://scenes/entities/switch.tscn" id="8_uxmrb"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true ao_enabled = true
@ -76,3 +77,7 @@ shadow_enabled = true
[node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")] [node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")]
xr_origin = NodePath("../XROrigin3D") xr_origin = NodePath("../XROrigin3D")
[node name="Switch" parent="." instance=ExtResource("8_uxmrb")]
transform = Transform3D(0.999999, -1.39635e-11, 0, 9.48031e-12, 1, 0, 0, 0, 1, 0.564168, 0.725642, -1.56163)
entity_id = "switch.plug_printer_2_fale"

View File

@ -6,6 +6,9 @@ extends StaticBody3D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id) var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id)
if stateInfo == null:
return
if stateInfo["state"] == "on": if stateInfo["state"] == "on":
sprite.set_frame(0) sprite.set_frame(0)
else: else:

View File

@ -10,6 +10,7 @@ var token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0M
var LOG_MESSAGES := false var LOG_MESSAGES := false
var authenticated := false var authenticated := false
var loading := true
var id := 1 var id := 1
var entities: Dictionary = {} var entities: Dictionary = {}
@ -100,6 +101,7 @@ func start_subscriptions():
"attributes": packet.event.a[entity]["a"] "attributes": packet.event.a[entity]["a"]
} }
entitiy_callbacks.call_key(entity, [entities[entity]]) entitiy_callbacks.call_key(entity, [entities[entity]])
loading = false
on_connect.emit() on_connect.emit()
if packet.event.has("c"): if packet.event.has("c"):
@ -171,13 +173,13 @@ func encode_packet(packet: Dictionary):
return JSON.stringify(packet) return JSON.stringify(packet)
func load_devices(): func load_devices():
if !authenticated: if loading:
await on_connect await on_connect
return entities return entities
func get_state(entity: String): func get_state(entity: String):
if !authenticated: if loading:
await on_connect await on_connect
if entities.has(entity): if entities.has(entity):
@ -186,14 +188,14 @@ func get_state(entity: String):
func watch_state(entity: String, callback: Callable): func watch_state(entity: String, callback: Callable):
if !authenticated: if loading:
await on_connect await on_connect
entitiy_callbacks.add(entity, callback) entitiy_callbacks.add(entity, callback)
func set_state(entity: String, state: String, attributes: Dictionary = {}): func set_state(entity: String, state: String, attributes: Dictionary = {}):
assert(authenticated, "Not authenticated") assert(!loading, "Still loading")
var domain = entity.split(".")[0] var domain = entity.split(".")[0]
var service: String var service: String

View File

@ -5,23 +5,92 @@ extends Node3D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
_controller.button_pressed.connect(self._on_button_pressed) _controller.button_pressed.connect(_on_button_pressed)
_controller.button_released.connect(_on_button_released)
# Called every frame. 'delta' is the elapsed time since the previous frame. var _last_collided: Object = null
func _process(delta): var _is_pressed := false
pass var _is_grabbed := false
var _moved := false
var _click_point := Vector3.ZERO
func _physics_process(delta):
_handle_enter_leave()
_handle_move()
func _get_event_data():
return {
"controller": _controller,
"ray": ray,
}
func _handle_move():
var distance = ray.get_collision_point().distance_to(_click_point)
if distance > 0.01:
if _is_pressed:
_call_fn("_on_press_move")
_moved = true
if _is_grabbed:
_call_fn("_on_grab_move")
_moved = true
func _handle_enter_leave():
var collider = ray.get_collider()
if collider == _last_collided:
return
if _last_collided != null && _last_collided.has_method("_on_ray_enter"):
_last_collided._on_ray_enter(_get_event_data())
if collider != null && collider.has_method("_on_ray_leave"):
collider._on_ray_leave(_get_event_data())
_last_collided = collider
func _on_button_pressed(button): func _on_button_pressed(button):
print(button)
if button != "trigger_click":
return
var collider = ray.get_collider() var collider = ray.get_collider()
if collider == null: if collider == null:
return return
print(collider) match button:
"trigger_click":
_is_pressed = true
_click_point = ray.get_collision_point()
_call_fn("_on_press_down")
"grip_click":
_is_grabbed = true
_click_point = ray.get_collision_point()
_call_fn("_on_grab_down")
if collider.has_method("_on_toggle"): func _on_button_released(button):
collider._on_toggle() var collider = ray.get_collider()
if collider == null:
return
match button:
"trigger_click":
if _is_pressed:
if _moved == false:
_call_fn("_on_click")
_call_fn("_on_press_up")
_is_pressed = false
_moved = false
"grip_click":
if _is_grabbed:
_call_fn("_on_grab_up")
_is_grabbed = false
_moved = false
func _call_fn(fn_name: String):
print("call_fn", fn_name)
var collider = ray.get_collider()
if collider == null:
return
if collider.has_method(fn_name):
collider.call(fn_name, _get_event_data())