Merge pull request #125 from Nitwel/entity_menu

Add entities back to mini view + batch edit entities + palm shortcuts
This commit is contained in:
Nitwel 2024-04-17 21:36:39 +02:00 committed by GitHub
commit 9f2cb273d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 533 additions and 186 deletions

View File

@ -3,25 +3,27 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://co2ishj2hx57p" uid="uid://co2ishj2hx57p"
path="res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.ctex" path.s3tc="res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.s3tc.ctex"
path.etc2="res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.etc2.ctex"
metadata={ metadata={
"vram_texture": false "imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
} }
[deps] [deps]
source_file="res://assets/materials/switch_off.png" source_file="res://assets/materials/switch_off.png"
dest_files=["res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.ctex"] dest_files=["res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.s3tc.ctex", "res://.godot/imported/switch_off.png-c31f6b401a5d3d7cba3c9d0f2c8b28fe.etc2.ctex"]
[params] [params]
compress/mode=0 compress/mode=2
compress/high_quality=false compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_compression=1 compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
compress/channel_pack=0 compress/channel_pack=0
mipmaps/generate=false mipmaps/generate=true
mipmaps/limit=-1 mipmaps/limit=-1
roughness/mode=0 roughness/mode=0
roughness/src_normal="" roughness/src_normal=""
@ -31,4 +33,4 @@ process/normal_map_invert_y=false
process/hdr_as_srgb=false process/hdr_as_srgb=false
process/hdr_clamp_exposure=false process/hdr_clamp_exposure=false
process/size_limit=0 process/size_limit=0
detect_3d/compress_to=1 detect_3d/compress_to=0

View File

@ -1,12 +1,14 @@
extends Entity extends Entity
const Entity = preload("../entity.gd") const Entity = preload ("../entity.gd")
@onready var button = $Button @onready var button = $Button
func _ready(): func _ready():
super() super()
icon.value = "radio_button_checked"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
if stateInfo == null: if stateInfo == null:
@ -32,3 +34,6 @@ func set_state(state):
else: else:
button.icon = false button.icon = false
button.label = name button.label = name
func quick_action():
HomeApi.set_state(entity_id, "pressed")

View File

@ -8,7 +8,7 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_um5pa"] [sub_resource type="BoxShape3D" id="BoxShape3D_um5pa"]
size = Vector3(0.0700684, 0.011734, 0.0703125) size = Vector3(0.0700684, 0.011734, 0.0703125)
[node name="Button" type="StaticBody3D" groups=["entity"]] [node name="Button" type="StaticBody3D"]
script = ExtResource("1_ja7lt") script = ExtResource("1_ja7lt")
[node name="Button" parent="." instance=ExtResource("1_r4tef")] [node name="Button" parent="." instance=ExtResource("1_r4tef")]

View File

@ -1,6 +1,6 @@
extends Entity extends Entity
const Entity = preload("../entity.gd") const Entity = preload ("../entity.gd")
@export var view_width = 0.15 @export var view_width = 0.15
@ -8,11 +8,12 @@ const Entity = preload("../entity.gd")
@onready var http_request = $HTTPRequest @onready var http_request = $HTTPRequest
@onready var mesh = $MeshInstance3D @onready var mesh = $MeshInstance3D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
super() super()
icon.value = "photo_camera"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
set_state(stateInfo) set_state(stateInfo)
@ -37,7 +38,6 @@ func set_state(stateInfo):
if stateInfo["attributes"].has("entity_picture"): if stateInfo["attributes"].has("entity_picture"):
load_image(stateInfo["attributes"]["entity_picture"]) load_image(stateInfo["attributes"]["entity_picture"])
func load_image(url: String): func load_image(url: String):
http_request.request("http://192.168.33.33:8123" + url) http_request.request("http://192.168.33.33:8123" + url)

View File

@ -10,7 +10,7 @@ size = Vector2(0.15, 0.15)
[sub_resource type="BoxShape3D" id="BoxShape3D_te0pn"] [sub_resource type="BoxShape3D" id="BoxShape3D_te0pn"]
size = Vector3(0.15, 0.15, 0.01) size = Vector3(0.15, 0.15, 0.01)
[node name="Camera" type="StaticBody3D" groups=["entity"]] [node name="Camera" type="StaticBody3D" ]
script = ExtResource("1_htxq3") script = ExtResource("1_htxq3")
[node name="View" type="Sprite3D" parent="."] [node name="View" type="Sprite3D" parent="."]

View File

@ -1,6 +1,8 @@
extends StaticBody3D extends StaticBody3D
var entity_id: String var entity_id: String
var icon = R.state("question_mark")
var icon_color = R.state(Color(1, 1, 1, 1))
func _ready(): func _ready():
var movable = get_node("Movable") var movable = get_node("Movable")

View File

