diff --git a/content/entities/light/light.tscn b/content/entities/light/light.tscn index 4602274..cedeac3 100644 --- a/content/entities/light/light.tscn +++ b/content/entities/light/light.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=9 format=3 uid="uid://cw86rc42dv2d8"] +[gd_scene load_steps=10 format=3 uid="uid://cw86rc42dv2d8"] [ext_resource type="Script" path="res://content/entities/light/light.gd" id="1_ykxy3"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="4_4sfxb"] [ext_resource type="Material" uid="uid://vce66e7sbc3n" path="res://content/entities/light/light_on.tres" id="5_50gph"] +[ext_resource type="Script" path="res://content/functions/occludable.gd" id="5_oh4jg"] [ext_resource type="PackedScene" uid="uid://pk5k1q8bx0rj" path="res://content/ui/components/slider/slider.tscn" id="6_mhjlm"] [sub_resource type="SphereShape3D" id="SphereShape3D_ukj14"] @@ -52,6 +53,9 @@ script = ExtResource("1_ykxy3") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] shape = SubResource("SphereShape3D_ukj14") +[node name="Occludable" type="Node" parent="."] +script = ExtResource("5_oh4jg") + [node name="Movable" type="Node" parent="."] script = ExtResource("4_4sfxb") diff --git a/content/entities/media_player/media_player.tscn b/content/entities/media_player/media_player.tscn index b23422a..aad010a 100644 --- a/content/entities/media_player/media_player.tscn +++ b/content/entities/media_player/media_player.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=7 format=3 uid="uid://dyktdg7ggiwl4"] +[gd_scene load_steps=8 format=3 uid="uid://dyktdg7ggiwl4"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_8opk3"] [ext_resource type="Script" path="res://content/entities/media_player/media_player.gd" id="1_ame17"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="3_bguto"] +[ext_resource type="Script" path="res://content/functions/occludable.gd" id="4_fnfum"] [ext_resource type="PackedScene" uid="uid://pk5k1q8bx0rj" path="res://content/ui/components/slider/slider.tscn" id="4_w73hw"] [ext_resource type="FontVariation" uid="uid://sshfnckriqxn" path="res://assets/icons/icons.tres" id="5_koe28"] @@ -59,6 +60,9 @@ pixel_size = 0.001 [node name="Movable" type="Node" parent="."] script = ExtResource("3_bguto") +[node name="Occludable" type="Node" parent="."] +script = ExtResource("4_fnfum") + [node name="Slider" parent="." instance=ExtResource("4_w73hw")] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, -0.0562844, 0) max = 100.0 diff --git a/content/entities/sensor/sensor.tscn b/content/entities/sensor/sensor.tscn index 5117fb1..b8fc03e 100644 --- a/content/entities/sensor/sensor.tscn +++ b/content/entities/sensor/sensor.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://xsiy71rsqulj"] +[gd_scene load_steps=5 format=3 uid="uid://xsiy71rsqulj"] [ext_resource type="Script" path="res://content/entities/sensor/sensor.gd" id="1_57ac8"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="2_fpq5q"] +[ext_resource type="Script" path="res://content/functions/occludable.gd" id="3_l3sp5"] [sub_resource type="SphereShape3D" id="SphereShape3D_r20gc"] radius = 0.1 @@ -22,3 +23,6 @@ font_size = 80 [node name="Movable" type="Node" parent="."] script = ExtResource("2_fpq5q") + +[node name="Occludable" type="Node" parent="."] +script = ExtResource("3_l3sp5") diff --git a/content/entities/switch/switch.tscn b/content/entities/switch/switch.tscn index 44f8635..73188c6 100644 --- a/content/entities/switch/switch.tscn +++ b/content/entities/switch/switch.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=7 format=3 uid="uid://cscl5k7lhopj5"] +[gd_scene load_steps=8 format=3 uid="uid://cscl5k7lhopj5"] [ext_resource type="Script" path="res://content/entities/switch/switch.gd" id="1_8ffhi"] [ext_resource type="Texture2D" uid="uid://br3p0c2foputg" path="res://assets/materials/swich_on.png" id="1_w68gw"] [ext_resource type="Texture2D" uid="uid://co2ishj2hx57p" path="res://assets/materials/switch_off.png" id="2_86ba1"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="4_6xr03"] +[ext_resource type="Script" path="res://content/functions/occludable.gd" id="5_j5ucu"] [sub_resource type="SphereShape3D" id="SphereShape3D_ukj14"] radius = 0.1 @@ -36,3 +37,6 @@ sprite_frames = SubResource("SpriteFrames_ldpuo") [node name="Movable" type="Node" parent="."] script = ExtResource("4_6xr03") + +[node name="Occludable" type="Node" parent="."] +script = ExtResource("5_j5ucu") diff --git a/content/functions/occludable.gd b/content/functions/occludable.gd new file mode 100644 index 0000000..1479ab3 --- /dev/null +++ b/content/functions/occludable.gd @@ -0,0 +1,16 @@ +extends Function +class_name Occludable + +var ray := RayCast3D.new() +@onready var player_camera: XRCamera3D = get_node("/root/Main/XROrigin3D/XRCamera3D") + +func _ready(): + ray.set_collision_mask_value(1, false) + ray.set_collision_mask_value(5, true) + get_parent().add_child.call_deferred(ray) + +func _process(_delta): + ray.target_position = get_parent().to_local(player_camera.global_position) + + get_parent().visible = ray.is_colliding() == false + diff --git a/content/main.tscn b/content/main.tscn index b12959a..6c09599 100644 --- a/content/main.tscn +++ b/content/main.tscn @@ -78,4 +78,6 @@ visible = false [node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")] transform = Transform3D(0.499999, -6.98142e-12, 0, 4.74065e-12, 0.5, -2.27374e-13, 0, 2.27374e-13, 0.5, -0.125313, 0.424282, -0.263966) +[node name="Rooms" type="Node3D" parent="."] + [editable path="XROrigin3D/XRControllerLeft"] diff --git a/content/system/room/room.gd b/content/system/room/room.gd new file mode 100644 index 0000000..d744f7a --- /dev/null +++ b/content/system/room/room.gd @@ -0,0 +1,202 @@ +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 := true: + 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 + +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 old_coll in wall_collisions.get_children(): + old_coll.queue_free() + + 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): + for corner in data["corners"]: + add_corner(corner) + + _end_edit_mode() diff --git a/content/system/room/room.tscn b/content/system/room/room.tscn new file mode 100644 index 0000000..8cc9291 --- /dev/null +++ b/content/system/room/room.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=6 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" path="res://content/system/room/walls.tres" id="3_al1ev"] + +[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_08sv0"] + +[sub_resource type="ArrayMesh" id="ArrayMesh_7dibq"] + +[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="."] diff --git a/content/ui/menu/room/wall_corner.tscn b/content/system/room/wall_corner.tscn similarity index 92% rename from content/ui/menu/room/wall_corner.tscn rename to content/system/room/wall_corner.tscn index 1e781b5..c12b7ed 100644 --- a/content/ui/menu/room/wall_corner.tscn +++ b/content/system/room/wall_corner.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://eht83kc5wtiw"] +[gd_scene load_steps=5 format=3 uid="uid://brf6mm2gxj7y2"] [ext_resource type="Script" path="res://content/functions/clickable.gd" id="1_e5awq"] diff --git a/content/ui/menu/room/wall_edge.tscn b/content/system/room/wall_edge.tscn similarity index 84% rename from content/ui/menu/room/wall_edge.tscn rename to content/system/room/wall_edge.tscn index 859e691..21f2718 100644 --- a/content/ui/menu/room/wall_edge.tscn +++ b/content/system/room/wall_edge.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=3 format=3 uid="uid://cfcabpcbp577o"] +[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"] diff --git a/content/ui/menu/room/walls.tres b/content/system/room/walls.tres similarity index 100% rename from content/ui/menu/room/walls.tres rename to content/system/room/walls.tres diff --git a/content/ui/menu/room/room_menu.gd b/content/ui/menu/room/room_menu.gd index 0ab7023..7a94699 100644 --- a/content/ui/menu/room/room_menu.gd +++ b/content/ui/menu/room/room_menu.gd @@ -1,217 +1,36 @@ extends Node3D -const wall_corner_scene = preload("./wall_corner.tscn") -const wall_edge_scene = preload("./wall_edge.tscn") +const Room = preload("res://content/system/room/room.tscn") + const window_scene = preload("./window.tscn") -@onready var teleport_root = $TeleportRoot @onready var background = $Background -@onready var wall_corners = $TeleportRoot/WallCorners -@onready var wall_edges = $TeleportRoot/WallEdges -@onready var wall_mesh = $TeleportRoot/WallMesh -@onready var wall_collisions = $TeleportRoot/WallCollisions @onready var toggle_edit_button = $Interface/ToggleEdit @onready var spawn_windows = $SpawnWindows - -var moving = null -var ground_plane = Plane(Vector3.UP, Vector3.ZERO) -var edit_enabled = false +@onready var rooms = get_tree().root.get_node("Main/Rooms") +var room: Node3D func _ready(): - remove_child(teleport_root) background.visible = false - get_tree().get_root().get_node("Main").add_child.call_deferred(teleport_root) + + HomeApi.on_connect.connect(func(): + if rooms.get_child_count() == 0: + room = Room.instantiate() + rooms.add_child(room) + else: + room = rooms.get_child(0) + ) spawn_windows.on_button_down.connect(func(): get_tree().root.get_node("Main").add_child.call_deferred(window_scene.instantiate()) ) - teleport_root.get_node("Ground/Clickable").on_click.connect(func(event): - if !edit_enabled: - return - - add_corner(event.ray.get_collision_point()) - ) - toggle_edit_button.on_button_down.connect(func(): - edit_enabled = true - - wall_corners.visible = true - wall_edges.visible = true - wall_mesh.visible = false + if room != null: + room.editable = true ) - toggle_edit_button.on_button_up.connect(_handle_button_up) - -func _handle_button_up(): - edit_enabled = false - - 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 old_coll in wall_collisions.get_children(): - old_coll.queue_free() - - 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) - - print(corner.position, " ", corner.position + wall_up) - - 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) - - print(collision_shapes) - - 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 !edit_enabled: - return - - moving = event.target + toggle_edit_button.on_button_up.connect(func(): + if room != null: + room.editable = false ) - - 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): - for corner in data["corners"]: - add_corner(corner) - - _handle_button_up() - - queue_free() - diff --git a/content/ui/menu/room/room_menu.tscn b/content/ui/menu/room/room_menu.tscn index 558efff..88da1c8 100644 --- a/content/ui/menu/room/room_menu.tscn +++ b/content/ui/menu/room/room_menu.tscn @@ -1,42 +1,15 @@ -[gd_scene load_steps=8 format=3 uid="uid://c01gkeldvjwtr"] +[gd_scene load_steps=5 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/functions/clickable.gd" id="2_elugy"] -[ext_resource type="Material" uid="uid://bbx6fv7jq50tr" path="res://content/ui/menu/room/walls.tres" id="3_fke3j"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_whl7a"] -[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_08sv0"] - -[sub_resource type="ArrayMesh" id="ArrayMesh_7dibq"] - [sub_resource type="BoxMesh" id="BoxMesh_e37nn"] size = Vector3(0.3, 0.01, 0.3) [node name="RoomMenu" type="Node3D"] script = ExtResource("1_ch4jb") -[node name="TeleportRoot" type="Node3D" parent="."] - -[node name="Ground" type="StaticBody3D" parent="TeleportRoot"] -collision_layer = 24 -collision_mask = 0 - -[node name="CollisionShape3D" type="CollisionShape3D" parent="TeleportRoot/Ground"] -shape = SubResource("WorldBoundaryShape3D_08sv0") - -[node name="Clickable" type="Node" parent="TeleportRoot/Ground"] -script = ExtResource("2_elugy") - -[node name="WallCorners" type="Node3D" parent="TeleportRoot"] - -[node name="WallEdges" type="Node3D" parent="TeleportRoot"] - -[node name="WallMesh" type="MeshInstance3D" parent="TeleportRoot"] -material_override = ExtResource("3_fke3j") -mesh = SubResource("ArrayMesh_7dibq") - -[node name="WallCollisions" type="Node3D" parent="TeleportRoot"] - [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_e37nn")