Merge pull request #83 from Nitwel/room-setup

Add support for multiple rooms and advanced room configuration
This commit is contained in:
Nitwel 2024-01-25 12:40:42 +01:00 committed by GitHub
commit c5cb73867f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
68 changed files with 1500 additions and 442 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
# Godot 4+ specific ignores # Godot 4+ specific ignores
.godot/ .godot/
android/build/ android/build/
builds/
# Godot-specific ignores # Godot-specific ignores
.import/ .import/

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5b6a62d5ec5e2c9414b983a90041f1d674e092f71a9b5563277d2b6ad552a8d2
size 6274408

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:70a9f2c799d3d6703bd95abaacdd82c0d1b7a66fc39098aac64c330b0be0db06
size 5855024

View File

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

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:27f82d0c296c1ae8d71754353ee3f9c32955fe7a56ffbd54ca4f171a40827387
size 5612432

View File

@ -0,0 +1,21 @@
[configuration]
entry_symbol = "example_library_init"
compatibility_minimum = 4.1
[libraries]
macos.debug = "res://addons/godot-cdt/libcdt.macos.template_debug.framework"
macos.release = "res://addons/godot-cdt/libcdt.macos.template_release.framework"
windows.debug.x86_32 = "res://addons/godot-cdt/libcdt.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res://addons/godot-cdt/libcdt.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://addons/godot-cdt/libcdt.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://addons/godot-cdt/libcdt.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res://addons/godot-cdt/libcdt.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://addons/godot-cdt/libcdt.linux.template_release.x86_64.so"
linux.debug.arm64 = "res://addons/godot-cdt/libcdt.linux.template_debug.arm64.so"
linux.release.arm64 = "res://addons/godot-cdt/libcdt.linux.template_release.arm64.so"
linux.debug.rv64 = "res://addons/godot-cdt/libcdt.linux.template_debug.rv64.so"
linux.release.rv64 = "res://addons/godot-cdt/libcdt.linux.template_release.rv64.so"
android.debug.arm64 = "res://addons/godot-cdt/libcdt.android.template_debug.arm64.so"
android.release.arm64 = "res://addons/godot-cdt/libcdt.android.template_release.arm64.so"

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:95bda34ae6ebb2010c5a5e1bd0ccd994df43e5e5f956e214da3c6adae4521add
size 974176

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:418c2ca8e73932710184b3bc4de4b40a32fc7ef0369354f8a08fbacd01155f50
size 871936

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:418c2ca8e73932710184b3bc4de4b40a32fc7ef0369354f8a08fbacd01155f50
size 871936

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e54002ccb9b04b9b4fb4642cc3b5fd6512f910e65ecb52e41c117a2345d1d22b oid sha256:b117dc5a7537a60ff341010636802131c9aa3b80982130e63d5d94902c002d07
size 17810864 size 13505995

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:68e2b9d5e723a2009f341e45e2968893dd2a1dd5077fe1d9ba970f01d0d75e02 oid sha256:9738010a57d2157a53e4f537afbcfb50dd28e9de40bae510621d0ea8c94c5844
size 56989 size 51682

View File

@ -2,14 +2,34 @@
extends Function extends Function
class_name Movable class_name Movable
signal on_move(position: Vector3, rotation: Vector3)
@export var restricted: bool = false
@export var restrict_movement: Callable
@export var lock_rotation: bool = false
var hit_node := Node3D.new() var hit_node := Node3D.new()
func _on_grab_down(event: EventPointer): func _on_grab_down(event: EventPointer):
if restricted && event.target != get_parent():
return
event.initiator.node.add_child(hit_node) event.initiator.node.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: EventPointer): func _on_grab_move(_event: EventPointer):
get_parent().global_transform = hit_node.global_transform if hit_node.get_parent() == null:
return
if restrict_movement:
get_parent().global_position = restrict_movement.call(hit_node.global_position)
else:
get_parent().global_position = hit_node.global_position
if !lock_rotation:
get_parent().global_basis = hit_node.global_basis
on_move.emit(get_parent().global_position, get_parent().global_rotation)
else:
on_move.emit(get_parent().global_position, Vector3(0, 0, 0))
func _on_grab_up(event: EventPointer): func _on_grab_up(event: EventPointer):
event.initiator.node.remove_child(hit_node) event.initiator.node.remove_child(hit_node)

View File

