rework event system and add keyboard

This commit is contained in:
Nitwel 2023-11-22 01:44:07 +01:00
parent 16201224ce
commit a2bc1a5d37
21 changed files with 359 additions and 228 deletions

View File

@ -101,6 +101,10 @@ InteractionEvent {
"ray": RayCast3D, # The ray-cast that triggered the event "ray": RayCast3D, # The ray-cast that triggered the event
"target": Node3D, # The node that was hit by the ray-cast "target": Node3D, # The node that was hit by the ray-cast
} }
KeyEvent {
"key": String, # The key that was pressed
}
``` ```
| Function called | Args | Description | | Function called | Args | Description |
@ -114,6 +118,12 @@ InteractionEvent {
| `_on_grab_up` | `[event: InteractionEvent]` | The side grab button been released | | `_on_grab_up` | `[event: InteractionEvent]` | The side grab button been released |
| `_on_ray_enter` | `[event: InteractionEvent]` | The ray-cast enters the the collision body | | `_on_ray_enter` | `[event: InteractionEvent]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: InteractionEvent]` | The ray-cast leaves the the collision body | | `_on_ray_leave` | `[event: InteractionEvent]` | The ray-cast leaves the the collision body |
| `_on_key_down` | `[event: KeyEvent]` | The ray-cast leaves the the collision body |
| `_on_key_up` | `[event: KeyEvent]` | The ray-cast leaves the the collision body |
After considering using the build in godot event system, I've decided that it would be better to use a custom event system.
The reason being that we would have to check each tick if the event matches the desired one which seems very inefficient compared to using signals like the browser does.
Thus I've decided to use a custom event system that is similar to the one used in the browser.
### Functions ### Functions

View File

@ -1,39 +1,39 @@
extends Function extends Function
class_name Clickable class_name Clickable
signal on_click(event: Dictionary) signal on_click(event: EventRay)
signal on_press_down(event: Dictionary) signal on_press_down(event: EventRay)
signal on_press_move(event: Dictionary) signal on_press_move(event: EventRay)
signal on_press_up(event: Dictionary) signal on_press_up(event: EventRay)
signal on_grab_down(event: Dictionary) signal on_grab_down(event: EventRay)
signal on_grab_move(event: Dictionary) signal on_grab_move(event: EventRay)
signal on_grab_up(event: Dictionary) signal on_grab_up(event: EventRay)
signal on_ray_enter(event: Dictionary) signal on_ray_enter(event: EventRay)
signal on_ray_leave(event: Dictionary) signal on_ray_leave(event: EventRay)
func _on_click(event: Dictionary): func _on_click(event: EventRay):
on_click.emit(event) on_click.emit(event)
func _on_press_down(event: Dictionary): func _on_press_down(event: EventRay):
on_press_down.emit(event) on_press_down.emit(event)
func _on_press_move(event: Dictionary): func _on_press_move(event: EventRay):
on_press_move.emit(event) on_press_move.emit(event)
func _on_press_up(event: Dictionary): func _on_press_up(event: EventRay):
on_press_up.emit(event) on_press_up.emit(event)
func _on_grab_down(event: Dictionary): func _on_grab_down(event: EventRay):
on_grab_down.emit(event) on_grab_down.emit(event)
func _on_grab_move(event: Dictionary): func _on_grab_move(event: EventRay):
on_grab_move.emit(event) on_grab_move.emit(event)
func _on_grab_up(event: Dictionary): func _on_grab_up(event: EventRay):
on_grab_up.emit(event) on_grab_up.emit(event)
func _on_ray_enter(event: Dictionary): func _on_ray_enter(event: EventRay):
on_ray_enter.emit(event) on_ray_enter.emit(event)
func _on_ray_leave(event: Dictionary): func _on_ray_leave(event: EventRay):
on_ray_leave.emit(event) on_ray_leave.emit(event)

View File

@ -4,14 +4,14 @@ class_name Movable
var hit_node := Node3D.new() var hit_node := Node3D.new()
func _on_grab_down(event): func _on_grab_down(event: EventRay):
event.controller.add_child(hit_node) event.controller.add_child(hit_node)
hit_node.global_transform = get_parent().global_transform hit_node.global_transform = get_parent().global_transform
func _on_grab_move(event): func _on_grab_move(_event: EventRay):
get_parent().global_transform = hit_node.global_transform get_parent().global_transform = hit_node.global_transform
func _on_grab_up(event): func _on_grab_up(event: EventRay):
event.controller.remove_child(hit_node) event.controller.remove_child(hit_node)
func _get_configuration_warnings() -> PackedStringArray: func _get_configuration_warnings() -> PackedStringArray:

View File

@ -1,13 +1,13 @@
[gd_scene load_steps=13 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://content/raycast.gd" id="1_tsqxc"]
[ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"] [ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"]
[ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/controller_left.tscn" id="2_2lraw"] [ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"]
[ext_resource type="Texture2D" uid="uid://bo55nohs0wsgf" path="res://assets/materials/pointer.png" id="4_wcfej"] [ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="3_67lii"]
[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://83lb5p4e0qk0" path="res://content/scenes/house.tscn" id="8_qkrg7"] [ext_resource type="PackedScene" uid="uid://83lb5p4e0qk0" path="res://content/scenes/house.tscn" id="8_qkrg7"]
[ext_resource type="PackedScene" uid="uid://lrehk38exd5n" path="res://content/ui/keyboard/keyboard.tscn" id="9_e5n3p"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true ao_enabled = true
@ -46,20 +46,7 @@ pose = &"aim"
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/XRControllerRight"] [node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/XRControllerRight"]
mesh = SubResource("BoxMesh_ir3co") mesh = SubResource("BoxMesh_ir3co")
[node name="Raycast" type="Node3D" parent="XROrigin3D/XRControllerRight" node_paths=PackedStringArray("ray")] [node name="Raycast" parent="XROrigin3D/XRControllerRight" instance=ExtResource("3_67lii")]
script = ExtResource("1_tsqxc")
ray = NodePath("RayCast3D")
[node name="RayCast3D" type="RayCast3D" parent="XROrigin3D/XRControllerRight/Raycast"]
transform = Transform3D(-4.62364e-10, 4.3714e-08, 0.999998, 0.999999, -4.37194e-08, 9.2768e-12, 4.37103e-08, 0.999999, -4.3714e-08, -0.000467122, 0.00228411, -0.0016689)
target_position = Vector3(0, -5, 0)
[node name="Decal" type="Decal" parent="XROrigin3D/XRControllerRight/Raycast"]
transform = Transform3D(0.999999, -0.000567105, -2.5179e-05, -2.51789e-05, 4.39886e-08, -0.999999, 0.000567105, 1, 2.97064e-08, -0.000775784, -1.09076e-05, -2.46767)
size = Vector3(0.02, 4.91995, 0.02)
texture_albedo = ExtResource("4_wcfej")
upper_fade = 0.000985425
lower_fade = 0.000919435
[node name="StartXR" parent="." instance=ExtResource("1_i4c04")] [node name="StartXR" parent="." instance=ExtResource("1_i4c04")]
enable_passthrough = true enable_passthrough = true
@ -77,3 +64,6 @@ xr_origin = NodePath("../XROrigin3D")
[node name="House" parent="." instance=ExtResource("8_qkrg7")] [node name="House" parent="." instance=ExtResource("8_qkrg7")]
transform = Transform3D(0.404247, 0.000180645, 0.914648, 0.00017221, 0.999999, -0.000273614, -0.914648, 0.00026812, 0.404247, -0.343479, 0.000110551, 1.91547) transform = Transform3D(0.404247, 0.000180645, 0.914648, 0.00017221, 0.999999, -0.000273614, -0.914648, 0.00026812, 0.404247, -0.343479, 0.000110551, 1.91547)
visible = false visible = false
[node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")]
transform = Transform3D(0.5, -6.98186e-12, 0, 4.73988e-12, 0.5, 0, 0, 0, 0.5, -0.00874073, 0.253873, -0.357135)

View File

@ -1,121 +0,0 @@
extends Node3D
@onready var _controller := XRHelpers.get_xr_controller(self)
@export var ray: RayCast3D
@export var timespan_click = 200.0
# Called when the node enters the scene tree for the first time.
func _ready():
_controller.button_pressed.connect(_on_button_pressed)
_controller.button_released.connect(_on_button_released)
var _last_collided: Object = null
var _is_pressed := false
var _is_grabbed := false
var _time_pressed := 0.0
var _moved := false
var _click_point := Vector3.ZERO
func _physics_process(delta):
_handle_enter_leave()
_handle_move()
func _handle_move():
var time_passed = Time.get_ticks_msec() - _time_pressed
if time_passed <= timespan_click || (_is_pressed == false && _is_grabbed == false):
return
_moved = true
if _is_pressed:
_call_fn(_last_collided, "_on_press_move")
if _is_grabbed:
_call_fn(_last_collided, "_on_grab_move")
func _handle_enter_leave():
var collider = ray.get_collider()
if collider == _last_collided || _is_grabbed || _is_pressed:
return
_call_fn(collider, "_on_ray_enter")
_call_fn(_last_collided, "_on_ray_leave")
_last_collided = collider
func _on_button_pressed(button):
var collider = ray.get_collider()
if collider == null:
return
match button:
"trigger_click":
_is_pressed = true
_time_pressed = Time.get_ticks_msec()
_click_point = ray.get_collision_point()
_call_fn(collider, "_on_press_down")
"grip_click":
_is_grabbed = true
_click_point = ray.get_collision_point()
_call_fn(collider, "_on_grab_down")
func _on_button_released(button):
if _last_collided == null:
return
match button:
"trigger_click":
if _is_pressed:
if _moved == false:
_call_fn(_last_collided, "_on_click")
_call_fn(_last_collided, "_on_press_up")
_is_pressed = false
_last_collided = null
_moved = false
"grip_click":
if _is_grabbed:
_call_fn(_last_collided, "_on_grab_up")
_is_grabbed = false
_last_collided = null
_moved = false
func _call_fn(collider: Variant, fn_name: String, node: Node3D = null, event = null):
if collider == null:
return
if node == null:
node = collider
event = {
"controller": _controller,
"ray": ray,
"target": collider,
}
if node.has_method(fn_name):
var result = node.call(fn_name, event)
if result != null && result is Dictionary:
result.merge(event, true)
event = result
if result != null && result is bool && result == false:
# Stop the event from bubbling up
return
for child in node.get_children():
if child is Function && child.has_method(fn_name):
child.call(fn_name, event)
var parent = node.get_parent()
if parent != null && parent is Node3D:
_call_fn(collider, fn_name, parent, event)
else:
# in case the top has been reached
_call_global_fn(fn_name, event)
func _call_global_fn(fn_name: String, event = null):
Events.get(fn_name.substr(1)).emit(event)

View File

@ -34,11 +34,11 @@ var trash_bin_large: bool = false:
func _ready(): func _ready():
trash_bin_visible = false trash_bin_visible = false
Events.on_grab_down.connect(func(event): EventSystem.on_grab_down.connect(func(event: EventRay):
trash_bin_visible = event.target.is_in_group("entity") trash_bin_visible = event.target.is_in_group("entity")
) )
Events.on_grab_move.connect(func(event): EventSystem.on_grab_move.connect(func(event):
if !trash_bin_visible: if !trash_bin_visible:
return return
@ -53,7 +53,7 @@ func _ready():
) )
Events.on_grab_up.connect(func(event): EventSystem.on_grab_up.connect(func(_event: EventRay):
if !trash_bin_visible: if !trash_bin_visible:
return return

View File

@ -1,8 +1,9 @@
[gd_scene load_steps=10 format=3 uid="uid://b30w6tywfj4fp"] [gd_scene load_steps=11 format=3 uid="uid://b30w6tywfj4fp"]
[ext_resource type="Script" path="res://content/controller_left.gd" id="1_2j3qs"] [ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"]
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="1_ccbr3"] [ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="1_ccbr3"]
[ext_resource type="PackedScene" uid="uid://cj42our8uhfq6" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"] [ext_resource type="PackedScene" uid="uid://cj42our8uhfq6" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true ao_enabled = true
@ -119,3 +120,5 @@ shape = SubResource("CylinderShape3D_x2eyr")
libraries = { libraries = {
"": SubResource("AnimationLibrary_hkli8") "": SubResource("AnimationLibrary_hkli8")
} }
[node name="Raycast" parent="." instance=ExtResource("4_n7lao")]

View File

@ -0,0 +1,94 @@
extends RayCast3D
@export var is_right: bool = true
var controller: XRController3D
var timespan_click = 200.0
var last_collided: Object = null
var is_pressed := false
var is_grabbed := false
var time_pressed := 0.0
var moved := false
var click_point := Vector3.ZERO
func _ready():
controller = get_parent()
assert(controller is XRController3D, "XRController3D is not found in parent")
controller.button_pressed.connect(_on_button_pressed)
controller.button_released.connect(_on_button_released)
func _physics_process(_delta):
_handle_enter_leave()
_handle_move()
func _handle_move():
var time_passed = Time.get_ticks_msec() - time_pressed
if time_passed <= timespan_click || (is_pressed == false && is_grabbed == false):
return
moved = true
if is_pressed:
_emit_event("press_move", last_collided )
if is_grabbed:
_emit_event("grab_move", last_collided )
func _handle_enter_leave():
var collider = get_collider()
if collider == last_collided || is_grabbed || is_pressed:
return
_emit_event("ray_enter", collider )
_emit_event("ray_leave", last_collided )
last_collided = collider
func _on_button_pressed(button: String):
var collider = get_collider()
if collider == null:
return
match button:
"trigger_click":
is_pressed = true
time_pressed = Time.get_ticks_msec()
click_point = get_collision_point()
_emit_event("press_down", collider )
"grip_click":
is_grabbed = true
click_point = get_collision_point()
_emit_event("grab_down", collider )
func _on_button_released(button: String):
if last_collided == null:
return
match button:
"trigger_click":
if is_pressed:
if moved == false:
_emit_event("click", last_collided )
_emit_event("press_up", last_collided )
is_pressed = false
last_collided = null
moved = false
"grip_click":
if is_grabbed:
_emit_event("grab_up", last_collided )
is_grabbed = false
last_collided = null
moved = false
func _emit_event(type: String, target: Object):
var event = EventRay.new()
event.controller = controller
event.target = target
event.ray = self
event.is_right_controller = is_right
EventSystem.emit(type, event)

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://d3f8glx1xgm5w"]
[ext_resource type="Texture2D" uid="uid://bo55nohs0wsgf" path="res://assets/materials/pointer.png" id="1_2f2iv"]
[ext_resource type="Script" path="res://content/system/raycast/raycast.gd" id="1_gp8nv"]
[node name="Raycast" type="RayCast3D"]
transform = Transform3D(0.999999, -1.39624e-11, 0, 9.48108e-12, 0.999999, 0, 0, 4.54747e-13, 0.999998, -0.000467122, 0.00228411, -0.0016689)
target_position = Vector3(0, 0, -5)
script = ExtResource("1_gp8nv")
[node name="Decal" type="Decal" parent="."]
transform = Transform3D(1, -0.000567106, -2.5179e-05, -2.5179e-05, 4.39886e-08, -1, 0.000567106, 1, 2.97068e-08, -0.000308663, -0.00229502, -2.46601)
size = Vector3(0.02, 4.91995, 0.02)
texture_albedo = ExtResource("1_2f2iv")
upper_fade = 0.000985425
lower_fade = 0.000919435

View File

@ -1,12 +1,14 @@
extends StaticBody3D extends StaticBody3D
class_name Button3D class_name Button3D
signal on_button_down()
signal on_button_up()
@export var toggleable: bool = false @export var toggleable: bool = false
@export var disabled: bool = false @export var disabled: bool = false
@export var initial_active: bool = false @export var initial_active: bool = false
var active: bool = false : var active: bool = false :
set(value): set(value):
print("set active", value)
animation_player.stop() animation_player.stop()
if value == active: if value == active:
return return
@ -17,8 +19,6 @@ var active: bool = false :
animation_player.play("down") animation_player.play("down")
else: else:
animation_player.play_backwards("down") animation_player.play_backwards("down")
get:
return active
@onready var animation_player: AnimationPlayer = $AnimationPlayer @onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var click_sound: AudioStreamPlayer = $ClickSound @onready var click_sound: AudioStreamPlayer = $ClickSound
@ -27,35 +27,31 @@ func _ready():
if initial_active: if initial_active:
active = true active = true
func _on_click(_event): func _on_press_down(event):
if disabled: if disabled:
return false event.bubbling = false
if !toggleable:
return return
active = !active
AudioPlayer.play_effect("click")
return {
"active": active
}
func _on_press_down(_event):
if disabled:
return false
if toggleable: if toggleable:
return return
active = true
on_button_down.emit()
AudioPlayer.play_effect("click") AudioPlayer.play_effect("click")
animation_player.play("down")
func _on_press_up(_event):
func _on_press_up(event):
if disabled: if disabled:
return false event.bubbling = false
if toggleable:
return return
animation_player.play_backwards("down") if toggleable:
active = !active
if active:
on_button_down.emit()
else:
on_button_up.emit()
else:
active = false
on_button_up.emit()

View File

@ -1,51 +1,84 @@
extends Node3D @tool
extends StaticBody3D
const button_scene = preload("res://content/ui/components/button/button.tscn") const button_scene = preload("res://content/ui/components/button/button.tscn")
@onready var keys = $Keys @onready var keys = $Keys
@onready var caps_button = $Caps @onready var caps_button = $Caps
@onready var backspace_button = $Backspace
var key_list = [ var key_list = [
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "~"], [KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_ASCIITILDE],
["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "/"], [KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_SLASH],
["A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\\"], [KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_COLON, KEY_BACKSLASH],
["Z", "X", "C", "V", "B", "N", "M", ",", ".", "-"] [KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA , KEY_PERIOD, KEY_MINUS]
] ]
var caps = false var caps = false :
set(value):
caps = value
update_labels()
func _ready(): func _ready():
for row in key_list: for row in key_list:
for key in row: for key in row:
print(key)
var button = create_key(key) var button = create_key(key)
keys.add_child(button) keys.add_child(button)
button.on_button_down.connect(func():
_emit_event("key_down", key)
)
button.on_button_up.connect(func():
_emit_event("key_up", key)
)
keys.columns = key_list[0].size() keys.columns = key_list[0].size()
func _on_click(event): backspace_button.on_button_down.connect(func():
if event.target == caps_button: _emit_event("key_down", KEY_BACKSPACE)
caps = event.active )
return
var code = event.target.get_children()[event.target.get_child_count() - 1].text backspace_button.on_button_up.connect(func():
_emit_event("key_up", KEY_BACKSPACE)
)
if caps: caps_button.on_button_down.connect(func():
code = code.to_upper() caps = true
else: _emit_event("key_down", KEY_CAPSLOCK)
code = code.to_lower() )
Events.typed.emit(code) caps_button.on_button_up.connect(func():
print(code) caps = false
_emit_event("key_up", KEY_CAPSLOCK)
)
func create_key(key: String): func create_key(key: Key):
var button = button_scene.instantiate() var button = button_scene.instantiate()
var label = Label3D.new() var label = Label3D.new()
label.text = key label.text = EventKey.key_to_string(key, caps)
label.pixel_size = 0.001 label.pixel_size = 0.001
label.position = Vector3(0, 0.012, 0) label.position = Vector3(0, 0.012, 0)
label.rotate_x(deg_to_rad(-90)) label.rotate_x(deg_to_rad(-90))
label.add_to_group("button_label")
button.set_meta("key", key)
button.add_child(label) button.add_child(label)
return button return button
func update_labels():
for key_button in keys.get_children():
var label = key_button.get_children()[key_button.get_children().size() - 1]
if caps:
label.text = label.text.to_upper()
else:
label.text = label.text.to_lower()
func _emit_event(type: String, key: Key):
var event = EventKey.new()
event.key = key
event.shift_pressed = caps
EventSystem.emit(type, event)
print("Emitting event: " + type + " " + EventKey.key_to_string(key, caps))

View File

@ -1,14 +1,28 @@
[gd_scene load_steps=4 format=3 uid="uid://lrehk38exd5n"] [gd_scene load_steps=6 format=3 uid="uid://lrehk38exd5n"]
[ext_resource type="Script" path="res://content/ui/keyboard/keyboard.gd" id="1_maojw"] [ext_resource type="Script" path="res://content/ui/keyboard/keyboard.gd" id="1_maojw"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_xdpwr"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_xdpwr"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_mx544"] [ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_mx544"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="4_86fct"]
[node name="Keyboard" type="Node3D"] [sub_resource type="BoxShape3D" id="BoxShape3D_k5ib7"]
size = Vector3(0.744504, 0.0402036, 0.296009)
[node name="Keyboard" type="StaticBody3D"]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0)
script = ExtResource("1_maojw") script = ExtResource("1_maojw")
[node name="Backspace" parent="." instance=ExtResource("1_xdpwr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66, 0, 0.02)
metadata/key = 4194308
[node name="Label3D" type="Label3D" parent="Backspace"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.012, 0)
pixel_size = 0.001
text = "back"
[node name="Caps" parent="." instance=ExtResource("1_xdpwr")] [node name="Caps" parent="." instance=ExtResource("1_xdpwr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0668889, 0, 0.03) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.06, 0, 0.15)
toggleable = true toggleable = true
[node name="Label3D" type="Label3D" parent="Caps"] [node name="Label3D" type="Label3D" parent="Caps"]
@ -18,6 +32,13 @@ text = "caps"
[node name="Keys" type="Node3D" parent="."] [node name="Keys" type="Node3D" parent="."]
script = ExtResource("3_mx544") script = ExtResource("3_mx544")
columns = 1 columns = 11
depth_gap = 0.06 depth_gap = 0.06
size = Vector3(0.6, 1, 1) size = Vector3(0.6, 1, 1)
[node name="Movable" type="Node" parent="."]
script = ExtResource("4_86fct")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.276719, -0.025645, 0.0928761)
shape = SubResource("BoxShape3D_k5ib7")

9
lib/events/event.gd Normal file
View File

@ -0,0 +1,9 @@
extends Resource
class_name Event
func merge(event: Event):
assert(self.is_class(event.get_class()), "Can only merge events of the same type.")
for prop in event.get_property_list():
if prop.name in self:
self.set(prop.name, event.get(prop.name))

View File

@ -0,0 +1,5 @@
extends Event
class_name EventBubble
var bubbling := true
var target: Node

16
lib/events/event_key.gd Normal file
View File

@ -0,0 +1,16 @@
extends EventWithModifiers
class_name EventKey
var key: Key
var echo: bool
static func key_to_string(key: Key, caps: bool = false) -> String:
match key:
KEY_ASCIITILDE: return "~"
KEY_SLASH: return "/"
KEY_BACKSLASH: return "\\"
KEY_COLON: return ";"
KEY_COMMA: return ","
KEY_PERIOD: return "."
KEY_MINUS: return "-"
_: return OS.get_keycode_string(key).to_upper() if caps else OS.get_keycode_string(key).to_lower()

6
lib/events/event_ray.gd Normal file
View File

@ -0,0 +1,6 @@
extends EventBubble
class_name EventRay
var controller: XRController3D
var is_right_controller: bool
var ray: RayCast3D

View File

@ -0,0 +1,7 @@
extends Event
class_name EventWithModifiers
var alt_pressed := false
var shift_pressed := false
var control_pressed := false
var meta_pressed := false

View File

@ -0,0 +1,55 @@
extends Node
const FN_PREFIX = "_on_"
const SIGNAL_PREFIX = "on_"
# Interaction Events
signal on_click(event: EventRay)
signal on_press_down(event: EventRay)
signal on_press_move(event: EventRay)
signal on_press_up(event: EventRay)
signal on_grab_down(event: EventRay)
signal on_grab_move(event: EventRay)
signal on_grab_up(event: EventRay)
signal on_ray_enter(event: EventRay)
signal on_ray_leave(event: EventRay)
signal on_key_down(event: EventKey)
signal on_key_up(event: EventKey)
func emit(type: String, event: Event):
if event is EventBubble:
_bubble_call(type, event.target, event)
else:
_root_call(type, event)
func _bubble_call(type: String, target: Variant, event: EventBubble):
if target == null:
return
if target.has_method(FN_PREFIX + type):
var updated_event = target.call(FN_PREFIX + type, event)
if updated_event is EventBubble:
updated_event.merge(event)
event = updated_event
if event.bubbling == false:
return
for child in target.get_children():
if child is Function && child.has_method(FN_PREFIX + type):
child.call(FN_PREFIX + type, event)
var parent = target.get_parent()
if parent != null && parent is Node:
_bubble_call(type, parent, event)
else:
# in case the top has been reached
_root_call(type, event)
func _root_call(type: String, event: Event):
get(SIGNAL_PREFIX + type).emit(event)

View File

@ -1,15 +0,0 @@
# Global event bus
extends Node
# Interaction Events
signal on_click(event: Dictionary)
signal on_press_down(event: Dictionary)
signal on_press_move(event: Dictionary)
signal on_press_up(event: Dictionary)
signal on_grab_down(event: Dictionary)
signal on_grab_move(event: Dictionary)
signal on_grab_up(event: Dictionary)
signal on_ray_enter(event: Dictionary)
signal on_ray_leave(event: Dictionary)
signal typed(key: String)

View File

@ -16,6 +16,7 @@ var authenticated := false
var loading := true var loading := true
var id := 1 var id := 1
var entities: Dictionary = {} var entities: Dictionary = {}
var retries := 5
var entitiy_callbacks := CallbackMap.new() var entitiy_callbacks := CallbackMap.new()
var packet_callbacks := CallbackMap.new() var packet_callbacks := CallbackMap.new()
@ -31,6 +32,11 @@ func _init(url := self.url, token := self.token):
connect_ws() connect_ws()
func connect_ws(): func connect_ws():
retries -= 1
if retries < 0:
print("Failed to connect to %s" % self.url)
return
print("Connecting to %s" % self.url) print("Connecting to %s" % self.url)
socket.connect_to_url(self.url) socket.connect_to_url(self.url)
set_process(true) set_process(true)

View File

@ -21,7 +21,7 @@ XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd
Request="*res://lib/globals/request.gd" Request="*res://lib/globals/request.gd"
HomeAdapters="*res://lib/globals/home_adapters.gd" HomeAdapters="*res://lib/globals/home_adapters.gd"
AudioPlayer="*res://lib/globals/audio_player.gd" AudioPlayer="*res://lib/globals/audio_player.gd"
Events="*res://lib/globals/events.gd" EventSystem="*res://lib/globals/event_system.gd"
[editor_plugins] [editor_plugins]