diff --git a/app/addons/rdot/graph.gd b/app/addons/rdot/graph.gd index 6fde0d0..e61de00 100644 --- a/app/addons/rdot/graph.gd +++ b/app/addons/rdot/graph.gd @@ -4,9 +4,9 @@ class_name RdotGraph static var instance: RdotGraph = null static func getInstance() -> RdotGraph: - if instance == null: - instance = RdotGraph.new() - return instance + if instance == null: + instance = RdotGraph.new() + return instance var activeConsumer: RdotNode = null var inNotificationPhase := false @@ -17,209 +17,209 @@ var postSignalSetFn := Callable() var watcherPending := false var watcher = R.Watcher.new(func(_arg): - if watcherPending: - return + if watcherPending: + return - watcherPending=true - var endOfFrame=func(): + watcherPending=true + var endOfFrame=func(): - watcherPending=false - for s in watcher.getPending(): - s.do_get() + watcherPending=false + for s in watcher.getPending(): + s.do_get() - watcher.watch() + watcher.watch() - endOfFrame.call_deferred() + endOfFrame.call_deferred() ) func setActiveConsumer(consumer: RdotNode) -> RdotNode: - var prev = activeConsumer - activeConsumer = consumer - return prev + var prev = activeConsumer + activeConsumer = consumer + return prev func getActiveConsumer() -> RdotNode: - return activeConsumer + return activeConsumer func isInNotificationPhase() -> bool: - return inNotificationPhase + return inNotificationPhase func producerAccessed(node: RdotNode): - assert(inNotificationPhase == false, "Signal read during notification phase") + assert(inNotificationPhase == false, "Signal read during notification phase") - if activeConsumer == null: - return + if activeConsumer == null: + return - if activeConsumer.consumerOnSignalRead.is_null() == false: - activeConsumer.consumerOnSignalRead.call(node) + if activeConsumer.consumerOnSignalRead.is_null() == false: + activeConsumer.consumerOnSignalRead.call(node) - var idx = activeConsumer.nextProducerIndex; - activeConsumer.nextProducerIndex += 1 + var idx = activeConsumer.nextProducerIndex; + activeConsumer.nextProducerIndex += 1 - assertConsumerNode(activeConsumer) + assertConsumerNode(activeConsumer) - if idx < activeConsumer.producerNode.size()&&activeConsumer.producerNode[idx] != node: - if consumerIsLive(activeConsumer): - var staleProducer = activeConsumer.producerNode[idx] - producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]) + if idx < activeConsumer.producerNode.size()&&activeConsumer.producerNode[idx] != node: + if consumerIsLive(activeConsumer): + var staleProducer = activeConsumer.producerNode[idx] + producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]) - if RdotArray.do_get(activeConsumer.producerNode, idx) != node: - RdotArray.do_set(activeConsumer.producerNode, idx, node) - RdotArray.do_set(activeConsumer.producerIndexOfThis, idx, producerAddLiveConsumer(node, activeConsumer, idx) if consumerIsLive(activeConsumer) else 0) + if RdotArray.do_get(activeConsumer.producerNode, idx) != node: + RdotArray.do_set(activeConsumer.producerNode, idx, node) + RdotArray.do_set(activeConsumer.producerIndexOfThis, idx, producerAddLiveConsumer(node, activeConsumer, idx) if consumerIsLive(activeConsumer) else 0) - RdotArray.do_set(activeConsumer.producerLastReadVersion, idx, node.version) + RdotArray.do_set(activeConsumer.producerLastReadVersion, idx, node.version) func producerIncrementEpoch(): - epoch += 1 + epoch += 1 func producerUpdateValueVersion(node: RdotNode): - if consumerIsLive(node)&&!node.dirty: - return + if consumerIsLive(node)&&!node.dirty: + return - if !node.dirty&&node.lastCleanEpoch == epoch: - return + if !node.dirty&&node.lastCleanEpoch == epoch: + return - if !node.producerMustRecompute(node)&&!consumerPollProducersForChange(node): - node.dirty = false; - node.lastCleanEpoch = epoch - return + if !node.producerMustRecompute(node)&&!consumerPollProducersForChange(node): + node.dirty = false; + node.lastCleanEpoch = epoch + return - if node.producerRecomputeValue.is_null() == false: - node.producerRecomputeValue.call(node) + if node.producerRecomputeValue.is_null() == false: + node.producerRecomputeValue.call(node) - node.dirty = false - node.lastCleanEpoch = epoch + node.dirty = false + node.lastCleanEpoch = epoch func producerNotifyConsumers(node: RdotNode): - if node.liveConsumerNode == null: - return + if node.liveConsumerNode == null: + return - var prev = inNotificationPhase - inNotificationPhase = true + var prev = inNotificationPhase + inNotificationPhase = true - for consumer in node.liveConsumerNode: - if !consumer.dirty: - consumerMarkDirty(consumer) + for consumer in node.liveConsumerNode: + if !consumer.dirty: + consumerMarkDirty(consumer) - inNotificationPhase = prev + inNotificationPhase = prev func producerUpdatesAllowed() -> bool: - return activeConsumer == null||activeConsumer.consumerAllowSignalWrites != false + return activeConsumer == null||activeConsumer.consumerAllowSignalWrites != false func consumerMarkDirty(node: RdotNode): - node.dirty = true - producerNotifyConsumers(node) + node.dirty = true + producerNotifyConsumers(node) - if node.consumerMarkedDirty.is_null() == false: - node.consumerMarkedDirty.call(node) + if node.consumerMarkedDirty.is_null() == false: + node.consumerMarkedDirty.call(node) func consumerBeforeComputation(node: RdotNode) -> RdotNode: - if node: - node.nextProducerIndex = 0 + if node: + node.nextProducerIndex = 0 - return setActiveConsumer(node) + return setActiveConsumer(node) func consumerAfterComputation(node: RdotNode, prevConsumer: RdotNode): - setActiveConsumer(prevConsumer) + setActiveConsumer(prevConsumer) - if node == null||node.producerNode == null||node.producerIndexOfThis == null||node.producerLastReadVersion == null: - return + if node == null||node.producerNode == null||node.producerIndexOfThis == null||node.producerLastReadVersion == null: + return - if consumerIsLive(node): - for i in range(node.nextProducerIndex, node.producerNode.size()): - producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) + if consumerIsLive(node): + for i in range(node.nextProducerIndex, node.producerNode.size()): + producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) - while node.producerNode.size() > node.nextProducerIndex: - node.producerNode.pop_back() - node.producerLastReadVersion.pop_back() - node.producerIndexOfThis.pop_back() + while node.producerNode.size() > node.nextProducerIndex: + node.producerNode.pop_back() + node.producerLastReadVersion.pop_back() + node.producerIndexOfThis.pop_back() func consumerPollProducersForChange(node: RdotNode) -> bool: - assertConsumerNode(node) + assertConsumerNode(node) - for i in range(node.producerNode.size()): - var producer = node.producerNode[i] - var seenVersion = node.producerLastReadVersion[i] + for i in range(node.producerNode.size()): + var producer = node.producerNode[i] + var seenVersion = node.producerLastReadVersion[i] - if seenVersion != producer.version: - return true + if seenVersion != producer.version: + return true - producerUpdateValueVersion(producer) + producerUpdateValueVersion(producer) - if seenVersion != producer.version: - return true + if seenVersion != producer.version: + return true - return false + return false func consumerDestroy(node: RdotNode): - assertConsumerNode(node) + assertConsumerNode(node) - if consumerIsLive(node): - for i in range(node.producerNode.size()): - producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) + if consumerIsLive(node): + for i in range(node.producerNode.size()): + producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) - node.producerNode.clear() - node.producerLastReadVersion.clear() - node.producerIndexOfThis.clear() + node.producerNode.clear() + node.producerLastReadVersion.clear() + node.producerIndexOfThis.clear() - if node.liveConsumerNode: - node.liveConsumerNode.clear() - node.liveConsumerIndexOfThis.clear() + if node.liveConsumerNode: + node.liveConsumerNode.clear() + node.liveConsumerIndexOfThis.clear() static func producerAddLiveConsumer(node: RdotNode, consumer: RdotNode, indexOfThis: int) -> int: - assertProducerNode(node) - assertConsumerNode(node) + assertProducerNode(node) + assertConsumerNode(node) - if node.liveConsumerNode.size() == 0: - if node.watched.is_null() == false: - node.watched.call(node.wrapper) + if node.liveConsumerNode.size() == 0: + if node.watched.is_null() == false: + node.watched.call(node.wrapper) - for i in range(node.producerNode.size()): - node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i) + for i in range(node.producerNode.size()): + node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i) - node.liveConsumerIndexOfThis.push_back(indexOfThis) - node.liveConsumerNode.push_back(consumer) + node.liveConsumerIndexOfThis.push_back(indexOfThis) + node.liveConsumerNode.push_back(consumer) - return node.liveConsumerNode.size() - 1 + return node.liveConsumerNode.size() - 1 static func producerRemoveLiveConsumerAtIndex(node: RdotNode, idx: int): - assertProducerNode(node) - assertConsumerNode(node) + assertProducerNode(node) + assertConsumerNode(node) - assert(idx < node.liveConsumerNode.size(), "active consumer index %s is out of bounds of %s consumers)" % [idx, node.liveConsumerNode.size()]) + assert(idx < node.liveConsumerNode.size(), "active consumer index %s is out of bounds of %s consumers)" % [idx, node.liveConsumerNode.size()]) - if node.liveConsumerNode.size() == 1: - if node.unwatched.is_null() == false: - node.unwatched.call(node.wrapper) + if node.liveConsumerNode.size() == 1: + if node.unwatched.is_null() == false: + node.unwatched.call(node.wrapper) - for i in range(node.producerNode.size()): - producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) + for i in range(node.producerNode.size()): + producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]) - var lastIdx = node.liveConsumerNode.size() - 1 - node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx] - node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx] + var lastIdx = node.liveConsumerNode.size() - 1 + node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx] + node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx] - node.liveConsumerNode.pop_back() - node.liveConsumerIndexOfThis.pop_back() + node.liveConsumerNode.pop_back() + node.liveConsumerIndexOfThis.pop_back() - if idx < node.liveConsumerNode.size(): - var idxProducer = node.liveConsumerIndexOfThis[idx] - var consumer = node.liveConsumerNode[idx] - assertConsumerNode(consumer) - consumer.producerIndexOfThis[idxProducer] = idx + if idx < node.liveConsumerNode.size(): + var idxProducer = node.liveConsumerIndexOfThis[idx] + var consumer = node.liveConsumerNode[idx] + assertConsumerNode(consumer) + consumer.producerIndexOfThis[idxProducer] = idx static func consumerIsLive(node: RdotNode) -> bool: - return node.consumerIsAlwaysLive||(node.liveConsumerNode != null&&node.liveConsumerNode.size() > 0) + return node.consumerIsAlwaysLive||(node.liveConsumerNode != null&&node.liveConsumerNode.size() > 0) static func assertConsumerNode(node: RdotNode): - if node.producerNode == null: - node.producerNode = [] - if node.producerIndexOfThis == null: - node.producerIndexOfThis = [] - if node.producerLastReadVersion == null: - node.producerLastReadVersion = [] + if node.producerNode == null: + node.producerNode = [] + if node.producerIndexOfThis == null: + node.producerIndexOfThis = [] + if node.producerLastReadVersion == null: + node.producerLastReadVersion = [] static func assertProducerNode(node: RdotNode): - if node.liveConsumerNode == null: - node.liveConsumerNode = [] - if node.liveConsumerIndexOfThis == null: - node.liveConsumerIndexOfThis = [] \ No newline at end of file + if node.liveConsumerNode == null: + node.liveConsumerNode = [] + if node.liveConsumerIndexOfThis == null: + node.liveConsumerIndexOfThis = [] diff --git a/app/content/entities/light/light.gd b/app/content/entities/light/light.gd index b867392..7335c40 100644 --- a/app/content/entities/light/light.gd +++ b/app/content/entities/light/light.gd @@ -15,9 +15,9 @@ const color_wheel_img := preload ("res://assets/canvas.png") @onready var mode_before = $Modes/Previous @onready var mode_label = $Modes/Label -var state = true -var brightness = 0 # 0-255 -var color = color_on +var active = R.state(false) +var brightness = R.state(0) # 0-255 +var color = R.state(color_on) var color_supported = false # Called when the node enters the scene tree for the first time. @@ -26,7 +26,7 @@ func _ready(): icon.value = "lightbulb" var stateInfo = await HomeApi.get_state(entity_id) - set_state(stateInfo["state"] == "on", stateInfo["attributes"]) + set_state(stateInfo) if stateInfo.has("attributes")&&stateInfo["attributes"].has("effect_list")&&stateInfo["attributes"]["effect_list"].size() > 0: if stateInfo["attributes"].has("effect")&&stateInfo["attributes"]["effect"] != null: @@ -65,79 +65,70 @@ func _ready(): var delta=Vector2(target_point.x, target_point.z) * (1.0 / 0.08) if delta.length() > 1: delta=delta.normalized() - - print("delta", delta) - var color=color_wheel_img.get_image().get_pixel((delta.x * 0.5 + 0.5) * 1000, (delta.y * 0.5 + 0.5) * 1000) + var picked_color=color_wheel_img.get_image().get_pixel((delta.x * 0.5 + 0.5) * 1000, (delta.y * 0.5 + 0.5) * 1000) - print("color", color) - - color_puck.material_override.albedo_color=color + color_puck.material_override.albedo_color=picked_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(picked_color.r * 255), int(picked_color.g * 255), int(picked_color.b * 255)], } HomeApi.set_state(entity_id, "on", attributes) - set_state(state, attributes) ) color_supported = true else: remove_child(color_wheel) await HomeApi.watch_state(entity_id, func(new_state): - if (new_state["state"] == "on") == state: - return - set_state(new_state["state"] == "on", new_state["attributes"]) + set_state(new_state) ) slider.on_value_changed.connect(func(new_value): var value=new_value / 100 * 255 - HomeApi.set_state(entity_id, "on" if state else "off", {"brightness": int(value)}) - set_state(state, {"brightness": value}) + HomeApi.set_state(entity_id, "on" if active.value else "off", {"brightness": int(value)}) ) -func set_state(new_state: bool, attributes={}): - if state == false&&new_state == false: +func set_state(stateInfo): + if active.value == false&&stateInfo["state"] == "off": return - state = new_state + var attributes = stateInfo["attributes"] - if attributes.has("brightness"): - brightness = attributes["brightness"] + active.value = stateInfo["state"] == "on" + + if attributes.has("brightness")&&attributes["brightness"] != null: + brightness.value = attributes["brightness"] + slider.value = attributes["brightness"] / 255.0 * 100 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) + color.value = 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 brightness == null: - target_color = color if color_supported else color_on + if active.value: + if brightness.value == null: + target_color = color.value if color_supported else color_on else: - target_color = color_off.lerp(color if color_supported else color_on, brightness / 255.0) + target_color = color_off.lerp(color.value if color_supported else color_on, brightness.value / 255.0) icon_color.value = target_color tween.tween_property(lightbulb, "material_override:albedo_color", target_color, 0.3) func _on_click(event): if event.target == self: - 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) + _toggle() func quick_action(): + _toggle() + +func _toggle(): var attributes = {} - if !state&&brightness != null: - attributes["brightness"] = int(brightness) + if !active.value&&brightness.value != null: + attributes["brightness"] = int(brightness.value) - HomeApi.set_state(entity_id, "on" if !state else "off", attributes) - set_state(!state, attributes) \ No newline at end of file + HomeApi.set_state(entity_id, "off" if active.value else "on", attributes) \ No newline at end of file diff --git a/app/content/entities/switch/switch.gd b/app/content/entities/switch/switch.gd index 1a0c5d7..17ef18c 100644 --- a/app/content/entities/switch/switch.gd +++ b/app/content/entities/switch/switch.gd @@ -4,42 +4,35 @@ const Entity = preload ("../entity.gd") @onready var sprite: AnimatedSprite3D = $Icon +var active = R.state(false) + # Called when the node enters the scene tree for the first time. func _ready(): super() var stateInfo = await HomeApi.get_state(entity_id) + + set_state(stateInfo) + + await HomeApi.watch_state(entity_id, func(new_state): + set_state(new_state) + ) + + R.effect(func(_arg): + sprite.set_frame(1 if active.value else 0) + ) + +func set_state(stateInfo): if stateInfo == null: return - if stateInfo["state"] == "on": - sprite.set_frame(0) - else: - sprite.set_frame(1) - + active.value = stateInfo["state"] == "on" icon.value = "toggle_" + stateInfo["state"] - await HomeApi.watch_state(entity_id, func(new_state): - if new_state["state"] == "on": - sprite.set_frame(0) - else: - sprite.set_frame(1) - - icon.value="toggle_" + new_state["state"] - ) - func _on_click(_event): - 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) - -func _on_request_completed(): - pass + _toggle() 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) \ No newline at end of file + _toggle() + +func _toggle(): + HomeApi.set_state(entity_id, "off" if active.value else "on") \ No newline at end of file diff --git a/app/content/entities/switch/switch.tscn b/app/content/entities/switch/switch.tscn index 0fbeddc..d143a95 100644 --- a/app/content/entities/switch/switch.tscn +++ b/app/content/entities/switch/switch.tscn @@ -13,17 +13,17 @@ radius = 0.0482081 animations = [{ "frames": [{ "duration": 1.0, -"texture": ExtResource("1_w68gw") +"texture": ExtResource("2_86ba1") }, { "duration": 1.0, -"texture": ExtResource("2_86ba1") +"texture": ExtResource("1_w68gw") }], "loop": true, "name": &"default", "speed": 5.0 }] -[node name="Switch" type="StaticBody3D" ] +[node name="Switch" type="StaticBody3D"] collision_mask = 0 script = ExtResource("1_8ffhi")