@ -1,12 +1,12 @@
extends Entity extends Entity
const Entity = preload("../entity.gd") const Entity = preload ("../entity.gd")
const color_wheel_img := preload("res://assets/canvas.png") const color_wheel_img := preload ("res://assets/canvas.png")
@export var color_off = Color(0.23, 0.23, 0.23) @export var color_off = Color(0.23, 0.23, 0.23)
@export var color_on = Color(1.0, 0.85, 0.0) @export var color_on = Color(1.0, 0.85, 0.0)
@onready var animation: AnimationPlayer = $AnimationPlayer @onready var lightbulb = $Lightbulb
@onready var slider: Slider3D = $Slider @onready var slider: Slider3D = $Slider
@onready var color_wheel = $ColorWheel @onready var color_wheel = $ColorWheel
@onready var color_puck = $ColorWheel/Puck @onready var color_puck = $ColorWheel/Puck
@ -17,105 +17,127 @@ const color_wheel_img := preload("res://assets/canvas.png")
var state = true var state = true
var brightness = 0 # 0-255 var brightness = 0 # 0-255
var color = color_on
var color_supported = false
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
super() super()
icon.value = "lightbulb"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
set_state(stateInfo["state"] == "on") set_state(stateInfo["state"] == "on", stateInfo["attributes"])
if stateInfo.has("attributes") && stateInfo["attributes"].has("effect_list") && stateInfo["attributes"]["effect_list"].size() > 0: if stateInfo.has("attributes")&&stateInfo["attributes"].has("effect_list")&&stateInfo["attributes"]["effect_list"].size() > 0:
if stateInfo["attributes"].has("effect") && stateInfo["attributes"]["effect"] != null: if stateInfo["attributes"].has("effect")&&stateInfo["attributes"]["effect"] != null:
mode_label.text = stateInfo["attributes"]["effect"] mode_label.text = stateInfo["attributes"]["effect"]
mode_next.on_button_down.connect(func(): mode_next.on_button_down.connect(func():
var index = stateInfo["attributes"]["effect_list"].find(stateInfo["attributes"]["effect"]) var index=stateInfo["attributes"]["effect_list"].find(stateInfo["attributes"]["effect"])
if index == -1: if index == - 1:
index = 0 index=0
else: else:
index = (index + 1) % stateInfo["attributes"]["effect_list"].size() index=(index + 1) % stateInfo["attributes"]["effect_list"].size()
mode_label.text = stateInfo["attributes"]["effect_list"][index] mode_label.text=stateInfo["attributes"]["effect_list"][index]
HomeApi.set_state(entity_id, "on", {"effect": stateInfo["attributes"]["effect_list"][index]}) HomeApi.set_state(entity_id, "on", {"effect": stateInfo["attributes"]["effect_list"][index]})
) )
mode_before.on_button_down.connect(func(): mode_before.on_button_down.connect(func():
var index = stateInfo["attributes"]["effect_list"].find(stateInfo["attributes"]["effect"]) var index=stateInfo["attributes"]["effect_list"].find(stateInfo["attributes"]["effect"])
if index == -1: if index == - 1:
index = 0 index=0
else: else:
index = (index - 1) % stateInfo["attributes"]["effect_list"].size() index=(index - 1) % stateInfo["attributes"]["effect_list"].size()
mode_label.text = stateInfo["attributes"]["effect_list"][index] mode_label.text=stateInfo["attributes"]["effect_list"][index]
HomeApi.set_state(entity_id, "on", {"effect": stateInfo["attributes"]["effect_list"][index]}) HomeApi.set_state(entity_id, "on", {"effect": stateInfo["attributes"]["effect_list"][index]})
) )
else: else:
remove_child(modes) remove_child(modes)
if stateInfo.has("attributes")&&stateInfo["attributes"].has("supported_color_modes")&&stateInfo["attributes"]["supported_color_modes"].has("rgb"):
if stateInfo.has("attributes") && stateInfo["attributes"].has("supported_color_modes") && stateInfo["attributes"]["supported_color_modes"].has("rgb"):
color_wheel.get_node("Clickable").on_press_down.connect(func(event: EventPointer): color_wheel.get_node("Clickable").on_press_down.connect(func(event: EventPointer):
var target_point = color_wheel.to_local(event.ray.get_collision_point()) var target_point=color_wheel.to_local(event.ray.get_collision_point())
var delta = Vector2(target_point.x, target_point.z) * (1.0 / 0.08) var delta=Vector2(target_point.x, target_point.z) * (1.0 / 0.08)
if delta.length() > 1: if delta.length() > 1:
delta = delta.normalized() delta=delta.normalized()
var color = color_wheel_img.get_image().get_pixel((delta.x * 0.5 + 0.5) * 1000, (delta.y * 0.5 + 0.5) * 1000) print("delta", delta)
color_puck.material_override.albedo_color = color var color=color_wheel_img.get_image().get_pixel((delta.x * 0.5 + 0.5) * 1000, (delta.y * 0.5 + 0.5) * 1000)
color_puck.position = Vector3(target_point.x, color_puck.position.y, target_point.z)
var attributes = { print("color", color)
color_puck.material_override.albedo_color=color
color_puck.position=Vector3(target_point.x, color_puck.position.y, target_point.z)
var attributes={
"rgb_color": [int(color.r * 255), int(color.g * 255), int(color.b * 255)], "rgb_color": [int(color.r * 255), int(color.g * 255), int(color.b * 255)],
} }
HomeApi.set_state(entity_id, "on", attributes) HomeApi.set_state(entity_id, "on", attributes)
set_state(state, attributes)
) )
color_supported = true
else: else:
remove_child(color_wheel) remove_child(color_wheel)
await HomeApi.watch_state(entity_id, func(new_state): await HomeApi.watch_state(entity_id, func(new_state):
if (new_state["state"] == "on") == state: if (new_state["state"] == "on") == state:
return return
set_state(new_state["state"] == "on") set_state(new_state["state"] == "on", new_state["attributes"])
) )
slider.on_value_changed.connect(func(new_value): slider.on_value_changed.connect(func(new_value):
var value = new_value / 100 * 255 var value=new_value / 100 * 255
HomeApi.set_state(entity_id, "on" if state else "off", {"brightness": int(value)}) HomeApi.set_state(entity_id, "on" if state else "off", {"brightness": int(value)})
set_state(state, value) set_state(state, {"brightness": value})
) )
func set_state(new_state: bool, new_brightness = null): func set_state(new_state: bool, attributes={}):
if state == false && new_state == false: if state == false&&new_state == false:
return return
state = new_state state = new_state
brightness = new_brightness
if attributes.has("brightness"):
brightness = attributes["brightness"]
if attributes.has("rgb_color")&&attributes["rgb_color"] != null:
color = Color(attributes["rgb_color"][0] / 255.0, attributes["rgb_color"][1] / 255.0, attributes["rgb_color"][2] / 255.0, 1)
var tween = create_tween()
var target_color = color_off
if state: if state:
if brightness == null: if brightness == null:
animation.speed_scale = 1 target_color = color if color_supported else color_on
animation.play_backwards("light")
else: else:
var duration = animation.get_animation("light").length target_color = color_off.lerp(color if color_supported else color_on, brightness / 255.0)
animation.speed_scale = 0
animation.seek(lerpf(0, duration, 1 - (brightness / 255.0)), true)
else:
animation.speed_scale = 1
animation.play("light")
icon_color.value = target_color
tween.tween_property(lightbulb, "material_override:albedo_color", target_color, 0.3)
func _on_click(event): func _on_click(event):
if event.target == self: if event.target == self:
var attributes = {} var attributes = {}
if !state && brightness != null: if !state&&brightness != null:
attributes["brightness"] = int(brightness) attributes["brightness"] = int(brightness)
HomeApi.set_state(entity_id, "on" if !state else "off", attributes) HomeApi.set_state(entity_id, "on" if !state else "off", attributes)
set_state(!state, brightness) set_state(!state, attributes)
func quick_action():
var attributes = {}
if !state&&brightness != null:
attributes["brightness"] = int(brightness)
HomeApi.set_state(entity_id, "on" if !state else "off", attributes)
set_state(!state, attributes)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=18 format=3 uid="uid://cw86rc42dv2d8"] [gd_scene load_steps=15 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/entities/light/light.gd" id="1_ykxy3"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="4_4sfxb"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="4_4sfxb"]
@ -12,43 +12,6 @@
[sub_resource type="SphereShape3D" id="SphereShape3D_ukj14"] [sub_resource type="SphereShape3D" id="SphereShape3D_ukj14"]
radius = 0.05 radius = 0.05
[sub_resource type="Animation" id="Animation_afofi"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("CSGCombiner3D:material_override:albedo_color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 0.85098, 0, 1)]
}
[sub_resource type="Animation" id="Animation_7o31s"]
resource_name = "light"
length = 0.3
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("CSGCombiner3D:material_override:albedo_color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.3),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(1, 0.85098, 0, 1), Color(0.231373, 0.231373, 0.231373, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_8a76q"]
_data = {
"RESET": SubResource("Animation_afofi"),
"light": SubResource("Animation_7o31s")
}
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_k3ob2"] [sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_k3ob2"]
points = PackedVector3Array(0, -0.005, -0.08, -0.00784652, -0.005, -0.0796241, 0, 0.005, -0.08, 0.00783085, -0.005, -0.0796241, -0.00784652, 0.005, -0.0796241, -0.0156147, -0.005, -0.0784651, 0.00783085, 0.005, -0.0796241, 0.0155991, -0.005, -0.0784651, -0.0156147, 0.005, -0.0784651, -0.0232263, -0.005, -0.0765701, 0.0155991, 0.005, -0.0784651, 0.0232106, -0.005, -0.0765701, -0.0232263, 0.005, -0.0765701, -0.0306186, -0.005, -0.0739233, 0.0232106, 0.005, -0.0765701, 0.030603, -0.005, -0.0739233, -0.0306186, 0.005, -0.0739233, -0.0377134, -0.005, -0.070556, 0.030603, 0.005, -0.0739233, 0.0376977, -0.005, -0.070556, -0.0377134, 0.005, -0.070556, -0.0444479, -0.005, -0.0665309, 0.0376977, 0.005, -0.070556, 0.0444323, -0.005, -0.0665309, -0.0444479, 0.005, -0.0665309, -0.0507596, -0.005, -0.0618481, 0.0444323, 0.005, -0.0665309, 0.0507439, -0.005, -0.0618481, -0.0507596, 0.005, -0.0618481, -0.0565701, -0.005, -0.0565701, 0.0507439, 0.005, -0.0618481, 0.0565544, -0.005, -0.0565701, -0.0565701, 0.005, -0.0565701, -0.0618481, -0.005, -0.0507596, 0.0565544, 0.005, -0.0565701, 0.0618324, -0.005, -0.0507596, -0.0618481, 0.005, -0.0507596, -0.0665309, -0.005, -0.0444479, 0.0618324, 0.005, -0.0507596, 0.0665153, -0.005, -0.0444479, -0.0665309, 0.005, -0.0444479, -0.070556, -0.005, -0.0377134, 0.0665153, 0.005, -0.0444479, 0.0705403, -0.005, -0.0377134, -0.070556, 0.005, -0.0377134, -0.0739233, -0.005, -0.0306186, 0.0705403, 0.005, -0.0377134, 0.0739076, -0.005, -0.0306186, -0.0739233, 0.005, -0.0306186, -0.0765701, -0.005, -0.0232263, 0.0739076, 0.005, -0.0306186, 0.0765544, -0.005, -0.0232263, -0.0765701, 0.005, -0.0232263, -0.0784651, -0.005, -0.0156147, 0.0765544, 0.005, -0.0232263, 0.0784495, -0.005, -0.0156147, -0.0784651, 0.005, -0.0156147, -0.0796241, -0.005, -0.00784652, 0.0784495, 0.005, -0.0156147, 0.0796085, -0.005, -0.00784652, -0.0796241, 0.005, -0.00784652, -0.08, -0.005, 0, 0.0796085, 0.005, -0.00784652, 0.08, -0.005, 0, -0.08, 0.005, 0, -0.0796241, -0.005, 0.00783085, 0.08, 0.005, 0, 0.0796085, -0.005, 0.00783085, -0.0796241, 0.005, 0.00783085, -0.0784651, -0.005, 0.0155991, 0.0796085, 0.005, 0.00783085, 0.0784495, -0.005, 0.0155991, -0.0784651, 0.005, 0.0155991, -0.0765701, -0.005, 0.0232106, 0.0784495, 0.005, 0.0155991, 0.0765544, -0.005, 0.0232106, -0.0765701, 0.005, 0.0232106, -0.0739233, -0.005, 0.030603, 0.0765544, 0.005, 0.0232106, 0.0739076, -0.005, 0.030603, -0.0739233, 0.005, 0.030603, -0.070556, -0.005, 0.0376977, 0.0739076, 0.005, 0.030603, 0.0705403, -0.005, 0.0376977, -0.070556, 0.005, 0.0376977, -0.0665309, -0.005, 0.0444323, 0.0705403, 0.005, 0.0376977, 0.0665153, -0.005, 0.0444323, -0.0665309, 0.005, 0.0444323, -0.0618481, -0.005, 0.0507439, 0.0665153, 0.005, 0.0444323, 0.0618324, -0.005, 0.0507439, -0.0618481, 0.005, 0.0507439, -0.0565701, -0.005, 0.0565544, 0.0618324, 0.005, 0.0507439, 0.0565544, -0.005, 0.0565544, -0.0565701, 0.005, 0.0565544, -0.0507596, -0.005, 0.0618324, 0.0565544, 0.005, 0.0565544, 0.0507439, -0.005, 0.0618324, -0.0507596, 0.005, 0.0618324, -0.0444479, -0.005, 0.0665153, 0.0507439, 0.005, 0.0618324, 0.0444323, -0.005, 0.0665153, -0.0444479, 0.005, 0.0665153, -0.0377134, -0.005, 0.0705403, 0.0444323, 0.005, 0.0665153, 0.0376977, -0.005, 0.0705403, -0.0377134, 0.005, 0.0705403, -0.0306186, -0.005, 0.0739076, 0.0376977, 0.005, 0.0705403, 0.030603, -0.005, 0.0739076, -0.0306186, 0.005, 0.0739076, -0.0232263, -0.005, 0.0765544, 0.030603, 0.005, 0.0739076, 0.0232106, -0.005, 0.0765544, -0.0232263, 0.005, 0.0765544, -0.0156147, -0.005, 0.0784495, 0.0232106, 0.005, 0.0765544, 0.0155991, -0.005, 0.0784495, -0.0156147, 0.005, 0.0784495, -0.00784652, -0.005, 0.0796085, 0.0155991, 0.005, 0.0784495, 0.00783085, -0.005, 0.0796085, -0.00784652, 0.005, 0.0796085, 0, -0.005, 0.08, 0.00783085, 0.005, 0.0796085, 0, 0.005, 0.08) points = PackedVector3Array(0, -0.005, -0.08, -0.00784652, -0.005, -0.0796241, 0, 0.005, -0.08, 0.00783085, -0.005, -0.0796241, -0.00784652, 0.005, -0.0796241, -0.0156147, -0.005, -0.0784651, 0.00783085, 0.005, -0.0796241, 0.0155991, -0.005, -0.0784651, -0.0156147, 0.005, -0.0784651, -0.0232263, -0.005, -0.0765701, 0.0155991, 0.005, -0.0784651, 0.0232106, -0.005, -0.0765701, -0.0232263, 0.005, -0.0765701, -0.0306186, -0.005, -0.0739233, 0.0232106, 0.005, -0.0765701, 0.030603, -0.005, -0.0739233, -0.0306186, 0.005, -0.0739233, -0.0377134, -0.005, -0.070556, 0.030603, 0.005, -0.0739233, 0.0376977, -0.005, -0.070556, -0.0377134, 0.005, -0.070556, -0.0444479, -0.005, -0.0665309, 0.0376977, 0.005, -0.070556, 0.0444323, -0.005, -0.0665309, -0.0444479, 0.005, -0.0665309, -0.0507596, -0.005, -0.0618481, 0.0444323, 0.005, -0.0665309, 0.0507439, -0.005, -0.0618481, -0.0507596, 0.005, -0.0618481, -0.0565701, -0.005, -0.0565701, 0.0507439, 0.005, -0.0618481, 0.0565544, -0.005, -0.0565701, -0.0565701, 0.005, -0.0565701, -0.0618481, -0.005, -0.0507596, 0.0565544, 0.005, -0.0565701, 0.0618324, -0.005, -0.0507596, -0.0618481, 0.005, -0.0507596, -0.0665309, -0.005, -0.0444479, 0.0618324, 0.005, -0.0507596, 0.0665153, -0.005, -0.0444479, -0.0665309, 0.005, -0.0444479, -0.070556, -0.005, -0.0377134, 0.0665153, 0.005, -0.0444479, 0.0705403, -0.005, -0.0377134, -0.070556, 0.005, -0.0377134, -0.0739233, -0.005, -0.0306186, 0.0705403, 0.005, -0.0377134, 0.0739076, -0.005, -0.0306186, -0.0739233, 0.005, -0.0306186, -0.0765701, -0.005, -0.0232263, 0.0739076, 0.005, -0.0306186, 0.0765544, -0.005, -0.0232263, -0.0765701, 0.005, -0.0232263, -0.0784651, -0.005, -0.0156147, 0.0765544, 0.005, -0.0232263, 0.0784495, -0.005, -0.0156147, -0.0784651, 0.005, -0.0156147, -0.0796241, -0.005, -0.00784652, 0.0784495, 0.005, -0.0156147, 0.0796085, -0.005, -0.00784652, -0.0796241, 0.005, -0.00784652, -0.08, -0.005, 0, 0.0796085, 0.005, -0.00784652, 0.08, -0.005, 0, -0.08, 0.005, 0, -0.0796241, -0.005, 0.00783085, 0.08, 0.005, 0, 0.0796085, -0.005, 0.00783085, -0.0796241, 0.005, 0.00783085, -0.0784651, -0.005, 0.0155991, 0.0796085, 0.005, 0.00783085, 0.0784495, -0.005, 0.0155991, -0.0784651, 0.005, 0.0155991, -0.0765701, -0.005, 0.0232106, 0.0784495, 0.005, 0.0155991, 0.0765544, -0.005, 0.0232106, -0.0765701, 0.005, 0.0232106, -0.0739233, -0.005, 0.030603, 0.0765544, 0.005, 0.0232106, 0.0739076, -0.005, 0.030603, -0.0739233, 0.005, 0.030603, -0.070556, -0.005, 0.0376977, 0.0739076, 0.005, 0.030603, 0.0705403, -0.005, 0.0376977, -0.070556, 0.005, 0.0376977, -0.0665309, -0.005, 0.0444323, 0.0705403, 0.005, 0.0376977, 0.0665153, -0.005, 0.0444323, -0.0665309, 0.005, 0.0444323, -0.0618481, -0.005, 0.0507439, 0.0665153, 0.005, 0.0444323, 0.0618324, -0.005, 0.0507439, -0.0618481, 0.005, 0.0507439, -0.0565701, -0.005, 0.0565544, 0.0618324, 0.005, 0.0507439, 0.0565544, -0.005, 0.0565544, -0.0565701, 0.005, 0.0565544, -0.0507596, -0.005, 0.0618324, 0.0565544, 0.005, 0.0565544, 0.0507439, -0.005, 0.0618324, -0.0507596, 0.005, 0.0618324, -0.0444479, -0.005, 0.0665153, 0.0507439, 0.005, 0.0618324, 0.0444323, -0.005, 0.0665153, -0.0444479, 0.005, 0.0665153, -0.0377134, -0.005, 0.0705403, 0.0444323, 0.005, 0.0665153, 0.0376977, -0.005, 0.0705403, -0.0377134, 0.005, 0.0705403, -0.0306186, -0.005, 0.0739076, 0.0376977, 0.005, 0.0705403, 0.030603, -0.005, 0.0739076, -0.0306186, 0.005, 0.0739076, -0.0232263, -0.005, 0.0765544, 0.030603, 0.005, 0.0739076, 0.0232106, -0.005, 0.0765544, -0.0232263, 0.005, 0.0765544, -0.0156147, -0.005, 0.0784495, 0.0232106, 0.005, 0.0765544, 0.0155991, -0.005, 0.0784495, -0.0156147, 0.005, 0.0784495, -0.00784652, -0.005, 0.0796085, 0.0155991, 0.005, 0.0784495, 0.00783085, -0.005, 0.0796085, -0.00784652, 0.005, 0.0796085, 0, -0.005, 0.08, 0.00783085, 0.005, 0.0796085, 0, 0.005, 0.08)
@ -67,7 +30,7 @@ top_radius = 0.01
bottom_radius = 0.01 bottom_radius = 0.01
height = 0.005 height = 0.005
[node name="Light" type="StaticBody3D" groups=["entity"]] [node name="Light" type="StaticBody3D"]
collision_mask = 0 collision_mask = 0
script = ExtResource("1_ykxy3") script = ExtResource("1_ykxy3")
@ -80,26 +43,21 @@ script = ExtResource("5_oh4jg")
[node name="Movable" type="Node" parent="."] [node name="Movable" type="Node" parent="."]
script = ExtResource("4_4sfxb") script = ExtResource("4_4sfxb")
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="."] [node name="Lightbulb" type="CSGCombiner3D" parent="."]
transform = Transform3D(1, 9.69949e-05, 0.000589194, -9.77749e-05, 0.999999, 0.00135802, -0.000589065, -0.00135808, 0.999999, 0, 0, 0) transform = Transform3D(1, 9.69949e-05, 0.000589194, -9.77749e-05, 0.999999, 0.00135802, -0.000589065, -0.00135808, 0.999999, 0, 0, 0)
material_override = ExtResource("5_50gph") material_override = ExtResource("5_50gph")
[node name="CSGSphere3D" type="CSGSphere3D" parent="CSGCombiner3D"] [node name="CSGSphere3D" type="CSGSphere3D" parent="Lightbulb"]
radius = 0.05 radius = 0.05
radial_segments = 36 radial_segments = 36
rings = 12 rings = 12
[node name="CSGCylinder3D" type="CSGCylinder3D" parent="CSGCombiner3D"] [node name="CSGCylinder3D" type="CSGCylinder3D" parent="Lightbulb"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.0485739, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.0485739, 0)
radius = 0.02 radius = 0.02
height = 0.03 height = 0.03
sides = 36 sides = 36
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_8a76q")
}
[node name="Slider" parent="." instance=ExtResource("6_mhjlm")] [node name="Slider" parent="." instance=ExtResource("6_mhjlm")]
transform = Transform3D(1.91069e-15, 4.37114e-08, 1, 1, -4.37114e-08, 0, 4.37114e-08, 1, -4.37114e-08, 0.08, 0, 0) transform = Transform3D(1.91069e-15, 4.37114e-08, 1, 1, -4.37114e-08, 0, 4.37114e-08, 1, -4.37114e-08, 0.08, 0, 0)
max = 100.0 max = 100.0

