diff --git a/app/content/entities/sensor/sensor.gd b/app/content/entities/sensor/sensor.gd index c7c49f5..cb82054 100644 --- a/app/content/entities/sensor/sensor.gd +++ b/app/content/entities/sensor/sensor.gd @@ -6,6 +6,7 @@ const Entity = preload ("../entity.gd") @onready var collision_shape = $CollisionShape3D var sensor_data = {} +var unit = null # Called when the node enters the scene tree for the first time. func _ready(): @@ -28,6 +29,7 @@ func set_text(stateInfo): text = stateInfo["attributes"]["friendly_name"] + "\n" + text if stateInfo["attributes"].has("unit_of_measurement")&&stateInfo["attributes"]["unit_of_measurement"] != null: + unit = stateInfo["attributes"]["unit_of_measurement"] text += " " + stateInfo["attributes"]["unit_of_measurement"] if stateInfo["attributes"].has("device_class"): @@ -49,3 +51,9 @@ func get_sensor_data(type: String): return null return sensor_data[type] + +func get_sensor_unit(type: String): + if sensor_data.has(type) == false: + return null + + return unit diff --git a/app/content/system/house/mini/humid_gradient.tres b/app/content/system/house/mini/humid_gradient.tres new file mode 100644 index 0000000..ac40fcb --- /dev/null +++ b/app/content/system/house/mini/humid_gradient.tres @@ -0,0 +1,11 @@ +[gd_resource type="GradientTexture1D" load_steps=2 format=3 uid="uid://gfemvrlwowg7"] + +[sub_resource type="Gradient" id="Gradient_2jwis"] +interpolation_color_space = 2 +offsets = PackedFloat32Array(0, 0.333333, 0.5, 1) +colors = PackedColorArray(0.999396, 0, 0.058647, 1, 1, 0.85, 0, 1, 0, 0.95, 1, 1, 0.0333333, 0, 1, 1) +metadata/_snap_enabled = true +metadata/_snap_count = 6 + +[resource] +gradient = SubResource("Gradient_2jwis") diff --git a/app/content/system/house/mini/mini_wall.tres b/app/content/system/house/mini/mini_wall.tres index ea81d20..d8f483f 100644 --- a/app/content/system/house/mini/mini_wall.tres +++ b/app/content/system/house/mini/mini_wall.tres @@ -1,16 +1,7 @@ -[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://bcfcough6ucvc"] +[gd_resource type="ShaderMaterial" load_steps=3 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.00840336, 0.1, 0.4375, 0.5625, 1) -colors = PackedColorArray(0.533333, 0, 1, 1, 0, 0.45, 1, 1, 0, 0.95, 1, 1, 0.983333, 1, 0, 1, 0.999396, 0, 0.058647, 1) -metadata/_snap_enabled = true -metadata/_snap_count = 16 - -[sub_resource type="GradientTexture1D" id="GradientTexture1D_rrsal"] -gradient = SubResource("Gradient_2jwis") +[ext_resource type="Texture2D" uid="uid://bbuq4wn7e5o2q" path="res://content/system/house/mini/temp_gradient.tres" id="2_3lwi8"] [resource] render_priority = 0 @@ -18,4 +9,4 @@ shader = ExtResource("1_sbr3e") shader_parameter/data = PackedFloat32Array() shader_parameter/data_size = 0 shader_parameter/alpha = 0.3 -shader_parameter/color_gradient = SubResource("GradientTexture1D_rrsal") +shader_parameter/color_gradient = ExtResource("2_3lwi8") diff --git a/app/content/system/house/mini/mini_wall_shader.gdshader b/app/content/system/house/mini/mini_wall_shader.gdshader index 34e3bf1..b11c4e6 100644 --- a/app/content/system/house/mini/mini_wall_shader.gdshader +++ b/app/content/system/house/mini/mini_wall_shader.gdshader @@ -59,5 +59,5 @@ void vertex() { void fragment() { ALBEDO = vec3(color.xyz); - ALPHA = 0.3; + ALPHA = alpha; } diff --git a/app/content/system/house/mini/miniature.gd b/app/content/system/house/mini/miniature.gd index 1a97d62..688e2fe 100644 --- a/app/content/system/house/mini/miniature.gd +++ b/app/content/system/house/mini/miniature.gd @@ -3,6 +3,9 @@ extends Node3D const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd") const wall_material = preload ("./mini_wall.tres") +const humidity_gradient = preload ("./humid_gradient.tres") +const temperature_gradient = preload ("./temp_gradient.tres") + @onready var body = $Body @onready var model = $Body/Model @onready var collision_shape = $Body/CollisionShape3D @@ -14,9 +17,19 @@ enum HeatmapType { HUMIDITY = 2 } -# var temperature_scale := Vector2( - 20.0, 60.0) -var temperature_scale := Vector2(22.0, 26.0) +var heatmap_type_strings = { + HeatmapType.NONE: "none", + HeatmapType.TEMPERATURE: "temperature", + HeatmapType.HUMIDITY: "humidity" +} +var base_scale = { + HeatmapType.NONE: Vector2(0.0, 1.0), + HeatmapType.TEMPERATURE: Vector2( - 20.0, 60.0), + HeatmapType.HUMIDITY: Vector2(0.0, 100.0) +} +var selected_scale = R.state(Vector2(0.0, 1.0)) +var opacity = R.state(30) var heatmap_type = R.state(HeatmapType.NONE) var small = R.state(false) @@ -100,27 +113,33 @@ func _ready(): R.effect(func(_arg): if heatmap_type.value != HeatmapType.NONE: EventSystem.on_slow_tick.connect(update_data) + if heatmap_type.value == HeatmapType.TEMPERATURE: + wall_material.set_shader_parameter("color_gradient", temperature_gradient) + else: + wall_material.set_shader_parameter("color_gradient", humidity_gradient) else: EventSystem.on_slow_tick.disconnect(update_data) wall_material.set_shader_parameter("data", []) wall_material.set_shader_parameter("data_size", 0) ) + R.effect(func(_arg): + wall_material.set_shader_parameter("alpha", opacity.value / 100.0) + ) + const SensorEntity = preload ("res://content/entities/sensor/sensor.gd") -# func _process(delta): -# for mesh in model.get_children(): -# if mesh is MeshInstance3D: -# mesh.material_override.set_shader_parameter("mesh_pos", +func get_base_scale() -> Vector2: + return base_scale[heatmap_type.value] -func update_data(_delta: float) -> void: +func get_sensor_data(): var data_list = [] 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") + var data = sensor.get_sensor_data(heatmap_type_strings[heatmap_type.value]) if data == null: continue @@ -128,8 +147,40 @@ func update_data(_delta: float) -> void: data_list.append(Vector4(sensor_pos.x, sensor_pos.y, sensor_pos.z, float(data))) + return data_list + +func get_sensor_unit(): + 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 sensor_unit = sensor.get_sensor_unit(heatmap_type_strings[heatmap_type.value]) + if sensor_unit != null: + return sensor_unit + + return "" + +func get_sensor_scale(): + var data = get_sensor_data() + var minmax + + for sensor in data: + if minmax == null: + minmax = Vector2(sensor.w, sensor.w) + else: + minmax.x = min(sensor.w, minmax.x) + minmax.y = max(sensor.w, minmax.y) + + if minmax == null: + return Vector2(0.0, 1.0) + + return minmax + +func update_data(_delta: float) -> void: + var data_list = get_sensor_data() + data_list = data_list.map(func(data: Vector4) -> Vector4: - data.w=(data.w - temperature_scale.x) / (temperature_scale.y - temperature_scale.x) + data.w=clamp((data.w - selected_scale.value.x) / (selected_scale.value.y - selected_scale.value.x), 0.0, 1.0) return data ) diff --git a/app/content/system/house/mini/temp_gradient.tres b/app/content/system/house/mini/temp_gradient.tres new file mode 100644 index 0000000..c55abeb --- /dev/null +++ b/app/content/system/house/mini/temp_gradient.tres @@ -0,0 +1,11 @@ +[gd_resource type="GradientTexture1D" load_steps=2 format=3 uid="uid://bbuq4wn7e5o2q"] + +[sub_resource type="Gradient" id="Gradient_2jwis"] +interpolation_color_space = 2 +offsets = PackedFloat32Array(0.00840336, 0.1, 0.4375, 0.5625, 1) +colors = PackedColorArray(0.533333, 0, 1, 1, 0, 0.45, 1, 1, 0, 0.95, 1, 1, 0.983333, 1, 0, 1, 0.999396, 0, 0.058647, 1) +metadata/_snap_enabled = true +metadata/_snap_count = 16 + +[resource] +gradient = SubResource("Gradient_2jwis") diff --git a/app/content/system/house/room/states/edit.gd b/app/content/system/house/room/states/edit.gd index e17a000..b11fb4f 100644 --- a/app/content/system/house/room/states/edit.gd +++ b/app/content/system/house/room/states/edit.gd @@ -1,8 +1,8 @@ extends RoomState -const wall_corner_scene = preload("../wall_corner.tscn") -const wall_edge_scene = preload("../wall_edge.tscn") -const RoomState = preload("./room_state.gd") +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 @@ -27,7 +27,7 @@ func _on_enter(): for i in range(1, corners.size()): add_corner(room.to_local(Vector3(corners[i].x, 0, corners[i].y))) - room.room_ceiling.get_node("CollisionShape3D").disabled = (floor_corner == null && height_corner == null) + 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() @@ -73,7 +73,7 @@ func remove_corner(index: int): get_edge(index).queue_free() func _on_click_floor(event): - if floor_corner != null && height_corner != null: + if floor_corner != null&&height_corner != null: return add_floor_corner(event.ray.get_collision_point()) @@ -81,7 +81,7 @@ func _on_click_floor(event): 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: + if floor_corner == null||height_corner == null||event.target != room.room_ceiling: return var pos = event.ray.get_collision_point() @@ -97,39 +97,39 @@ func add_floor_corner(position: Vector3): height_edge.align_to_corners(position, position + Vector3.UP * room.room_ceiling.position.y) floor_corner.get_node("Clickable").on_grab_down.connect(func(event): - if !is_active() || moving != null: + if !is_active()||moving != null: return - moving = event.target + 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) + 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 + moving.position=new_position height_edge.align_to_corners(new_position, new_position + Vector3.UP * room.room_ceiling.global_position.y) - get_corner(moving_index).position.x = new_position.x - get_corner(moving_index).position.z = new_position.z + get_corner(moving_index).position.x=new_position.x + get_corner(moving_index).position.z=new_position.z if room.wall_edges.get_child_count() == 0: return get_edge(moving_index).align_to_corners(new_position, get_corner(moving_index + 1).position) - get_edge(moving_index - 1).align_to_corners(get_corner(moving_index - 1).position, new_position) + get_edge(moving_index - 1).align_to_corners(get_corner(moving_index - 1).position, new_position) ) floor_corner.get_node("Clickable").on_grab_up.connect(func(_event): - moving = null + moving=null ) room.add_child(floor_corner) @@ -141,96 +141,95 @@ func add_height_corner(position: Vector3): height_corner.position.z = position.z height_corner.get_node("Clickable").on_grab_down.connect(func(event): - if !is_active() || moving != null: + if !is_active()||moving != null: return - moving = event.target + 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 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 plane=Plane(plane_direction, moving.position) - var new_position = plane.intersects_ray(event.ray.global_position, direction) + var new_position=plane.intersects_ray(event.ray.global_position, direction) if new_position == null: return - room.room_ceiling.position.y = new_position.y + room.room_ceiling.position.y=new_position.y height_edge.align_to_corners(floor_corner.position, floor_corner.position + Vector3.UP * room.room_ceiling.position.y) ) height_corner.get_node("Clickable").on_grab_up.connect(func(_event): - moving = null + moving=null ) room.wall_corners.add_child(height_corner) -func add_corner(position: Vector3, index: int = -1): +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: + if !is_active()||moving != null: return - moving = event.target + 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) + 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 + deleting=true - new_position = event.ray.global_position + direction + new_position=event.ray.global_position + direction - get_corner(moving_index).global_position = new_position + get_corner(moving_index).global_position=new_position if room.wall_edges.get_child_count() == 0: return get_edge(moving_index).align_to_corners(get_corner(moving_index - 1).position, get_corner(moving_index + 1).position) - get_edge(moving_index - 1).transform = get_edge(moving_index).transform + get_edge(moving_index - 1).transform=get_edge(moving_index).transform return - deleting = false + deleting=false - new_position.y = 0 + new_position.y=0 - moving.position = new_position - + moving.position=new_position if room.wall_edges.get_child_count() == 0: return get_edge(moving_index).align_to_corners(new_position, get_corner(moving_index + 1).position) - get_edge(moving_index - 1).align_to_corners(get_corner(moving_index - 1).position, new_position) + get_edge(moving_index - 1).align_to_corners(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() + var moving_index=moving.get_index() remove_corner(moving_index) - moving = null - deleting = false + moving=null + deleting=false ) room.wall_corners.add_child(corner) @@ -243,22 +242,20 @@ func add_corner(position: Vector3, index: int = -1): if num_corners > 2: if num_corners != room.wall_edges.get_child_count(): - add_edge(get_corner(-2).position, get_corner(-1).position, -2) + add_edge(get_corner( - 2).position, get_corner( - 1).position, -2) else: get_edge(index - 1).align_to_corners(get_corner(index - 1).position, position) - -func add_edge(from_pos: Vector3, to_pos: Vector3, index: int = -1): +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 + 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 @@ -277,4 +274,7 @@ func update_store(): store_room.corners = corners store_room.height = room.room_ceiling.position.y + # Manually update the array + Store.house.state.rooms = Store.house.state.rooms + Store.house.save_local() diff --git a/app/content/ui/menu/view/view_menu.gd b/app/content/ui/menu/view/view_menu.gd index d22a003..2fb3dd5 100644 --- a/app/content/ui/menu/view/view_menu.gd +++ b/app/content/ui/menu/view/view_menu.gd @@ -5,6 +5,9 @@ const Miniature = preload ("res://content/system/house/mini/miniature.gd") @onready var mini_view_button = $Content/MiniView @onready var heat_map_button = $Content/HeatMap @onready var humudity_map_button = $Content/HumidityMap +@onready var min_slider = $Content/MinSlider +@onready var max_slider = $Content/MaxSlider +@onready var opacity_slider = $Content/OpacitySlider @onready var background = $Background func _ready(): @@ -40,5 +43,51 @@ func _ready(): R.effect(func(_arg): heat_map_button.active=mini_view.heatmap_type.value == Miniature.HeatmapType.TEMPERATURE humudity_map_button.active=mini_view.heatmap_type.value == Miniature.HeatmapType.HUMIDITY - ) + + min_slider.on_value_changed.connect(func(value): + if value >= mini_view.selected_scale.value.y: + min_slider.value=mini_view.selected_scale.value.y + return + + mini_view.selected_scale.value.x=value + ) + + max_slider.on_value_changed.connect(func(value): + if value <= mini_view.selected_scale.value.x: + max_slider.value=mini_view.selected_scale.value.x + return + + mini_view.selected_scale.value.y=value + ) + + R.effect(func(_arg): + min_slider.value=mini_view.selected_scale.value.x + max_slider.value=mini_view.selected_scale.value.y + ) + + # Update Slider + R.effect(func(_arg): + var minmax=mini_view.get_base_scale() + min_slider.min=minmax.x + min_slider.max=minmax.y + + max_slider.min=minmax.x + max_slider.max=minmax.y + + var sensor_minmax=mini_view.get_sensor_scale() + + sensor_minmax.x=floor(sensor_minmax.x) + sensor_minmax.y=ceil(sensor_minmax.y) + + mini_view.selected_scale.value=sensor_minmax + min_slider.value=sensor_minmax.x + max_slider.value=sensor_minmax.y + + var unit=mini_view.get_sensor_unit() + + min_slider.label_unit=unit + max_slider.label_unit=unit + ) + + R.bind(opacity_slider, "value", mini_view.opacity, opacity_slider.on_value_changed) diff --git a/app/content/ui/menu/view/view_menu.tscn b/app/content/ui/menu/view/view_menu.tscn index a69710f..03cac72 100644 --- a/app/content/ui/menu/view/view_menu.tscn +++ b/app/content/ui/menu/view/view_menu.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=5 format=3 uid="uid://ddpxthb414unp"] +[gd_scene load_steps=6 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"] [ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/pri-500.material" id="2_se6ic"] +[ext_resource type="PackedScene" uid="uid://pk5k1q8bx0rj" path="res://content/ui/components/slider/slider.tscn" id="4_d3xhb"] [sub_resource type="BoxMesh" id="BoxMesh_qr3bi"] size = Vector3(0.3, 0.01, 0.3) @@ -58,3 +59,48 @@ text = "Humidity Map" font_size = 18 outline_size = 0 horizontal_alignment = 0 + +[node name="MinSlider" parent="Content" instance=ExtResource("4_d3xhb")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0.01, 0.2) +step = 1.0 +show_label = true +size = Vector3(10, 0.4, 1) + +[node name="MinValue" type="Label3D" parent="Content"] +transform = Transform3D(1, 0, 0, 0, 0, 1, 0, -1, 0, 0.15, 0.01, 0.2) +pixel_size = 0.001 +text = "Min Value" +font_size = 18 +outline_size = 0 +horizontal_alignment = 0 + +[node name="MaxSlider" parent="Content" instance=ExtResource("4_d3xhb")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0.01, 0.24) +step = 1.0 +show_label = true +size = Vector3(10, 0.4, 1) + +[node name="MaxValue" type="Label3D" parent="Content"] +transform = Transform3D(1, 0, 0, 0, 0, 1, 0, -1, 0, 0.15, 0.01, 0.24) +pixel_size = 0.001 +text = "Max Value" +font_size = 18 +outline_size = 0 +horizontal_alignment = 0 + +[node name="OpacitySlider" parent="Content" instance=ExtResource("4_d3xhb")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0.01, 0.28) +max = 100.0 +value = 30.0 +step = 10.0 +show_label = true +label_unit = "%" +size = Vector3(10, 0.4, 1) + +[node name="OpacityLabel" type="Label3D" parent="Content"] +transform = Transform3D(1, 0, 0, 0, 0, 1, 0, -1, 0, 0.15, 0.01, 0.28) +pixel_size = 0.001 +text = "Opacity" +font_size = 18 +outline_size = 0 +horizontal_alignment = 0