From 93604be82dc3c47190f5edd02c94092870d6a423 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Mon, 11 Mar 2024 18:09:50 +0100 Subject: [PATCH 1/7] add hass integration support --- content/main.gd | 27 ++++-- content/main.tscn | 2 +- content/ui/components/input/text_handler.gd | 2 - content/ui/menu/edit/edit_menu.gd | 2 +- lib/home_apis/hass_ws/callback_map.gd | 17 ++-- lib/home_apis/hass_ws/handlers/auth.gd | 28 ++++++ lib/home_apis/hass_ws/handlers/integration.gd | 19 ++++ lib/home_apis/hass_ws/hass.gd | 90 +++++++++---------- 8 files changed, 121 insertions(+), 66 deletions(-) create mode 100644 lib/home_apis/hass_ws/handlers/auth.gd create mode 100644 lib/home_apis/hass_ws/handlers/integration.gd diff --git a/content/main.gd b/content/main.gd index f46b74a..6cc7fcf 100644 --- a/content/main.gd +++ b/content/main.gd @@ -1,7 +1,7 @@ extends Node3D -var sky = preload("res://assets/materials/sky.material") -var sky_passthrough = preload("res://assets/materials/sky_passthrough.material") +var sky = preload ("res://assets/materials/sky.material") +var sky_passthrough = preload ("res://assets/materials/sky_passthrough.material") @onready var environment: WorldEnvironment = $WorldEnvironment @onready var camera: XRCamera3D = $XROrigin3D/XRCamera3D @@ -11,6 +11,8 @@ var sky_passthrough = preload("res://assets/materials/sky_passthrough.material") @onready var menu = $Menu @onready var keyboard = $Keyboard +var last_room = null + func _ready(): # In case we're running on the headset, use the passthrough sky if OS.get_name() == "Android": @@ -43,7 +45,7 @@ func _ready(): if action.name == "menu_button": toggle_menu() elif action.name == "by_button": - House.body.mini_view = !House.body.mini_view + House.body.mini_view=!House.body.mini_view ) EventSystem.on_focus_in.connect(func(event): @@ -51,7 +53,7 @@ func _ready(): return add_child(keyboard) - keyboard.global_transform = menu.get_node("AnimationContainer/KeyboardPlace").global_transform + keyboard.global_transform=menu.get_node("AnimationContainer/KeyboardPlace").global_transform ) EventSystem.on_focus_out.connect(func(event): @@ -70,7 +72,7 @@ func toggle_menu(): 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() event.name = name event.value = value @@ -82,6 +84,19 @@ func _emit_action(name: String, value, right_controller: bool = true): TYPE_FLOAT, TYPE_VECTOR2: EventSystem.emit("action_value", event) +func _physics_process(delta): + var room = House.body.find_room_at(camera.global_position) + + if room != last_room: + if room: + print("Room changed to: ", room.name) + HomeApi.api.update_room(room.name) + last_room = room + else: + print("Room changed to: ", "outside") + HomeApi.api.update_room("outside") + last_room = null + func _process(delta): if OS.get_name() != "Android": @@ -128,7 +143,7 @@ func vector_key_mapping(key_positive_x: int, key_negative_x: int, key_positive_y elif Input.is_physical_key_pressed(key_negative_x): x = -1 - var vec = Vector3(x, 0 , y) + var vec = Vector3(x, 0, y) if vec: vec = vec.normalized() diff --git a/content/main.tscn b/content/main.tscn index 9ac6eb6..1fe7a43 100644 --- a/content/main.tscn +++ b/content/main.tscn @@ -47,7 +47,7 @@ shadow_enabled = true [node name="XROrigin3D" type="XROrigin3D" parent="."] [node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] -transform = Transform3D(1, 1.8976e-10, 4.07454e-10, 6.76872e-11, 1, 2.08734e-08, -5.82077e-11, 1.09139e-11, 1, 0.0356618, 0.71033, 0.00564247) +transform = Transform3D(0.999992, 0.00357422, -0.00141238, -0.00357241, 0.999993, 0.00127761, 0.00141693, -0.00127253, 0.999998, 0.0356617, 0.71033, 0.00564247) cull_mask = 524287 current = true diff --git a/content/ui/components/input/text_handler.gd b/content/ui/components/input/text_handler.gd index 18ac058..51bef8b 100644 --- a/content/ui/components/input/text_handler.gd +++ b/content/ui/components/input/text_handler.gd @@ -33,8 +33,6 @@ func set_text(value: String, insert: bool=false): overflow_index = _calculate_overflow_index() focus_caret() - print(overflow_index, " ", char_offset, " ", caret_position) - func get_display_text(): # In case all chars fit, return the whole text. if overflow_index == - 1: diff --git a/content/ui/menu/edit/edit_menu.gd b/content/ui/menu/edit/edit_menu.gd index 6db33e9..0a08a91 100644 --- a/content/ui/menu/edit/edit_menu.gd +++ b/content/ui/menu/edit/edit_menu.gd @@ -154,4 +154,4 @@ func _on_entity_click(entity_name): func clear_menu(): for child in devices_node.get_children(): devices_node.remove_child(child) - child.queue_free() \ No newline at end of file + child.queue_free() diff --git a/lib/home_apis/hass_ws/callback_map.gd b/lib/home_apis/hass_ws/callback_map.gd index ee85c12..6979927 100644 --- a/lib/home_apis/hass_ws/callback_map.gd +++ b/lib/home_apis/hass_ws/callback_map.gd @@ -3,6 +3,7 @@ extends Node class_name CallbackMap var callbacks := {} +var single_callbacks: Array = [] func add(key: Variant, callback: Callable) -> void: _validate_key(key) @@ -15,13 +16,9 @@ func add(key: Variant, callback: Callable) -> void: func add_once(key: Variant, callback: Callable) -> void: _validate_key(key) - var fn: Callable - - fn = func(args: Array): - remove(key, fn) - callback.callv(args) + single_callbacks.append(callback) - add(key, fn) + add(key, callback) func remove(key: Variant, callback: Callable) -> void: _validate_key(key) @@ -29,6 +26,9 @@ func remove(key: Variant, callback: Callable) -> void: if callbacks.has(key): callbacks[key].erase(callback) + if single_callbacks.has(callback): + single_callbacks.erase(callback) + func call_key(key: Variant, args: Array) -> void: _validate_key(key) @@ -36,5 +36,8 @@ func call_key(key: Variant, args: Array) -> void: for callback in callbacks[key]: callback.callv(args) + if single_callbacks.has(callback): + remove(key, callback) + func _validate_key(key: Variant): - assert(typeof(key) == TYPE_STRING || typeof(key) == TYPE_INT || typeof(key) == TYPE_FLOAT, "key must be a string or number") + assert(typeof(key) == TYPE_STRING||typeof(key) == TYPE_INT||typeof(key) == TYPE_FLOAT, "key must be a string or number") diff --git a/lib/home_apis/hass_ws/handlers/auth.gd b/lib/home_apis/hass_ws/handlers/auth.gd new file mode 100644 index 0000000..036ccd2 --- /dev/null +++ b/lib/home_apis/hass_ws/handlers/auth.gd @@ -0,0 +1,28 @@ +const HASS_API = preload ("../hass.gd") + +signal on_authenticated() + +var api: HASS_API +var url: String +var token: String + +var authenticated := false + +func _init(hass: HASS_API, url: String, token: String): + self.api = hass + self.url = url + self.token = token + +func handle_message(message): + match message["type"]: + "auth_required": + api.send_packet({"type": "auth", "access_token": self.token}) + "auth_ok": + authenticated = true + on_authenticated.emit() + "auth_invalid": + EventSystem.notify("Failed to authenticate with Home Assistant. Check your token and try again.", EventNotify.Type.DANGER) + api.handle_disconnect() + +func on_disconnect(): + authenticated = false \ No newline at end of file diff --git a/lib/home_apis/hass_ws/handlers/integration.gd b/lib/home_apis/hass_ws/handlers/integration.gd new file mode 100644 index 0000000..7e55162 --- /dev/null +++ b/lib/home_apis/hass_ws/handlers/integration.gd @@ -0,0 +1,19 @@ +const HASS_API = preload ("../hass.gd") + +var api: HASS_API +var integration_exists: bool = false + +func _init(hass: HASS_API): + self.api = hass + +func on_connect(): + var response = await api.send_request_packet({ + "type": "immersive_home/register", + "device_id": OS.get_unique_id(), + "name": OS.get_model_name(), + "version": OS.get_version(), + "platform": OS.get_name(), + }) + + if response.status == Promise.Status.RESOLVED: + integration_exists = true \ No newline at end of file diff --git a/lib/home_apis/hass_ws/hass.gd b/lib/home_apis/hass_ws/hass.gd index 7c26a2a..ca1402c 100644 --- a/lib/home_apis/hass_ws/hass.gd +++ b/lib/home_apis/hass_ws/hass.gd @@ -1,5 +1,8 @@ extends Node +const AuthHandler = preload ("./handlers/auth.gd") +const IntegrationHandler = preload ("./handlers/integration.gd") + signal on_connect() signal on_disconnect() var connected := false @@ -13,25 +16,32 @@ var request_timeout := 10.0 var url := "" var token := "" - var LOG_MESSAGES := false -var authenticated := false - var id := 1 var entities: Dictionary = {} var entitiy_callbacks := CallbackMap.new() var packet_callbacks := CallbackMap.new() -func _init(url := self.url, token := self.token): +var auth_handler: AuthHandler +var integration_handler: IntegrationHandler + +func _init(url:=self.url, token:=self.token): self.url = url self.token = token + auth_handler = AuthHandler.new(self, url, token) + integration_handler = IntegrationHandler.new(self) + devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ") connect_ws() + auth_handler.on_authenticated.connect(func(): + start_subscriptions() + ) + func connect_ws(): - if url == "" || token == "": + if url == ""||token == "": return print("Connecting to %s" % url + "/api/websocket") @@ -71,38 +81,12 @@ func _process(delta): func handle_packet(packet: Dictionary): if LOG_MESSAGES: print("Received packet: %s" % str(packet).substr(0, 1000)) - if packet.type == "auth_required": - send_packet({ - "type": "auth", - "access_token": self.token - }) + auth_handler.handle_message(packet) - elif packet.type == "auth_ok": - authenticated = true - start_subscriptions() - - elif packet.type == "auth_invalid": - EventSystem.notify("Failed to authenticate, invalid auth token", EventNotify.Type.DANGER) - print("Failed to authenticate, invalid auth token") - handle_disconnect() - else: + if packet.has("id"): packet_callbacks.call_key(int(packet.id), [packet]) func start_subscriptions(): - assert(authenticated, "Not authenticated") - - # await send_request_packet({ - # "type": "supported_features", - # "features": { - # "coalesce_messages": 1 - # } - # }) - - # await send_request_packet({ - # "type": "subscribe_events", - # "event_type": "state_changed" - # }) - send_subscribe_packet({ "type": "subscribe_entities" }, func(packet: Dictionary): @@ -111,13 +95,12 @@ func start_subscriptions(): if packet.event.has("a"): for entity in packet.event.a.keys(): - entities[entity] = { + entities[entity]={ "state": packet.event.a[entity]["s"], "attributes": packet.event.a[entity]["a"] } entitiy_callbacks.call_key(entity, [entities[entity]]) - connected = true - on_connect.emit() + handle_connect() if packet.event.has("c"): for entity in packet.event.c.keys(): @@ -126,14 +109,19 @@ func start_subscriptions(): if packet.event.c[entity].has("+"): if packet.event.c[entity]["+"].has("s"): - entities[entity]["state"] = packet.event.c[entity]["+"]["s"] + entities[entity]["state"]=packet.event.c[entity]["+"]["s"] if packet.event.c[entity]["+"].has("a"): entities[entity]["attributes"].merge(packet.event.c[entity]["+"]["a"], true) entitiy_callbacks.call_key(entity, [entities[entity]]) ) +func handle_connect(): + integration_handler.on_connect() + connected = true + on_connect.emit() + func handle_disconnect(): - authenticated = false + auth_handler.on_disconnect() set_process(false) on_disconnect.emit() @@ -153,18 +141,15 @@ func send_subscribe_packet(packet: Dictionary, callback: Callable): }) id += 1 - -func send_request_packet(packet: Dictionary, ignore_initial := false): +func send_request_packet(packet: Dictionary, ignore_initial:=false): packet.id = id id += 1 - send_packet(packet) - var promise = Promise.new(func(resolve: Callable, reject: Callable): var fn: Callable if ignore_initial: - fn = func(packet: Dictionary): + fn=func(packet: Dictionary): if packet.type == "event": resolve.call(packet) packet_callbacks.remove(packet.id, fn) @@ -173,7 +158,7 @@ func send_request_packet(packet: Dictionary, ignore_initial := false): else: packet_callbacks.add_once(packet.id, resolve) - var timeout = Timer.new() + var timeout=Timer.new() timeout.set_wait_time(request_timeout) timeout.set_one_shot(true) timeout.timeout.connect(func(): @@ -187,8 +172,9 @@ func send_request_packet(packet: Dictionary, ignore_initial := false): timeout.start() ) - return await promise.settled + send_packet(packet) + return await promise.settled func send_packet(packet: Dictionary): if LOG_MESSAGES: print("Sending packet: %s" % encode_packet(packet)) @@ -221,15 +207,13 @@ func get_state(entity: String): return entities[entity] return null - func watch_state(entity: String, callback: Callable): entitiy_callbacks.add(entity, callback) return func(): entitiy_callbacks.remove(entity, callback) - -func set_state(entity: String, state: String, attributes: Dictionary = {}): +func set_state(entity: String, state: String, attributes: Dictionary={}): var domain = entity.split(".")[0] var service: String @@ -271,4 +255,12 @@ func set_state(entity: String, state: String, attributes: Dictionary = {}): } }) - +func update_room(room: String): + var response = await send_request_packet({ + "type": "immersive_home/update", + "device_id": OS.get_unique_id(), + "room": room + }) + + if response.status == Promise.Status.RESOLVED: + print("Room updated") \ No newline at end of file From 7b0a7530785238f2c0da314241fd65c61be85153 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 11:35:15 +0100 Subject: [PATCH 2/7] fix room crashing bug --- content/main.tscn | 2 +- content/system/house/room/room.gd | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/content/main.tscn b/content/main.tscn index 1fe7a43..3ef5a93 100644 --- a/content/main.tscn +++ b/content/main.tscn @@ -47,7 +47,7 @@ shadow_enabled = true [node name="XROrigin3D" type="XROrigin3D" parent="."] [node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] -transform = Transform3D(0.999992, 0.00357422, -0.00141238, -0.00357241, 0.999993, 0.00127761, 0.00141693, -0.00127253, 0.999998, 0.0356617, 0.71033, 0.00564247) +transform = Transform3D(0.999999, 0.00106283, -0.000420545, -0.00106267, 0.999999, 0.000379457, 0.000420948, -0.000378989, 1, 0.0356617, 0.71033, 0.00564247) cull_mask = 524287 current = true diff --git a/content/system/house/room/room.gd b/content/system/house/room/room.gd index ec9e131..6ccc18c 100644 --- a/content/system/house/room/room.gd +++ b/content/system/house/room/room.gd @@ -26,6 +26,9 @@ func has_point(point: Vector3) -> bool: func get_aabb(): var room_store = Store.house.get_room(name) + if room_store == null: + return AABB() + var corners = room_store.corners if corners.size() == 0: @@ -119,4 +122,3 @@ static func generate_ceiling_mesh(room_store: Dictionary): var mesh = st.commit() return mesh - From e2fcc5b08f87d41b8e0799d1857724be5fdef7fd Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 12:23:39 +0100 Subject: [PATCH 3/7] add room renaming and disable input option --- content/system/house/house.gd | 23 +++++++--- content/ui/components/input/input.gd | 46 +++++++++++++++---- content/ui/menu/room/views/rooms.gd | 49 +++++++++++++-------- content/ui/menu/room/views/rooms.tscn | 1 + content/ui/menu/settings/settings_menu.tscn | 2 + 5 files changed, 88 insertions(+), 33 deletions(-) diff --git a/content/system/house/house.gd b/content/system/house/house.gd index 2a52242..8e3ae90 100644 --- a/content/system/house/house.gd +++ b/content/system/house/house.gd @@ -1,7 +1,7 @@ extends Node3D -const Room = preload("./room/room.tscn") -const RoomType = preload("./room/room.gd") +const Room = preload ("./room/room.tscn") +const RoomType = preload ("./room/room.gd") @onready var levels = $Levels @onready var collision_shape = $Levels/CollisionShape3D @@ -89,7 +89,6 @@ func is_valid_room(room_name): return return room.wall_corners.get_child_count() >= 3 - func delete_room(room_name): var room = find_room(room_name) @@ -111,7 +110,7 @@ func delete_room(room_name): Store.house.save_local() func is_editiong(room_name): - return editing_room != null && editing_room.name == room_name + return editing_room != null&&editing_room.name == room_name func find_room(room_name): for room in get_rooms(0): @@ -125,6 +124,21 @@ func find_room_at(entity_position: Vector3): return room return null +func rename_room(old_room: String, new_name: String): + var room = find_room(old_room) + + if room == null: + return + + room.name = new_name + + var store_room = Store.house.get_room(old_room) + + if store_room != null: + store_room.name = new_name + + Store.house.save_local() + func get_level(level: int): return levels.get_child(level) @@ -206,7 +220,6 @@ func update_mini_view(): camera_position.y *= 0.5 camera_direction.y = 0.0 - var target_position = camera_position + camera_direction.normalized() * 0.2 levels.global_position = target_position - center * 0.1 else: diff --git a/content/ui/components/input/input.gd b/content/ui/components/input/input.gd index 6dd76e6..01522c9 100644 --- a/content/ui/components/input/input.gd +++ b/content/ui/components/input/input.gd @@ -2,7 +2,7 @@ extends StaticBody3D class_name Input3D -var text_handler = preload("res://content/ui/components/input/text_handler.gd").new() +var text_handler = preload ("res://content/ui/components/input/text_handler.gd").new() @onready var caret: MeshInstance3D = $Label/Caret @onready var mesh_box: MeshInstance3D = $Box @@ -26,13 +26,27 @@ var text_handler = preload("res://content/ui/components/input/text_handler.gd"). get: return text_handler.text set(value): - var focused = Engine.is_editor_hint() == false && EventSystem.is_focused(self) == false + var focused = Engine.is_editor_hint() == false&&EventSystem.is_focused(self) == false if !is_node_ready(): await ready text_handler.set_text(value, focused) label.text = text_handler.get_display_text() +@export var disabled: bool = false: + set(value): + if !is_node_ready(): await ready + + disabled = value + if disabled: + label.modulate = Color(0.7, 0.7, 0.7) + add_to_group("ui_focus_skip") + animation.stop() + caret.hide() + else: + label.modulate = Color(1, 1, 1) + remove_from_group("ui_focus_skip") + var keyboard_input: bool = false var input_plane = Plane(Vector3.UP, Vector3.ZERO) @@ -44,20 +58,23 @@ func _ready(): return EventSystem.on_key_down.connect(func(event): - if EventSystem.is_focused(self) == false: + if EventSystem.is_focused(self) == false||disabled: return - text = EventKey.key_to_string(event.key, event.shift_pressed, text.substr(0, text_handler.caret_position)) + text.substr(text_handler.caret_position, text.length()) - caret.position.x = text_handler.get_caret_position() - label.text = text_handler.get_display_text() + text=EventKey.key_to_string(event.key, event.shift_pressed, text.substr(0, text_handler.caret_position)) + text.substr(text_handler.caret_position, text.length()) + caret.position.x=text_handler.get_caret_position() + label.text=text_handler.get_display_text() ) func _input(event): - if event is InputEventKey && EventSystem.is_focused(self) && event.pressed: + if event is InputEventKey&&EventSystem.is_focused(self)&&event.pressed: if event.keycode == KEY_F1: keyboard_input = !keyboard_input return + if disabled: + return + if keyboard_input: text = EventKey.key_to_string(event.keycode, event.shift_pressed, text.substr(0, text_handler.caret_position)) + text.substr(text_handler.caret_position, text.length()) caret.position.x = text_handler.get_caret_position() @@ -66,14 +83,20 @@ func _process(_delta): if Engine.is_editor_hint(): return - if get_tree().debug_collisions_hint && OS.get_name() != "Android": + if get_tree().debug_collisions_hint&&OS.get_name() != "Android": _draw_debug_text_gaps() func _on_press_down(event): + if disabled: + return + var pos_x = label.to_local(event.ray.get_collision_point()).x text_handler.update_caret_position(pos_x) func _on_press_move(event): + if disabled: + return + var ray_pos = event.ray.global_position var ray_dir = -event.ray.global_transform.basis.z @@ -92,6 +115,9 @@ func _on_press_move(event): label.text = text_handler.get_display_text() func _on_focus_in(_event): + if disabled: + return + caret.position.x = text_handler.get_caret_position() label.text = text_handler.get_display_text() caret.show() @@ -113,9 +139,11 @@ func update_caret_position(event): text_handler.update_caret_position(pos_x) caret.position.x = text_handler.get_caret_position() - func _on_focus_out(_event): + if disabled: + return + animation.stop() caret.hide() diff --git a/content/ui/menu/room/views/rooms.gd b/content/ui/menu/room/views/rooms.gd index 2ab4392..1bbb571 100644 --- a/content/ui/menu/room/views/rooms.gd +++ b/content/ui/menu/room/views/rooms.gd @@ -1,11 +1,10 @@ extends Node3D -const Room = preload("res://content/system/house/room/room.tscn") -const RoomType = preload("res://content/system/house/room/room.gd") - -const material_selected = preload("../room_selected.tres") -const material_unselected = preload("../room_unselected.tres") +const Room = preload ("res://content/system/house/room/room.tscn") +const RoomType = preload ("res://content/system/house/room/room.gd") +const material_selected = preload ("../room_selected.tres") +const material_unselected = preload ("../room_unselected.tres") @onready var room_button = $Button @onready var input = $Input @@ -13,32 +12,41 @@ const material_unselected = preload("../room_unselected.tres") var selected_room = null: set(value): - if selected_room != null && value == null: + if selected_room != null&&value == null: room_button.label = "add" input.text = "Room %s" % (rooms_map.get_child_count() + 1) - if selected_room != null: - var old_room = get_room(selected_room) - if old_room != null: - old_room.get_node("MeshInstance3D").material_override = material_unselected + var old_room = get_room(selected_room) + + if old_room != null: + old_room.get_node("MeshInstance3D").material_override = material_unselected if value != null: + room_button.label = "edit" input.text = value edit_room = false var new_room = get_room(value) if new_room != null: new_room.get_node("MeshInstance3D").material_override = material_selected - selected_room = value var edit_room = false: set(value): + if value == edit_room: + return + edit_room = value if value: room_button.label = "save" + input.disabled = false else: room_button.label = "edit" + input.disabled = true + + if selected_room != null&&selected_room != input.text: + House.body.rename_room(selected_room, input.text) + selected_room = input.text func _ready(): if Store.house.is_loaded(): @@ -50,33 +58,36 @@ func _ready(): room_button.on_button_down.connect(func(): if selected_room == null: - var room_name = input.text + var room_name=input.text if get_room(room_name) != null: EventSystem.notify("Name already taken", EventNotify.Type.WARNING) return House.body.create_room(room_name, 0) House.body.edit_room(room_name) - selected_room = room_name - edit_room = true + selected_room=room_name + edit_room=true else: if edit_room: - edit_room = false + edit_room=false if !House.body.is_valid_room(selected_room): House.body.delete_room(selected_room) - selected_room = null + selected_room=null else: House.body.edit_room(null) _generate_room_map() else: - edit_room = true + edit_room=true House.body.edit_room(selected_room) ) func get_room(room_name): - if rooms_map.has_node("%s" % room_name): - return rooms_map.get_node("%s" % room_name) + if room_name == null: + return null + + if rooms_map.has_node("%s"% room_name): + return rooms_map.get_node("%s"% room_name) return null func _on_click(event: EventPointer): diff --git a/content/ui/menu/room/views/rooms.tscn b/content/ui/menu/room/views/rooms.tscn index d666af7..5eab1e4 100644 --- a/content/ui/menu/room/views/rooms.tscn +++ b/content/ui/menu/room/views/rooms.tscn @@ -18,3 +18,4 @@ icon = true [node name="Input" parent="." instance=ExtResource("2_hstw7")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.12, 0.005, 0.27) text = "Room 1" +disabled = true diff --git a/content/ui/menu/settings/settings_menu.tscn b/content/ui/menu/settings/settings_menu.tscn index c41a242..74143f9 100644 --- a/content/ui/menu/settings/settings_menu.tscn +++ b/content/ui/menu/settings/settings_menu.tscn @@ -43,6 +43,7 @@ horizontal_alignment = 0 [node name="InputURL" parent="Content" instance=ExtResource("4_q3x6k")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.03) text = "ws://192.168.0.1:8123" +disabled = null [node name="LabelToken" type="Label3D" parent="Content"] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.07) @@ -55,6 +56,7 @@ horizontal_alignment = 0 [node name="InputToken" parent="Content" instance=ExtResource("4_q3x6k")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.07) text = "..." +disabled = null [node name="LabelConnect" type="Label3D" parent="Content"] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.14, 0, 0.12) From d91b2fb5fc1a25410446cb6d040ebfd28bb21e23 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 12:34:44 +0100 Subject: [PATCH 4/7] fix reoccurring errors and clean code --- content/functions/occludable.gd | 4 +--- content/main.gd | 2 -- content/ui/components/button/button.gd | 3 +++ lib/home_apis/hass_ws/hass.gd | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/content/functions/occludable.gd b/content/functions/occludable.gd index e0bf7a2..432b004 100644 --- a/content/functions/occludable.gd +++ b/content/functions/occludable.gd @@ -12,11 +12,9 @@ func _ready(): EventSystem.on_slow_tick.connect(_slow_tick) func _slow_tick(_delta): - if player_camera.is_inside_tree() == false: - printerr("Player camera is not inside the tree") + if player_camera.is_inside_tree() == false||ray.is_inside_tree() == false: return ray.target_position = get_parent().to_local(player_camera.global_position) get_parent().visible = ray.is_colliding() == false - diff --git a/content/main.gd b/content/main.gd index 6cc7fcf..d42c1a7 100644 --- a/content/main.gd +++ b/content/main.gd @@ -89,11 +89,9 @@ func _physics_process(delta): if room != last_room: if room: - print("Room changed to: ", room.name) HomeApi.api.update_room(room.name) last_room = room else: - print("Room changed to: ", "outside") HomeApi.api.update_room("outside") last_room = null diff --git a/content/ui/components/button/button.gd b/content/ui/components/button/button.gd index bcc14ea..31b9372 100644 --- a/content/ui/components/button/button.gd +++ b/content/ui/components/button/button.gd @@ -99,6 +99,9 @@ func _ready(): func update_animation(): var length = animation_player.get_animation("down").length + if animation_player.current_animation == "": + return + if active&&animation_player.current_animation_position != length: animation_player.play("down") elif !active&&animation_player.current_animation_position != 0: diff --git a/lib/home_apis/hass_ws/hass.gd b/lib/home_apis/hass_ws/hass.gd index ca1402c..fd6a16d 100644 --- a/lib/home_apis/hass_ws/hass.gd +++ b/lib/home_apis/hass_ws/hass.gd @@ -263,4 +263,4 @@ func update_room(room: String): }) if response.status == Promise.Status.RESOLVED: - print("Room updated") \ No newline at end of file + pass \ No newline at end of file From 9e280b60f7df1980d69609c0c2de1e77e544c09d Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 12:41:46 +0100 Subject: [PATCH 5/7] make sure entities get update on rename --- content/system/house/house.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/content/system/house/house.gd b/content/system/house/house.gd index 8e3ae90..d29ea00 100644 --- a/content/system/house/house.gd +++ b/content/system/house/house.gd @@ -137,6 +137,7 @@ func rename_room(old_room: String, new_name: String): if store_room != null: store_room.name = new_name + save_all_entities() Store.house.save_local() func get_level(level: int): From f0aae4a7ab8e6471e13dec5048379292623a34f9 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 12:44:08 +0100 Subject: [PATCH 6/7] fix XRSimulator --- addons/xr-simulator/XRSimulator.gd | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/addons/xr-simulator/XRSimulator.gd b/addons/xr-simulator/XRSimulator.gd index cedeec3..1ae5d33 100644 --- a/addons/xr-simulator/XRSimulator.gd +++ b/addons/xr-simulator/XRSimulator.gd @@ -83,7 +83,6 @@ func _ready(): right_controller = child right_tracker.set_pose(pose, child.transform, Vector3.ZERO, Vector3.ZERO, XRPose.XR_TRACKING_CONFIDENCE_HIGH) XRServer.add_tracker(right_tracker) - func _process(_delta): if enabled and disable_xr_in_editor and OS.has_feature("editor") and viewport.use_xr: @@ -95,7 +94,7 @@ func _input(event): if Input.is_key_pressed(KEY_ESCAPE): Input.mouse_mode = Input.MOUSE_MODE_VISIBLE elif Input.mouse_mode != Input.MOUSE_MODE_CAPTURED and event is InputEventMouseButton: - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED: return @@ -154,10 +153,10 @@ func camera_height(event: InputEventMouseButton): return var pos = camera.transform.origin - var camera_y = pos.y + (scroll_sensitivity * direction)/20 + var camera_y = pos.y + (scroll_sensitivity * direction) / 20 if (camera_y >= max_camera_height or camera_y <= min_camera_height) and is_camera_height_limited: camera_y = pos.y - camera.transform.origin = Vector3(pos.x, camera_y , pos.z) + camera.transform.origin = Vector3(pos.x, camera_y, pos.z) func simulate_joysticks(): var vec_left = vector_key_mapping(KEY_D, KEY_A, KEY_W, KEY_S) @@ -195,8 +194,8 @@ func simulate_buttons(event: InputEventKey, controller: XRController3D): func move_controller(event: InputEventMouseMotion, controller: XRController3D): var movement = Vector3() - movement += camera.global_transform.basis.x * event.relative.x * device_x_sensitivity/1000 - movement += camera.global_transform.basis.y * event.relative.y * -device_y_sensitivity/1000 + movement += camera.global_transform.basis.x * event.relative.x * device_x_sensitivity / 1000 + movement += camera.global_transform.basis.y * event.relative.y * - device_y_sensitivity / 1000 controller.global_translate(movement) func attract_controller(event: InputEventMouseButton, controller: XRController3D): @@ -212,26 +211,26 @@ func attract_controller(event: InputEventMouseButton, controller: XRController3D var distance_vector = controller.global_transform.origin - camera.global_transform.origin var forward = distance_vector.normalized() * direction - var movement = distance_vector + forward * (scroll_sensitivity/20) + var movement = distance_vector + forward * (scroll_sensitivity / 20) if distance_vector.length() > 0.1 and movement.length() > 0.1: - controller.global_translate(forward * (scroll_sensitivity/20)) + controller.global_translate(forward * (scroll_sensitivity / 20)) func rotate_device(event: InputEventMouseMotion, device: Node3D): var motion = event.relative - device.rotate_y(motion.x * -device_x_sensitivity/1000) - device.rotate(device.transform.basis.x, motion.y * -device_y_sensitivity/1000) + device.rotate_y(motion.x * - device_x_sensitivity / 1000) + device.rotate(device.transform.basis.x.normalized(), motion.y * - device_y_sensitivity / 1000) func vector_key_mapping(key_positive_x: int, key_negative_x: int, key_positive_y: int, key_negative_y: int): var x = 0 var y = 0 - if Input.is_physical_key_pressed (key_positive_y): + if Input.is_physical_key_pressed(key_positive_y): y = 1 - elif Input.is_physical_key_pressed (key_negative_y): + elif Input.is_physical_key_pressed(key_negative_y): y = -1 - if Input.is_physical_key_pressed (key_positive_x): + if Input.is_physical_key_pressed(key_positive_x): x = 1 - elif Input.is_physical_key_pressed (key_negative_x): + elif Input.is_physical_key_pressed(key_negative_x): x = -1 var vec = Vector2(x, y) From 5834fee507847909bed51dc440560c16f25a60fb Mon Sep 17 00:00:00 2001 From: Nitwel Date: Tue, 12 Mar 2024 12:49:17 +0100 Subject: [PATCH 7/7] decouple integration from main --- content/main.gd | 13 ------------- content/main.tscn | 8 +++----- content/system/camera/camera.gd | 18 ++++++++++++++++++ content/system/camera/camera.tscn | 6 ++++++ lib/home_apis/hass_ws/hass.gd | 3 +++ 5 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 content/system/camera/camera.gd create mode 100644 content/system/camera/camera.tscn diff --git a/content/main.gd b/content/main.gd index d42c1a7..9feab7e 100644 --- a/content/main.gd +++ b/content/main.gd @@ -11,8 +11,6 @@ var sky_passthrough = preload ("res://assets/materials/sky_passthrough.material" @onready var menu = $Menu @onready var keyboard = $Keyboard -var last_room = null - func _ready(): # In case we're running on the headset, use the passthrough sky if OS.get_name() == "Android": @@ -84,17 +82,6 @@ func _emit_action(name: String, value, right_controller: bool=true): TYPE_FLOAT, TYPE_VECTOR2: EventSystem.emit("action_value", event) -func _physics_process(delta): - var room = House.body.find_room_at(camera.global_position) - - if room != last_room: - if room: - HomeApi.api.update_room(room.name) - last_room = room - else: - HomeApi.api.update_room("outside") - last_room = null - func _process(delta): if OS.get_name() != "Android": diff --git a/content/main.tscn b/content/main.tscn index 3ef5a93..421b116 100644 --- a/content/main.tscn +++ b/content/main.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=15 format=3 uid="uid://eecv28y6jxk4"] +[gd_scene load_steps=16 format=3 uid="uid://eecv28y6jxk4"] [ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"] [ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"] [ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"] [ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="3_67lii"] +[ext_resource type="PackedScene" uid="uid://b2kjh1fpjptdr" path="res://content/system/camera/camera.tscn" id="3_rj4ac"] [ext_resource type="PackedScene" uid="uid://bsx12q23v8apy" path="res://content/system/hands/hands.tscn" id="4_v8xu6"] [ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"] [ext_resource type="Material" uid="uid://bf5ina366dwm6" path="res://assets/materials/sky.material" id="5_wgwf8"] @@ -46,10 +47,7 @@ shadow_enabled = true [node name="XROrigin3D" type="XROrigin3D" parent="."] -[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] -transform = Transform3D(0.999999, 0.00106283, -0.000420545, -0.00106267, 0.999999, 0.000379457, 0.000420948, -0.000378989, 1, 0.0356617, 0.71033, 0.00564247) -cull_mask = 524287 -current = true +[node name="XRCamera3D" parent="XROrigin3D" instance=ExtResource("3_rj4ac")] [node name="XRControllerLeft" parent="XROrigin3D" instance=ExtResource("2_2lraw")] transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, -0.355145, 0.550439, -0.477945) diff --git a/content/system/camera/camera.gd b/content/system/camera/camera.gd new file mode 100644 index 0000000..a6b7e01 --- /dev/null +++ b/content/system/camera/camera.gd @@ -0,0 +1,18 @@ +extends XRCamera3D + +var last_room = null + +func _physics_process(_delta): + if HomeApi.api.has_integration(): + update_room() + +func update_room(): + var room = House.body.find_room_at(global_position) + + if room != last_room: + if room: + HomeApi.api.update_room(room.name) + last_room = room + else: + HomeApi.api.update_room("outside") + last_room = null \ No newline at end of file diff --git a/content/system/camera/camera.tscn b/content/system/camera/camera.tscn new file mode 100644 index 0000000..50c955b --- /dev/null +++ b/content/system/camera/camera.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://b2kjh1fpjptdr"] + +[node name="XRCamera3D" type="XRCamera3D"] +transform = Transform3D(0.999999, 0.00106283, -0.000420545, -0.00106267, 0.999999, 0.000379457, 0.000420948, -0.000378989, 1, 0.0356617, 0.71033, 0.00564247) +cull_mask = 524287 +current = true diff --git a/lib/home_apis/hass_ws/hass.gd b/lib/home_apis/hass_ws/hass.gd index fd6a16d..2755574 100644 --- a/lib/home_apis/hass_ws/hass.gd +++ b/lib/home_apis/hass_ws/hass.gd @@ -255,6 +255,9 @@ func set_state(entity: String, state: String, attributes: Dictionary={}): } }) +func has_integration(): + return integration_handler.integration_exists + func update_room(room: String): var response = await send_request_packet({ "type": "immersive_home/update",