View File

@ -2,7 +2,5 @@
[resource] [resource]
resource_local_to_scene = true resource_local_to_scene = true
albedo_color = Color(1, 0.85098, 0, 1)
emission_enabled = true
emission = Color(1, 0.65098, 0, 1) emission = Color(1, 0.65098, 0, 1)
emission_energy_multiplier = 0.0 emission_energy_multiplier = 0.0

View File

@ -9,6 +9,8 @@ const Entity = preload ("../entity.gd")
func _ready(): func _ready():
super() super()
icon.value = "finance"
label.text = entity_id label.text = entity_id
if HomeApi.has_connected() == false: if HomeApi.has_connected() == false:

View File

@ -7,7 +7,7 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_rmm5v"] [sub_resource type="BoxShape3D" id="BoxShape3D_rmm5v"]
size = Vector3(0.5, 0.3, 0.001) size = Vector3(0.5, 0.3, 0.001)
[node name="LineChart" type="StaticBody3D" groups=["entity"]] [node name="LineChart" type="StaticBody3D"]
collision_layer = 5 collision_layer = 5
collision_mask = 0 collision_mask = 0
script = ExtResource("1_5dxim") script = ExtResource("1_5dxim")

View File

@ -20,6 +20,8 @@ var volume = 50
func _ready(): func _ready():
super() super()
icon.value = "pause_circle"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
set_state(stateInfo) set_state(stateInfo)
@ -65,9 +67,11 @@ func set_state(stateInfo):
playing = true playing = true
play.label = "pause" play.label = "pause"
icon.value = "play_circle"
else: else:
playing = false playing = false
play.label = "play_arrow" play.label = "play_arrow"
icon.value = "pause_circle"
func load_image(url: String): func load_image(url: String):
http_request.request("http://192.168.33.33:8123" + url) http_request.request("http://192.168.33.33:8123" + url)

