rework event system and add keyboard
This commit is contained in:
parent
16201224ce
commit
a2bc1a5d37
10
README.md
10
README.md
|
@ -101,6 +101,10 @@ InteractionEvent {
|
|||
"ray": RayCast3D, # The ray-cast that triggered the event
|
||||
"target": Node3D, # The node that was hit by the ray-cast
|
||||
}
|
||||
|
||||
KeyEvent {
|
||||
"key": String, # The key that was pressed
|
||||
}
|
||||
```
|
||||
|
||||
| Function called | Args | Description |
|
||||
|
@ -114,6 +118,12 @@ InteractionEvent {
|
|||
| `_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_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
|
||||
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
extends Function
|
||||
class_name Clickable
|
||||
|
||||
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 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)
|
||||
|
||||
func _on_click(event: Dictionary):
|
||||
func _on_click(event: EventRay):
|
||||
on_click.emit(event)
|
||||
|
||||
func _on_press_down(event: Dictionary):
|
||||
func _on_press_down(event: EventRay):
|
||||
on_press_down.emit(event)
|
||||
|
||||
func _on_press_move(event: Dictionary):
|
||||
func _on_press_move(event: EventRay):
|
||||
on_press_move.emit(event)
|
||||
|
||||
func _on_press_up(event: Dictionary):
|
||||
func _on_press_up(event: EventRay):
|
||||
on_press_up.emit(event)
|
||||
|
||||
func _on_grab_down(event: Dictionary):
|
||||
func _on_grab_down(event: EventRay):
|
||||
on_grab_down.emit(event)
|
||||
|
||||
func _on_grab_move(event: Dictionary):
|
||||
func _on_grab_move(event: EventRay):
|
||||
on_grab_move.emit(event)
|
||||
|
||||
func _on_grab_up(event: Dictionary):
|
||||
func _on_grab_up(event: EventRay):
|
||||
on_grab_up.emit(event)
|
||||
|
||||
func _on_ray_enter(event: Dictionary):
|
||||
func _on_ray_enter(event: EventRay):
|
||||
on_ray_enter.emit(event)
|
||||
|
||||
func _on_ray_leave(event: Dictionary):
|
||||
func _on_ray_leave(event: EventRay):
|
||||
on_ray_leave.emit(event)
|
|
@ -4,14 +4,14 @@ class_name Movable
|
|||
|
||||
var hit_node := Node3D.new()
|
||||
|
||||
func _on_grab_down(event):
|
||||
func _on_grab_down(event: EventRay):
|
||||
event.controller.add_child(hit_node)
|
||||
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
|
||||
|
||||
func _on_grab_up(event):
|
||||
func _on_grab_up(event: EventRay):
|
||||
event.controller.remove_child(hit_node)
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
[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="Script" path="res://content/raycast.gd" id="1_tsqxc"]
|
||||
[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="Texture2D" uid="uid://bo55nohs0wsgf" path="res://assets/materials/pointer.png" id="4_wcfej"]
|
||||
[ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"]
|
||||
[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="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://lrehk38exd5n" path="res://content/ui/keyboard/keyboard.tscn" id="9_e5n3p"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
|
||||
ao_enabled = true
|
||||
|
@ -46,20 +46,7 @@ pose = &"aim"
|
|||
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/XRControllerRight"]
|
||||
mesh = SubResource("BoxMesh_ir3co")
|
||||
|
||||
[node name="Raycast" type="Node3D" parent="XROrigin3D/XRControllerRight" node_paths=PackedStringArray("ray")]
|
||||
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="Raycast" parent="XROrigin3D/XRControllerRight" instance=ExtResource("3_67lii")]
|
||||
|
||||
[node name="StartXR" parent="." instance=ExtResource("1_i4c04")]
|
||||
enable_passthrough = true
|
||||
|
@ -77,3 +64,6 @@ xr_origin = NodePath("../XROrigin3D")
|
|||
[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)
|
||||
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)
|
||||
|
|
|
@ -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)
|
|
@ -34,11 +34,11 @@ var trash_bin_large: bool = false:
|
|||
func _ready():
|
||||
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")
|
||||
)
|
||||
|
||||
Events.on_grab_move.connect(func(event):
|
||||
EventSystem.on_grab_move.connect(func(event):
|
||||
if !trash_bin_visible:
|
||||
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:
|
||||
return
|
||||
|
|
@ -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://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"]
|
||||
ao_enabled = true
|
||||
|
@ -119,3 +120,5 @@ shape = SubResource("CylinderShape3D_x2eyr")
|
|||
libraries = {
|
||||
"": SubResource("AnimationLibrary_hkli8")
|
||||
}
|
||||
|
||||
[node name="Raycast" parent="." instance=ExtResource("4_n7lao")]
|
94
content/system/raycast/raycast.gd
Normal file
94
content/system/raycast/raycast.gd
Normal 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)
|
16
content/system/raycast/raycast.tscn
Normal file
16
content/system/raycast/raycast.tscn
Normal 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
|
|
@ -1,12 +1,14 @@
|
|||
extends StaticBody3D
|
||||
class_name Button3D
|
||||
|
||||
signal on_button_down()
|
||||
signal on_button_up()
|
||||
|
||||
@export var toggleable: bool = false
|
||||
@export var disabled: bool = false
|
||||
@export var initial_active: bool = false
|
||||
var active: bool = false :
|
||||
set(value):
|
||||
print("set active", value)
|
||||
animation_player.stop()
|
||||
if value == active:
|
||||
return
|
||||
|
@ -17,8 +19,6 @@ var active: bool = false :
|
|||
animation_player.play("down")
|
||||
else:
|
||||
animation_player.play_backwards("down")
|
||||
get:
|
||||
return active
|
||||
|
||||
@onready var animation_player: AnimationPlayer = $AnimationPlayer
|
||||
@onready var click_sound: AudioStreamPlayer = $ClickSound
|
||||
|
@ -27,35 +27,31 @@ func _ready():
|
|||
if initial_active:
|
||||
active = true
|
||||
|
||||
func _on_click(_event):
|
||||
func _on_press_down(event):
|
||||
if disabled:
|
||||
return false
|
||||
|
||||
if !toggleable:
|
||||
event.bubbling = false
|
||||
return
|
||||
|
||||
if toggleable:
|
||||
return
|
||||
|
||||
active = true
|
||||
on_button_down.emit()
|
||||
|
||||
AudioPlayer.play_effect("click")
|
||||
|
||||
|
||||
func _on_press_up(event):
|
||||
if disabled:
|
||||
event.bubbling = false
|
||||
return
|
||||
|
||||
if toggleable:
|
||||
active = !active
|
||||
AudioPlayer.play_effect("click")
|
||||
|
||||
return {
|
||||
"active": active
|
||||
}
|
||||
|
||||
func _on_press_down(_event):
|
||||
if disabled:
|
||||
return false
|
||||
|
||||
if toggleable:
|
||||
return
|
||||
|
||||
AudioPlayer.play_effect("click")
|
||||
animation_player.play("down")
|
||||
|
||||
func _on_press_up(_event):
|
||||
if disabled:
|
||||
return false
|
||||
|
||||
if toggleable:
|
||||
return
|
||||
|
||||
animation_player.play_backwards("down")
|
||||
if active:
|
||||
on_button_down.emit()
|
||||
else:
|
||||
on_button_up.emit()
|
||||
else:
|
||||
active = false
|
||||
on_button_up.emit()
|
||||
|
|
|
@ -1,51 +1,84 @@
|
|||
extends Node3D
|
||||
@tool
|
||||
extends StaticBody3D
|
||||
|
||||
const button_scene = preload("res://content/ui/components/button/button.tscn")
|
||||
|
||||
@onready var keys = $Keys
|
||||
@onready var caps_button = $Caps
|
||||
@onready var backspace_button = $Backspace
|
||||
var key_list = [
|
||||
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "~"],
|
||||
["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "/"],
|
||||
["A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\\"],
|
||||
["Z", "X", "C", "V", "B", "N", "M", ",", ".", "-"]
|
||||
[KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_ASCIITILDE],
|
||||
[KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_SLASH],
|
||||
[KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_COLON, KEY_BACKSLASH],
|
||||
[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():
|
||||
for row in key_list:
|
||||
for key in row:
|
||||
print(key)
|
||||
var button = create_key(key)
|
||||
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()
|
||||
|
||||
func _on_click(event):
|
||||
if event.target == caps_button:
|
||||
caps = event.active
|
||||
return
|
||||
backspace_button.on_button_down.connect(func():
|
||||
_emit_event("key_down", KEY_BACKSPACE)
|
||||
)
|
||||
|
||||
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:
|
||||
code = code.to_upper()
|
||||
else:
|
||||
code = code.to_lower()
|
||||
caps_button.on_button_down.connect(func():
|
||||
caps = true
|
||||
_emit_event("key_down", KEY_CAPSLOCK)
|
||||
)
|
||||
|
||||
Events.typed.emit(code)
|
||||
print(code)
|
||||
caps_button.on_button_up.connect(func():
|
||||
caps = false
|
||||
_emit_event("key_up", KEY_CAPSLOCK)
|
||||
)
|
||||
|
||||
func create_key(key: String):
|
||||
func create_key(key: Key):
|
||||
var button = button_scene.instantiate()
|
||||
|
||||
var label = Label3D.new()
|
||||
label.text = key
|
||||
label.text = EventKey.key_to_string(key, caps)
|
||||
label.pixel_size = 0.001
|
||||
label.position = Vector3(0, 0.012, 0)
|
||||
label.rotate_x(deg_to_rad(-90))
|
||||
label.add_to_group("button_label")
|
||||
|
||||
button.set_meta("key", key)
|
||||
|
||||
button.add_child(label)
|
||||
|
||||
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))
|
||||
|
||||
|
|
|
@ -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="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/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")
|
||||
|
||||
[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")]
|
||||
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
|
||||
|
||||
[node name="Label3D" type="Label3D" parent="Caps"]
|
||||
|
@ -18,6 +32,13 @@ text = "caps"
|
|||
|
||||
[node name="Keys" type="Node3D" parent="."]
|
||||
script = ExtResource("3_mx544")
|
||||
columns = 1
|
||||
columns = 11
|
||||
depth_gap = 0.06
|
||||
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
9
lib/events/event.gd
Normal 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))
|
5
lib/events/event_bubble.gd
Normal file
5
lib/events/event_bubble.gd
Normal file
|
@ -0,0 +1,5 @@
|
|||
extends Event
|
||||
class_name EventBubble
|
||||
|
||||
var bubbling := true
|
||||
var target: Node
|
16
lib/events/event_key.gd
Normal file
16
lib/events/event_key.gd
Normal 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
6
lib/events/event_ray.gd
Normal file
|
@ -0,0 +1,6 @@
|
|||
extends EventBubble
|
||||
class_name EventRay
|
||||
|
||||
var controller: XRController3D
|
||||
var is_right_controller: bool
|
||||
var ray: RayCast3D
|
7
lib/events/event_with_modifiers.gd
Normal file
7
lib/events/event_with_modifiers.gd
Normal 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
|
55
lib/globals/event_system.gd
Normal file
55
lib/globals/event_system.gd
Normal 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)
|
|
@ -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)
|
|
@ -16,6 +16,7 @@ var authenticated := false
|
|||
var loading := true
|
||||
var id := 1
|
||||
var entities: Dictionary = {}
|
||||
var retries := 5
|
||||
|
||||
var entitiy_callbacks := CallbackMap.new()
|
||||
var packet_callbacks := CallbackMap.new()
|
||||
|
@ -31,6 +32,11 @@ func _init(url := self.url, token := self.token):
|
|||
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)
|
||||
socket.connect_to_url(self.url)
|
||||
set_process(true)
|
||||
|
|
|
@ -21,7 +21,7 @@ XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd
|
|||
Request="*res://lib/globals/request.gd"
|
||||
HomeAdapters="*res://lib/globals/home_adapters.gd"
|
||||
AudioPlayer="*res://lib/globals/audio_player.gd"
|
||||
Events="*res://lib/globals/events.gd"
|
||||
EventSystem="*res://lib/globals/event_system.gd"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user