add navigation buttons

This commit is contained in:
Nitwel 2023-11-16 19:23:17 +01:00
parent 91bd0403c4
commit 9811194df7
29 changed files with 384844 additions and 242 deletions

View File

@ -84,6 +84,8 @@ Each time a button is pressed on the primary controller, a ray-cast is done to b
Additionally, each event will bubble up until the root node is reached, allowing to handle events on parents. Additionally, each event will bubble up until the root node is reached, allowing to handle events on parents.
In case that an event of a specific node has to be reacted on, use the `Clickable` function node. In case that an event of a specific node has to be reacted on, use the `Clickable` function node.
It is also possible to bubble up information by returning a dictionary from a function like `_on_click`.
```python ```python
InteractionEvent { InteractionEvent {
"controller": XRController3D, # The controller that triggered the event "controller": XRController3D, # The controller that triggered the event

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:991ebe1738a0621dd536436b99a7b5149d10e6b185008ec533eb2c5ca79fec0c oid sha256:a8a8155035309697c511a28e0e7ca8912f19cb4ddb705be118ec5a0740336d29
size 3087839 size 4088828

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:06023dd670a93311f9c757dac2c72c2b5dde6682a800456841715c6dd422f505
size 341

View File

@ -0,0 +1,39 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dch6rwihrl3i2"
path.s3tc="res://.godot/imported/schema_white_24dp.svg-78416867d0323ea24692e91bbbd6eccf.s3tc.ctex"
path.etc2="res://.godot/imported/schema_white_24dp.svg-78416867d0323ea24692e91bbbd6eccf.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/icons/schema_white_24dp.svg"
dest_files=["res://.godot/imported/schema_white_24dp.svg-78416867d0323ea24692e91bbbd6eccf.s3tc.ctex", "res://.godot/imported/schema_white_24dp.svg-78416867d0323ea24692e91bbbd6eccf.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
svg/scale=8.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:85603fc1d26b1cc7300b47368ea1324ee639685c7e081ec1753db8fe6e890ebf
size 1462

View File

@ -0,0 +1,39 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dyh0ax51xqp8n"
path.s3tc="res://.godot/imported/settings_white_24dp.svg-00489b947e07e7f772d9a02d10ec99e3.s3tc.ctex"
path.etc2="res://.godot/imported/settings_white_24dp.svg-00489b947e07e7f772d9a02d10ec99e3.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/icons/settings_white_24dp.svg"
dest_files=["res://.godot/imported/settings_white_24dp.svg-00489b947e07e7f772d9a02d10ec99e3.s3tc.ctex", "res://.godot/imported/settings_white_24dp.svg-00489b947e07e7f772d9a02d10ec99e3.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
svg/scale=8.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7bd032062986d308937d62aca2c753cd5bedfe34c50ede397e596c6c9593df51
size 870

View File

@ -0,0 +1,39 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://jodf3dm654j3"
path.s3tc="res://.godot/imported/view_in_ar_white_24dp.svg-5b49634cd6aa27ec8f9e11a0780ef941.s3tc.ctex"
path.etc2="res://.godot/imported/view_in_ar_white_24dp.svg-5b49634cd6aa27ec8f9e11a0780ef941.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/icons/view_in_ar_white_24dp.svg"
dest_files=["res://.godot/imported/view_in_ar_white_24dp.svg-5b49634cd6aa27ec8f9e11a0780ef941.s3tc.ctex", "res://.godot/imported/view_in_ar_white_24dp.svg-5b49634cd6aa27ec8f9e11a0780ef941.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
svg/scale=8.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1259941b0164449141d01ea7db1e1ceaf224aed6010c1a8a425625f891c09570
size 493

View File

@ -0,0 +1,39 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cattgsppxnbq4"
path.s3tc="res://.godot/imported/visibility_white_24dp.svg-78a4c7f3f7d3e93235e396c65d5f8e8c.s3tc.ctex"
path.etc2="res://.godot/imported/visibility_white_24dp.svg-78a4c7f3f7d3e93235e396c65d5f8e8c.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/icons/visibility_white_24dp.svg"
dest_files=["res://.godot/imported/visibility_white_24dp.svg-78a4c7f3f7d3e93235e396c65d5f8e8c.s3tc.ctex", "res://.godot/imported/visibility_white_24dp.svg-78a4c7f3f7d3e93235e396c65d5f8e8c.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
svg/scale=8.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:602db8fb276c43354096ff9144a94e99ec0d271e7d8216db80a5467f804c247e
size 348

View File

@ -0,0 +1,39 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://csq5a4gk6ba5b"
path.s3tc="res://.godot/imported/widgets_white_24dp.svg-4200d261601a457250005cb067bd0ad7.s3tc.ctex"
path.etc2="res://.godot/imported/widgets_white_24dp.svg-4200d261601a457250005cb067bd0ad7.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/icons/widgets_white_24dp.svg"
dest_files=["res://.godot/imported/widgets_white_24dp.svg-4200d261601a457250005cb067bd0ad7.s3tc.ctex", "res://.godot/imported/widgets_white_24dp.svg-4200d261601a457250005cb067bd0ad7.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
svg/scale=8.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,102 @@
# Blender 3.4.0 MTL File: 'None'
# www.blender.org
newmtl PhongF3EF37
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.952941 0.937255 0.215686
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Reflective53504B
Ns 925.000061
Ka 1.000000 1.000000 1.000000
Kd 0.325490 0.313726 0.294118
Ks 0.800000 0.800000 0.800000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
newmtl ReflectiveA5B3A8
Ns 925.000061
Ka 1.000000 1.000000 1.000000
Kd 0.647059 0.701961 0.658823
Ks 0.800000 0.800000 0.800000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
newmtl Standard000000.001
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard5DD756
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.364706 0.843137 0.337255
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard9F9F9F.001
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.623529 0.623529 0.623529
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl StandardD3D237
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.827451 0.823529 0.215686
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl StandardD3D23789
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.827451 0.823529 0.215686
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 0.537255
illum 1
newmtl StandardD82429
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.847059 0.141177 0.160784
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl StandardE72C34
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.905882 0.172549 0.203922
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://ibv3j8a6punc"
path="res://.godot/imported/immersive_home.obj-80e9509dc5c96b9f5522ea6ac8cd2d99.mesh"
[deps]
files=["res://.godot/imported/immersive_home.obj-80e9509dc5c96b9f5522ea6ac8cd2d99.mesh"]
source_file="res://assets/immersive_home/immersive_home.obj"
dest_files=["res://.godot/imported/immersive_home.obj-80e9509dc5c96b9f5522ea6ac8cd2d99.mesh", "res://.godot/imported/immersive_home.obj-80e9509dc5c96b9f5522ea6ac8cd2d99.mesh"]
[params]
generate_tangents=true
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
optimize_mesh=true

View File

@ -0,0 +1,62 @@
# Blender 3.4.0 MTL File: 'None'
# www.blender.org
newmtl Standard000000
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard3AE864
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.227451 0.909804 0.392157
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard626262
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.384314 0.384314 0.384314
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard7BFFC5
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.482353 1.000000 0.772549
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl Standard9F9F9F
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.623529 0.623529 0.623529
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
newmtl StandardFFFFFF
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://cejvc23wfwjqj"
path="res://.godot/imported/immersive_home_panels.obj-25bf3167534aaaf96f611e3e962c5139.mesh"
[deps]
files=["res://.godot/imported/immersive_home_panels.obj-25bf3167534aaaf96f611e3e962c5139.mesh"]
source_file="res://assets/immersive_home_panels/immersive_home_panels.obj"
dest_files=["res://.godot/imported/immersive_home_panels.obj-25bf3167534aaaf96f611e3e962c5139.mesh", "res://.godot/imported/immersive_home_panels.obj-25bf3167534aaaf96f611e3e962c5139.mesh"]
[params]
generate_tangents=true
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
optimize_mesh=true

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7d62537d8aa4fee28ed5484c8c7ba96c2c9a7fa7bc0740e79420f01105602ca5 oid sha256:68e2b9d5e723a2009f341e45e2968893dd2a1dd5077fe1d9ba970f01d0d75e02
size 43035 size 56989

View File

@ -66,6 +66,8 @@ target_position = Vector3(0, -5, 0)
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) 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, 5, 0.02) size = Vector3(0.02, 5, 0.02)
texture_albedo = ExtResource("4_wcfej") 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

View File

@ -77,27 +77,34 @@ func _on_button_released(button):
_is_grabbed = false _is_grabbed = false
_moved = false _moved = false
func _call_fn(collider: Object, fn_name: String, node: Node3D = null): func _call_fn(collider: Object, fn_name: String, node: Node3D = null, event = null):
if collider == null: if collider == null:
return return
if node == null: if node == null:
node = collider node = collider
event = {
var event = {
"controller": _controller, "controller": _controller,
"ray": ray, "ray": ray,
"target": collider, "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)
if result != null && result is bool && result == false:
# Stop the event from bubbling up
return
for child in node.get_children(): for child in node.get_children():
if child is Function && child.has_method(fn_name): if child is Function && child.has_method(fn_name):
child.call(fn_name, event) child.call(fn_name, event)
if node.has_method(fn_name):
node.call(fn_name, event)
var parent = node.get_parent() var parent = node.get_parent()
if parent != null && parent is Node3D: if parent != null && parent is Node3D:
_call_fn(collider, fn_name, parent) _call_fn(collider, fn_name, parent, event)

View File

@ -1,9 +0,0 @@
extends StaticBody3D
@onready var animation_player: AnimationPlayer = $AnimationPlayer
func _on_press_down(_event):
animation_player.play("down")
func _on_press_up(_event):
animation_player.play("up")

View File

@ -0,0 +1,58 @@
extends StaticBody3D
class_name Button3D
@export var toggleable: bool = false
@export var disabled: bool = false
var active: bool = false :
set(value):
print("set active", value)
animation_player.stop()
if value == active:
return
active = value
if active:
animation_player.play("down")
else:
animation_player.play_backwards("down")
get:
return active
@onready var animation_player: AnimationPlayer = $AnimationPlayer
func _on_click(_event):
if disabled:
return false
if !toggleable:
return
active = !active
return {
"active": active
}
func _on_press_down(_event):
if disabled:
return false
if toggleable:
return
animation_player.play("down")
func _on_press_up(_event):
if disabled:
return false
if toggleable:
return
animation_player.play_backwards("down")

View File

@ -1,18 +1,56 @@
[gd_scene load_steps=9 format=3 uid="uid://bsjqdvkt0u87c"] [gd_scene load_steps=8 format=3 uid="uid://bsjqdvkt0u87c"]
[ext_resource type="Script" path="res://content/ui/button/button.gd" id="1_g5u54"] [ext_resource type="Script" path="res://content/ui/components/button/button.gd" id="1_74x7g"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_peqek"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_peqek"]
albedo_color = Color(0.151534, 0.211909, 0.619523, 1) albedo_color = Color(0.151534, 0.211909, 0.619523, 1)
[sub_resource type="BoxMesh" id="BoxMesh_jwpm5"] [sub_resource type="BoxMesh" id="BoxMesh_jwpm5"]
resource_local_to_scene = true
material = SubResource("StandardMaterial3D_peqek") material = SubResource("StandardMaterial3D_peqek")
size = Vector3(0.05, 0.02, 0.05) size = Vector3(0.05, 0.02, 0.05)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_o4j7g"] [sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_o4j7g"]
points = PackedVector3Array(-0.025, -0.01, -0.025, -0.025, 0.01, -0.025, 0.025, -0.01, -0.025, -0.025, -0.01, 0.025, -0.025, 0.01, 0.025, 0.025, 0.01, -0.025, 0.025, -0.01, 0.025, 0.025, 0.01, 0.025) points = PackedVector3Array(-0.025, -0.01, -0.025, -0.025, 0.01, -0.025, 0.025, -0.01, -0.025, -0.025, -0.01, 0.025, -0.025, 0.01, 0.025, 0.025, 0.01, -0.025, 0.025, -0.01, 0.025, 0.025, 0.01, 0.025)
[sub_resource type="Animation" id="Animation_04k6i"] [sub_resource type="Animation" id="Animation_iu2ed"]
resource_name = "down"
length = 0.2
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, -0.01, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("MeshInstance3D:mesh:size:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0.02, -0.25, 0, 0.25, 0, 0.01, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("MeshInstance3D:position:y")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0.005, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
[sub_resource type="Animation" id="Animation_gvfrg"]
length = 0.001 length = 0.001
tracks/0/type = "bezier" tracks/0/type = "bezier"
tracks/0/imported = false tracks/0/imported = false
@ -22,50 +60,29 @@ tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
"handle_modes": PackedInt32Array(0), "handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0.01, -0.25, 0, 0.25, 0), "points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0) "times": PackedFloat32Array(0)
} }
tracks/1/type = "bezier"
[sub_resource type="Animation" id="Animation_iu2ed"] tracks/1/imported = false
resource_name = "down" tracks/1/enabled = true
length = 0.4 tracks/1/path = NodePath("MeshInstance3D:position:y")
tracks/0/type = "bezier" tracks/1/interp = 1
tracks/0/imported = false tracks/1/loop_wrap = true
tracks/0/enabled = true tracks/1/keys = {
tracks/0/path = NodePath(".:position:y") "handle_modes": PackedInt32Array(0),
tracks/0/interp = 1 "points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
tracks/0/loop_wrap = true "times": PackedFloat32Array(0)
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0.01, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.4)
}
[sub_resource type="Animation" id="Animation_y7xum"]
resource_name = "up"
length = 0.4
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0.01, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.4)
} }
[sub_resource type="AnimationLibrary" id="AnimationLibrary_sbgno"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_sbgno"]
_data = { _data = {
"RESET": SubResource("Animation_04k6i"), "RESET": SubResource("Animation_gvfrg"),
"down": SubResource("Animation_iu2ed"), "down": SubResource("Animation_iu2ed")
"up": SubResource("Animation_y7xum")
} }
[node name="Button" type="StaticBody3D"] [node name="Button" type="StaticBody3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 0) script = ExtResource("1_74x7g")
script = ExtResource("1_g5u54")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."] [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_jwpm5") mesh = SubResource("BoxMesh_jwpm5")

View File

@ -0,0 +1,157 @@
extends Node3D
const Device = preload("res://content/ui/device/device.tscn")
const Entity = preload("res://content/ui/entity/entity.tscn")
const Switch = preload("res://content/entities/switch/switch.tscn")
const Light = preload("res://content/entities/light/light.tscn")
const Sensor = preload("res://content/entities/sensor/sensor.tscn")
@onready var devices_node: GridContainer3D = $Devices
@onready var next_page_button = $Buttons/NextPageButton
@onready var previous_page_button = $Buttons/PreviousPageButton
@onready var page_number_label = $PageNumberLabel
var devices
var page = 0
var last_device_page = 0
var page_size = 20
var pages = 0
var selected_device = null
# Called when the node enters the scene tree for the first time.
func _ready():
devices = await HomeAdapters.adapter.get_devices()
next_page_button.get_node("Clickable").on_click.connect(func(_event):
print("next page")
next_page()
)
previous_page_button.get_node("Clickable").on_click.connect(func(_event):
previous_page()
)
render()
func update_pages():
if selected_device == null:
pages = ceil(float(devices.size()) / page_size)
else:
for device in devices:
if device.keys()[0] == selected_device:
pages = ceil(float(device.values()[0]["entities"].size()) / page_size)
func get_page():
if selected_device == null:
return devices.slice(page * page_size, page * page_size + page_size)
else:
for device in devices:
if device.keys()[0] == selected_device:
return device.values()[0]["entities"].slice(page * page_size, page * page_size + page_size)
func next_page():
if page >= pages - 1:
return
page += 1
render()
func previous_page():
if page <= 0:
return
page -= 1
render()
func render():
update_pages()
page_number_label.set_text(str(page + 1) + " / " + str(pages))
previous_page_button.visible = page > 0
next_page_button.visible = page < pages - 1
clear_menu()
if selected_device == null:
render_devices()
else:
render_entities()
func render_devices():
var page_devices = get_page()
for device in page_devices:
var info = device.values()[0]
var device_instance = Device.instantiate()
device_instance.id = device.keys()[0]
device_instance.get_node("Clickable").on_click.connect(func(_event):
_on_device_click(device_instance.id)
)
devices_node.add_child(device_instance)
device_instance.set_device_name(info["name"])
devices_node._update_container()
func render_entities():
var entities = get_page()
var back_button = Entity.instantiate()
back_button.get_node("Clickable").on_click.connect(func(_event):
_on_entity_click("#back")
)
devices_node.add_child(back_button)
back_button.set_entity_name("#back")
for entity in entities:
var entity_instance = Entity.instantiate()
entity_instance.get_node("Clickable").on_click.connect(func(_event):
_on_entity_click(entity)
)
devices_node.add_child(entity_instance)
entity_instance.set_entity_name(entity)
devices_node._update_container()
func _on_device_click(device_id):
selected_device = device_id
last_device_page = page
page = 0
render()
func _on_entity_click(entity_name):
if entity_name == "#back":
selected_device = null
page = last_device_page
render()
return
var type = entity_name.split(".")[0]
print(type)
if type == "switch":
var switch = Switch.instantiate()
switch.entity_id = entity_name
switch.set_position(global_position)
get_node("/root").add_child(switch)
if type == "light":
var light = Light.instantiate()
light.entity_id = entity_name
light.set_position(global_position)
get_node("/root").add_child(light)
if type == "sensor":
var sensor = Sensor.instantiate()
sensor.entity_id = entity_name
sensor.set_position(global_position)
get_node("/root").add_child(sensor)
func clear_menu():
for child in devices_node.get_children():
devices_node.remove_child(child)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

View File

@ -0,0 +1,45 @@
[gd_scene load_steps=6 format=3 uid="uid://crrb0l3ekuotj"]
[ext_resource type="Script" path="res://content/ui/menu/edit/edit_menu.gd" id="1_34cbn"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_0xvyw"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_tvimg"]
[ext_resource type="Texture2D" uid="uid://tr8yrx470k03" path="res://assets/materials/arrow_right.png" id="5_0uvv4"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="6_pf8jy"]
[node name="EditMenu" type="Node3D"]
script = ExtResource("1_34cbn")
[node name="Devices" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.03, 0.01, 0.03)
script = ExtResource("3_0xvyw")
depth_gap = 0.06
size = Vector3(0.24, 0.1, 0.1)
[node name="PageNumberLabel" type="Label3D" parent="."]
transform = Transform3D(0.1, 0, 0, 0, -4.37114e-09, 0.1, 0, -0.1, -4.37114e-09, 0.26, 0.01, 0.27)
text = "1 / 3"
font_size = 36
[node name="Buttons" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.19, 0.01, 0.27)
[node name="NextPageButton" parent="Buttons" instance=ExtResource("4_tvimg")]
[node name="Decal" type="Decal" parent="Buttons/NextPageButton"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0)
size = Vector3(0.04, 0.04, 0.04)
texture_albedo = ExtResource("5_0uvv4")
[node name="Clickable" type="Node" parent="Buttons/NextPageButton"]
script = ExtResource("6_pf8jy")
[node name="PreviousPageButton" parent="Buttons" instance=ExtResource("4_tvimg")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.08, 0, 0)
[node name="Decal" type="Decal" parent="Buttons/PreviousPageButton"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0.02, 0)
size = Vector3(0.04, 0.04, 0.04)
texture_albedo = ExtResource("5_0uvv4")
[node name="Clickable" type="Node" parent="Buttons/PreviousPageButton"]
script = ExtResource("6_pf8jy")

View File

@ -1,157 +1,76 @@
extends Node3D extends Node3D
const Device = preload("res://content/ui/device/device.tscn") @onready var nav_view = $Navigation/View
const Entity = preload("res://content/ui/entity/entity.tscn") @onready var nav_edit: Button3D = $Navigation/Edit
const Switch = preload("res://content/entities/switch/switch.tscn") @onready var menu_edit: Node3D = $Content/EditMenu
const Light = preload("res://content/entities/light/light.tscn") @onready var nav_room = $Navigation/Room
const Sensor = preload("res://content/entities/sensor/sensor.tscn") @onready var nav_automate = $Navigation/Automate
@onready var nav_settings = $Navigation/Settings
@onready var devices_node: GridContainer3D = $Devices enum Menu {
@onready var next_page_button = $NextPageButton VIEW,
@onready var previous_page_button = $PreviousPageButton EDIT,
@onready var page_number_label = $PageNumberLabel ROOM,
var devices AUTOMATE,
var page = 0 SETTINGS
var last_device_page = 0 }
var page_size = 20
var pages = 0 var selected_menu := Menu.EDIT
var selected_device = null
# Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
devices = await HomeAdapters.adapter.get_devices() select_menu(selected_menu)
next_page_button.get_node("Clickable").on_click.connect(func(_event): func _on_click(event):
print("next page") if event.target == nav_view:
next_page() select_menu(Menu.VIEW)
) elif event.target == nav_edit:
select_menu(Menu.EDIT)
elif event.target == nav_room:
select_menu(Menu.ROOM)
elif event.target == nav_automate:
select_menu(Menu.AUTOMATE)
elif event.target == nav_settings:
select_menu(Menu.SETTINGS)
previous_page_button.get_node("Clickable").on_click.connect(func(_event): func select_menu(menu: Menu):
previous_page() selected_menu = menu
) for child in $Content.get_children():
if child.is_visible():
child.hide()
render() var menu_node = enum_to_menu(menu)
var nav_node = enum_to_nav(menu)
func update_pages(): if menu_node != null:
if selected_device == null: menu_node.show()
pages = ceil(float(devices.size()) / page_size)
else:
for device in devices:
if device.keys()[0] == selected_device:
pages = ceil(float(device.values()[0]["entities"].size()) / page_size)
func get_page(): for child in $Navigation.get_children():
if selected_device == null: if child.active && child != nav_node:
return devices.slice(page * page_size, page * page_size + page_size) child.active = false
else: child.disabled = false
for device in devices:
if device.keys()[0] == selected_device:
return device.values()[0]["entities"].slice(page * page_size, page * page_size + page_size)
func next_page(): func enum_to_nav(menu: Menu):
if page >= pages - 1: match menu:
return Menu.VIEW:
page += 1 return nav_view
render() Menu.EDIT:
return nav_edit
Menu.ROOM:
return nav_room
Menu.AUTOMATE:
return nav_automate
Menu.SETTINGS:
return nav_settings
func previous_page(): func enum_to_menu(menu: Menu):
if page <= 0: match menu:
return Menu.VIEW:
return null
page -= 1 Menu.EDIT:
render() return menu_edit
Menu.ROOM:
func render(): return null
update_pages() Menu.AUTOMATE:
page_number_label.set_text(str(page + 1) + " / " + str(pages)) return null
Menu.SETTINGS:
previous_page_button.visible = page > 0 return null
next_page_button.visible = page < pages - 1
clear_menu()
if selected_device == null:
render_devices()
else:
render_entities()
func render_devices():
var page_devices = get_page()
for device in page_devices:
var info = device.values()[0]
var device_instance = Device.instantiate()
device_instance.id = device.keys()[0]
device_instance.get_node("Clickable").on_click.connect(func(_event):
_on_device_click(device_instance.id)
)
devices_node.add_child(device_instance)
device_instance.set_device_name(info["name"])
devices_node._update_container()
func render_entities():
var entities = get_page()
var back_button = Entity.instantiate()
back_button.get_node("Clickable").on_click.connect(func(_event):
_on_entity_click("#back")
)
devices_node.add_child(back_button)
back_button.set_entity_name("#back")
for entity in entities:
var entity_instance = Entity.instantiate()
entity_instance.get_node("Clickable").on_click.connect(func(_event):
_on_entity_click(entity)
)
devices_node.add_child(entity_instance)
entity_instance.set_entity_name(entity)
devices_node._update_container()
func _on_device_click(device_id):
selected_device = device_id
last_device_page = page
page = 0
render()
func _on_entity_click(entity_name):
if entity_name == "#back":
selected_device = null
page = last_device_page
render()
return
var type = entity_name.split(".")[0]
print(type)
if type == "switch":
var switch = Switch.instantiate()
switch.entity_id = entity_name
switch.set_position(global_position)
get_node("/root").add_child(switch)
if type == "light":
var light = Light.instantiate()
light.entity_id = entity_name
light.set_position(global_position)
get_node("/root").add_child(light)
if type == "sensor":
var sensor = Sensor.instantiate()
sensor.entity_id = entity_name
sensor.set_position(global_position)
get_node("/root").add_child(sensor)
func clear_menu():
for child in devices_node.get_children():
devices_node.remove_child(child)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

View File

@ -1,52 +1,81 @@
[gd_scene load_steps=8 format=3 uid="uid://c3kdssrmv84kv"] [gd_scene load_steps=11 format=3 uid="uid://c3kdssrmv84kv"]
[ext_resource type="Script" path="res://content/ui/menu/menu.gd" id="1_ng4u3"] [ext_resource type="Script" path="res://content/ui/menu/menu.gd" id="1_ng4u3"]
[ext_resource type="Material" uid="uid://bertj8bp8b5l1" path="res://assets/materials/interface.tres" id="2_nsukb"] [ext_resource type="PackedScene" uid="uid://crrb0l3ekuotj" path="res://content/ui/menu/edit/edit_menu.tscn" id="4_r2raj"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_35a5r"] [ext_resource type="Texture2D" uid="uid://cattgsppxnbq4" path="res://assets/icons/visibility_white_24dp.svg" id="5_8o1rb"]
[ext_resource type="Texture2D" uid="uid://tr8yrx470k03" path="res://assets/materials/arrow_right.png" id="4_7frvc"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="5_w4i01"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="4_f385t"] [ext_resource type="Texture2D" uid="uid://csq5a4gk6ba5b" path="res://assets/icons/widgets_white_24dp.svg" id="6_344ot"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/button/button.tscn" id="5_w4i01"] [ext_resource type="ArrayMesh" uid="uid://cejvc23wfwjqj" path="res://assets/immersive_home_panels/immersive_home_panels.obj" id="7_f4u4o"]
[ext_resource type="Texture2D" uid="uid://jodf3dm654j3" path="res://assets/icons/view_in_ar_white_24dp.svg" id="7_wvovx"]
[ext_resource type="Texture2D" uid="uid://dch6rwihrl3i2" path="res://assets/icons/schema_white_24dp.svg" id="8_3d082"]
[ext_resource type="Texture2D" uid="uid://dyh0ax51xqp8n" path="res://assets/icons/settings_white_24dp.svg" id="9_mel13"]
[sub_resource type="PlaneMesh" id="PlaneMesh_6t3dn"] [sub_resource type="BoxMesh" id="BoxMesh_08du6"]
material = ExtResource("2_nsukb") size = Vector3(0.3, 0.01, 0.3)
size = Vector2(0.3, 0.3)
[node name="Menu" type="Node3D"] [node name="Menu" type="Node3D"]
script = ExtResource("1_ng4u3") script = ExtResource("1_ng4u3")
[node name="Background" type="MeshInstance3D" parent="."] [node name="Background" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15, 0, 0.15) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15, 0, 0.15)
mesh = SubResource("PlaneMesh_6t3dn") mesh = SubResource("BoxMesh_08du6")
[node name="Devices" type="Node3D" parent="."] [node name="ImmersiveHomePanels" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.03, 0, 0.03) transform = Transform3D(-4.37114e-10, 0, 0.01, 0, 0.01, 0, -0.01, 0, -4.37114e-10, 0.32, 0, -0.0500001)
script = ExtResource("3_35a5r") mesh = ExtResource("7_f4u4o")
depth_gap = 0.06
size = Vector3(0.24, 0.1, 0.1)
[node name="NextPageButton" parent="." instance=ExtResource("5_w4i01")] [node name="Navigation" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.19, 0.01, 0.27)
[node name="Decal" type="Decal" parent="NextPageButton"] [node name="View" parent="Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.03)
size = Vector3(0.04, 0.04, 0.04) toggleable = true
texture_albedo = ExtResource("4_7frvc")
[node name="Clickable" type="Node" parent="NextPageButton"] [node name="Sprite3D" type="Sprite3D" parent="Navigation/View"]
script = ExtResource("4_f385t") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012, 0)
pixel_size = 0.0002
axis = 1
texture = ExtResource("5_8o1rb")
[node name="PreviousPageButton" parent="." instance=ExtResource("5_w4i01")] [node name="Edit" parent="Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.11, 0.01, 0.27) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.09)
toggleable = true
[node name="Decal" type="Decal" parent="PreviousPageButton"] [node name="Sprite3D" type="Sprite3D" parent="Navigation/Edit"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0.02, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012, 0)
size = Vector3(0.04, 0.04, 0.04) pixel_size = 0.0002
texture_albedo = ExtResource("4_7frvc") axis = 1
texture = ExtResource("6_344ot")
[node name="Clickable" type="Node" parent="PreviousPageButton"] [node name="Room" parent="Navigation" instance=ExtResource("5_w4i01")]
script = ExtResource("4_f385t") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.15)
toggleable = true
[node name="PageNumberLabel" type="Label3D" parent="."] [node name="Sprite3D" type="Sprite3D" parent="Navigation/Room"]
transform = Transform3D(0.1, 0, 0, 0, -4.37114e-09, 0.1, 0, -0.1, -4.37114e-09, 0.26, 0.01, 0.27) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012, 0)
text = "1 / 3" pixel_size = 0.0002
font_size = 36 axis = 1
texture = ExtResource("7_wvovx")
[node name="Automate" parent="Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.21)
toggleable = true
[node name="Sprite3D" type="Sprite3D" parent="Navigation/Automate"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012, 0)
pixel_size = 0.0002
axis = 1
texture = ExtResource("8_3d082")
[node name="Settings" parent="Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.27)
toggleable = true
[node name="Sprite3D" type="Sprite3D" parent="Navigation/Settings"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.012, 0)
pixel_size = 0.0002
axis = 1
texture = ExtResource("9_mel13")
[node name="Content" type="Node3D" parent="."]
[node name="EditMenu" parent="Content" instance=ExtResource("4_r2raj")]

View File

@ -34,6 +34,7 @@ func _init(url := self.url, token := self.token):
func connect_ws(): func connect_ws():
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)
# https://github.com/godotengine/godot/issues/84423 # https://github.com/godotengine/godot/issues/84423
# Otherwise the WebSocketPeer will crash when receiving large packets # Otherwise the WebSocketPeer will crash when receiving large packets
@ -126,6 +127,9 @@ func handle_disconnect():
set_process(false) set_process(false)
on_disconnect.emit() on_disconnect.emit()
# Reconnect
connect_ws()
func send_subscribe_packet(packet: Dictionary, callback: Callable): func send_subscribe_packet(packet: Dictionary, callback: Callable):
packet.id = id packet.id = id
id += 1 id += 1