View File

@ -10,7 +10,7 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_vi3eg"] [sub_resource type="BoxShape3D" id="BoxShape3D_vi3eg"]
size = Vector3(0.23, 0.142768, 0.01) size = Vector3(0.23, 0.142768, 0.01)
[node name="MediaPlayer" type="StaticBody3D" groups=["entity"]] [node name="MediaPlayer" type="StaticBody3D" ]
collision_mask = 0 collision_mask = 0
script = ExtResource("1_ame17") script = ExtResource("1_ame17")

View File

@ -8,6 +8,8 @@ const Entity = preload ("../entity.gd")
func _ready(): func _ready():
super() super()
icon.value = "sliders"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
if stateInfo == null: if stateInfo == null:
return return

View File

@ -8,7 +8,7 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_7mk8w"] [sub_resource type="BoxShape3D" id="BoxShape3D_7mk8w"]
size = Vector3(0.0390625, 0.114258, 0.0142822) size = Vector3(0.0390625, 0.114258, 0.0142822)
[node name="Number" type="StaticBody3D" groups=["entity"]] [node name="Number" type="StaticBody3D" ]
script = ExtResource("1_26xwp") script = ExtResource("1_26xwp")
[node name="Slider" parent="." instance=ExtResource("2_sninv")] [node name="Slider" parent="." instance=ExtResource("2_sninv")]

View File

@ -14,6 +14,8 @@ var is_text = true
func _ready(): func _ready():
super() super()
icon.value = "sensors"
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
set_text(stateInfo) set_text(stateInfo)

View File

@ -10,7 +10,7 @@
resource_local_to_scene = true resource_local_to_scene = true
size = Vector3(0.18, 0.03, 0.02) size = Vector3(0.18, 0.03, 0.02)
[node name="Sensor" type="StaticBody3D" groups=["entity"]] [node name="Sensor" type="StaticBody3D" ]
collision_mask = 0 collision_mask = 0
script = ExtResource("1_57ac8") script = ExtResource("1_57ac8")

View File

@ -1,13 +1,12 @@
extends Entity extends Entity
const Entity = preload("../entity.gd") const Entity = preload ("../entity.gd")
@onready var sprite: AnimatedSprite3D = $Icon @onready var sprite: AnimatedSprite3D = $Icon
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
super() super()
var stateInfo = await HomeApi.get_state(entity_id) var stateInfo = await HomeApi.get_state(entity_id)
if stateInfo == null: if stateInfo == null:
return return
@ -17,15 +16,18 @@ func _ready():
else: else:
sprite.set_frame(1) sprite.set_frame(1)
icon.value = "toggle_" + stateInfo["state"]
await HomeApi.watch_state(entity_id, func(new_state): await HomeApi.watch_state(entity_id, func(new_state):
if new_state["state"] == "on": if new_state["state"] == "on":
sprite.set_frame(0) sprite.set_frame(0)
else: else:
sprite.set_frame(1) sprite.set_frame(1)
icon.value="toggle_" + new_state["state"]
) )
func _on_click(_event):
func _on_click(event):
HomeApi.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on") HomeApi.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
if sprite.get_frame() == 0: if sprite.get_frame() == 0:
sprite.set_frame(1) sprite.set_frame(1)
@ -34,3 +36,10 @@ func _on_click(event):
func _on_request_completed(): func _on_request_completed():
pass pass
func quick_action():
HomeApi.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
if sprite.get_frame() == 0:
sprite.set_frame(1)
else:
sprite.set_frame(0)