@ -16,9 +16,8 @@ func _ready():
if OS.get_name() == "Android": if OS.get_name() == "Android":
# OS.request_permissions() # OS.request_permissions()
environment.environment.sky.set_material(sky_passthrough) environment.environment.sky.set_material(sky_passthrough)
house.visible = false
else: else:
house.visible = true RenderingServer.set_debug_generate_wireframes(true)
controller_left.button_pressed.connect(func(name): controller_left.button_pressed.connect(func(name):
_emit_action(name, true, false) _emit_action(name, true, false)
@ -41,7 +40,9 @@ func _ready():
EventSystem.on_action_down.connect(func(action): EventSystem.on_action_down.connect(func(action):
if action.name == "menu_button": if action.name == "menu_button":
_toggle_menu() toggle_menu()
elif action.name == "by_button":
House.body.mini_view = !House.body.mini_view
) )
EventSystem.on_focus_in.connect(func(event): EventSystem.on_focus_in.connect(func(event):
@ -49,8 +50,7 @@ func _ready():
return return
add_child(keyboard) add_child(keyboard)
if event.previous_target == null: keyboard.global_transform = menu.get_node("AnimationContainer/KeyboardPlace").global_transform
keyboard.global_transform = menu.get_node("AnimationContainer/KeyboardPlace").global_transform
) )
EventSystem.on_focus_out.connect(func(event): EventSystem.on_focus_out.connect(func(event):
@ -60,7 +60,7 @@ func _ready():
remove_child(keyboard) remove_child(keyboard)
) )
func _toggle_menu(): func toggle_menu():
if menu.show_menu == false: if menu.show_menu == false:
add_child(menu) add_child(menu)
menu.global_transform = _get_menu_transform() menu.global_transform = _get_menu_transform()
@ -98,9 +98,13 @@ func _process(delta):
controller_left.position += movement controller_left.position += movement
controller_right.position += movement controller_right.position += movement
func _input(evnet): func _input(event):
if Input.is_key_pressed(KEY_M): if event is InputEventKey and Input.is_key_pressed(KEY_F10):
_toggle_menu() var vp = get_viewport()
vp.debug_draw = (vp.debug_draw + 1) % 5
if event is InputEventKey and Input.is_key_pressed(KEY_M):
toggle_menu()
func _get_menu_transform(): func _get_menu_transform():
var transform = camera.get_global_transform() var transform = camera.get_global_transform()

View File

@ -8,8 +8,8 @@
[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://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="8_du83w"] [ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="8_du83w"]
[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/system/keyboard/keyboard.tscn" id="9_e5n3p"] [ext_resource type="PackedScene" uid="uid://lrehk38exd5n" path="res://content/system/keyboard/keyboard.tscn" id="9_e5n3p"]
[ext_resource type="PackedScene" uid="uid://cbemihbxkd4ll" path="res://content/system/house/house.tscn" id="9_np6mw"]
[sub_resource type="Sky" id="Sky_vhymk"] [sub_resource type="Sky" id="Sky_vhymk"]
sky_material = ExtResource("5_wgwf8") sky_material = ExtResource("5_wgwf8")
@ -78,10 +78,8 @@ transform = Transform3D(0.999998, -0.000514899, -6.55874e-05, 1.96975e-05, 0.163
[node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")] [node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")]
transform = Transform3D(0.499999, -0.000139169, -6.50204e-05, 5.24307e-05, 0.353553, -0.353553, 0.000144383, 0.353553, 0.353553, -0.0199266, 0.550784, -0.47368) transform = Transform3D(0.499999, -0.000139169, -6.50204e-05, 5.24307e-05, 0.353553, -0.353553, 0.000144383, 0.353553, 0.353553, -0.0199266, 0.550784, -0.47368)
[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="Rooms" type="Node3D" parent="."] [node name="Rooms" type="Node3D" parent="."]
[node name="House" parent="." instance=ExtResource("9_np6mw")]
[editable path="XROrigin3D/XRControllerLeft"] [editable path="XROrigin3D/XRControllerLeft"]

View File

@ -0,0 +1,15 @@
extends Node3D
@onready var menu_button = $Menu
@onready var mini_button = $Mini
@onready var clock = $Clock
@onready var main = $"/root/Main"
func _ready():
menu_button.on_button_down.connect(func():
main.toggle_menu()
)
mini_button.on_button_down.connect(func():
House.body.mini_view = !House.body.mini_view
)

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=3 format=3 uid="uid://bexxngoxcegul"]
[ext_resource type="Script" path="res://content/system/armband/armband.gd" id="1_4tskg"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_egcvm"]
[node name="Armband" type="Node3D"]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0)
script = ExtResource("1_4tskg")
[node name="Menu" parent="." instance=ExtResource("1_egcvm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.04, 0, 0.04)
label = "menu"
icon = true
[node name="Mini" parent="." instance=ExtResource("1_egcvm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.02, 0, 0.04)
label = "view_comfy"
icon = true
[node name="Clock" type="Label3D" parent="."]
transform = Transform3D(1, 4.37114e-08, 4.37114e-08, -4.37114e-08, -4.37114e-08, 1, 4.37114e-08, -1, -4.37114e-08, 0, 0.02, -0.02)
pixel_size = 0.001
text = "10:00"

View File

@ -0,0 +1,46 @@
extends Node3D
@onready var corner1 = $Corner1
@onready var corner2 = $Corner1/Corner2
@onready var edge = $Edge
@onready var marker = $Edge/Marker3D
@export var disabled: bool:
set(value):
disabled = value
if !is_node_ready(): await ready
corner1.get_node("CollisionShape3D").disabled = value
corner2.get_node("CollisionShape3D").disabled = value
edge.get_node("CollisionShape3D").disabled = value
corner1.visible = !value
corner2.visible = !value
edge.visible = !value
func _ready():
update_initial_positions()
corner1.get_node("Movable").on_move.connect(func(position, rotation):
edge.align_to_corners(corner1.global_position, corner2.global_position)
)
corner2.get_node("Movable").on_move.connect(func(position, rotation):
edge.align_to_corners(corner1.global_position, corner2.global_position)
)
corner2.get_node("Movable").restrict_movement = func(new_position):
new_position.y = corner1.global_position.y
var delta_new_pos_corner1 = (new_position - corner1.position).normalized()
return corner1.position + delta_new_pos_corner1
func update_initial_positions():
edge.align_to_corners(corner1.global_position, corner2.global_position)
marker.global_transform = House.body.transform
func get_new_transform(old_transform: Transform3D):
marker.scale = Vector3(1, 1, 1)
return marker.global_transform

View File

@ -0,0 +1,41 @@
[gd_scene load_steps=7 format=3 uid="uid://jls16btb8nko"]
[ext_resource type="Script" path="res://content/system/house/align_reference.gd" id="1_8fatp"]
[ext_resource type="PackedScene" uid="uid://brf6mm2gxj7y2" path="res://content/system/house/room/wall_corner.tscn" id="2_ppkie"]
[ext_resource type="PackedScene" uid="uid://dlj5chj7ndgua" path="res://content/system/house/room/wall_edge.tscn" id="3_6o3xn"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="3_7ktdq"]
[ext_resource type="Material" uid="uid://dxyuncqxagt28" path="res://content/system/house/room/walls_mini.tres" id="4_jkpj4"]
[sub_resource type="CylinderMesh" id="CylinderMesh_k2m3v"]
top_radius = 0.001
bottom_radius = 0.05
height = 0.1
[node name="AlignReference" type="Node3D"]
script = ExtResource("1_8fatp")
[node name="Corner1" parent="." instance=ExtResource("2_ppkie")]
[node name="Movable" type="Node" parent="Corner1"]
script = ExtResource("3_7ktdq")
restricted = true
lock_rotation = true
[node name="Corner2" parent="Corner1" instance=ExtResource("2_ppkie")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
[node name="MeshInstance3D" parent="Corner1/Corner2" index="1"]
transform = Transform3D(-4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0, 1, 0, 0, 0)
material_override = ExtResource("4_jkpj4")
mesh = SubResource("CylinderMesh_k2m3v")
[node name="Movable" type="Node" parent="Corner1/Corner2"]
script = ExtResource("3_7ktdq")
lock_rotation = true
[node name="Edge" parent="." instance=ExtResource("3_6o3xn")]
transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 0.5, 0, 0)
[node name="Marker3D" type="Marker3D" parent="Edge"]
[editable path="Corner1/Corner2"]

View File

@ -0,0 +1,168 @@
extends Node3D
const Room = preload("./room/room.tscn")
const RoomType = preload("./room/room.gd")
@onready var levels = $Levels
@onready var collision_shape = $Levels/CollisionShape3D
@onready var align_reference = $AlignReference
var fixing_reference: bool = false
var editing_room: RoomType = null
var mini_view: bool = false:
set(value):
mini_view = value
update_mini_view()
var target_size: float = 1.0
func _physics_process(delta):
levels.scale.x = lerp(levels.scale.x, target_size, 10.0 * delta)
levels.scale.y = lerp(levels.scale.y, target_size, 10.0 * delta)
levels.scale.z = lerp(levels.scale.z, target_size, 10.0 * delta)
func create_room(room_name: String, level: int) -> RoomType:
if editing_room != null:
editing_room.editable = false
editing_room = null
var room = Room.instantiate()
room.name = room_name
room.editable = true
editing_room = room
get_level(level).add_child(room)
return room
func edit_room(room_name):
var room = find_room(room_name)
if room == editing_room:
return
if editing_room != null:
editing_room.editable = false
editing_room = null
if room != null:
room.editable = true
editing_room = room
func is_valid_room(room_name):
var room = find_room(room_name)
if room == null:
return
return room.wall_corners.get_child_count() >= 3
func delete_room(room_name):
var room = find_room(room_name)
if room == null:
return
if editing_room == room:
editing_room = null
room.get_parent().remove_child(room)
room.queue_free()
func is_editiong(room_name):
return editing_room != null && editing_room.name == room_name
func find_room(room_name):
for level in levels.get_children():
for room in level.get_children():
if room.name == room_name:
return room
return null
func find_room_at(entity_position: Vector3):
for level in levels.get_children():
for room in level.get_children():
if room.has_point(entity_position):
return room
return null
func get_level(level: int):
return levels.get_child(level)
func get_level_aabb(level: int):
var rooms = get_level(level).get_children()
if rooms.size() == 0:
return AABB()
var min_pos = rooms[0].get_aabb().position
var max_pos = min_pos + rooms[0].get_aabb().size
for room in rooms:
var room_min = room.get_aabb().position
var room_max = room_min + room.get_aabb().size
min_pos.x = min(min_pos.x, room_min.x)
min_pos.y = min(min_pos.y, room_min.y)
min_pos.z = min(min_pos.z, room_min.z)
max_pos.x = max(max_pos.x, room_max.x)
max_pos.y = max(max_pos.y, room_max.y)
max_pos.z = max(max_pos.z, room_max.z)
return AABB(min_pos, max_pos - min_pos)
func get_rooms(level: int):
return get_level(level).get_children()
func create_entity(entity_id: String, entity_position: Vector3):
var room = find_room_at(entity_position)
if room == null:
return
var entity = EntityFactory.create_entity(entity_id)
if entity == null:
return
room.add_child(entity)
entity.global_position = entity_position
func update_mini_view():
collision_shape.disabled = !mini_view
if mini_view:
var aabb = get_level_aabb(0)
aabb.position.y = -0.03
aabb.size.y = 0.06
var center = aabb.position + aabb.size / 2.0
collision_shape.global_position = center
collision_shape.shape.size = aabb.size
else:
levels.position = Vector3(0, 0, 0)
target_size = 0.1 if mini_view else 1.0
for room in get_rooms(0):
room.state_machine.change_to("Mini" if mini_view else "View")
func edit_reference():
fixing_reference = false
align_reference.disabled = false
func fix_reference():
fixing_reference = true
align_reference.disabled = false
align_reference.update_initial_positions()
func save_reference():
if fixing_reference:
var align_transform = align_reference.global_transform
transform = align_reference.get_new_transform(transform)
align_reference.global_transform = align_transform
align_reference.disabled = true
align_reference.update_initial_positions()

View File

@ -0,0 +1,27 @@
[gd_scene load_steps=5 format=3 uid="uid://cbemihbxkd4ll"]
[ext_resource type="Script" path="res://content/system/house/house.gd" id="1_p8amj"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="2_w1auk"]
[ext_resource type="PackedScene" uid="uid://jls16btb8nko" path="res://content/system/house/align_reference.tscn" id="3_e1tcn"]
[sub_resource type="BoxShape3D" id="BoxShape3D_x81up"]
[node name="House" type="Node3D"]
script = ExtResource("1_p8amj")
[node name="Levels" type="StaticBody3D" parent="."]
[node name="Level0" type="Node3D" parent="Levels"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Levels"]
shape = SubResource("BoxShape3D_x81up")
disabled = true
[node name="Movable" type="Node" parent="Levels"]
script = ExtResource("2_w1auk")
restricted = true
lock_rotation = true
[node name="AlignReference" parent="." instance=ExtResource("3_e1tcn")]
visible = false
disabled = true

View File

@ -0,0 +1,53 @@
extends Node3D
@onready var wall_corners = $Ceiling/WallCorners
@onready var wall_edges = $Ceiling/WallEdges
@onready var wall_mesh: MeshInstance3D = $WallMesh
@onready var ceiling_mesh: MeshInstance3D = $CeilingMesh
@onready var wall_collisions = $WallCollisions
@onready var room_floor = $Floor
@onready var room_ceiling = $Ceiling
@onready var state_machine = $StateMachine
var editable: bool = false:
set(value):
if !is_node_ready(): await ready
if value:
state_machine.change_to("Edit")
else:
state_machine.change_to("View")
func get_corner(index: int) -> MeshInstance3D:
return wall_corners.get_child(index % wall_corners.get_child_count())
func get_edge(index: int) -> MeshInstance3D:
return wall_edges.get_child(index % wall_edges.get_child_count())
func has_point(point: Vector3) -> bool:
return get_aabb().has_point(point)
func remove_corner(index: int):
get_corner(index).queue_free()
get_edge(index).queue_free()
func get_aabb():
if wall_corners.get_child_count() == 0:
return AABB()
var min_pos = wall_corners.get_child(0).position
var max_pos = wall_corners.get_child(0).position
for corner in wall_corners.get_children():
min_pos.x = min(min_pos.x, corner.position.x)
min_pos.z = min(min_pos.z, corner.position.z)
max_pos.x = max(max_pos.x, corner.position.x)
max_pos.z = max(max_pos.z, corner.position.z)
min_pos.y = room_floor.position.y
max_pos.y = room_ceiling.position.y
return AABB(to_global(min_pos), to_global(max_pos) - to_global(min_pos))

View File

@ -0,0 +1,67 @@
[gd_scene load_steps=11 format=3 uid="uid://bswgmclohuqui"]
[ext_resource type="Script" path="res://content/system/house/room/room.gd" id="1_fccq0"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="1_ugebq"]
[ext_resource type="Material" uid="uid://bbx6fv7jq50tr" path="res://content/system/house/room/walls.tres" id="3_al1ev"]
[ext_resource type="Script" path="res://lib/utils/state_machine/state_machine.gd" id="4_nbbo6"]
[ext_resource type="Script" path="res://content/system/house/room/states/mini.gd" id="6_g4qca"]
[ext_resource type="Script" path="res://content/system/house/room/states/view.gd" id="6_g066t"]
[ext_resource type="Script" path="res://content/system/house/room/states/edit.gd" id="7_ap14h"]
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_08sv0"]
[sub_resource type="ArrayMesh" id="ArrayMesh_7dibq"]
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_ap613"]
plane = Plane(0, -1, 0, 0)
[node name="Room" type="Node3D"]
script = ExtResource("1_fccq0")
[node name="Floor" type="StaticBody3D" parent="."]
collision_layer = 24
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor"]
shape = SubResource("WorldBoundaryShape3D_08sv0")
[node name="Clickable" type="Node" parent="Floor"]
script = ExtResource("1_ugebq")
[node name="WallMesh" type="MeshInstance3D" parent="."]
material_override = ExtResource("3_al1ev")
mesh = SubResource("ArrayMesh_7dibq")
[node name="CeilingMesh" type="MeshInstance3D" parent="."]
material_override = ExtResource("3_al1ev")
[node name="WallCollisions" type="Node3D" parent="."]
[node name="Ceiling" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
collision_layer = 24
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ceiling"]
shape = SubResource("WorldBoundaryShape3D_ap613")
disabled = true
[node name="Clickable" type="Node" parent="Ceiling"]
script = ExtResource("1_ugebq")
[node name="WallCorners" type="Node3D" parent="Ceiling"]
[node name="WallEdges" type="Node3D" parent="Ceiling"]
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("current_state")]
script = ExtResource("4_nbbo6")
current_state = NodePath("View")
[node name="View" type="Node" parent="StateMachine"]
script = ExtResource("6_g066t")
[node name="Edit" type="Node" parent="StateMachine"]
script = ExtResource("7_ap14h")
[node name="Mini" type="Node" parent="StateMachine"]
script = ExtResource("6_g4qca")

View File

@ -0,0 +1,238 @@
extends RoomState
const wall_corner_scene = preload("../wall_corner.tscn")
const wall_edge_scene = preload("../wall_edge.tscn")
const RoomState = preload("./room_state.gd")
var moving = null
var deleting: bool = false
var floor_corner: StaticBody3D = null
var height_corner: StaticBody3D = null
var height_edge: StaticBody3D = null
func _on_enter():
room.wall_corners.visible = true
room.wall_edges.visible = true
if floor_corner != null:
floor_corner.visible = true
height_corner.visible = true
height_edge.visible = true
room.room_ceiling.get_node("CollisionShape3D").disabled = (floor_corner == null && height_corner == null)
room.room_floor.get_node("CollisionShape3D").disabled = false
var ceiling_shape = WorldBoundaryShape3D.new()
ceiling_shape.plane = Plane(Vector3.DOWN, 0)
room.room_ceiling.get_node("CollisionShape3D").shape = ceiling_shape
room.room_floor.get_node("CollisionShape3D").shape = WorldBoundaryShape3D.new()
room.room_ceiling.get_node("Clickable").on_click.connect(_on_click_ceiling)
room.room_floor.get_node("Clickable").on_click.connect(_on_click_floor)
func _on_leave():
room.wall_corners.visible = false
room.wall_edges.visible = false
if floor_corner != null:
floor_corner.visible = false
height_corner.visible = false
height_edge.visible = false
room.room_ceiling.get_node("CollisionShape3D").disabled = true
room.room_floor.get_node("CollisionShape3D").disabled = true
room.room_ceiling.get_node("Clickable").on_click.disconnect(_on_click_ceiling)
room.room_floor.get_node("Clickable").on_click.disconnect(_on_click_floor)
func _on_click_floor(event):
if floor_corner != null && height_corner != null:
return
add_floor_corner(event.ray.get_collision_point())
add_height_corner(event.ray.get_collision_point())
room.room_ceiling.get_node("CollisionShape3D").disabled = false
func _on_click_ceiling(event):
if floor_corner == null || height_corner == null || event.target != room.room_ceiling:
return
var pos = event.ray.get_collision_point()
pos.y = 0
add_corner(pos)
func add_floor_corner(position: Vector3):
floor_corner = wall_corner_scene.instantiate()
floor_corner.position = position
height_edge = wall_edge_scene.instantiate()
height_edge.align_to_corners(position, position + Vector3.UP * room.room_ceiling.global_position.y)
floor_corner.get_node("Clickable").on_grab_down.connect(func(event):
if !is_active() || moving != null:
return
moving = event.target
)
floor_corner.get_node("Clickable").on_grab_move.connect(func(event):
if moving == null:
return
var moving_index = height_corner.get_index()
var direction = -event.ray.global_transform.basis.z
var new_position = room.room_floor.get_node("CollisionShape3D").shape.plane.intersects_ray(event.ray.global_position, direction)
if new_position == null:
return
moving.position = new_position
height_edge.align_to_corners(new_position, new_position + Vector3.UP * room.room_ceiling.global_position.y)
room.get_corner(moving_index).position.x = new_position.x
room.get_corner(moving_index).position.z = new_position.z
if room.wall_edges.get_child_count() == 0:
return
room.get_edge(moving_index).align_to_corners(new_position, room.get_corner(moving_index + 1).position)
room.get_edge(moving_index - 1).align_to_corners(room.get_corner(moving_index - 1).position, new_position)
)
floor_corner.get_node("Clickable").on_grab_up.connect(func(_event):
moving = null
)
room.add_child(floor_corner)
room.add_child(height_edge)
func add_height_corner(position: Vector3):
height_corner = wall_corner_scene.instantiate()
height_corner.position.x = position.x
height_corner.position.z = position.z
height_corner.get_node("Clickable").on_grab_down.connect(func(event):
if !is_active() || moving != null:
return
moving = event.target
)
height_corner.get_node("Clickable").on_grab_move.connect(func(event):
if moving == null:
return
var direction = -event.ray.global_transform.basis.z
var plane_direction = direction
plane_direction.y = 0
plane_direction = plane_direction.normalized() * -1
var plane = Plane(plane_direction, moving.position)
var new_position = plane.intersects_ray(event.ray.global_position, direction)
if new_position == null:
return
room.room_ceiling.position.y = new_position.y
height_edge.align_to_corners(floor_corner.global_position, height_corner.global_position)
)
height_corner.get_node("Clickable").on_grab_up.connect(func(_event):
moving = null
)
room.wall_corners.add_child(height_corner)
func add_corner(position: Vector3, index: int = -1):
var corner = wall_corner_scene.instantiate()
corner.position.x = position.x
corner.position.z = position.z
corner.get_node("Clickable").on_grab_down.connect(func(event):
if !is_active() || moving != null:
return
moving = event.target
)
corner.get_node("Clickable").on_grab_move.connect(func(event):
if moving == null:
return
var moving_index = moving.get_index()
var direction = -event.ray.global_transform.basis.z
var ceiling_plane = Plane(Vector3.DOWN, room.room_ceiling.global_position)
var new_position = ceiling_plane.intersects_ray(event.ray.global_position, direction)
if new_position == null:
deleting = true
new_position = event.ray.global_position + direction
room.get_corner(moving_index).global_position = new_position
if room.wall_edges.get_child_count() == 0:
return
room.get_edge(moving_index).align_to_corners(room.get_corner(moving_index - 1).position, room.get_corner(moving_index + 1).position)
room.get_edge(moving_index - 1).transform = room.get_edge(moving_index).transform
return
deleting = false
new_position.y = 0
moving.position = new_position
if room.wall_edges.get_child_count() == 0:
return
room.get_edge(moving_index).align_to_corners(new_position, room.get_corner(moving_index + 1).position)
room.get_edge(moving_index - 1).align_to_corners(room.get_corner(moving_index - 1).position, new_position)
)
corner.get_node("Clickable").on_grab_up.connect(func(_event):
if deleting:
var moving_index = moving.get_index()
room.remove_corner(moving_index)
moving = null
deleting = false
)
room.wall_corners.add_child(corner)
room.wall_corners.move_child(corner, index)
var num_corners = room.wall_corners.get_child_count()
if num_corners > 1:
add_edge(position, room.get_corner(index + 1).position, index)
if num_corners > 2:
if num_corners != room.wall_edges.get_child_count():
add_edge(room.get_corner(-2).position, room.get_corner(-1).position, -2)
else:
room.get_edge(index - 1).align_to_corners(room.get_corner(index - 1).position, position)
func add_edge(from_pos: Vector3, to_pos: Vector3, index: int = -1):
var edge: StaticBody3D = wall_edge_scene.instantiate()
edge.align_to_corners(from_pos, to_pos)
edge.get_node("Clickable").on_press_down.connect(func(event):
var point = event.ray.get_collision_point()
point.y = 0
add_corner(point, edge.get_index() + 1)
)
room.wall_edges.add_child(edge)
room.wall_edges.move_child(edge, index)
return edge

View File

@ -0,0 +1,41 @@
extends RoomState
const RoomState = preload("./room_state.gd")
const walls_mini_material = preload("../walls_mini.tres")
const walls_material = preload("../walls.tres")
func _on_enter():
room.wall_mesh.visible = true
room.ceiling_mesh.visible = true
room.wall_mesh.material_override = walls_mini_material
room.room_ceiling.get_node("CollisionShape3D").disabled = true
room.room_floor.get_node("CollisionShape3D").disabled = true
for collision in room.wall_collisions.get_children():
collision.get_child(0).disabled = true
for corner in room.wall_corners.get_children():
corner.get_node("CollisionShape3D").disabled = true
for edge in room.wall_edges.get_children():
edge.get_node("CollisionShape3D").disabled = true
func _on_leave():
room.wall_mesh.visible = false
room.ceiling_mesh.visible = false
room.wall_mesh.material_override = walls_material
room.room_ceiling.get_node("CollisionShape3D").disabled = false
room.room_floor.get_node("CollisionShape3D").disabled = false
for collision in room.wall_collisions.get_children():
collision.get_child(0).disabled = false
for corner in room.wall_corners.get_children():
corner.get_node("CollisionShape3D").disabled = false
for edge in room.wall_edges.get_children():
edge.get_node("CollisionShape3D").disabled = false

View File

@ -0,0 +1,7 @@
extends State
const Room = preload("res://content/system/house/room/room.gd")
var room: Room
func _ready():
room = get_parent().get_parent()

View File

@ -0,0 +1,144 @@
extends RoomState
const RoomState = preload("./room_state.gd")
var room_height = 3
var corner_count = 0
func _on_enter():
corner_count = room.wall_corners.get_child_count()
if corner_count < 3:
return
room_height = room.room_ceiling.position.y
room.wall_mesh.visible = true
room.ceiling_mesh.visible = true
room.wall_mesh.mesh = generate_mesh()
if room.wall_mesh.mesh == null:
return
var ceiling_shape = room.room_ceiling.get_node("CollisionShape3D")
var floor_shape = room.room_floor.get_node("CollisionShape3D")
ceiling_shape.disabled = false
floor_shape.disabled = false
room.ceiling_mesh.mesh = generate_ceiling_mesh()
ceiling_shape.shape = room.ceiling_mesh.mesh.create_trimesh_shape()
floor_shape.shape = room.ceiling_mesh.mesh.create_trimesh_shape()
ceiling_shape.shape.backface_collision = true
var collisions = generate_collision()
for collision in collisions:
var static_body = StaticBody3D.new()
static_body.set_collision_layer_value(4, true)
static_body.set_collision_layer_value(5, true)
static_body.collision_mask = 0
static_body.add_child(collision)
room.wall_collisions.add_child(static_body)
room.wall_mesh.visible = true
func _on_leave():
room.wall_mesh.visible = false
room.ceiling_mesh.visible = false
room.room_ceiling.get_node("CollisionShape3D").disabled = true
room.room_floor.get_node("CollisionShape3D").disabled = true
for collision in room.wall_collisions.get_children():
collision.queue_free()
func generate_mesh():
var st = SurfaceTool.new()
var wall_up = Vector3.UP * room_height
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
for i in range(corner_count):
var corner = room.get_corner(i)
st.add_vertex(corner.position)
st.add_vertex(corner.position + wall_up)
var first_corner = room.get_corner(0)
st.add_vertex(first_corner.position)
st.add_vertex(first_corner.position + wall_up)
st.index()
st.generate_normals()
st.generate_tangents()
var mesh = st.commit()
return mesh
func generate_ceiling_mesh():
var points: PackedVector2Array = PackedVector2Array()
var edges: PackedInt32Array = PackedInt32Array()
var triangles: PackedInt32Array
for i in range(corner_count):
var corner = room.get_corner(i)
points.append(Vector2(corner.position.x, corner.position.z))
edges.append(i)
edges.append((i + 1) % corner_count)
var cdt: ConstrainedTriangulation = ConstrainedTriangulation.new()
cdt.init(true, true, 0.1)
cdt.insert_vertices(points)
cdt.insert_edges(edges)
cdt.erase_outer_triangles()
points = cdt.get_all_vertices()
triangles = cdt.get_all_triangles()
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
for i in range(points.size()):
st.add_vertex(Vector3(points[i].x, 0, points[i].y))
for i in range(triangles.size()):
st.add_index(triangles[i])
st.index()
st.generate_normals()
st.generate_tangents()
var mesh = st.commit()
return mesh
func generate_collision():
var collision_shapes: Array[CollisionShape3D] = []
for i in range(corner_count):
var corner = room.get_corner(i)
var next_corner = room.get_corner(i + 1)
var shape = BoxShape3D.new()
shape.size = Vector3((next_corner.position - corner.position).length(), room_height, 0.04)
var transform = Transform3D()
var back_vector = (corner.position - next_corner.position).cross(Vector3.UP).normalized() * shape.size.z / 2
transform.basis = Basis((next_corner.position - corner.position).normalized(), Vector3.UP, back_vector.normalized())
transform.origin = corner.position + (next_corner.position - corner.position) / 2 + back_vector + Vector3.UP * shape.size.y / 2
var collision_shape = CollisionShape3D.new()
collision_shape.shape = shape
collision_shape.transform = transform
collision_shapes.append(collision_shape)
return collision_shapes

View File

@ -3,7 +3,7 @@
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="1_e5awq"] [ext_resource type="Script" path="res://content/functions/clickable.gd" id="1_e5awq"]
[sub_resource type="SphereShape3D" id="SphereShape3D_86rci"] [sub_resource type="SphereShape3D" id="SphereShape3D_86rci"]
radius = 0.05 radius = 0.1
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i1w3w"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i1w3w"]
transparency = 1 transparency = 1

View File

@ -0,0 +1,16 @@
extends StaticBody3D
func align_to_corners(from_pos: Vector3, to_pos: Vector3):
var diff = to_pos - from_pos
var direction = diff.normalized()
var tangent = Vector3(direction.z, 0, -direction.x).normalized()
if tangent == Vector3.ZERO:
tangent = Vector3(1, 0, 0)
var edge_position = from_pos + diff / 2
var edge_basis = Basis(tangent, diff, tangent.cross(direction))
transform = Transform3D(edge_basis, edge_position)

View File

@ -0,0 +1,26 @@
[gd_scene load_steps=6 format=3 uid="uid://dlj5chj7ndgua"]
[ext_resource type="Script" path="res://content/system/house/room/wall_edge.gd" id="1_0c5rj"]
[ext_resource type="Material" uid="uid://j12e5wwthtaa" path="res://content/system/house/room/edge.tres" id="1_hs3tw"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="2_cfvx2"]
[sub_resource type="CapsuleMesh" id="CapsuleMesh_a2dct"]
material = ExtResource("1_hs3tw")
radius = 0.01
height = 1.0
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_6m53l"]
radius = 0.04
height = 1.0
[node name="StaticBody3D" type="StaticBody3D"]
script = ExtResource("1_0c5rj")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("CapsuleMesh_a2dct")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_6m53l")
[node name="Clickable" type="Node" parent="."]
script = ExtResource("2_cfvx2")

View File

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

View File

@ -90,5 +90,4 @@ func _emit_event(type: String, key: Key):
event.shift_pressed = caps event.shift_pressed = caps
EventSystem.emit(type, event) EventSystem.emit(type, event)
print("Emitting event: " + type + " " + EventKey.key_to_string(key, caps))

View File

@ -1,205 +0,0 @@
extends Node3D
const wall_corner_scene = preload("./wall_corner.tscn")
const wall_edge_scene = preload("./wall_edge.tscn")
@onready var wall_corners = $WallCorners
@onready var wall_edges = $WallEdges
@onready var wall_mesh = $WallMesh
@onready var wall_collisions = $WallCollisions
@onready var ground = $Ground/Clickable
var moving = null
var editable := false:
set(value):
if value == editable:
return
editable = value
if value:
_start_edit_mode()
else:
_end_edit_mode()
var ground_plane = Plane(Vector3.UP, Vector3.ZERO)
func _ready():
ground.on_click.connect(func(event):
if !editable:
return
add_corner(event.ray.get_collision_point())
)
func _start_edit_mode():
wall_corners.visible = true
wall_edges.visible = true
wall_mesh.visible = false
wall_mesh.mesh = null
for old_coll in wall_collisions.get_children():
old_coll.queue_free()
func _end_edit_mode():
wall_corners.visible = false
wall_edges.visible = false
wall_mesh.mesh = generate_mesh()
if wall_mesh.mesh == null:
return
var collisions = generate_collision(wall_mesh.mesh)
for collision in collisions:
var static_body = StaticBody3D.new()
static_body.set_collision_layer_value(4, true)
static_body.set_collision_layer_value(5, true)
static_body.collision_mask = 0
static_body.add_child(collision)
wall_collisions.add_child(static_body)
wall_mesh.visible = true
func generate_mesh():
var corner_count = wall_corners.get_child_count()
if corner_count < 3:
return
var st = SurfaceTool.new()
var wall_up = Vector3.UP * 3
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
for i in range(corner_count):
var corner = get_corner(i)
st.add_vertex(corner.position)
st.add_vertex(corner.position + wall_up)
var first_corner = get_corner(0)
st.add_vertex(first_corner.position)
st.add_vertex(first_corner.position + wall_up)
st.index()
st.generate_normals()
st.generate_tangents()
var mesh = st.commit()
return mesh
func generate_collision(mesh: ArrayMesh):
var corner_count = wall_corners.get_child_count()
if corner_count < 3:
return
var collision_shapes: Array[CollisionShape3D] = []
for i in range(corner_count):
var corner = get_corner(i)
var next_corner = get_corner(i + 1)
var shape = BoxShape3D.new()
shape.size = Vector3((next_corner.position - corner.position).length(), 3, 0.04)
var transform = Transform3D()
var back_vector = (corner.position - next_corner.position).cross(Vector3.UP).normalized() * shape.size.z / 2
transform.basis = Basis((next_corner.position - corner.position).normalized(), Vector3.UP, back_vector.normalized())
transform.origin = corner.position + (next_corner.position - corner.position) / 2 + back_vector + Vector3.UP * shape.size.y / 2
var collision_shape = CollisionShape3D.new()
collision_shape.shape = shape
collision_shape.transform = transform
collision_shapes.append(collision_shape)
return collision_shapes
func add_corner(position: Vector3):
var corner = wall_corner_scene.instantiate()
corner.position = position
corner.get_node("Clickable").on_grab_down.connect(func(event):
if !editable:
return
moving = event.target
)
corner.get_node("Clickable").on_grab_move.connect(func(event):
if moving == null:
return
var direction = -event.ray.global_transform.basis.z
var new_position = ground_plane.intersects_ray(event.ray.global_position, direction)
if new_position == null:
return
moving.position = new_position
var moving_index = moving.get_index()
get_edge(moving_index).transform = corners_to_edge_transform(new_position, get_corner(moving_index + 1).position)
get_edge(moving_index - 1).transform = corners_to_edge_transform(get_corner(moving_index - 1).position, new_position)
)
corner.get_node("Clickable").on_grab_up.connect(func(_event):
moving = null
)
wall_corners.add_child(corner)
var num_corners = wall_corners.get_child_count()
var edge
if num_corners > 1:
edge = add_edge(wall_corners.get_child(num_corners - 2).position, position)
if num_corners > 2:
if num_corners != wall_edges.get_child_count():
add_edge(position, wall_corners.get_child(0).position)
else:
wall_edges.move_child(edge, num_corners - 2)
get_edge(-1).transform = corners_to_edge_transform(position, get_corner(0).position)
func get_corner(index: int) -> MeshInstance3D:
return wall_corners.get_child(index % wall_corners.get_child_count())
func get_edge(index: int) -> MeshInstance3D:
return wall_edges.get_child(index % wall_edges.get_child_count())
func add_edge(from_pos: Vector3, to_pos: Vector3):
var edge: MeshInstance3D = wall_edge_scene.instantiate()
edge.transform = corners_to_edge_transform(from_pos, to_pos)
wall_edges.add_child(edge)
return edge
func corners_to_edge_transform(from_pos: Vector3, to_pos: Vector3) -> Transform3D:
var diff = to_pos - from_pos
var direction = diff.normalized()
var edge_position = from_pos + diff / 2
var edge_basis = Basis(Vector3.UP, diff, direction.cross(Vector3.UP))
var edge_transform = Transform3D(edge_basis, edge_position)
return edge_transform
func _save():
return {
"corners": wall_corners.get_children().map(func(corner): return corner.position),
}
func _load(data):
await ready
for corner in data["corners"]:
add_corner(corner)
_end_edit_mode()

View File

@ -1,42 +0,0 @@
[gd_scene load_steps=7 format=3 uid="uid://bswgmclohuqui"]
[ext_resource type="Script" path="res://content/system/room/room.gd" id="1_fccq0"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="1_ugebq"]
[ext_resource type="Material" uid="uid://bbx6fv7jq50tr" path="res://content/system/room/walls.tres" id="3_al1ev"]
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_08sv0"]
[sub_resource type="ArrayMesh" id="ArrayMesh_7dibq"]
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_ap613"]
[node name="Room" type="Node3D"]
script = ExtResource("1_fccq0")
[node name="Ground" type="StaticBody3D" parent="."]
collision_layer = 24
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
shape = SubResource("WorldBoundaryShape3D_08sv0")
[node name="Clickable" type="Node" parent="Ground"]
script = ExtResource("1_ugebq")
[node name="WallCorners" type="Node3D" parent="."]
[node name="WallEdges" type="Node3D" parent="."]
[node name="WallMesh" type="MeshInstance3D" parent="."]
material_override = ExtResource("3_al1ev")
mesh = SubResource("ArrayMesh_7dibq")
[node name="WallCollisions" type="Node3D" parent="."]
[node name="Celing" type="StaticBody3D" parent="."]
transform = Transform3D(-1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0, 1, 0, 3.07, 0)
collision_layer = 0
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Celing"]
shape = SubResource("WorldBoundaryShape3D_ap613")

View File

@ -1,11 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://dlj5chj7ndgua"]
[ext_resource type="Material" uid="uid://j12e5wwthtaa" path="res://content/ui/menu/room/edge.tres" id="1_b21dw"]
[sub_resource type="CapsuleMesh" id="CapsuleMesh_a2dct"]
material = ExtResource("1_b21dw")
radius = 0.01
height = 1.0
[node name="MeshInstance3D" type="MeshInstance3D"]
mesh = SubResource("CapsuleMesh_a2dct")

View File

@ -3,8 +3,6 @@
extends Node3D extends Node3D
class_name Button3D class_name Button3D
const Proxy = preload("res://lib/utils/proxy.gd")
signal on_button_down() signal on_button_down()
signal on_button_up() signal on_button_up()
@ -38,7 +36,7 @@ const IconFont = preload("res://assets/icons/icons.tres")
if value: if value:
label_node.font = IconFont label_node.font = IconFont
label_node.font_size = 48 label_node.font_size = 36
label_node.width = 1000 label_node.width = 1000
label_node.autowrap_mode = TextServer.AUTOWRAP_OFF label_node.autowrap_mode = TextServer.AUTOWRAP_OFF
else: else:
@ -50,13 +48,24 @@ const IconFont = preload("res://assets/icons/icons.tres")
@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 external_value: Proxy = null var external_value: Proxy = null:
set(value):
if !is_node_ready(): await ready
external_value = value
if value != null:
value.on_set.connect(func(_value):
update_animation()
)
var active: bool = false: var active: bool = false:
get: get:
if external_value != null: if external_value != null:
return external_value.value return external_value.value
return active return active
set(value): set(value):
if !is_node_ready(): await ready
if external_value != null: if external_value != null:
external_value.value = value external_value.value = value
else: else:

View File

@ -116,7 +116,6 @@ func update_caret_position(event):
func _on_focus_out(_event): func _on_focus_out(_event):
print("focus out")
animation.stop() animation.stop()
caret.hide() caret.hide()

View File

@ -13,7 +13,6 @@ extends Node3D
set(value): set(value):
type = value type = value
if !is_node_ready(): await ready if !is_node_ready(): await ready
print(value, " ", _type_to_string(value))
icon_label.text = _type_to_string(value) icon_label.text = _type_to_string(value)
@export var text: String = "": @export var text: String = "":
set(value): set(value):

View File

@ -0,0 +1,28 @@
extends Node3D
class_name Tabs3D
signal on_select(selected: int)
var selected: Node3D
@export var initial_selected: Node3D
var proxy_group = ProxyGroup.new()
func _ready():
if initial_selected != null:
selected = initial_selected
on_select.emit(selected.get_index())
for option in get_children():
if option is Button3D == false:
continue
var proxy = proxy_group.proxy(func():
return selected == option
, func(value: bool):
if value == true:
selected = option
on_select.emit(selected.get_index())
)
option.external_value = proxy
option.toggleable = true

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://doavdm6fskmrt"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs.gd" id="1_xt6wm"]
[node name="Tabs" type="Node3D"]
script = ExtResource("1_xt6wm")

View File

@ -0,0 +1,22 @@
extends Node3D
class_name TabsContent3D
@export var tabs: Tabs3D
var children: Array = []
func _ready():
children = get_children()
for child in children:
child.visible = true
if tabs.selected != null && tabs.selected.get_index() == child.get_index():
continue
remove_child(child)
tabs.on_select.connect(func(index):
for child in get_children():
remove_child(child)
add_child(children[index])
)

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://wewhef3qmulp"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs_content.gd" id="1_ljgkj"]
[node name="TabsContent" type="Node3D"]
script = ExtResource("1_ljgkj")

View File

@ -1,7 +1,6 @@
extends Node3D extends Node3D
const ButtonScene = preload("res://content/ui/components/button/button.tscn") const ButtonScene = preload("res://content/ui/components/button/button.tscn")
const EntityCreator = preload("./entity_creator.gd")
@onready var devices_node: GridContainer3D = $Devices @onready var devices_node: GridContainer3D = $Devices
@onready var next_page_button = $Buttons/NextPageButton @onready var next_page_button = $Buttons/NextPageButton
@ -145,22 +144,11 @@ func _on_entity_click(entity_name):
render() render()
return return
var type = entity_name.split(".")[0]
AudioPlayer.play_effect("spawn") AudioPlayer.play_effect("spawn")
var entity = EntityCreator.create_entity(type, entity_name) House.body.create_entity(entity_name, global_position)
if entity == null:
return
entity.set_position(global_position)
get_node("/root/Main").add_child(entity)
func clear_menu(): func clear_menu():
for child in devices_node.get_children(): for child in devices_node.get_children():
devices_node.remove_child(child) devices_node.remove_child(child)
child.queue_free() child.queue_free()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

View File

@ -3,15 +3,6 @@ extends Node3D
const Proxy = preload("res://lib/utils/proxy.gd") const Proxy = preload("res://lib/utils/proxy.gd")
const Notification = preload("res://content/ui/components/notification/notification.tscn") const Notification = preload("res://content/ui/components/notification/notification.tscn")
@onready var nav_view = $AnimationContainer/Navigation/View
@onready var nav_edit: Button3D = $AnimationContainer/Navigation/Edit
@onready var menu_edit: Node3D = $AnimationContainer/Content/EditMenu
@onready var nav_room = $AnimationContainer/Navigation/Room
@onready var menu_room: Node3D = $AnimationContainer/Content/RoomMenu
@onready var nav_automate = $AnimationContainer/Navigation/Automate
@onready var nav_settings = $AnimationContainer/Navigation/Settings
@onready var menu_settings: Node3D = $AnimationContainer/Content/SettingsMenu
@onready var menu_root = $AnimationContainer @onready var menu_root = $AnimationContainer
@onready var content = $AnimationContainer/Content @onready var content = $AnimationContainer/Content
@onready var nav = $AnimationContainer/Navigation @onready var nav = $AnimationContainer/Navigation
@ -41,61 +32,3 @@ func _ready():
notify_place.add_child(notification_node) notify_place.add_child(notification_node)
) )
var nav_buttons = [
nav_view,
nav_edit,
nav_room,
nav_automate,
nav_settings
]
for nav_button in nav_buttons:
var getter = func():
return nav_button == selected_nav
var setter = func(value):
if value:
select_menu(nav_button)
nav_button.external_value = Proxy.new(getter, setter)
select_menu(nav_edit)
func select_menu(nav):
if _is_valid_nav(nav) == false || selected_nav == nav:
return
for child in content.get_children():
content.remove_child(child)
var old_nav = selected_nav
selected_nav = nav
if old_nav != null:
old_nav.update_animation()
if selected_nav != null:
selected_nav.update_animation()
var menu = _nav_to_menu(selected_nav)
if menu != null:
content.add_child(menu)
menu.visible = true
func _is_valid_nav(nav):
return nav == nav_view || nav == nav_edit || nav == nav_room || nav == nav_automate || nav == nav_settings
func _nav_to_menu(nav):
match nav:
nav_view:
return null
nav_edit:
return menu_edit
nav_room:
return menu_room
nav_automate:
return null
nav_settings:
return menu_settings
return null

View File

@ -1,11 +1,14 @@
[gd_scene load_steps=16 format=3 uid="uid://c3kdssrmv84kv"] [gd_scene load_steps=19 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://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="2_0x5at"] [ext_resource type="Material" uid="uid://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="2_0x5at"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="2_8coxu"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="2_8coxu"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs.gd" id="4_eavfx"]
[ext_resource type="PackedScene" uid="uid://crrb0l3ekuotj" path="res://content/ui/menu/edit/edit_menu.tscn" id="4_r2raj"] [ext_resource type="PackedScene" uid="uid://crrb0l3ekuotj" path="res://content/ui/menu/edit/edit_menu.tscn" id="4_r2raj"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="5_w4i01"] [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/ui/components/tabs/tabs_content.gd" id="6_7rntr"]
[ext_resource type="ArrayMesh" uid="uid://cbqhhnknyium2" path="res://assets/immersive_home_panels/immersive_home_panels.obj" id="7_f4u4o"] [ext_resource type="ArrayMesh" uid="uid://cbqhhnknyium2" path="res://assets/immersive_home_panels/immersive_home_panels.obj" id="7_f4u4o"]
[ext_resource type="PackedScene" uid="uid://ddpxthb414unp" path="res://content/ui/menu/view/view_menu.tscn" id="8_71pkg"]
[ext_resource type="PackedScene" uid="uid://c01gkeldvjwtr" path="res://content/ui/menu/room/room_menu.tscn" id="10_u4i1x"] [ext_resource type="PackedScene" uid="uid://c01gkeldvjwtr" path="res://content/ui/menu/room/room_menu.tscn" id="10_u4i1x"]
[ext_resource type="PackedScene" uid="uid://c6r4higceibif" path="res://content/ui/menu/settings/settings_menu.tscn" id="11_7wm6b"] [ext_resource type="PackedScene" uid="uid://c6r4higceibif" path="res://content/ui/menu/settings/settings_menu.tscn" id="11_7wm6b"]
@ -181,48 +184,58 @@ skeleton = NodePath("../..")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15)
shape = SubResource("ConvexPolygonShape3D_mgnm0") shape = SubResource("ConvexPolygonShape3D_mgnm0")
[node name="Navigation" type="Node3D" parent="AnimationContainer"] [node name="Tabs" type="Node3D" parent="AnimationContainer" node_paths=PackedStringArray("initial_selected")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0)
script = ExtResource("4_eavfx")
initial_selected = NodePath("View")
[node name="View" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")] [node name="View" parent="AnimationContainer/Tabs" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.03) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.03)
label = "visibility" label = "visibility"
icon = true icon = true
toggleable = true toggleable = true
[node name="Edit" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")] [node name="Edit" parent="AnimationContainer/Tabs" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.09) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.09)
label = "widgets" label = "widgets"
icon = true icon = true
toggleable = true toggleable = true
[node name="Room" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")] [node name="Room" parent="AnimationContainer/Tabs" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.15) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.15)
label = "view_in_ar" label = "view_in_ar"
icon = true icon = true
toggleable = true toggleable = true
[node name="Automate" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")] [node name="Automate" parent="AnimationContainer/Tabs" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.21) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.21)
label = "schema" label = "schema"
icon = true icon = true
toggleable = true toggleable = true
[node name="Settings" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")] [node name="Settings" parent="AnimationContainer/Tabs" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.27) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.27)
label = "settings" label = "settings"
icon = true icon = true
toggleable = true toggleable = true
[node name="Content" type="Node3D" parent="AnimationContainer"] [node name="TabsContent" type="Node3D" parent="AnimationContainer" node_paths=PackedStringArray("tabs")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0)
script = ExtResource("6_7rntr")
tabs = NodePath("../Tabs")
[node name="EditMenu" parent="AnimationContainer/Content" instance=ExtResource("4_r2raj")] [node name="ViewMenu" parent="AnimationContainer/TabsContent" instance=ExtResource("8_71pkg")]
[node name="RoomMenu" parent="AnimationContainer/Content" instance=ExtResource("10_u4i1x")]
visible = false visible = false
[node name="SettingsMenu" parent="AnimationContainer/Content" instance=ExtResource("11_7wm6b")] [node name="EditMenu" parent="AnimationContainer/TabsContent" instance=ExtResource("4_r2raj")]
[node name="RoomMenu" parent="AnimationContainer/TabsContent" instance=ExtResource("10_u4i1x")]
visible = false
[node name="AutomateMenu" type="Node3D" parent="AnimationContainer/TabsContent"]
visible = false
[node name="SettingsMenu" parent="AnimationContainer/TabsContent" instance=ExtResource("11_7wm6b")]
visible = false visible = false
[node name="NotifyPlace" type="Marker3D" parent="AnimationContainer"] [node name="NotifyPlace" type="Marker3D" parent="AnimationContainer"]

View File

@ -1,40 +1,16 @@
extends Node3D extends Node3D
const Room = preload("res://content/system/room/room.tscn")
const window_scene = preload("./window.tscn") const window_scene = preload("./window.tscn")
@onready var background = $Background @onready var background = $Background
@onready var toggle_edit_button = $Interface/ToggleEdit
@onready var spawn_windows = $SpawnWindows
@onready var rooms = get_tree().root.get_node("Main/Rooms")
var room: Node3D
func _ready(): func _ready():
background.visible = false background.visible = false
HomeApi.on_connect.connect(func(): HomeApi.on_connect.connect(func():
if rooms.get_child_count() == 0: # var rooms = House.body.get_rooms(0)
room = Room.instantiate()
rooms.add_child(room)
else:
room = rooms.get_child(0)
if rooms.get_child_count() > 1:
for child in rooms.get_children():
if child != room:
child.queue_free()
)
spawn_windows.on_button_down.connect(func(): # for room in rooms:
get_tree().root.get_node("Main").add_child.call_deferred(window_scene.instantiate()) # var mesh = room.wall_mesh
) pass
toggle_edit_button.on_button_down.connect(func():
if room != null:
room.editable = true
)
toggle_edit_button.on_button_up.connect(func():
if room != null:
room.editable = false
) )

View File

@ -1,8 +1,12 @@
[gd_scene load_steps=5 format=3 uid="uid://c01gkeldvjwtr"] [gd_scene load_steps=9 format=3 uid="uid://c01gkeldvjwtr"]
[ext_resource type="Script" path="res://content/ui/menu/room/room_menu.gd" id="1_ch4jb"] [ext_resource type="Script" path="res://content/ui/menu/room/room_menu.gd" id="1_ch4jb"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="2_elugy"] [ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/pri-500.material" id="2_7m4yn"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_whl7a"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_cghmp"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs.gd" id="5_ddrep"]
[ext_resource type="PackedScene" uid="uid://dd71loi64gnmp" path="res://content/ui/menu/room/views/overview.tscn" id="6_206ad"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs_content.gd" id="6_ba00g"]
[ext_resource type="PackedScene" uid="uid://bpta22fahai46" path="res://content/ui/menu/room/views/rooms.tscn" id="7_2f8e0"]
[sub_resource type="BoxMesh" id="BoxMesh_e37nn"] [sub_resource type="BoxMesh" id="BoxMesh_e37nn"]
size = Vector3(0.3, 0.01, 0.3) size = Vector3(0.3, 0.01, 0.3)
@ -12,35 +16,27 @@ script = ExtResource("1_ch4jb")
[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)
material_override = ExtResource("2_7m4yn")
mesh = SubResource("BoxMesh_e37nn") mesh = SubResource("BoxMesh_e37nn")
[node name="Interface" type="Node3D" parent="."] [node name="Interface" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 0)
[node name="ToggleEdit" parent="Interface" instance=ExtResource("3_whl7a")] [node name="Tabs3D" type="Node3D" parent="Interface" node_paths=PackedStringArray("initial_selected")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0, 0.05) script = ExtResource("5_ddrep")
label = "room_preferences" initial_selected = NodePath("Overview")
icon = true
toggleable = true
[node name="Clickable" type="Node" parent="Interface/ToggleEdit"] [node name="Overview" parent="Interface/Tabs3D" instance=ExtResource("4_cghmp")]
script = ExtResource("2_elugy") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.03, 0, -0.02)
label = "Overview"
[node name="Label3D" type="Label3D" parent="Interface"] [node name="Rooms" parent="Interface/Tabs3D" instance=ExtResource("4_cghmp")]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.13, -1.86265e-09, 0.05) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.09, 0, -0.02)
pixel_size = 0.001 label = "Rooms"
text = "Edit Room"
font_size = 18
outline_size = 0
[node name="CreateBlur" type="Label3D" parent="."] [node name="TabsContent3D" type="Node3D" parent="Interface" node_paths=PackedStringArray("tabs")]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.15, 0.01, 0.261858) script = ExtResource("6_ba00g")
pixel_size = 0.001 tabs = NodePath("../Tabs3D")
text = "Fake Windows"
font_size = 18
outline_size = 0
[node name="SpawnWindows" parent="." instance=ExtResource("3_whl7a")] [node name="Overview" parent="Interface/TabsContent3D" instance=ExtResource("6_206ad")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0, 0.26)
label = "lens_blur" [node name="Rooms" parent="Interface/TabsContent3D" instance=ExtResource("7_2f8e0")]
icon = true

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5245272378c86fb17cf012dee95460df366d7781d3119604e447ae2330de7199
size 134

View File

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

View File

@ -0,0 +1,31 @@
extends Node3D
@onready var edit_button = $EditButton
@onready var fix_button = $FixButton
var active = false:
set(value):
if value:
edit_button.label = "save"
fix_button.disabled = true
fix_button.visible = false
else:
edit_button.label = "edit"
fix_button.disabled = false
fix_button.visible = true
active = value
func _ready():
edit_button.on_button_down.connect(func():
if active:
House.body.save_reference()
else:
House.body.edit_reference()
active = !active
)
fix_button.on_button_down.connect(func():
House.body.fix_reference()
active = true
)

View File

@ -0,0 +1,24 @@
[gd_scene load_steps=3 format=3 uid="uid://dd71loi64gnmp"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_fteh8"]
[ext_resource type="Script" path="res://content/ui/menu/room/views/overview.gd" id="1_jesad"]
[node name="Overview" type="Node3D"]
script = ExtResource("1_jesad")
[node name="EditButton" parent="." instance=ExtResource("1_fteh8")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.04, 0, 0.07)
label = "edit"
icon = true
[node name="FixButton" parent="." instance=ExtResource("1_fteh8")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.1, 0, 0.07)
label = "healing"
icon = true
[node name="Label3D" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.06, 0.01, 0.02)
pixel_size = 0.001
text = "Reference"
font_size = 18
outline_size = 0

View File

@ -0,0 +1,130 @@
extends Node3D
const Room = preload("res://content/system/house/room/room.tscn")
const RoomType = preload("res://content/system/house/room/room.gd")
const material_selected = preload("../room_selected.tres")
const material_unselected = preload("../room_unselected.tres")
@onready var room_button = $Button
@onready var input = $Input
@onready var rooms_map = $Rooms
var selected_room = null:
set(value):
if selected_room != null && value == null:
room_button.label = "add"
input.text = "Room %s" % (rooms_map.get_child_count() + 1)
if selected_room != null:
var old_room = get_room(selected_room)
if old_room != null:
old_room.get_node("MeshInstance3D").material_override = material_unselected
if value != null:
input.text = value
edit_room = false
var new_room = get_room(value)
if new_room != null:
new_room.get_node("MeshInstance3D").material_override = material_selected
selected_room = value
var edit_room = false:
set(value):
edit_room = value
if value:
room_button.label = "save"
else:
room_button.label = "edit"
func _ready():
room_button.on_button_down.connect(func():
if selected_room == null:
var room_name = input.text
if get_room(room_name) != null:
EventSystem.notify("Name already taken", EventNotify.Type.WARNING)
return
House.body.create_room(room_name, 0)
selected_room = room_name
edit_room = true
else:
if edit_room:
edit_room = false
if !House.body.is_valid_room(selected_room):
House.body.delete_room(selected_room)
selected_room = null
else:
House.body.edit_room(null)
_generate_room_map()
else:
edit_room = true
House.body.edit_room(selected_room)
)
func get_room(room_name):
if rooms_map.has_node("%s" % room_name):
return rooms_map.get_node("%s" % room_name)
return null
func _on_click(event: EventPointer):
if event.target.get_parent() == rooms_map:
var room_name = event.target.name
if selected_room == room_name:
selected_room = null
House.body.edit_room(null)
return
selected_room = room_name
func _generate_room_map():
var rooms = House.body.get_rooms(0)
var target_size = Vector3(0.3, 1, 0.24)
for old_room in rooms_map.get_children():
old_room.queue_free()
await old_room.tree_exited
var aabb = House.body.get_level_aabb(0)
var current_min = aabb.position
var current_max = aabb.position + aabb.size
for room in rooms:
var mesh = room.ceiling_mesh.mesh
if mesh == null:
continue
var body = StaticBody3D.new()
body.name = room.name
var mesh_instance = MeshInstance3D.new()
mesh_instance.name = "MeshInstance3D"
mesh_instance.mesh = mesh
mesh_instance.material_override = material_unselected if selected_room != room.name else material_selected
body.add_child(mesh_instance)
var collision_shape = CollisionShape3D.new()
collision_shape.shape = mesh.create_trimesh_shape()
body.add_child(collision_shape)
rooms_map.add_child(body)
if current_min == null:
return
var current_size = current_max - current_min
var target_scale = target_size / current_size
var scale_value = min(target_scale.x, target_scale.z)
rooms_map.position.x = -current_min.x * scale_value
rooms_map.position.z = -current_min.z * scale_value
rooms_map.scale = Vector3(scale_value, scale_value, scale_value)

View File

@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://bpta22fahai46"]
[ext_resource type="Script" path="res://content/ui/menu/room/views/rooms.gd" id="1_3a1oa"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_y3lty"]
[ext_resource type="PackedScene" uid="uid://blrhy2uccrdn4" path="res://content/ui/components/input/input.tscn" id="2_hstw7"]
[node name="Rooms" type="Node3D"]
script = ExtResource("1_3a1oa")
[node name="Rooms" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15, 0.01, 0.12)
[node name="Button" parent="." instance=ExtResource("1_y3lty")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.27, 0, 0.27)
label = "add"
icon = true
[node name="Input" parent="." instance=ExtResource("2_hstw7")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.12, 0.005, 0.27)
text = "Room 1"

View File

@ -23,14 +23,14 @@ mesh = SubResource("BoxMesh_e51x8")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.007, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.007, 0)
[node name="Label3D" type="Label3D" parent="Content"] [node name="Label3D" type="Label3D" parent="Content"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.134377, 0, 0.253575) transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.124377, 0, 0.263575)
pixel_size = 0.001 pixel_size = 0.001
text = "Spawn Ball" text = "Spawn Ball"
font_size = 18 font_size = 18
outline_size = 0 outline_size = 0
[node name="Button" parent="Content" instance=ExtResource("1_faxng")] [node name="Button" parent="Content" instance=ExtResource("1_faxng")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0458097, 0, 0.253575) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0358097, 0, 0.263575)
label = "sports_basketball" label = "sports_basketball"
icon = true icon = true
@ -109,11 +109,11 @@ outline_size = 0
script = ExtResource("3_qmg6q") script = ExtResource("3_qmg6q")
[node name="Save" parent="Content" instance=ExtResource("1_faxng")] [node name="Save" parent="Content" instance=ExtResource("1_faxng")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.04, 0, 0.17) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.03, 0, 0.12)
label = "save" label = "save"
icon = true icon = true
[node name="ClearSave" parent="Content" instance=ExtResource("1_faxng")] [node name="ClearSave" parent="Content" instance=ExtResource("1_faxng")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.1, 0, 0.17) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.09, 0, 0.12)
label = "close" label = "close"
icon = true icon = true

View File

@ -0,0 +1,12 @@
extends Node3D
@onready var mini_view = $Content/MiniView
@onready var background = $Background
func _ready():
background.visible = false
mini_view.on_button_down.connect(func():
House.body.mini_view = !House.body.mini_view
)

View File

@ -0,0 +1,21 @@
[gd_scene load_steps=4 format=3 uid="uid://ddpxthb414unp"]
[ext_resource type="Script" path="res://content/ui/menu/view/view_menu.gd" id="1_hxajx"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="2_qan1b"]
[sub_resource type="BoxMesh" id="BoxMesh_qr3bi"]
size = Vector3(0.3, 0.01, 0.3)
[node name="ViewMenu" type="Node3D"]
script = ExtResource("1_hxajx")
[node name="Background" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15, 0, 0.15)
mesh = SubResource("BoxMesh_qr3bi")
[node name="Content" type="Node3D" parent="."]
[node name="MiniView" parent="Content" instance=ExtResource("2_qan1b")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.03, 0, 0.03)
label = "view_comfy"
icon = true

View File

@ -96,4 +96,5 @@ func watch_state(entity: String, callback: Callable):
func _notification(what): func _notification(what):
if what == NOTIFICATION_WM_CLOSE_REQUEST || what == NOTIFICATION_WM_GO_BACK_REQUEST: if what == NOTIFICATION_WM_CLOSE_REQUEST || what == NOTIFICATION_WM_GO_BACK_REQUEST:
SaveSystem.save() # SaveSystem.save()
pass

View File

@ -0,0 +1,3 @@
extends Node
@onready var body = get_node("/root/Main/House")

View File

@ -2,8 +2,17 @@ extends Node
const VariantSerializer = preload("res://lib/utils/variant_serializer.gd") const VariantSerializer = preload("res://lib/utils/variant_serializer.gd")
signal loaded()
signal unloaded()
var is_loaded := false
var export_config = ConfigFile.new()
var export_config_path = "res://export_presets.cfg"
func clear(): func clear():
await _clear_save_tree(get_tree().root.get_node("Main")) await _clear_save_tree(get_tree().root.get_node("Main"))
unloaded.emit()
is_loaded = false
func save(): func save():
if HomeApi.has_connected() == false: if HomeApi.has_connected() == false:
@ -18,7 +27,10 @@ func save():
var save_tree = _generate_save_tree(get_tree().root.get_node("Main")) var save_tree = _generate_save_tree(get_tree().root.get_node("Main"))
var json_text = JSON.stringify(save_tree) var json_text = JSON.stringify({
"version": get_version(),
"tree": save_tree
})
save_file.store_line(json_text) save_file.store_line(json_text)
func load(): func load():
@ -35,7 +47,19 @@ func load():
return return
var json_text = save_file.get_line() var json_text = save_file.get_line()
var save_tree = JSON.parse_string(json_text) var save_data = JSON.parse_string(json_text)
if save_data == null:
return
if save_data.has("version") == false:
save()
return
var save_tree = save_data["tree"]
if save_tree == null:
return
if save_tree is Array: if save_tree is Array:
for tree in save_tree: for tree in save_tree:
@ -43,6 +67,22 @@ func load():
else: else:
_build_save_tree(save_tree) _build_save_tree(save_tree)
loaded.emit()
is_loaded = true
func get_version():
var config_error = export_config.load(export_config_path)
if config_error != OK:
return null
var version = export_config.get_value("preset.1.options", "version/name")
if version == null:
return null
return version
func _clear_save_tree(node: Node): func _clear_save_tree(node: Node):
for child in node.get_children(): for child in node.get_children():
await _clear_save_tree(child) await _clear_save_tree(child)

View File

@ -1,4 +1,5 @@
extends RefCounted extends RefCounted
class_name EntityFactory
const Switch = preload("res://content/entities/switch/switch.tscn") const Switch = preload("res://content/entities/switch/switch.tscn")
const Light = preload("res://content/entities/light/light.tscn") const Light = preload("res://content/entities/light/light.tscn")
@ -7,8 +8,9 @@ const MediaPlayer = preload("res://content/entities/media_player/media_player.ts
const Camera = preload("res://content/entities/camera/camera.tscn") const Camera = preload("res://content/entities/camera/camera.tscn")
const ButtonEntity = preload("res://content/entities/button/button.tscn") const ButtonEntity = preload("res://content/entities/button/button.tscn")
static func create_entity(type: String, id: String): static func create_entity(id: String):
var entity = null var entity = null
var type = id.split(".")[0]
match type: match type:
"switch": "switch":

View File

@ -1,4 +1,7 @@
extends RefCounted extends RefCounted
class_name Proxy
signal on_set(new_value: Variant)
var gettable: Callable var gettable: Callable
var settable: Callable var settable: Callable
@ -7,8 +10,12 @@ func _init(gettable: Callable, settable: Callable):
self.gettable = gettable self.gettable = gettable
self.settable = settable self.settable = settable
var value: Variant: var value: Variant:
get: get:
return gettable.call() return gettable.call()
set(new_value): set(new_value):
settable.call(new_value) settable.call(new_value)
on_set.emit(new_value)

19
lib/utils/proxy_group.gd Normal file
View File

@ -0,0 +1,19 @@
extends RefCounted
class_name ProxyGroup
var proxies = []
func proxy(_get: Callable, _set: Callable):
var _proxy
_proxy = Proxy.new(_get, func(value):
_set.call(value)
for p in proxies:
if p != _proxy:
p.on_set.emit(value)
)
proxies.append(_proxy)
return _proxy

View File

@ -0,0 +1,13 @@
extends Node
class_name State
var state_machine: StateMachine
func is_active():
return state_machine.current_state == self
func _on_enter():
pass
func _on_leave():
pass

View File

@ -0,0 +1,32 @@
class_name StateMachine
extends Node
signal changed(state_name: String, old_state: String)
@export var current_state: Node
var states: Dictionary = {}
func _ready() -> void:
for state in get_children():
states[state.get_name()] = state
state.state_machine = self
if state != current_state:
remove_child(state)
await get_parent().ready
current_state._on_enter()
func change_to(new_state: String) -> void:
if states.has(new_state) == false:
return
var old_state = current_state.get_name()
current_state._on_leave()
remove_child(current_state)
current_state = states[new_state]
add_child(current_state)
current_state._on_enter()
changed.emit(new_state, old_state)

View File

@ -24,6 +24,7 @@ HomeApi="*res://lib/globals/home_api.gd"
AudioPlayer="*res://lib/globals/audio_player.gd" AudioPlayer="*res://lib/globals/audio_player.gd"
EventSystem="*res://lib/globals/event_system.gd" EventSystem="*res://lib/globals/event_system.gd"
SaveSystem="*res://lib/globals/save_system.gd" SaveSystem="*res://lib/globals/save_system.gd"
House="*res://lib/globals/house_body.gd"
[editor_plugins] [editor_plugins]