From c0dccc8401ba809d6288fb434f0fa49be0e96e3b Mon Sep 17 00:00:00 2001 From: Nitwel Date: Fri, 5 Apr 2024 19:29:18 +0200 Subject: [PATCH] make miniature view separate --- app/content/entities/sensor/sensor.gd | 14 ++ app/content/system/house/house.gd | 43 +--- app/content/system/house/house.tscn | 5 +- .../system/house/mini/mini_view_options.gd | 3 + app/content/system/house/mini/mini_wall.tres | 19 ++ .../house/mini/mini_wall_shader.gdshader | 39 ++++ app/content/system/house/mini/miniature.gd | 84 ++++++++ app/content/system/house/mini/miniature.tscn | 24 +++ app/content/system/house/room/room.gd | 73 +------ app/content/system/house/room/room.tscn | 6 +- app/content/system/house/room/states/mini.gd | 41 ---- app/content/system/house/room/states/view.gd | 48 +---- .../house/room/{walls.tres => wall.tres} | 0 app/content/system/house/room/walls_mini.tres | 6 - app/content/ui/menu/edit/edit_menu.gd | 9 + app/content/ui/menu/view/view_menu.gd | 3 +- app/lib/utils/mesh/construct_room_mesh.gd | 194 ++++++++++++++++++ 17 files changed, 408 insertions(+), 203 deletions(-) create mode 100644 app/content/system/house/mini/mini_view_options.gd create mode 100644 app/content/system/house/mini/mini_wall.tres create mode 100644 app/content/system/house/mini/mini_wall_shader.gdshader create mode 100644 app/content/system/house/mini/miniature.gd create mode 100644 app/content/system/house/mini/miniature.tscn delete mode 100644 app/content/system/house/room/states/mini.gd rename app/content/system/house/room/{walls.tres => wall.tres} (100%) delete mode 100644 app/content/system/house/room/walls_mini.tres create mode 100644 app/lib/utils/mesh/construct_room_mesh.gd diff --git a/app/content/entities/sensor/sensor.gd b/app/content/entities/sensor/sensor.gd index 998c0e6..c7c49f5 100644 --- a/app/content/entities/sensor/sensor.gd +++ b/app/content/entities/sensor/sensor.gd @@ -5,6 +5,8 @@ const Entity = preload ("../entity.gd") @onready var label: Label3D = $Label @onready var collision_shape = $CollisionShape3D +var sensor_data = {} + # Called when the node enters the scene tree for the first time. func _ready(): super() @@ -17,6 +19,9 @@ func _ready(): ) func set_text(stateInfo): + if stateInfo == null: + return + var text = stateInfo["state"] if stateInfo["attributes"]["friendly_name"] != null: @@ -25,6 +30,9 @@ func set_text(stateInfo): if stateInfo["attributes"].has("unit_of_measurement")&&stateInfo["attributes"]["unit_of_measurement"] != null: text += " " + stateInfo["attributes"]["unit_of_measurement"] + if stateInfo["attributes"].has("device_class"): + sensor_data[stateInfo["attributes"]["device_class"]] = stateInfo["state"] + label.text = text var font = label.get_font() @@ -35,3 +43,9 @@ func set_text(stateInfo): collision_shape.shape.size.x = size.x * label.pixel_size * 0.5 collision_shape.shape.size.y = size.y * label.pixel_size * 0.25 + +func get_sensor_data(type: String): + if sensor_data.has(type) == false: + return null + + return sensor_data[type] diff --git a/app/content/system/house/house.gd b/app/content/system/house/house.gd index 2edfeb5..9d8392b 100644 --- a/app/content/system/house/house.gd +++ b/app/content/system/house/house.gd @@ -6,13 +6,10 @@ const RoomType = preload ("./room/room.gd") @onready var levels = $Levels @onready var collision_shape = $Levels/CollisionShape3D @onready var align_reference = $AlignReference +@onready var mini_view = $Miniature var fixing_reference: bool = false var editing_room: RoomType = null -var mini_view: bool = false: - set(value): - mini_view = value - update_mini_view() func _ready(): Store.house.on_loaded.connect(func(): @@ -198,44 +195,6 @@ func create_entity_in(entity_id: String, room_name: String): return entity -func update_mini_view(): - collision_shape.disabled = !mini_view - - var tween = create_tween() - tween.set_parallel(true) - tween.set_trans(Tween.TRANS_CUBIC) - - 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 - - var camera = get_node("/root/Main/XROrigin3D/XRCamera3D") - var camera_position = camera.global_position - var camera_direction = -camera.global_transform.basis.z - - camera_position.y *= 0.5 - camera_direction.y = 0.0 - - var target_position = camera_position + camera_direction.normalized() * 0.2 - var new_position = target_position - center * 0.1 - tween.tween_property(levels, "global_position", new_position, 0.5) - tween.tween_property(levels, "scale", Vector3(0.1, 0.1, 0.1), 0.5) - - for room in get_rooms(0): - room.state_machine.change_to("Mini") - else: - tween.tween_property(levels, "global_position", Vector3(0, 0, 0), 0.5) - tween.tween_property(levels, "scale", Vector3(1.0, 1.0, 1.0), 0.5) - await tween.finished - - for room in get_rooms(0): - room.state_machine.change_to("View") - func edit_reference(): fixing_reference = false align_reference.visible = true diff --git a/app/content/system/house/house.tscn b/app/content/system/house/house.tscn index b17ab66..aad1919 100644 --- a/app/content/system/house/house.tscn +++ b/app/content/system/house/house.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=5 format=3 uid="uid://cbemihbxkd4ll"] +[gd_scene load_steps=6 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"] +[ext_resource type="PackedScene" uid="uid://ds60i5n211hi3" path="res://content/system/house/mini/miniature.tscn" id="4_qjbly"] [sub_resource type="BoxShape3D" id="BoxShape3D_x81up"] @@ -25,3 +26,5 @@ lock_rotation = true [node name="AlignReference" parent="." instance=ExtResource("3_e1tcn")] visible = false disabled = true + +[node name="Miniature" parent="." instance=ExtResource("4_qjbly")] diff --git a/app/content/system/house/mini/mini_view_options.gd b/app/content/system/house/mini/mini_view_options.gd new file mode 100644 index 0000000..ab7dc6b --- /dev/null +++ b/app/content/system/house/mini/mini_view_options.gd @@ -0,0 +1,3 @@ +extends Node3D + +const mini_wall_shader: ShaderMaterial = preload ("./mini_wall.tres") diff --git a/app/content/system/house/mini/mini_wall.tres b/app/content/system/house/mini/mini_wall.tres new file mode 100644 index 0000000..05daa0c --- /dev/null +++ b/app/content/system/house/mini/mini_wall.tres @@ -0,0 +1,19 @@ +[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://bcfcough6ucvc"] + +[ext_resource type="Shader" path="res://content/system/house/mini/mini_wall_shader.gdshader" id="1_sbr3e"] + +[sub_resource type="Gradient" id="Gradient_2jwis"] +interpolation_color_space = 2 +offsets = PackedFloat32Array(0.00280112, 1) +colors = PackedColorArray(0, 0.558935, 0.886772, 1, 0.999396, 0, 0.058647, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_rrsal"] +gradient = SubResource("Gradient_2jwis") + +[resource] +render_priority = 0 +shader = ExtResource("1_sbr3e") +shader_parameter/data = PackedFloat32Array() +shader_parameter/data_size = 0 +shader_parameter/min_max_data = null +shader_parameter/color_gradient = SubResource("GradientTexture1D_rrsal") diff --git a/app/content/system/house/mini/mini_wall_shader.gdshader b/app/content/system/house/mini/mini_wall_shader.gdshader new file mode 100644 index 0000000..66bb686 --- /dev/null +++ b/app/content/system/house/mini/mini_wall_shader.gdshader @@ -0,0 +1,39 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_disabled, diffuse_lambert, specular_schlick_ggx, unshaded; + +uniform vec4 data[100]; +uniform int data_size: hint_range(0, 100, 1); +uniform vec2 min_max_data; +uniform sampler2D color_gradient; + +varying vec3 color; + + + +void vertex() { + // Calculate Global Coordinates + vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; + + color = vec3(1.0, 1.0, 1.0); + vec2 distances[100]; + float dist_sum = 0.0; + + if(data_size > 0) { + for(int i = 0; i < data_size; i++) { + float delta = 1.0 / distance(data[i].xyz, world_position); + + distances[i] = vec2(delta, data[i].w); + dist_sum += delta; + } + + for(int i = 0; i < data_size; i++) { + float average = distances[i].x / dist_sum * distances[i].y; + color.xyz = texture(color_gradient, vec2(average, 0)).xyz; + } + } +} + +void fragment() { + ALBEDO = vec3(color.xyz); + ALPHA = 0.3; +} diff --git a/app/content/system/house/mini/miniature.gd b/app/content/system/house/mini/miniature.gd new file mode 100644 index 0000000..0a63fd4 --- /dev/null +++ b/app/content/system/house/mini/miniature.gd @@ -0,0 +1,84 @@ +extends Node3D + +const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd") +const wall_material = preload ("./mini_wall.tres") + +@onready var walls_mesh = $WallsMesh +@onready var floor_mesh = $FloorMesh +@onready var collision_shape = $CollisionShape3D +@onready var toggle_heatmap = $HeatmapButton + +var enabled = true: + set(value): + enabled = value + update() + +func _ready(): + update() + + if Store.house.is_loaded() == false: + await Store.house.on_loaded + + var room = Store.house.rooms[0] + + var corners = room.corners + var height = room.height + + walls_mesh.mesh = ConstructRoomMesh.generate_wall_mesh_grid(corners, height) + floor_mesh.mesh = ConstructRoomMesh.generate_ceiling_mesh_grid(corners) + + walls_mesh.material_override = wall_material + floor_mesh.material_override = wall_material + + active = true + update_data(0.0) + + toggle_heatmap.on_button_down.connect(func(): + active=true + EventSystem.on_slow_tick.connect(update_data) + ) + + toggle_heatmap.on_button_up.connect(func(): + wall_material.set_shader_parameter("data", []) + wall_material.set_shader_parameter("data_size", 0) + active=false + EventSystem.on_slow_tick.disconnect(update_data) + ) + +func update(): + walls_mesh.visible = enabled + floor_mesh.visible = enabled + collision_shape.disabled = not enabled + +const SensorEntity = preload ("res://content/entities/sensor/sensor.gd") + +var active: bool = false + +func update_data(delta: float) -> void: + var data_list = [] + var min_max_data + + for room in House.body.get_rooms(0): + for entity in room.get_node("Entities").get_children(): + if entity is SensorEntity: + var sensor = entity as SensorEntity + var data = sensor.get_sensor_data("temperature") + if data == null: + continue + + var sensor_pos = sensor.global_position + + if min_max_data == null: + min_max_data = Vector2(float(data), float(data)) + else: + min_max_data.x = min(min_max_data.x, float(data)) + min_max_data.y = max(min_max_data.y, float(data)) + + data_list.append(Vector4(sensor_pos.x, sensor_pos.y, sensor_pos.z, float(data))) + + for data in data_list: + data.w = (data.w - min_max_data.x) / (min_max_data.y - min_max_data.x) + + wall_material.set_shader_parameter("data", data_list) + wall_material.set_shader_parameter("min_max_data", min_max_data) + wall_material.set_shader_parameter("data_size", data_list.size()) diff --git a/app/content/system/house/mini/miniature.tscn b/app/content/system/house/mini/miniature.tscn new file mode 100644 index 0000000..a48b30b --- /dev/null +++ b/app/content/system/house/mini/miniature.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=5 format=3 uid="uid://ds60i5n211hi3"] + +[ext_resource type="Script" path="res://content/system/house/mini/miniature.gd" id="1_b53yn"] +[ext_resource type="Script" path="res://content/functions/movable.gd" id="2_x7oed"] +[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_tgdcf"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_bckw3"] + +[node name="Miniature" type="StaticBody3D"] +script = ExtResource("1_b53yn") + +[node name="WallsMesh" type="MeshInstance3D" parent="."] + +[node name="FloorMesh" type="MeshInstance3D" parent="."] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape3D_bckw3") + +[node name="Movable" type="Node" parent="."] +script = ExtResource("2_x7oed") + +[node name="HeatmapButton" parent="." instance=ExtResource("3_tgdcf")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.5, 0.48) +toggleable = true diff --git a/app/content/system/house/room/room.gd b/app/content/system/house/room/room.gd index 7c76b8f..e9f1107 100644 --- a/app/content/system/house/room/room.gd +++ b/app/content/system/house/room/room.gd @@ -1,5 +1,7 @@ extends Node3D +const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd") + @onready var wall_corners = $Ceiling/WallCorners @onready var wall_edges = $Ceiling/WallEdges @onready var wall_mesh: MeshInstance3D = $WallMesh @@ -55,75 +57,12 @@ func get_aabb(): return AABB(to_global(min_pos), to_global(max_pos) - to_global(min_pos)) static func generate_wall_mesh(room_store: Dictionary): - if room_store.corners.size() < 2: - return null + var corners = room_store.corners + var height = room_store.height - var st = SurfaceTool.new() - var wall_up = Vector3.UP * room_store.height - - st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) - - for corner in room_store.corners: - var corner3D = Vector3(corner.x, 0, corner.y) - - st.add_vertex(corner3D) - st.add_vertex(corner3D + wall_up) - - var first_corner = Vector3(room_store.corners[0].x, 0, room_store.corners[0].y) - - st.add_vertex(first_corner) - st.add_vertex(first_corner + wall_up) - - st.index() - st.generate_normals() - st.generate_tangents() - var mesh = st.commit() - - return mesh + return ConstructRoomMesh.generate_wall_mesh_grid(corners, height) static func generate_ceiling_mesh(room_store: Dictionary): - - var points: PackedVector2Array = PackedVector2Array() - var edges: PackedInt32Array = PackedInt32Array() - var triangles: PackedInt32Array - var corners = room_store.corners - if corners.size() < 3: - return null - - for i in range(corners.size()): - var corner = corners[i] - points.append(Vector2(corner.x, corner.y)) - edges.append(i) - edges.append((i + 1) % corners.size()) - - 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 + return ConstructRoomMesh.generate_ceiling_mesh_grid(corners) diff --git a/app/content/system/house/room/room.tscn b/app/content/system/house/room/room.tscn index 36a4f70..d222beb 100644 --- a/app/content/system/house/room/room.tscn +++ b/app/content/system/house/room/room.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=9 format=3 uid="uid://bswgmclohuqui"] +[gd_scene load_steps=8 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="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"] @@ -57,7 +56,4 @@ 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") - [node name="Entities" type="Node3D" parent="."] diff --git a/app/content/system/house/room/states/mini.gd b/app/content/system/house/room/states/mini.gd deleted file mode 100644 index 394db7a..0000000 --- a/app/content/system/house/room/states/mini.gd +++ /dev/null @@ -1,41 +0,0 @@ -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 = false - 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 - - diff --git a/app/content/system/house/room/states/view.gd b/app/content/system/house/room/states/view.gd index ade276a..e21c7ec 100644 --- a/app/content/system/house/room/states/view.gd +++ b/app/content/system/house/room/states/view.gd @@ -28,16 +28,16 @@ func _on_enter(): 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) + var collision = CollisionShape3D.new() + collision.shape = room.wall_mesh.mesh.create_trimesh_shape() + + 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) func _on_leave(): room.room_ceiling.get_node("CollisionShape3D").disabled = true @@ -46,33 +46,3 @@ func _on_leave(): for collision in room.wall_collisions.get_children(): collision.queue_free() await collision.tree_exited - -func generate_collision(): - var room_store = Store.house.get_room(room.name) - - var collision_shapes: Array[CollisionShape3D] = [] - - var corners = room_store.corners - - for i in range(corners.size()): - var corner = Vector3(corners[i].x, 0, corners[i].y) - var next_corner_index = (i + 1) % corners.size() - var next_corner = Vector3(corners[next_corner_index].x, 0, corners[next_corner_index].y) - - var shape = BoxShape3D.new() - shape.size = Vector3((next_corner - corner).length(), room_store.height, 0.04) - - var transform = Transform3D() - var back_vector = (corner - next_corner).cross(Vector3.UP).normalized() * shape.size.z / 2 - - transform.basis = Basis((next_corner - corner).normalized(), Vector3.UP, back_vector.normalized()) - transform.origin = corner + (next_corner - corner) / 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 diff --git a/app/content/system/house/room/walls.tres b/app/content/system/house/room/wall.tres similarity index 100% rename from app/content/system/house/room/walls.tres rename to app/content/system/house/room/wall.tres diff --git a/app/content/system/house/room/walls_mini.tres b/app/content/system/house/room/walls_mini.tres deleted file mode 100644 index ead6994..0000000 --- a/app/content/system/house/room/walls_mini.tres +++ /dev/null @@ -1,6 +0,0 @@ -[gd_resource type="StandardMaterial3D" format=3 uid="uid://dxyuncqxagt28"] - -[resource] -transparency = 1 -cull_mode = 2 -albedo_color = Color(1, 1, 1, 0.47451) diff --git a/app/content/ui/menu/edit/edit_menu.gd b/app/content/ui/menu/edit/edit_menu.gd index 9769d8c..84fa240 100644 --- a/app/content/ui/menu/edit/edit_menu.gd +++ b/app/content/ui/menu/edit/edit_menu.gd @@ -32,6 +32,15 @@ func _enter_tree(): func load_devices(): if devices.size() == 0: devices = await HomeApi.get_devices() + devices.sort_custom(func(a, b): + return a.values()[0]["name"].to_lower() < b.values()[0]["name"].to_lower() + ) + + for device in devices: + device.values()[0]["entities"].sort_custom(func(a, b): + return a.to_lower() < b.to_lower() + ) + render() HomeApi.on_disconnect.connect(func(): diff --git a/app/content/ui/menu/view/view_menu.gd b/app/content/ui/menu/view/view_menu.gd index 11fa1b9..4324da8 100644 --- a/app/content/ui/menu/view/view_menu.gd +++ b/app/content/ui/menu/view/view_menu.gd @@ -7,6 +7,5 @@ func _ready(): background.visible = false mini_view.on_button_down.connect(func(): - House.body.mini_view = !House.body.mini_view + House.body.mini_view.enabled=!House.body.mini_view.enabled ) - diff --git a/app/lib/utils/mesh/construct_room_mesh.gd b/app/lib/utils/mesh/construct_room_mesh.gd new file mode 100644 index 0000000..602cfc2 --- /dev/null +++ b/app/lib/utils/mesh/construct_room_mesh.gd @@ -0,0 +1,194 @@ +static func generate_wall_mesh(corners, height): + if corners.size() < 3: + return null + + var st = SurfaceTool.new() + var wall_up = Vector3.UP * height + + st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) + + for corner in corners: + var corner3D = Vector3(corner.x, 0, corner.y) + + st.add_vertex(corner3D) + st.add_vertex(corner3D + wall_up) + + var first_corner = Vector3(corners[0].x, 0, corners[0].y) + + st.add_vertex(first_corner) + st.add_vertex(first_corner + wall_up) + + st.index() + st.generate_normals() + st.generate_tangents() + var mesh = st.commit() + + return mesh + +static func generate_ceiling_mesh(corners): + var points: PackedVector2Array = PackedVector2Array() + var edges: PackedInt32Array = PackedInt32Array() + var triangles: PackedInt32Array + + if corners.size() < 3: + return null + + for i in range(corners.size()): + var corner = corners[i] + points.append(Vector2(corner.x, corner.y)) + edges.append(i) + edges.append((i + 1) % corners.size()) + + 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() + + return _create_mesh(points, triangles) + +static func generate_wall_mesh_grid(corners, height, grid: Vector2=Vector2(0.1, 0.1)): + if corners.size() < 3: + return null + + var st = SurfaceTool.new() + + st.begin(Mesh.PRIMITIVE_TRIANGLES) + + for corner_i in range(corners.size()): + var corner = Vector3(corners[corner_i].x, 0, corners[corner_i].y) + var next_index = (corner_i + 1) % corners.size() + var next_corner = Vector3(corners[next_index].x, 0, corners[next_index].y) + + var steps = ceil(Vector2((next_corner - corner).length() / grid.x, height / grid.y)) + + var forward_dir = (next_corner - corner).normalized() * grid.x + var up_dir = Vector3.UP * grid.y + + var close_distance = Vector2(1, 1) + + for y in range(0, steps.y): + + close_distance.x = 1 + + if y == steps.y - 1: + close_distance.y = fmod(height, grid.y) / grid.y + print(close_distance.y) + + for x in range(0, steps.x): + var point = corner + forward_dir * x + Vector3.UP * grid.y * y + + if x == steps.x - 1: + close_distance.x = fmod(corner.distance_to(next_corner), grid.x) / grid.x + + st.add_vertex(point) + st.add_vertex(point + forward_dir * close_distance.x) + st.add_vertex(point + up_dir * close_distance.y) + + st.add_vertex(point + forward_dir * close_distance.x) + st.add_vertex(point + forward_dir * close_distance.x + up_dir * close_distance.y) + st.add_vertex(point + up_dir * close_distance.y) + + st.index() + st.generate_normals() + st.generate_tangents() + var mesh = st.commit() + + return mesh + +static func generate_ceiling_mesh_grid(corners, grid: Vector2=Vector2(0.1, 0.1)): + var points: PackedVector2Array = PackedVector2Array() + var edges: PackedInt32Array = PackedInt32Array() + var triangles: PackedInt32Array + + if corners.size() < 3: + return null + + var min_val = Vector2(corners[0]) + var max_val = Vector2(corners[0]) + + for i in range(corners.size()): + var corner = corners[i] + + min_val.x = min(min_val.x, corner.x) + min_val.y = min(min_val.y, corner.y) + max_val.x = max(max_val.x, corner.x) + max_val.y = max(max_val.y, corner.y) + + points.append(Vector2(corner.x, corner.y)) + edges.append(i) + edges.append((i + 1) % corners.size()) + + var size = max_val - min_val + + ## Fill points insde the polygon + for y in range(1, int(size.y / grid.y)): + var x_intersections: Array[float] = [] + + var y_start = Vector2(min_val.x, min_val.y + y * grid.y) + var y_end = Vector2(max_val.x, min_val.y + y * grid.y) + + for i in range(corners.size()): + var a = corners[i] + var b = corners[(i + 1) % corners.size()] + + var result = Geometry2D.segment_intersects_segment(a, b, y_start, y_end) + + if result != null: + x_intersections.append(result.x) + + var intersection_counter = 0 + + x_intersections.sort() + + for x in range(1, int(size.x / grid.x)): + var point = min_val + Vector2(x * grid.x, y * grid.y) + + for i in range(intersection_counter, x_intersections.size()): + if x_intersections[i] < point.x: + intersection_counter += 1 + + var color = Color(1, 1, 0) + + if intersection_counter % 2 == 1: + color = Color(1, 0, 1) + points.append(point) + + 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() + + return _create_mesh(points, triangles) + +static func _create_mesh(points: PackedVector2Array, triangles: PackedInt32Array): + 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 \ No newline at end of file