View File

@ -23,7 +23,7 @@ animations = [{
"speed": 5.0 "speed": 5.0
}] }]
[node name="Switch" type="StaticBody3D" groups=["entity"]] [node name="Switch" type="StaticBody3D" ]
collision_mask = 0 collision_mask = 0
script = ExtResource("1_8ffhi") script = ExtResource("1_8ffhi")

View File

@ -40,7 +40,6 @@ func _ready():
_emit_action(name, false, true) _emit_action(name, false, true)
) )
remove_child(menu)
remove_child(keyboard) remove_child(keyboard)
EventSystem.on_action_down.connect(func(action): EventSystem.on_action_down.connect(func(action):
@ -81,13 +80,7 @@ func create_voice_assistant():
) )
func toggle_menu(): func toggle_menu():
if menu.show_menu == false: menu.show_menu.value = !menu.show_menu.value
add_child(menu)
menu.global_transform = _get_menu_transform()
menu.show_menu = !menu.show_menu
await menu.get_node("AnimationPlayer").animation_finished
if menu.show_menu == false:
remove_child(menu)
func _emit_action(name: String, value, right_controller: bool=true): func _emit_action(name: String, value, right_controller: bool=true):
var event = EventAction.new() var event = EventAction.new()
@ -126,14 +119,6 @@ func _input(event):
if event is InputEventKey and Input.is_key_pressed(KEY_M): if event is InputEventKey and Input.is_key_pressed(KEY_M):
toggle_menu() toggle_menu()
func _get_menu_transform():
var transform = camera.get_global_transform()
transform.origin -= transform.basis.z * 0.5
transform.basis = transform.basis.rotated(transform.basis.x, deg_to_rad(90))
return transform
func vector_key_mapping(key_positive_x: int, key_negative_x: int, key_positive_y: int, key_negative_y: int): func vector_key_mapping(key_positive_x: int, key_negative_x: int, key_positive_y: int, key_negative_y: int):
var x = 0 var x = 0
var y = 0 var y = 0

View File

@ -72,6 +72,7 @@ ray_right = NodePath("../XRControllerRight/Raycast")
enable_passthrough = true enable_passthrough = true
[node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")] [node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")]
min_camera_height = 0.01
xr_origin = NodePath("../XROrigin3D") xr_origin = NodePath("../XROrigin3D")
[node name="Menu" parent="." instance=ExtResource("8_du83w")] [node name="Menu" parent="." instance=ExtResource("8_du83w")]

View File

@ -1,5 +1,7 @@
extends XRController3D extends XRController3D
const Entity = preload ("res://content/entities/entity.gd")
@onready var area = $trash_bin/Area3D @onready var area = $trash_bin/Area3D
@onready var trash_bin = $trash_bin @onready var trash_bin = $trash_bin
@onready var animation = $AnimationPlayer @onready var animation = $AnimationPlayer
@ -35,21 +37,21 @@ func _ready():
trash_bin_visible = false trash_bin_visible = false
EventSystem.on_grab_down.connect(func(event: EventPointer): EventSystem.on_grab_down.connect(func(event: EventPointer):
trash_bin_visible = event.target.is_in_group("entity") trash_bin_visible=event.target is Entity
) )
EventSystem.on_grab_move.connect(func(event): EventSystem.on_grab_move.connect(func(event):
if !trash_bin_visible: if !trash_bin_visible:
return return
if event.target.is_in_group("entity") && area.overlaps_body(event.target): if event.target is Entity&&area.overlaps_body(event.target):
if !to_delete.has(event.target): if !to_delete.has(event.target):
to_delete.append(event.target) to_delete.append(event.target)
trash_bin_large = true trash_bin_large=true
else: else:
to_delete.erase(event.target) to_delete.erase(event.target)
trash_bin_large = false trash_bin_large=false
) )
@ -60,6 +62,6 @@ func _ready():
for entity in to_delete: for entity in to_delete:
entity.queue_free() entity.queue_free()
to_delete.clear() to_delete.clear()
trash_bin_large = false trash_bin_large=false
trash_bin_visible = false trash_bin_visible=false
) )

View File

@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"] [ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"]
[ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"] [ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"] [ext_resource type="PackedScene" uid="uid://dscp8x0ari57n" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true ao_enabled = true

View File

@ -0,0 +1,67 @@
extends StaticBody3D
const Entity = preload ("res://content/entities/entity.gd")
const TOUCH_LONG = 400.0
@export var entity: Entity
@onready var collision = $CollisionShape3D
@onready var label = $Label3D
var active = R.state(false)
var disabled = R.state(true)
var touched_enter = 0.0
var moved_ran = false
var touch_ran = false
var miniature = House.body.mini_view
func _ready():
R.effect(func(_arg):
label.text=entity.icon.value
label.modulate=entity.icon_color.value
)
# Update active
R.effect(func(_arg):
label.outline_modulate=Color(242 / 255.0, 90 / 255.0, 56 / 255.0, 1) if active.value else Color(0, 0, 0, 1)
)
# Update disabled
R.effect(func(_arg):
visible=!disabled.value
collision.disabled=disabled.value
)
func _on_click(_event: EventPointer):
if entity.has_method("quick_action"):
entity.quick_action()
else:
miniature.entity_select.toggle(entity)
func _on_press_move(_event: EventPointer):
if moved_ran: return
miniature.entity_select.toggle(entity)
moved_ran = true
func _on_press_up(_event: EventPointer):
moved_ran = false
func _on_touch_enter(_event: EventTouch):
touched_enter = Time.get_ticks_msec()
touch_ran = false
func _on_touch_move(_event: EventTouch):
if touch_ran||Time.get_ticks_msec() - touched_enter < TOUCH_LONG: return
miniature.entity_select.toggle(entity)
touch_ran = true
func _on_touch_leave(_event: EventTouch):
if touch_ran: return
if entity.has_method("quick_action"):
entity.quick_action()
else:
miniature.entity_select.toggle(entity)

View File

@ -0,0 +1,34 @@
[gd_scene load_steps=5 format=3 uid="uid://b5buw1sas18n4"]
[ext_resource type="Script" path="res://content/system/dot/dot.gd" id="1_vdpux"]
[ext_resource type="FontVariation" uid="uid://sshfnckriqxn" path="res://assets/icons/icons.tres" id="4_504vw"]
[sub_resource type="SphereShape3D" id="SphereShape3D_3wgjq"]
custom_solver_bias = 0.2
radius = 0.1
[sub_resource type="SphereShape3D" id="SphereShape3D_y1ne8"]
custom_solver_bias = 0.2
radius = 0.2
[node name="Dot" type="StaticBody3D"]
script = ExtResource("1_vdpux")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("SphereShape3D_3wgjq")
[node name="Label3D" type="Label3D" parent="."]
pixel_size = 0.002
billboard = 1
text = "lightbulb"
font = ExtResource("4_504vw")
font_size = 100
outline_size = 18
[node name="Area3D" type="Area3D" parent="."]
collision_layer = 4
collision_mask = 0
monitoring = false
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Area3D"]
shape = SubResource("SphereShape3D_y1ne8")

View File

@ -5,9 +5,16 @@ const Initiator = preload ("res://lib/utils/pointer/initiator.gd")
const Finger = preload ("res://lib/utils/touch/finger.gd") const Finger = preload ("res://lib/utils/touch/finger.gd")
const Touch = preload ("res://lib/utils/touch/touch.gd") const Touch = preload ("res://lib/utils/touch/touch.gd")
const Collide = preload ("res://lib/utils/touch/collide.gd") const Collide = preload ("res://lib/utils/touch/collide.gd")
const Miniature = preload ("res://content/system/house/mini/miniature.gd")
@onready var main = $"/root/Main"
@onready var hand_right: OpenXRHand = $XRHandRight @onready var hand_right: OpenXRHand = $XRHandRight
@onready var hand_left: OpenXRHand = $XRHandLeft @onready var hand_left: OpenXRHand = $XRHandLeft
@onready var palm = $XRHandLeft/Palm
@onready var quick_actions = $XRHandLeft/Palm/QuickActions
@onready var mini_view_button = $XRHandLeft/Palm/QuickActions/MiniView
@onready var temperature_button = $XRHandLeft/Palm/QuickActions/Temperature
@onready var humidity_button = $XRHandLeft/Palm/QuickActions/Humidity
@export var ray_left: RayCast3D @export var ray_left: RayCast3D
@export var ray_right: RayCast3D @export var ray_right: RayCast3D
var initiator: Initiator = Initiator.new() var initiator: Initiator = Initiator.new()
@ -38,6 +45,24 @@ func _ready():
_ready_hand(hand_right) _ready_hand(hand_right)
mini_view_button.on_button_up.connect(func():
House.body.mini_view.small.value=!House.body.mini_view.small.value
)
temperature_button.on_button_up.connect(func():
if House.body.mini_view.heatmap_type.value == Miniature.HeatmapType.TEMPERATURE:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.NONE
else:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.TEMPERATURE
)
humidity_button.on_button_up.connect(func():
if House.body.mini_view.heatmap_type.value == Miniature.HeatmapType.HUMIDITY:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.NONE
else:
House.body.mini_view.heatmap_type.value=Miniature.HeatmapType.HUMIDITY
)
func _ready_hand(hand: OpenXRHand): func _ready_hand(hand: OpenXRHand):
initiator.type = Initiator.Type.HAND_RIGHT if hand == hand_right else Initiator.Type.HAND_LEFT initiator.type = Initiator.Type.HAND_RIGHT if hand == hand_right else Initiator.Type.HAND_LEFT
initiator.node = ray_left.get_parent() if hand == hand_left else ray_right.get_parent() initiator.node = ray_left.get_parent() if hand == hand_left else ray_right.get_parent()
@ -45,7 +70,14 @@ func _ready_hand(hand: OpenXRHand):
pointer = Pointer.new(initiator, ray_left if hand == hand_left else ray_right) pointer = Pointer.new(initiator, ray_left if hand == hand_left else ray_right)
add_child(pointer) add_child(pointer)
func _process(_delta):
if main.camera.global_transform.basis.z.dot(palm.global_transform.basis.y) > 0.85:
if quick_actions.is_inside_tree() == false: palm.add_child(quick_actions)
else:
if quick_actions.is_inside_tree(): palm.remove_child(quick_actions)
func _physics_process(_delta): func _physics_process(_delta):
_process_hand(hand_left)
_process_hand(hand_right) _process_hand(hand_right)
func _process_hand(hand: OpenXRHand): func _process_hand(hand: OpenXRHand):

View File

@ -3,6 +3,7 @@
[ext_resource type="Script" path="res://content/system/hands/hands.gd" id="1_c4f76"] [ext_resource type="Script" path="res://content/system/hands/hands.gd" id="1_c4f76"]
[ext_resource type="PackedScene" uid="uid://c0kow4g10wolq" path="res://assets/models/hands_steam/right_hand.glb" id="1_uekbj"] [ext_resource type="PackedScene" uid="uid://c0kow4g10wolq" path="res://assets/models/hands_steam/right_hand.glb" id="1_uekbj"]
[ext_resource type="PackedScene" uid="uid://dt4ksvogfctkr" path="res://assets/models/hands_steam/left_hand.glb" id="2_n73lt"] [ext_resource type="PackedScene" uid="uid://dt4ksvogfctkr" path="res://assets/models/hands_steam/left_hand.glb" id="2_n73lt"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="3_te2p8"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_3bjtw"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_3bjtw"]
transparency = 1 transparency = 1
@ -12,9 +13,6 @@ albedo_color = Color(1, 1, 1, 0.705882)
radius = 0.001 radius = 0.001
height = 0.02 height = 0.02
[sub_resource type="BoxShape3D" id="BoxShape3D_1pxrt"]
size = Vector3(0.14, 0.0224609, 0.169383)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n27ki"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n27ki"]
transparency = 1 transparency = 1
albedo_color = Color(1, 1, 1, 0.705882) albedo_color = Color(1, 1, 1, 0.705882)
@ -82,18 +80,25 @@ monitorable = false
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0) transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke") shape = SubResource("CapsuleShape3D_dopke")
[node name="AnimatableBody3D" type="AnimatableBody3D" parent="XRHandLeft"] [node name="Palm" type="Node3D" parent="XRHandLeft"]
transform = Transform3D(1, 8.67362e-19, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) transform = Transform3D(-0.707107, -8.74228e-08, -0.707107, 6.18173e-08, -1, 6.18173e-08, -0.707107, -8.29045e-24, 0.707107, 0.01, -0.04, -5.58794e-09)
collision_layer = 8
collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandLeft/AnimatableBody3D"] [node name="QuickActions" type="Node3D" parent="XRHandLeft/Palm"]
transform = Transform3D(1, 1.05818e-16, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436) transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0)
shape = SubResource("BoxShape3D_1pxrt")
disabled = true
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandLeft"] [node name="MiniView" parent="XRHandLeft/Palm/QuickActions" instance=ExtResource("3_te2p8")]
remote_path = NodePath("../AnimatableBody3D") transform = Transform3D(1, -3.55271e-15, -4.33681e-19, 3.55271e-15, 1, 3.5525e-15, -4.33681e-19, -3.55291e-15, 1, -0.0600001, 0, 0)
label = "nest_multi_room"
icon = true
[node name="Temperature" parent="XRHandLeft/Palm/QuickActions" instance=ExtResource("3_te2p8")]
label = "device_thermostat"
icon = true
[node name="Humidity" parent="XRHandLeft/Palm/QuickActions" instance=ExtResource("3_te2p8")]
transform = Transform3D(1, 1.73472e-18, 0, 0, 1, 0, 0, 0, 1, 0.0600001, -5.68873e-13, 0)
label = "humidity_mid"
icon = true
[node name="XRHandRight" type="OpenXRHand" parent="."] [node name="XRHandRight" type="OpenXRHand" parent="."]
transform = Transform3D(0.999998, -0.000567105, 2.47889e-11, 0, -4.37113e-08, -0.999999, 0.000567104, 0.999999, -4.37113e-08, 0.264391, 0, 0) transform = Transform3D(0.999998, -0.000567105, 2.47889e-11, 0, -4.37113e-08, -0.999999, 0.000567104, 0.999999, -4.37113e-08, 0.264391, 0, 0)
@ -156,18 +161,5 @@ monitorable = false
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0) transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke") shape = SubResource("CapsuleShape3D_dopke")
[node name="AnimatableBody3D" type="AnimatableBody3D" parent="XRHandRight"]
transform = Transform3D(1, 0, 0, 0, 1, 3.55271e-15, 0, -3.55271e-15, 1, 0, 0, 0)
collision_layer = 8
collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/AnimatableBody3D"]
transform = Transform3D(1, 0, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436)
shape = SubResource("BoxShape3D_1pxrt")
disabled = true
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandRight"]
remote_path = NodePath("../AnimatableBody3D")
[editable path="XRHandLeft/left_hand"] [editable path="XRHandLeft/left_hand"]
[editable path="XRHandRight/right_hand"] [editable path="XRHandRight/right_hand"]

View File

@ -12,6 +12,7 @@ const AlignReference = preload ("./align_reference.gd")
var fixing_reference: bool = false var fixing_reference: bool = false
var editing_room: RoomType = null var editing_room: RoomType = null
var loaded = R.state(false)
func _ready(): func _ready():
Store.house.on_loaded.connect(func(): Store.house.on_loaded.connect(func():
@ -19,6 +20,7 @@ func _ready():
) )
func update_house(): func update_house():
loaded.value = false
for old_room in get_rooms(0): for old_room in get_rooms(0):
old_room.queue_free() old_room.queue_free()
await old_room.tree_exited await old_room.tree_exited
@ -46,6 +48,8 @@ func update_house():
entity_instance.global_position = entity.position entity_instance.global_position = entity.position
entity_instance.global_rotation = entity.rotation entity_instance.global_rotation = entity.rotation
loaded.value = true
func create_room(room_name: String, level: int) -> RoomType: func create_room(room_name: String, level: int) -> RoomType:
var existing_room = Store.house.get_room(room_name) var existing_room = Store.house.get_room(room_name)
@ -247,4 +251,5 @@ func save_all_entities():
Store.house.state.entities.append(entity_data) Store.house.state.entities.append(entity_data)
Store.house.state.entities = Store.house.state.entities
Store.house.save_local() Store.house.save_local()

View File

@ -0,0 +1,74 @@
extends Marker3D
const DotScene = preload ("res://content/system/dot/dot.tscn")
const Entity = preload ("res://content/entities/entity.gd")
@onready var dots = $"../Small/Dots"
var active_type = null
var editing = R.state([])
var group_entity = null
func _ready():
await House.body.ready
# Update Group Entity
R.effect(func(_arg):
if editing.value.size() == 0:
if group_entity != null:
group_entity.queue_free()
group_entity=null
elif group_entity == null:
var id=HomeApi.groups.create(editing.value.map(func(entity): return entity.entity_id))
group_entity=EntityFactory.create_entity(id, active_type)
for entity_node in group_entity.get_children():
if entity_node is Movable:
group_entity.remove_child(entity_node)
add_child(group_entity)
else:
HomeApi.groups.update_entities(group_entity.entity_id, editing.value.map(func(entity): return entity.entity_id))
)
var dots_disabled = R.computed(func(_arg):
return House.body.mini_view.small.value == false
)
# Update Entities
R.effect(func(_arg):
if House.body.loaded.value == false:
return
if Store.house.state.entities.size() == 0:
return
for old_dot in dots.get_children():
dots.remove_child(old_dot)
old_dot.free()
for room in House.body.get_rooms(0):
for entity in room.get_node("Entities").get_children():
var dot=DotScene.instantiate()
dot.position=House.body.to_local(entity.global_position)
dot.entity=entity
dot.active=R.computed(func(_arg2):
return editing.value.has(entity)
)
dot.disabled=dots_disabled
dots.add_child(dot)
)
func toggle(entity: Entity):
if active_type == null:
active_type = entity.entity_id.split(".")[0]
elif active_type != entity.entity_id.split(".")[0]:
return
if editing.value.has(entity):
editing.value.erase(entity)
if editing.value.size() == 0:
active_type = null
else:
editing.value.append(entity)
editing.value = editing.value

View File

@ -2,14 +2,15 @@ extends Node3D
const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd") const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd")
const wall_material = preload ("./mini_wall.tres") const wall_material = preload ("./mini_wall.tres")
const humidity_gradient = preload ("./humid_gradient.tres") const humidity_gradient = preload ("./humid_gradient.tres")
const temperature_gradient = preload ("./temp_gradient.tres") const temperature_gradient = preload ("./temp_gradient.tres")
@onready var body = $Body @onready var body = $Body
@onready var model = $Body/Model @onready var small_node = $Body/Small
@onready var model = $Body/Small/Model
@onready var collision_shape = $Body/CollisionShape3D @onready var collision_shape = $Body/CollisionShape3D
@onready var toggle_heatmap = $Body/HeatmapButton @onready var toggle_heatmap = $Body/HeatmapButton
@onready var entity_select = $Body/EntitySelect
enum HeatmapType { enum HeatmapType {
NONE = 0, NONE = 0,
@ -75,12 +76,15 @@ func _ready():
if small.value: if small.value:
var aabb=House.body.get_level_aabb(0) var aabb=House.body.get_level_aabb(0)
var height=aabb.size.y
aabb.position.y=- 0.03 aabb.position.y=- 0.03
aabb.size.y=0.06 aabb.size.y=0.06
var center=aabb.position + aabb.size / 2 var center=aabb.position + aabb.size / 2
collision_shape.shape.size=aabb.size * 0.1 collision_shape.shape.size=aabb.size * 0.1
entity_select.position=Vector3(0, height * 0.1 + 0.1, 0)
var camera=$"/root/Main/XROrigin3D/XRCamera3D" var camera=$"/root/Main/XROrigin3D/XRCamera3D"
var camera_position=camera.global_position var camera_position=camera.global_position
@ -92,10 +96,10 @@ func _ready():
var target_position=camera_position + camera_direction.normalized() * 0.2 var target_position=camera_position + camera_direction.normalized() * 0.2
var new_position=target_position - center * 0.1 var new_position=target_position - center * 0.1
tween.tween_property(model, "scale", Vector3(0.1, 0.1, 0.1), 0.5) tween.tween_property(small_node, "scale", Vector3(0.1, 0.1, 0.1), 0.5)
tween.tween_property(body, "position", new_position, 0.5) tween.tween_property(body, "position", new_position, 0.5)
else: else:
tween.tween_property(model, "scale", Vector3.ONE, 0.5) tween.tween_property(small_node, "scale", Vector3.ONE, 0.5)
tween.tween_property(body, "position", Vector3.ZERO, 0.5) tween.tween_property(body, "position", Vector3.ZERO, 0.5)
tween.tween_property(body, "quaternion", Quaternion.IDENTITY, 0.5) tween.tween_property(body, "quaternion", Quaternion.IDENTITY, 0.5)
) )
@ -105,8 +109,7 @@ func _ready():
var show_map=heatmap_type.value != HeatmapType.NONE var show_map=heatmap_type.value != HeatmapType.NONE
var show_small=small.value var show_small=small.value
for child in model.get_children(): model.visible=show_map||show_small
child.visible=show_map||show_small
) )
# Update Heatmap # Update Heatmap

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=4 format=3 uid="uid://ds60i5n211hi3"] [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/system/house/mini/miniature.gd" id="1_b53yn"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="2_x7oed"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="2_x7oed"]
[ext_resource type="Script" path="res://content/system/house/mini/Entity.gd" id="3_tgpny"]
[sub_resource type="BoxShape3D" id="BoxShape3D_bckw3"] [sub_resource type="BoxShape3D" id="BoxShape3D_bckw3"]
@ -15,5 +16,15 @@ shape = SubResource("BoxShape3D_bckw3")
[node name="Movable" type="Node" parent="Body"] [node name="Movable" type="Node" parent="Body"]
script = ExtResource("2_x7oed") script = ExtResource("2_x7oed")
restricted = true
[node name="Model" type="Node3D" parent="Body"] [node name="Small" type="Node3D" parent="Body"]
[node name="Model" type="Node3D" parent="Body/Small"]
[node name="Dots" type="Node3D" parent="Body/Small"]
[node name="EntitySelect" type="Marker3D" parent="Body"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.757576, 0)
gizmo_extents = 0.1
script = ExtResource("3_tgpny")

View File

@ -10,7 +10,7 @@ cull_mode = 2
shading_mode = 0 shading_mode = 0
albedo_color = Color(0.109804, 0.721569, 0.262745, 1) albedo_color = Color(0.109804, 0.721569, 0.262745, 1)
[sub_resource type="ArrayMesh" id="ArrayMesh_raxtd"] [sub_resource type="ArrayMesh" id="ArrayMesh_25da5"]
_surfaces = [{ _surfaces = [{
"aabb": AABB(-0.000587015, -0.000596339, 0.0005, 0.501171, 0.301189, 1e-05), "aabb": AABB(-0.000587015, -0.000596339, 0.0005, 0.501171, 0.301189, 1e-05),
"format": 34359742465, "format": 34359742465,
@ -43,7 +43,7 @@ script = ExtResource("1_n7fu8")
[node name="Line" type="MeshInstance3D" parent="."] [node name="Line" type="MeshInstance3D" parent="."]
material_override = SubResource("StandardMaterial3D_20gpn") material_override = SubResource("StandardMaterial3D_20gpn")
mesh = SubResource("ArrayMesh_raxtd") mesh = SubResource("ArrayMesh_25da5")
[node name="Plane" type="MeshInstance3D" parent="."] [node name="Plane" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.15, -0.001) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.15, -0.001)

View File

@ -1,28 +1,49 @@
extends Node3D extends Node3D
const Notification = preload("res://content/ui/components/notification/notification.tscn") const Notification = preload ("res://content/ui/components/notification/notification.tscn")
@onready var animation_player = $AnimationPlayer @onready var animation_player = $AnimationPlayer
@onready var notify_place = $AnimationContainer/NotifyPlace @onready var notify_place = $AnimationContainer/NotifyPlace
@onready var main = $"/root/Main"
var show_menu := false: var show_menu = R.state(false)
set(value):
show_menu = value func _ready():
if value: await main.ready
main.remove_child(self)
R.effect(func(_arg):
if show_menu.value:
main.add_child(self)
move_into_view()
animation_player.play_backwards("hide_menu") animation_player.play_backwards("hide_menu")
AudioPlayer.play_effect("open_menu") AudioPlayer.play_effect("open_menu")
else: else:
animation_player.play("hide_menu") animation_player.play("hide_menu")
AudioPlayer.play_effect("close_menu") AudioPlayer.play_effect("close_menu")
)
animation_player.animation_finished.connect(func(_animation):
if show_menu.value == false:
main.remove_child(self)
)
func _ready():
EventSystem.on_notify.connect(func(event: EventNotify): EventSystem.on_notify.connect(func(event: EventNotify):
var notification_node = Notification.instantiate() var notification_node=Notification.instantiate()
notification_node.text = event.message notification_node.text=event.message
notification_node.type = event.type notification_node.type=event.type
for child in notify_place.get_children(): for child in notify_place.get_children():
child.position += Vector3(0, 0, -0.06) child.position += Vector3(0, 0, -0.06)
notify_place.add_child(notification_node) notify_place.add_child(notification_node)
) )
func move_into_view():
var camera_transform = main.camera.global_transform
camera_transform.origin -= camera_transform.basis.z * 0.5
camera_transform.basis = camera_transform.basis.rotated(camera_transform.basis.x, deg_to_rad(90))
global_transform = camera_transform

View File

@ -18,10 +18,10 @@ size = Vector3(0.38, 0.0128076, 0.32)
[sub_resource type="BoxShape3D" id="BoxShape3D_6xn1i"] [sub_resource type="BoxShape3D" id="BoxShape3D_6xn1i"]
size = Vector3(0.3, 0.0264844, 0.3) size = Vector3(0.3, 0.0264844, 0.3)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ti5t2"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_01s1g"]
[sub_resource type="BoxMesh" id="BoxMesh_08du6"] [sub_resource type="BoxMesh" id="BoxMesh_08du6"]
material = SubResource("StandardMaterial3D_ti5t2") material = SubResource("StandardMaterial3D_01s1g")
size = Vector3(0.3, 0.01, 0.3) size = Vector3(0.3, 0.01, 0.3)
[sub_resource type="Animation" id="Animation_61md4"] [sub_resource type="Animation" id="Animation_61md4"]

View File

@ -0,0 +1 @@
extends Node3D

View File

@ -0,0 +1,42 @@
[gd_scene load_steps=6 format=3 uid="uid://cmtp5kof0ah2b"]
[ext_resource type="Material" uid="uid://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="1_mxydb"]
[ext_resource type="Script" path="res://content/ui/sub_menu/sub_menu.gd" id="1_xpjuw"]
[ext_resource type="PackedScene" uid="uid://blrhy2uccrdn4" path="res://content/ui/components/input/input.tscn" id="2_64uue"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ti5t2"]
[sub_resource type="BoxMesh" id="BoxMesh_aisgf"]
material = SubResource("StandardMaterial3D_ti5t2")
size = Vector3(0.3, 0.01, 0.3)
[node name="SubMenu" type="Node3D"]
script = ExtResource("1_xpjuw")
[node name="Background" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15, 0, 0.15)
material_override = ExtResource("1_mxydb")
mesh = SubResource("BoxMesh_aisgf")
skeleton = NodePath("../..")
[node name="Content" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.006, 0)
[node name="Label3D" type="Label3D" parent="Content"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.02)
pixel_size = 0.001
text = "Entity Name"
font_size = 24
outline_size = 0
horizontal_alignment = 0
[node name="Label3D2" type="Label3D" parent="Content"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.06)
pixel_size = 0.001
text = "ID:"
font_size = 18
outline_size = 0
horizontal_alignment = 0
[node name="Input" parent="Content" instance=ExtResource("2_64uue")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.12, 0, 0.06)

View File

@ -2,6 +2,7 @@ extends Node
## Manages the connection to the home automation system and provides a unified interface to the different home automation systems. ## Manages the connection to the home automation system and provides a unified interface to the different home automation systems.
const Hass = preload ("res://lib/home_apis/hass/hass.gd") const Hass = preload ("res://lib/home_apis/hass/hass.gd")
const EntityGroups = preload ("res://lib/utils/entity_group.gd")
const HassWebSocket = preload ("res://lib/home_apis/hass_ws/hass.gd") const HassWebSocket = preload ("res://lib/home_apis/hass_ws/hass.gd")
const VoiceAssistant = preload ("res://lib/home_apis/voice_handler.gd") const VoiceAssistant = preload ("res://lib/home_apis/voice_handler.gd")
@ -18,6 +19,8 @@ const methods = [
"watch_state" "watch_state"
] ]
var groups = EntityGroups.new()
## Emitted when the connection to the home automation system is established ## Emitted when the connection to the home automation system is established
signal on_connect() signal on_connect()
@ -86,16 +89,37 @@ func get_device(id: String):
## Returns the current state of an entity ## Returns the current state of an entity
func get_state(entity: String): func get_state(entity: String):
assert(has_connected(), "Not connected") assert(has_connected(), "Not connected")
var group = groups.get_group(entity)
if group != null:
return await api.get_state(group[0])
return await api.get_state(entity) return await api.get_state(entity)
## Updates the state of the entity and returns the resulting state ## Updates the state of the entity and returns the resulting state
func set_state(entity: String, state: Variant, attributes: Dictionary={}): func set_state(entity: String, state: Variant, attributes: Dictionary={}):
assert(has_connected(), "Not connected") assert(has_connected(), "Not connected")
var group = groups.get_group(entity)
if group != null:
for group_entity in group:
api.set_state(group_entity, state, attributes)
return null
return await api.set_state(entity, state, attributes) return await api.set_state(entity, state, attributes)
## Watches the state and each time it changes, calls the callback with the changed state, returns a function to stop watching the state ## Watches the state and each time it changes, calls the callback with the changed state, returns a function to stop watching the state
func watch_state(entity: String, callback: Callable): func watch_state(entity: String, callback: Callable):
assert(has_connected(), "Not connected") assert(has_connected(), "Not connected")
var group = groups.get_group(entity)
if group != null:
api.watch_state(group[0], callback)
return api.watch_state(entity, callback) return api.watch_state(entity, callback)
## Returns true if the adapter has an integration in the home automation system ## Returns true if the adapter has an integration in the home automation system
@ -128,4 +152,7 @@ func get_history(entity_id, start, end=null):
if api.has_method("get_history") == false: if api.has_method("get_history") == false:
return null return null
if groups.is_group(entity_id):
return null
return await api.get_history(entity_id, start, end) return await api.get_history(entity_id, start, end)

View File

@ -0,0 +1,44 @@
var groups = {}
var counter = 0
func create(entities):
var index = str(counter)
groups[index] = entities
counter += 1
return "group.%s" % index
func add_entity(id: String, entity):
if is_group(id) == false:
return false
groups[id.replace("group.", "")].append(entity)
return true
func update_entities(id: String, entities):
if is_group(id) == false:
return false
groups[id.replace("group.", "")] = entities
return true
func remove_entity(id: String, entity):
if is_group(id) == false:
return false
groups[id.replace("group.", "")].erase(entity)
return true
func remove(id: String):
if is_group(id) == false:
return false
return groups.erase(id.replace("group.", ""))
func is_group(id: String):
return id.begins_with("group.")
func get_group(id: String):
if is_group(id) == false:
return null
return groups[id.replace("group.", "")]