From 225f485ee1ce783bfd2966303c2f9399260a9af4 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Sun, 10 Mar 2024 21:25:49 +1300 Subject: [PATCH 01/20] Refactored Fixtures, and began file system migration to core folder --- Assets/Main.theme | Bin 1680 -> 1678 bytes Components/Virtual Fixture/Virtual_fixture.gd | 12 +- Fixtures/generic/rgbawuv-fader.json | 2 +- Main.tscn | 15 +- Panels/Fixtures/Fixtures.gd | 9 +- Panels/Home/Home.tscn | 17 ++ {Scripts => Panels/Playbacks}/Playbacks.gd | 0 Panels/{ => Playbacks}/Playbacks.tscn | 2 +- Panels/Virtual Fixtures/Virtual_fixtures.gd | 12 +- Scripts/Classes/Fixture.gd | 80 --------- Scripts/Global.gd | 4 +- Scripts/Node Config Editor/Code_edit.gd | 0 .../Node Config Editor/Node_config_editor.gd | 157 ------------------ Scripts/Node Config Editor/Template_node.gd | 13 -- Scripts/Node Config Editor/What is this.txt | 1 - core/components/Fixture.gd | 76 +++++++++ .../System.gd => core/components/system.gd | 0 .../components/universe.gd | 12 +- .../Uuid.gd => core/components/uuid.gd | 2 +- .../Editor_window.gd => core/engine/Engine.gd | 10 +- core/engine/EngineComponent.gd | 55 ++++++ project.godot | 1 + 22 files changed, 185 insertions(+), 295 deletions(-) create mode 100644 Panels/Home/Home.tscn rename {Scripts => Panels/Playbacks}/Playbacks.gd (100%) rename Panels/{ => Playbacks}/Playbacks.tscn (93%) delete mode 100644 Scripts/Classes/Fixture.gd delete mode 100644 Scripts/Node Config Editor/Code_edit.gd delete mode 100644 Scripts/Node Config Editor/Node_config_editor.gd delete mode 100644 Scripts/Node Config Editor/Template_node.gd delete mode 100644 Scripts/Node Config Editor/What is this.txt create mode 100644 core/components/Fixture.gd rename Scripts/System.gd => core/components/system.gd (100%) rename Scripts/Classes/Universe.gd => core/components/universe.gd (94%) rename Scripts/Classes/Uuid.gd => core/components/uuid.gd (99%) rename Scripts/Node Config Editor/Editor_window.gd => core/engine/Engine.gd (66%) create mode 100644 core/engine/EngineComponent.gd diff --git a/Assets/Main.theme b/Assets/Main.theme index d83e1d38e6eb9976c39710be28b9c1867bab798a..3ed66f6d81cc1bc0c6574838e718a1aeb33dd945 100644 GIT binary patch delta 323 zcmV-J0lfZ@4UP?v6ag2p6=ehgZIgQh<$txPp=G6#N~P@pgAtO*4H5t}2#HiAWhoH} zB@hv%%1NQr0fj{Mjrwu=oAQgv7afRTJlyH2z1kY~N!hTmHT8|iE^(A$%JDtgF;*!r zoa5-A3|cYthiI0=1@JkJf~LlhoSHM6deF_V0N*9PwP$x3T~dVlYN9_jE)xvt_I!J?74Ea%7>Tm&kj-#NdFr=sE%%&Q2H5`CVBlcSP`cWHfVM|A`+~1u1TPR-9r8>&$eB_u;1=HG z25yLV)xv{1xt53>yEo$q<5CO)!1bDW=|wo0F#f?U|JjJg?oR{{jUK1z0osqLiUW7b z#?Lg#Ya(K7@U&4^t-9)kaG(we`7%S}kEqOaI!}(eH4F4uSkUYQc|`n_+X$6HUG;+= XbtX2pa6hE1AvNUx&y-06Qd2`iZg`v0 diff --git a/Components/Virtual Fixture/Virtual_fixture.gd b/Components/Virtual Fixture/Virtual_fixture.gd index 36f7d96..ba59680 100644 --- a/Components/Virtual Fixture/Virtual_fixture.gd +++ b/Components/Virtual Fixture/Virtual_fixture.gd @@ -1,15 +1,23 @@ extends GraphElement -var control_node +var fixture: Fixture var color_override = false var is_highlight = false -# Called when the node enters the scene tree for the first time. + + +func _init(debug_text="") -> void: + print(debug_text) + func _ready(): $"Color Box".add_theme_stylebox_override("panel", $"Color Box".get_theme_stylebox("panel").duplicate()) func set_color_rgb(color): $"Color Box".get_theme_stylebox("panel").bg_color = color +func set_fixture(control_fixture: Fixture) -> void: + fixture = control_fixture + fixture.color_changed.connect(self.set_color_rgb) + func serialize(): return { "position_offset":{ diff --git a/Fixtures/generic/rgbawuv-fader.json b/Fixtures/generic/rgbawuv-fader.json index ca4c738..3bc3622 100644 --- a/Fixtures/generic/rgbawuv-fader.json +++ b/Fixtures/generic/rgbawuv-fader.json @@ -23,4 +23,4 @@ } } } - \ No newline at end of file + diff --git a/Main.tscn b/Main.tscn index 9539630..d1517bc 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,16 +1,15 @@ -[gd_scene load_steps=26 format=3 uid="uid://p3sohjs1pt37"] +[gd_scene load_steps=25 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] [ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] -[ext_resource type="Script" path="res://Scripts/System.gd" id="5_qili6"] +[ext_resource type="Script" path="res://core/components/system.gd" id="5_qili6"] [ext_resource type="PackedScene" uid="uid://dhor5xf4xd2ul" path="res://Panels/Desk/Desk.tscn" id="8_12iq0"] [ext_resource type="PackedScene" uid="uid://cdg8rr3v7el85" path="res://Panels/Patch Bay/Patch_bay.tscn" id="9_hxqqf"] [ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="10_e6e26"] [ext_resource type="Script" path="res://Panels/Popups/Popup_window.gd" id="10_yavq3"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="11_7alyx"] [ext_resource type="Texture2D" uid="uid://bhl73t2e0jcwn" path="res://Assets/Icons/close.svg" id="11_mn7am"] -[ext_resource type="Texture2D" uid="uid://vw0vs7dlct55" path="res://Assets/Icons/menu.svg" id="24_oc2jn"] [ext_resource type="PackedScene" uid="uid://nd4u83us3lgo" path="res://Panels/Settings/Settings.tscn" id="27_03pyd"] [ext_resource type="Script" path="res://Scripts/Window.gd" id="27_nmwy1"] @@ -128,16 +127,6 @@ layout_mode = 2 [node name="Virtual Fixtures" parent="TabContainer" instance=ExtResource("11_7alyx")] layout_mode = 2 -[node name="Open Drop Down" type="Button" parent="."] -layout_mode = 2 -offset_left = 3.0 -offset_top = 3.0 -offset_right = 44.0 -offset_bottom = 42.0 -size_flags_horizontal = 2 -icon = ExtResource("24_oc2jn") -icon_alignment = 1 - [node name="Menu Buttons" type="HBoxContainer" parent="."] layout_mode = 1 anchors_preset = 1 diff --git a/Panels/Fixtures/Fixtures.gd b/Panels/Fixtures/Fixtures.gd index d4bc309..1e4733c 100644 --- a/Panels/Fixtures/Fixtures.gd +++ b/Panels/Fixtures/Fixtures.gd @@ -2,6 +2,7 @@ # All rights reserved. extends Control +## GUI element for managing fixtures, and fixture groups @export var physical_fixture_list: NodePath @export var fixture_groups_list: NodePath @@ -71,8 +72,8 @@ func reload_fixtures() -> void: for fixture in universe.get_fixtures().values(): var node_to_add : Control = Globals.components.list_item.instantiate() node_to_add.control_node = self - node_to_add.set_item_name(fixture.config.fixture_name + " | " + universe.get_universe_name() + " CH: " + str(fixture.config.channel) + "-" + str(fixture.config.channel+fixture.config.length-1)) - node_to_add.name = fixture.config.uuid + node_to_add.set_item_name(fixture.meta.fixture_name + " | " + universe.get_universe_name() + " CH: " + str(fixture.channel) + "-" + str(fixture.channel+fixture.length-1)) + node_to_add.name = fixture.uuid node_to_add.set_meta("fixture", fixture) get_node(physical_fixture_list).add_child(node_to_add) @@ -84,8 +85,8 @@ func set_active_fixtures(fixtures:Array) -> void: fixture.set_highlighted(false) active_fixtures = fixtures - for fixture in active_fixtures: - get_node(physical_fixture_list).get_node(fixture.config.uuid).set_highlighted(true) + for fixture: Fixture in active_fixtures: + get_node(physical_fixture_list).get_node(fixture.uuid).set_highlighted(true) pass diff --git a/Panels/Home/Home.tscn b/Panels/Home/Home.tscn new file mode 100644 index 0000000..bf9ae08 --- /dev/null +++ b/Panels/Home/Home.tscn @@ -0,0 +1,17 @@ +[gd_scene format=3 uid="uid://bsp1a8e33a6u4"] + +[node name="Home" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/Scripts/Playbacks.gd b/Panels/Playbacks/Playbacks.gd similarity index 100% rename from Scripts/Playbacks.gd rename to Panels/Playbacks/Playbacks.gd diff --git a/Panels/Playbacks.tscn b/Panels/Playbacks/Playbacks.tscn similarity index 93% rename from Panels/Playbacks.tscn rename to Panels/Playbacks/Playbacks.tscn index 31d9396..e947a11 100644 --- a/Panels/Playbacks.tscn +++ b/Panels/Playbacks/Playbacks.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://baortk0rwrhup"] -[ext_resource type="Script" path="res://Scripts/Playbacks.gd" id="1_io88g"] +[ext_resource type="Script" path="res://Panels/Playbacks/Playbacks.gd" id="1_io88g"] [node name="MarginContainer" type="MarginContainer"] offset_right = 1920.0 diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 02f7ff8..4e25bf6 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -51,9 +51,7 @@ func _add_fixture() -> void: for fixture: Fixture in Globals.get_value("active_fixtures"): var node_to_add: Control = Globals.components.virtual_fixture.instantiate() - fixture.add_virtual_fixture(node_to_add) - - node_to_add.control_node = fixture + node_to_add.set_fixture(fixture) node_to_add.set_highlighted(true) node_to_add.position_offset += _position_offset _position_offset += Vector2(5, 5) @@ -81,7 +79,7 @@ func _active_fixtures_changed(new_active_fixtures: Array) -> void: virtual_fixture.set_highlighted(false) for active_fixture: Fixture in new_active_fixtures: - for virtual_fixture in active_fixture.virtual_fixtures: + for virtual_fixture in active_fixture.get_user_meta("virtual_fixtures", []): virtual_fixture.set_highlighted(true) _old_active_fixtures = new_active_fixtures @@ -111,7 +109,7 @@ func from(config: Dictionary, control_fixture: Fixture) -> void: var node_to_add: Control = Globals.components.virtual_fixture.instantiate() node_to_add._position_offset = Vector2(config._position_offset.x, config._position_offset.y) - node_to_add.control_node = control_fixture + node_to_add.set_fixture(control_fixture) control_fixture.add_virtual_fixture(node_to_add) self.add_child(node_to_add) @@ -120,9 +118,9 @@ func from(config: Dictionary, control_fixture: Fixture) -> void: func _on_virtual_fixture_selected(node) -> void: if node not in _selected_virtual_fixtures: _selected_virtual_fixtures.append(node) - Globals.select_fixture(node.control_node) + Globals.select_fixture(node.fixture) func _on_virtual_fixture_deselected(node) -> void: _selected_virtual_fixtures.erase(node) - Globals.deselect_fixture(node.control_node) + Globals.deselect_fixture(node.fixture) diff --git a/Scripts/Classes/Fixture.gd b/Scripts/Classes/Fixture.gd deleted file mode 100644 index 6d1dbef..0000000 --- a/Scripts/Classes/Fixture.gd +++ /dev/null @@ -1,80 +0,0 @@ -extends Node -class_name Fixture - -var config = { - "universe":null, - "channel":1, - "length":1, - "fixture_brand":"", - "fixture_name":"", - "display_name":"", - "file_path":"", - "uuid":"", - "mode":"" -} - -var channels = {} -var channel_ranges = {} -var compiled_dmx_data = {} -var virtual_fixtures = [] -var parameters = {} - -func serialize(): - var serialized_virtual_fixtures = [] - for fixture in virtual_fixtures: - serialized_virtual_fixtures.append(fixture.serialize()) - - return { - "display_name":config.display_name, - "fixture_brand":config.fixture_brand, - "fixture_name":config.fixture_name, - "mode":config.mode, - "virtual_fixtures":serialized_virtual_fixtures - } - -func from(universe, manifest, channel, mode, name, uuid, virtual_fixtures): - channel_ranges = manifest.get("channels", {}) - channels = manifest.modes.values()[mode].channels - config.universe = universe - config.channel = channel - config.length = len(manifest.modes.values()[mode].channels) - config.fixture_brand = manifest.info.brand - config.fixture_name = manifest.info.name - config.name = name - config.uuid = uuid - config.mode = mode - - if virtual_fixtures: - for fixture in virtual_fixtures: - Globals.nodes.virtual_fixtures.from(fixture, self) - - return self - -func set_color_rgb(r,g,b): - if "ColorIntensityRed" in channels: - compiled_dmx_data[int(channels.find("ColorIntensityRed")+config.channel)] = int(remap(r, 0.0, 1.0, 0.0, 255.0)) - if "ColorIntensityGreen" in channels: - compiled_dmx_data[int(channels.find("ColorIntensityGreen")+config.channel)] = int(remap(g, 0.0, 1.0, 0.0, 255.0)) - if "ColorIntensityBlue" in channels: - compiled_dmx_data[int(channels.find("ColorIntensityBlue")+config.channel)] = int(remap(b, 0.0, 1.0, 0.0, 255.0)) - config.universe.set_fixture_data(compiled_dmx_data) - - parameters.color = Color(r, g, b) - - update_virtual_fixtures() - -func update_virtual_fixtures(): - if not virtual_fixtures:return - - for fixture in virtual_fixtures: - fixture.set_color_rgb(parameters.color) - -func add_virtual_fixture(node): - virtual_fixtures.append(node) - -func remove_virtual_fixture(node): - virtual_fixtures.erase(node) - -func delete(): - for virtual_fixture in virtual_fixtures: - virtual_fixture.delete() diff --git a/Scripts/Global.gd b/Scripts/Global.gd index 7d869d3..055e109 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -1,7 +1,5 @@ extends Node -const uuid_util = preload('res://Scripts/Classes/Uuid.gd') -const Universe = preload('res://Scripts/Classes/Universe.gd') var node_path := "res://Nodes/" var widget_path := "res://Widgets/" @@ -251,7 +249,7 @@ func call_subscription(value_name:String) -> void: node_to_update.call() func new_uuid() -> String: - return uuid_util.v4() + return UUID_Util.v4() func select_fixture(fixture_to_add:Fixture) -> Array: diff --git a/Scripts/Node Config Editor/Code_edit.gd b/Scripts/Node Config Editor/Code_edit.gd deleted file mode 100644 index e69de29..0000000 diff --git a/Scripts/Node Config Editor/Node_config_editor.gd b/Scripts/Node Config Editor/Node_config_editor.gd deleted file mode 100644 index 4960d10..0000000 --- a/Scripts/Node Config Editor/Node_config_editor.gd +++ /dev/null @@ -1,157 +0,0 @@ -extends TabContainer - -@onready var name_input = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/VBoxContainer/Name Input") -@onready var template_node: GraphNode = self.get_node("Editor/Control/TemplateNode") -@onready var list: ItemList = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/VBoxContainer/List") -@onready var row_settings = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings") - -@onready var input_option_dropdown = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Options/Input Option") -@onready var output_option_dropdown = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Options/Output Option") - -@onready var input_name_field = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Names/Input Name") -@onready var output_name_field = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Names/Output Name") - -@onready var input_color_button = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Colors/Input Color") -@onready var output_color_button = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Colors/Output Color") - -@onready var input_visable_button = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Visibility/Input Visable") - -@onready var input_slot_visable_button = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Slot Visibility/Input Slot Visable") -@onready var output_slot_visable_button = self.get_node("Editor/PanelContainer/VBoxContainer/VSplitContainer/ScrollContainer/VBoxContainer/Row Settings/Slot Visibility/Output Slot Visable") - -var row_index = 0 -var row_select_index = 0 -var row_data = {} - -var input_types = { - "none": null, - "value": [[SpinBox,"Row$1 Value"]], - "dmx_value": [[SpinBox, "Row$1 Channel"], [SpinBox,"Row$1 Value"]], - "text": [[LineEdit, "Row$1 Text"]], - "custom": [] -} -# Called when the node enters the scene tree for the first time. -func _ready(): - pass - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - pass - -func _on_name_input_text_changed(new_text): - template_node.title = new_text - -func _on_new_row_pressed(): - var row_index = row_data.size() # Get the current size as the row index - list.add_item("Row " + str(row_index)) - - row_data[row_index] = { - "input": false, - "output": false, - "input_type": "none", - "output_type": "none", - "input_name":"", - "output_name":"", - "input_visable":false, - "input_slot_visable":true, - "output_slot_visable":true, - "row_name":"" - } - - update_rows() - -func _on_delete_row_pressed(): - var selected_items = list.get_selected_items() - # Remove items in reverse order to avoid index issues - for i in range(selected_items.size() - 1, -1, -1): - row_data.erase(selected_items[i]) - list.remove_item(selected_items[i]) - #template_node.remove_child(template_node.get_child(selected_items[i])) - update_rows() - -func update_rows(): - template_node.clear_all_slots() - for n in template_node.get_children(): - template_node.remove_child(n) - n.queue_free() - - for index in row_data: - var new_row = HBoxContainer.new() - new_row.name = "row" + str(index) - #new_row.set_h_size_flags(2) - template_node.add_child(new_row) - var current_row = template_node.get_node("row"+str(index)) - - template_node.set_slot(index, row_data[index].input,0,Color.WHITE,row_data[index].output, 0, Color.WHITE) - - if row_data[index].input_name: - var node_to_add = Label.new() - node_to_add.text = row_data[index].input_name - node_to_add.set_h_size_flags(3) - current_row.add_child(node_to_add) - - if row_data[index].input_type != "none": - if row_data[index].input_visable: - for node_to_add in input_types[row_data[index].input_type]: - var new_node = node_to_add[0].new() - new_node.set_name(node_to_add[1].replace("$1", str(index))) - if row_data[index].input_name: - new_node.set_h_size_flags(2) - new_node.set_h_size_flags(8) - else: - new_node.set_h_size_flags(3) - current_row.add_child(new_node) - - if row_data[index].output_name: - var node_to_add = Label.new() - node_to_add.text = row_data[index].output_name - node_to_add.set_h_size_flags(2) - node_to_add.set_h_size_flags(8) - current_row.add_child(node_to_add) - - -func _on_list_multi_selected(index, selected): - row_select_index = index - row_settings.visible = true - -func _on_input_option_item_selected(index): - row_data[row_select_index].input_type = input_types.keys()[index] - input_name_field.text = "" - row_data[row_select_index].input_name = "" - update_rows() - -func _on_output_option_item_selected(index): - row_data[row_select_index].output_type = input_types.keys()[index] - output_name_field.text = "" - row_data[row_select_index].output_name = "" - update_rows() - -func _on_input_name_text_changed(new_text): - row_data[row_select_index].input_name = new_text - update_rows() - -func _on_output_name_text_changed(new_text): - row_data[row_select_index].output_name = new_text - update_rows() - -func _on_input_color_color_changed(color): - pass # Replace with function body. - -func _on_output_color_color_changed(color): - pass # Replace with function body. - -func _on_input_slot_visable_toggled(toggled_on): - row_data[row_select_index].input = toggled_on - update_rows() - -func _on_output_slot_visable_toggled(toggled_on): - row_data[row_select_index].output = toggled_on - update_rows() - -func _on_input_visable_toggled(toggled_on): - row_data[row_select_index].input_visable = toggled_on - update_rows() - -func _on_output_visable_toggled(toggled_on): - pass # Replace with function body. - diff --git a/Scripts/Node Config Editor/Template_node.gd b/Scripts/Node Config Editor/Template_node.gd deleted file mode 100644 index 146c195..0000000 --- a/Scripts/Node Config Editor/Template_node.gd +++ /dev/null @@ -1,13 +0,0 @@ -extends GraphNode - - -# Called when the node enters the scene tree for the first time. -func _ready(): - pass # Replace with function body. - -func _on_resize_request(new_minsize): - size = new_minsize - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - pass diff --git a/Scripts/Node Config Editor/What is this.txt b/Scripts/Node Config Editor/What is this.txt deleted file mode 100644 index 0be2c65..0000000 --- a/Scripts/Node Config Editor/What is this.txt +++ /dev/null @@ -1 +0,0 @@ -If you're wondering what the 'Node Config Editor' is, it is a GUI that will allow you to create your own nodes using logic. Development on this has been postponed to a later release, but when that will be, no one knows. diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd new file mode 100644 index 0000000..3467416 --- /dev/null +++ b/core/components/Fixture.gd @@ -0,0 +1,76 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name Fixture extends EngineComponent +## Engine class to control parameters of fixtures + +signal color_changed(color: Color) ## Emmited when the color of this fixture is changed +signal mode_changed(mode: int) ## Emmited when the mode of the fixture is changed +signal channel_changed(new_channel: int) ## Emmited when the channel of the fixture is changed + +## Contains metadata infomation about this fixture +var meta: Dictionary = { + "fixture_brand":"", + "fixture_name":"", + "display_name":"", + "file_path":"", +} + +var universe: Universe ## The universe this fixture is patched to +var channel: int ## Universe channel of this fixture +var length: int ## Channel length, from start channel, to end channel +var mode: int ## Current mode +var manifest: Dictionary ## Fixture manifest +var channels: Array ## Channels this fixture uses, and what they do +var channel_ranges: Dictionary ## What happenes at each channel, at each value + +var _compiled_dmx_data: Dictionary +var _parameters: Dictionary + + +func _init(i: Dictionary = {}) -> void: + ## Init function to create a new fixture, from a set of prexisting infomation. If no infomation is passed a blank fixture is returne + + if not i: + return + + universe = i.universe as Universe + channel = i.channel as int + mode = i.mode as int + length = len(i.manifest.modes.values()[mode].channels) + manifest = i.manifest as Dictionary + channel_ranges = i.manifest.get("channels", {}) + channels = i.manifest.modes.values()[mode].channels + + meta.fixture_brand = i.manifest.info.brand + meta.fixture_name = i.manifest.info.name + + super._init() + +func serialize() -> Dictionary: + ## Returnes serialized infomation about this fixture + + return { + "universe":universe.uuid, + "channel":channel, + "mode":mode, + "meta":meta, + "user_meta": serialize_meta(), + "uuid":uuid + } + + +func set_color_rgb(r,g,b) -> void: + ## Sets the color of this fixture in 0-255 RBG values + + if "ColorIntensityRed" in channels: + _compiled_dmx_data[int(channels.find("ColorIntensityRed") + channel)] = int(r) + if "ColorIntensityGreen" in channels: + _compiled_dmx_data[int(channels.find("ColorIntensityGreen") + channel)] = int(g) + if "ColorIntensityBlue" in channels: + _compiled_dmx_data[int(channels.find("ColorIntensityBlue") + channel)] = int(b) + universe.set_fixture_data(_compiled_dmx_data) + + _parameters.color = Color(r, g, b) + + color_changed.emit(_parameters.color) diff --git a/Scripts/System.gd b/core/components/system.gd similarity index 100% rename from Scripts/System.gd rename to core/components/system.gd diff --git a/Scripts/Classes/Universe.gd b/core/components/universe.gd similarity index 94% rename from Scripts/Classes/Universe.gd rename to core/components/universe.gd index cfa47be..09cbf21 100644 --- a/Scripts/Classes/Universe.gd +++ b/core/components/universe.gd @@ -1,7 +1,4 @@ -extends Object -class_name Universe - -const Fixture = preload("res://Scripts/Classes/Fixture.gd") +class_name Universe extends Object var universe = { "name": "New Universe", @@ -54,7 +51,12 @@ func new_fixture(manifest, options): var channel_index = options.channel + options.offset channel_index += (len(manifest.modes.values()[options.mode].channels)) * i var uuid = Globals.new_uuid() - var new_fixture = Fixture.new().from(self, manifest, channel_index, options.mode, options.name, uuid, options.get("virtual_fixtures", [])) + var new_fixture = Fixture.new({ + "universe": self, + "channel": options.channel, + "mode": options.mode, + "manifest": manifest + }) universe.fixtures[channel_index] = new_fixture diff --git a/Scripts/Classes/Uuid.gd b/core/components/uuid.gd similarity index 99% rename from Scripts/Classes/Uuid.gd rename to core/components/uuid.gd index 6491260..6c78a6e 100644 --- a/Scripts/Classes/Uuid.gd +++ b/core/components/uuid.gd @@ -2,7 +2,7 @@ # Note: The code might not be as pretty it could be, since it's written # in a way that maximizes performance. Methods are inlined and loops are avoided. -extends Node +class_name UUID_Util extends Node const BYTE_MASK: int = 0b11111111 diff --git a/Scripts/Node Config Editor/Editor_window.gd b/core/engine/Engine.gd similarity index 66% rename from Scripts/Node Config Editor/Editor_window.gd rename to core/engine/Engine.gd index e5ba31d..fae2c76 100644 --- a/Scripts/Node Config Editor/Editor_window.gd +++ b/core/engine/Engine.gd @@ -1,15 +1,11 @@ -extends Window +extends Node # Called when the node enters the scene tree for the first time. -func _ready(): +func _ready() -> void: pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): +func _process(delta: float) -> void: pass - - -func _on_close_requested(): - self.hide() diff --git a/core/engine/EngineComponent.gd b/core/engine/EngineComponent.gd new file mode 100644 index 0000000..1751e88 --- /dev/null +++ b/core/engine/EngineComponent.gd @@ -0,0 +1,55 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name EngineComponent extends Object +## Base class for an engine components, contains functions for storing metadata, and uuid's + +var uuid: String = "" ## Uuid of the current component +var user_meta: Dictionary ## Infomation that can be stored by other scripts + +func _init() -> void: + print("EngineComponent") + uuid = UUID_Util.v4() + + +func set_user_meta(key: String, value: Variant): + ## Sets user_meta from the given value + + user_meta[key] = value + + +func get_user_meta(key: String, default=null) -> Variant: + ## Returns user_meta from the given key, if the key is not found, default is returned + + return user_meta.get(key, default) + + +func delete_user_meta(key: String) -> bool: + ## Delets an item from user-meta, returning true if item was found and deleted, and false if not + + return user_meta.erase(key) + + +func serialize() -> Dictionary: + ## When this object gets serialize all user metadata that is an Object, will be checked for a uuid propity. + ## If one is present it will be used as the serialized version of that object. If none is present, it will be ignored. + ## Other user_meta that is not an object will be directly added to the serialized data. + + return { + "uuid":uuid, + "user_meta":serialize_meta() + } + + +func serialize_meta() -> Dictionary: + ## Returnes serialized user_meta + + var serialized_user_meta: Dictionary + + for key: String in user_meta: + if user_meta[key] is Object and "uuid" in user_meta[key]: + serialized_user_meta[key] = user_meta[key].uuid + else: + serialized_user_meta[key] = user_meta[key] + + return serialized_user_meta diff --git a/project.godot b/project.godot index ad55088..e201873 100644 --- a/project.godot +++ b/project.godot @@ -30,6 +30,7 @@ driver/enable_input=true [autoload] +Spectrum="*res://core/engine/Engine.gd" Globals="*res://Scripts/Global.gd" [debug] From 924913b7e941943ff637db033b8aa7a10cc792a3 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 11 Mar 2024 20:46:03 +1300 Subject: [PATCH 02/20] Ability to save files --- Fixtures/generic/desk-channel.json | 36 ++++---- Main.tscn | 77 +--------------- Scripts/Menu_buttons.gd | 5 + core/components/Fixture.gd | 4 +- core/components/system.gd | 143 ----------------------------- core/engine/Engine.gd | 18 ++-- core/engine/EngineComponent.gd | 1 - core/engine/System.gd | 94 +++++++++++++++++++ core/engine/Utils.gd | 19 ++++ project.godot | 2 +- 10 files changed, 155 insertions(+), 244 deletions(-) create mode 100644 Scripts/Menu_buttons.gd delete mode 100644 core/components/system.gd create mode 100644 core/engine/System.gd create mode 100644 core/engine/Utils.gd diff --git a/Fixtures/generic/desk-channel.json b/Fixtures/generic/desk-channel.json index 704846e..7eb31e6 100644 --- a/Fixtures/generic/desk-channel.json +++ b/Fixtures/generic/desk-channel.json @@ -1,25 +1,25 @@ { "schema_version": "1.0", "info": { - "brand": "Generic", - "name": "Desk Channel", - "date": "21-07-2018", - "author": ["Flo Edelmann", "Liam Sherwin"], - "categories": ["Dimmer"], - "links": { - "Website": "https://open-fixture-library.org/generic/desk-channel", - "OFLLibrary": "https://open-fixture-library.org/generic/desk-channel" - } + "brand": "Generic", + "name": "Desk Channel", + "date": "21-07-2018", + "author": ["Flo Edelmann", "Liam Sherwin"], + "categories": ["Dimmer"], + "links": { + "Website": "https://open-fixture-library.org/generic/desk-channel", + "OFLLibrary": "https://open-fixture-library.org/generic/desk-channel" + } }, "modes": { - "1 Channel": { - "channels": ["Intensity"] - }, - "2 Channel": { - "channels": ["Intensity", "IntensityFine"] - }, - "3 Channel": { - "channels": ["Intensity", "IntensityFine", "IntensityFine2"] - } + "1 Channel": { + "channels": ["Intensity"] + }, + "2 Channel": { + "channels": ["Intensity", "IntensityFine"] + }, + "3 Channel": { + "channels": ["Intensity", "IntensityFine", "IntensityFine2"] + } } } diff --git a/Main.tscn b/Main.tscn index d1517bc..45fbe53 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,15 +1,13 @@ -[gd_scene load_steps=25 format=3 uid="uid://p3sohjs1pt37"] +[gd_scene load_steps=22 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] [ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] -[ext_resource type="Script" path="res://core/components/system.gd" id="5_qili6"] +[ext_resource type="Script" path="res://Scripts/Menu_buttons.gd" id="7_gussm"] [ext_resource type="PackedScene" uid="uid://dhor5xf4xd2ul" path="res://Panels/Desk/Desk.tscn" id="8_12iq0"] [ext_resource type="PackedScene" uid="uid://cdg8rr3v7el85" path="res://Panels/Patch Bay/Patch_bay.tscn" id="9_hxqqf"] [ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="10_e6e26"] -[ext_resource type="Script" path="res://Panels/Popups/Popup_window.gd" id="10_yavq3"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="11_7alyx"] -[ext_resource type="Texture2D" uid="uid://bhl73t2e0jcwn" path="res://Assets/Icons/close.svg" id="11_mn7am"] [ext_resource type="PackedScene" uid="uid://nd4u83us3lgo" path="res://Panels/Settings/Settings.tscn" id="27_03pyd"] [ext_resource type="Script" path="res://Scripts/Window.gd" id="27_nmwy1"] @@ -74,13 +72,6 @@ unicode = 112 [sub_resource type="Shortcut" id="Shortcut_sn8ws"] events = [SubResource("InputEventKey_7uieo")] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5sp73"] -content_margin_left = 5.0 -content_margin_top = 5.0 -content_margin_right = 5.0 -content_margin_bottom = 5.0 -bg_color = Color(0.12549, 0.12549, 0.12549, 0) - [node name="Main" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -89,7 +80,6 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 theme = ExtResource("1_lygr6") -script = ExtResource("5_qili6") [node name="ColorRect" type="ColorRect" parent="."] layout_mode = 1 @@ -136,6 +126,7 @@ offset_left = -495.915 offset_right = -3.91504 offset_bottom = 45.0 grow_horizontal = 0 +script = ExtResource("7_gussm") [node name="Label" type="Label" parent="Menu Buttons"] custom_minimum_size = Vector2(76, 0) @@ -208,60 +199,6 @@ color = Color(0.0666667, 0.0666667, 0.0666667, 1) [node name="Settings" parent="Settings" instance=ExtResource("27_03pyd")] -[node name="Popups" type="Window" parent="."] -title = "Warnings" -initial_position = 5 -size = Vector2i(570, 330) -visible = false -script = ExtResource("10_yavq3") - -[node name="VBoxContainer" type="PanelContainer" parent="Popups"] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="PanelContainer" type="VBoxContainer" parent="Popups/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Popups/VBoxContainer/PanelContainer"] -layout_mode = 2 -size_flags_vertical = 3 -theme_override_styles/panel = SubResource("StyleBoxFlat_5sp73") - -[node name="Content" type="VBoxContainer" parent="Popups/VBoxContainer/PanelContainer/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="HSeparator" type="HSeparator" parent="Popups/VBoxContainer/PanelContainer"] -layout_mode = 2 - -[node name="Close" type="Button" parent="Popups/VBoxContainer/PanelContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 8 -text = "Close" -icon = ExtResource("11_mn7am") - -[node name="Load File Dialog" type="FileDialog" parent="."] -title = "Open a File" -initial_position = 5 -size = Vector2i(532, 439) -ok_button_text = "Open" -dialog_hide_on_ok = true -file_mode = 0 -access = 2 -use_native_dialog = true - -[node name="Save File Dialog" type="FileDialog" parent="."] -initial_position = 5 -size = Vector2i(742, 659) -access = 2 -use_native_dialog = true - [node name="Debug Text" type="Label" parent="."] layout_mode = 1 anchors_preset = 3 @@ -281,12 +218,6 @@ text = "Beta Version 0.4.0 [connection signal="tab_button_pressed" from="TabContainer" to="TabContainer" method="_on_tab_button_pressed"] [connection signal="tab_clicked" from="TabContainer" to="TabContainer" method="_on_tab_clicked"] -[connection signal="toggled" from="Menu Buttons/Edit Mode" to="." method="_on_edit_mode_toggled"] -[connection signal="pressed" from="Menu Buttons/Save" to="." method="_on_save_pressed"] -[connection signal="pressed" from="Menu Buttons/Load" to="." method="_on_load_pressed"] +[connection signal="pressed" from="Menu Buttons/Save" to="Menu Buttons" method="_on_save_pressed"] [connection signal="pressed" from="Menu Buttons/Settings" to="Settings" method="show"] [connection signal="close_requested" from="Settings" to="Settings" method="_on_close_requested"] -[connection signal="close_requested" from="Popups" to="Popups" method="_on_close_requested"] -[connection signal="pressed" from="Popups/VBoxContainer/PanelContainer/Close" to="Popups" method="_on_close_pressed"] -[connection signal="file_selected" from="Load File Dialog" to="." method="_on_load_file_dialog_file_selected"] -[connection signal="file_selected" from="Save File Dialog" to="." method="_on_save_file_dialog_file_selected"] diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd new file mode 100644 index 0000000..1bbd88f --- /dev/null +++ b/Scripts/Menu_buttons.gd @@ -0,0 +1,5 @@ +extends HBoxContainer + +func _on_save_pressed() -> void: + print(OS.get_environment("HOME")) + print(Core.save("Debug_show.spsave", OS.get_environment("HOME"))) diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 3467416..36ecab2 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -49,9 +49,9 @@ func _init(i: Dictionary = {}) -> void: func serialize() -> Dictionary: ## Returnes serialized infomation about this fixture - + print(uuid) return { - "universe":universe.uuid, + "universe":universe.get_uuid(), "channel":channel, "mode":mode, "meta":meta, diff --git a/core/components/system.gd b/core/components/system.gd deleted file mode 100644 index bf02279..0000000 --- a/core/components/system.gd +++ /dev/null @@ -1,143 +0,0 @@ -extends Control - -var current_file = "" -var home_directory = OS.get_environment("HOME") -var save_folder_path = home_directory + "/Documents/Spectrum/" -var file_name = "" -var save_file = { - "nodes":{}, - "node_connections":{}, - "widgets":{} - } - -func _ready(): - OS.set_low_processor_usage_mode(true) - -func _on_save_pressed(): - save() - -func save(): - save_nodes() - save_widgets() - save_file.universes = Globals.serialize_universes() - Globals.nodes.save_file_dialog.popup() - -func save_nodes(): - for node_to_save in Globals.nodes.node_editor.get_children(): - var node_file_path = node_to_save.get_meta("node_file_path") - if not node_file_path: continue - var manifest_file = FileAccess.open(node_file_path+"manifest.json", FileAccess.READ) - if not manifest_file: - Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_MANIFEST,"from":node_file_path}]) - return - var manifest = JSON.parse_string(manifest_file.get_as_text()) - save_file.nodes[node_to_save.name] = { - "node_file_path":node_file_path, - "uuid":manifest.uuid, - "name":node_to_save.name, - "position_offset":[node_to_save.position_offset.x,node_to_save.position_offset.y], - "values":{ - - } - } - for key in manifest.values.keys(): - - if not node_to_save.get_node(manifest.values[key].node): - Globals.show_popup([{"type":Globals.error.NODE_SAVE_MANIFEST_ERROR,"from":node_file_path}]) - return - save_file.nodes[node_to_save.name].values[key] = node_to_save.get_node(manifest.values[key].node).get(manifest.values[key].content) - save_file.node_connections = Globals.nodes.node_editor.connected_nodes - -func save_widgets(): - for widget_to_save in Globals.nodes.console_editor.get_children(): - var widget_file_path = widget_to_save.get_meta("widget_file_path") - if not widget_file_path: continue - var manifest_file = FileAccess.open(widget_file_path+"manifest.json", FileAccess.READ) - if not manifest_file: - Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_MANIFEST,"from":widget_file_path}]) - return - var manifest = JSON.parse_string(manifest_file.get_as_text()) - save_file.widgets[widget_to_save.name] = { - "widget_file_path":widget_file_path, - "uuid":manifest.uuid, - "name":widget_to_save.name, - "position_offset":[widget_to_save.position_offset.x,widget_to_save.position_offset.y], - "size":[widget_to_save.size.x,widget_to_save.size.y], - "values":{ - - } - } - - for key in manifest.values.keys(): - if not widget_to_save.get_node(manifest.values[key].node): - Globals.show_popup([{"type":Globals.error.NODE_SAVE_MANIFEST_ERROR,"from":widget_file_path}]) - return - save_file.widgets[widget_to_save.name].values[key] = widget_to_save.get_node(manifest.values[key].node).get(manifest.values[key].content) - save_file.node_connections = Globals.nodes.node_editor.connected_nodes - -func _on_save_file_dialog_file_selected(path): - var input_file_name = Globals.nodes.save_file_dialog.current_file - - if not input_file_name: - input_file_name = "New Save" - file_name = input_file_name - - save_json_to_file(path, save_file, file_name) - -func save_json_to_file(folder_path, save_data, _file_name): - - var file_access = FileAccess.open(folder_path, FileAccess.WRITE) - - file_access.store_string(JSON.stringify(save_data, "\t")) - file_access.close() - -func _on_load_pressed(): - get_node("Load File Dialog").popup() - -func load_save(file_path): - # Check if save file is valid - var manifest_file = FileAccess.open(file_path, FileAccess.READ) - if manifest_file == null: - Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_FILE,"from":file_path}]) - return - var manifest = JSON.parse_string(manifest_file.get_as_text()) - if manifest == null: - Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_MANIFEST,"from":file_path}]) - return - - # Add Nodes - for node_to_add in manifest.nodes.values(): - var node_manifest_file = FileAccess.open(node_to_add.node_file_path + "manifest.json", FileAccess.READ) - if manifest == null: - Globals.show_popup([{"type":Globals.error.MISSING_NODES,"from":node_manifest_file}]) - return - Globals.nodes.node_editor._add_node(node_to_add.node_file_path, {"position_offset":node_to_add.position_offset, "values":node_to_add.values}) - # Add node connections - Globals.nodes.node_editor.generate_connected_nodes(manifest.node_connections) - - # Add Widgets - for widget_to_add in manifest.widgets.values(): - var widget_manifest_file = FileAccess.open(widget_to_add.widget_file_path + "manifest.json", FileAccess.READ) - if manifest == null: - Globals.show_popup([{"type":Globals.error.MISSING_NODES,"from":widget_manifest_file}]) - return - Globals.nodes.console_editor._add_widget(widget_to_add.widget_file_path, {"position_offset":widget_to_add.get("position_offset"), "values":widget_to_add.get("values"), "size":widget_to_add.get("size")}) - - #Add Universes - Globals.deserialize_universes(manifest.universes) - Globals.call_subscription("reload_universes") - Globals.call_subscription("reload_fixtures") - -func _on_load_file_dialog_file_selected(path): - load_save(path) - -func _on_edit_mode_toggled(toggled_on): - Globals.set_value("edit_mode", not toggled_on) - if toggled_on: - Globals.nodes.edit_mode_toggle.text = "Play Mode" - else: - Globals.nodes.edit_mode_toggle.text = "Edit Mode" - - -func on_keypad_button_pressed(extra_arg_0): - pass # Replace with function body. diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index fae2c76..08c0a0f 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -1,11 +1,17 @@ -extends Node +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. +class_name CoreEngine extends Node +## The core engine that powers Spectrum + +var current_file_name: String = "" +var current_file_path: String = "" + +var _system: System = System.new() # Called when the node enters the scene tree for the first time. func _ready() -> void: - pass # Replace with function body. - + OS.set_low_processor_usage_mode(true) -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass +func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: + return _system.save(self, file_name, file_path) diff --git a/core/engine/EngineComponent.gd b/core/engine/EngineComponent.gd index 1751e88..4552b02 100644 --- a/core/engine/EngineComponent.gd +++ b/core/engine/EngineComponent.gd @@ -8,7 +8,6 @@ var uuid: String = "" ## Uuid of the current component var user_meta: Dictionary ## Infomation that can be stored by other scripts func _init() -> void: - print("EngineComponent") uuid = UUID_Util.v4() diff --git a/core/engine/System.gd b/core/engine/System.gd new file mode 100644 index 0000000..8ed2ae7 --- /dev/null +++ b/core/engine/System.gd @@ -0,0 +1,94 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name System extends Object +## Engine class for the save load system + +var save_file: Dictionary = {} + +func save(engine: CoreEngine, file_name: String, file_path: String) -> Error: + ## Saves the current state of the given engine to a file + + save_file.universes = Globals.serialize_universes() + return Utils.save_json_to_file(file_path, file_name, save_file) + +#extends Object +# +#var current_file = "" +#var home_directory = OS.get_environment("HOME") +#var save_folder_path = home_directory + "/Documents/Spectrum/" +#var file_name = "" +#var save_file = { + #"nodes":{}, + #"node_connections":{}, + #"widgets":{} + #} +# +#func _ready(): + #OS.set_low_processor_usage_mode(true) +# +#func _on_save_pressed(): + #save() +# +#func save(): + #save_nodes() + #save_widgets() + #save_file.universes = Globals.serialize_universes() + #Globals.nodes.save_file_dialog.popup() +# +# +#func _on_save_file_dialog_file_selected(path): + #var input_file_name = Globals.nodes.save_file_dialog.current_file +# + #if not input_file_name: + #input_file_name = "New Save" + #file_name = input_file_name +# + #save_json_to_file(path, save_file, file_name) + # +#func save_json_to_file(folder_path, save_data, _file_name): + # + #var file_access = FileAccess.open(folder_path, FileAccess.WRITE) + # + #file_access.store_string(JSON.stringify(save_data, "\t")) + #file_access.close() +# +#func _on_load_pressed(): + #get_node("Load File Dialog").popup() + # +#func load_save(file_path): + ## Check if save file is valid + #var manifest_file = FileAccess.open(file_path, FileAccess.READ) + #if manifest_file == null: + #Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_FILE,"from":file_path}]) + #return + #var manifest = JSON.parse_string(manifest_file.get_as_text()) + #if manifest == null: + #Globals.show_popup([{"type":Globals.error.UNABLE_TO_LOAD_MANIFEST,"from":file_path}]) + #return + # + ## Add Nodes + #for node_to_add in manifest.nodes.values(): + #var node_manifest_file = FileAccess.open(node_to_add.node_file_path + "manifest.json", FileAccess.READ) + #if manifest == null: + #Globals.show_popup([{"type":Globals.error.MISSING_NODES,"from":node_manifest_file}]) + #return + #Globals.nodes.node_editor._add_node(node_to_add.node_file_path, {"position_offset":node_to_add.position_offset, "values":node_to_add.values}) + ## Add node connections + #Globals.nodes.node_editor.generate_connected_nodes(manifest.node_connections) + # + ## Add Widgets + #for widget_to_add in manifest.widgets.values(): + #var widget_manifest_file = FileAccess.open(widget_to_add.widget_file_path + "manifest.json", FileAccess.READ) + #if manifest == null: + #Globals.show_popup([{"type":Globals.error.MISSING_NODES,"from":widget_manifest_file}]) + #return + #Globals.nodes.console_editor._add_widget(widget_to_add.widget_file_path, {"position_offset":widget_to_add.get("position_offset"), "values":widget_to_add.get("values"), "size":widget_to_add.get("size")}) + # + ##Add Universes + #Globals.deserialize_universes(manifest.universes) + #Globals.call_subscription("reload_universes") + #Globals.call_subscription("reload_fixtures") + # +#func _on_load_file_dialog_file_selected(path): + #load_save(path) diff --git a/core/engine/Utils.gd b/core/engine/Utils.gd new file mode 100644 index 0000000..f3b6f70 --- /dev/null +++ b/core/engine/Utils.gd @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name Utils extends Object +## Usefull function that would be annoying to write out each time + +static func save_json_to_file(file_path: String, file_name: String, json: Dictionary) -> Error: + + var file_access: FileAccess = FileAccess.open(file_path+"/"+file_name, FileAccess.WRITE) + + if FileAccess.get_open_error(): + return FileAccess.get_open_error() + + print(JSON.stringify(json, "\t")) + file_access.store_string(JSON.stringify(json, "\t")) + file_access.close() + + return file_access.get_error() + diff --git a/project.godot b/project.godot index e201873..dd39df8 100644 --- a/project.godot +++ b/project.godot @@ -30,8 +30,8 @@ driver/enable_input=true [autoload] -Spectrum="*res://core/engine/Engine.gd" Globals="*res://Scripts/Global.gd" +Core="*res://core/engine/Engine.gd" [debug] From 6235cbae23bd60f19f2c655a252860cb5bda6ad3 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Sun, 17 Mar 2024 15:44:23 +1300 Subject: [PATCH 03/20] Move all engine related functions into Engine.gd class, updated all references to Globals to be CoreEngine --- Components/Accept Dialog/Accept_dialog.tscn | 1 - IO Plugins/DataIOPlugin.gd | 31 --- IO Plugins/Output Plugins/Empty Output.gd | 8 - Main.tscn | 19 +- Panels/Add Fixture/Add_fixture.gd | 25 ++- Panels/Fixtures/Fixtures.gd | 32 +-- Panels/Patch Bay/Patch_bay.gd | 116 +++++------ Panels/Virtual Fixtures/Virtual_fixtures.gd | 8 +- Scripts/Global.gd | 150 +++++++------- .../{engine => components}/EngineComponent.gd | 28 ++- core/components/Fixture.gd | 26 ++- core/components/Universe.gd | 176 ++++++++++++++++ core/components/universe.gd | 165 --------------- core/engine/Engine.gd | 188 +++++++++++++++++- core/engine/System.gd | 2 +- .../uuid.gd => engine/UUID_Util.gd} | 2 +- .../fixtures}/generic/cmy-fader.json | 0 .../fixtures}/generic/cw-ww-fader.json | 0 .../fixtures}/generic/desk-channel.json | 0 .../fixtures}/generic/drgb-fader.json | 0 .../fixtures}/generic/drgbw-fader.json | 0 .../fixtures}/generic/grbw-fader.json | 0 .../fixtures}/generic/pan-tilt.json | 0 .../fixtures}/generic/rgb-fader.json | 0 .../fixtures}/generic/rgba-fader.json | 0 .../fixtures}/generic/rgbawuv-fader.json | 0 .../fixtures}/generic/rgbd-fader.json | 0 .../fixtures}/generic/rgbw-fader.json | 0 .../fixtures}/generic/rgbwauv-fader.json | 0 .../fixtures}/generic/rgbww-fader.json | 0 .../fixtures}/generic/strobe.json | 0 core/io_plugins/DataIOPlugin.gd | 19 ++ .../io_plugins/input_plugins/Empty.gd | 0 .../io_plugins/output_plugins/ArtNetOutput.gd | 9 +- core/io_plugins/output_plugins/Empty.gd | 14 ++ project.godot | 2 + 36 files changed, 624 insertions(+), 397 deletions(-) delete mode 100644 IO Plugins/DataIOPlugin.gd delete mode 100644 IO Plugins/Output Plugins/Empty Output.gd rename core/{engine => components}/EngineComponent.gd (59%) create mode 100644 core/components/Universe.gd delete mode 100644 core/components/universe.gd rename core/{components/uuid.gd => engine/UUID_Util.gd} (98%) rename {Fixtures => core/fixtures}/generic/cmy-fader.json (100%) rename {Fixtures => core/fixtures}/generic/cw-ww-fader.json (100%) rename {Fixtures => core/fixtures}/generic/desk-channel.json (100%) rename {Fixtures => core/fixtures}/generic/drgb-fader.json (100%) rename {Fixtures => core/fixtures}/generic/drgbw-fader.json (100%) rename {Fixtures => core/fixtures}/generic/grbw-fader.json (100%) rename {Fixtures => core/fixtures}/generic/pan-tilt.json (100%) rename {Fixtures => core/fixtures}/generic/rgb-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgba-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgbawuv-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgbd-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgbw-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgbwauv-fader.json (100%) rename {Fixtures => core/fixtures}/generic/rgbww-fader.json (100%) rename {Fixtures => core/fixtures}/generic/strobe.json (100%) create mode 100644 core/io_plugins/DataIOPlugin.gd rename IO Plugins/Input Plugins/Empty Input.gd => core/io_plugins/input_plugins/Empty.gd (100%) rename IO Plugins/Output Plugins/Art Net.gd => core/io_plugins/output_plugins/ArtNetOutput.gd (95%) create mode 100644 core/io_plugins/output_plugins/Empty.gd diff --git a/Components/Accept Dialog/Accept_dialog.tscn b/Components/Accept Dialog/Accept_dialog.tscn index 358fa21..9ce7723 100644 --- a/Components/Accept Dialog/Accept_dialog.tscn +++ b/Components/Accept Dialog/Accept_dialog.tscn @@ -6,7 +6,6 @@ initial_position = 4 size = Vector2i(647, 100) visible = true -always_on_top = true dialog_autowrap = true script = ExtResource("1_55rlu") diff --git a/IO Plugins/DataIOPlugin.gd b/IO Plugins/DataIOPlugin.gd deleted file mode 100644 index c384e06..0000000 --- a/IO Plugins/DataIOPlugin.gd +++ /dev/null @@ -1,31 +0,0 @@ -extends Object -class_name DataIOPlugin - -var type: String = "" -var uuid: String = "" -var name: String = "" - -func set_type(new_type:String) -> void: - type = new_type - print(self, " Setting Type ", new_type, type) - -func get_type() -> String: - return type - -func set_uuid(new_uuid:String) -> void: - uuid = new_uuid - -func get_uuid() -> String: - return uuid - -func set_name(new_name: String) -> void: - name = new_name - -func get_name() -> String: - return name - -func send_packet(packet) -> void: - return - -func delete() -> void: - return diff --git a/IO Plugins/Output Plugins/Empty Output.gd b/IO Plugins/Output Plugins/Empty Output.gd deleted file mode 100644 index 6374537..0000000 --- a/IO Plugins/Output Plugins/Empty Output.gd +++ /dev/null @@ -1,8 +0,0 @@ -extends DataIOPlugin -class_name EmptyOutput - -var exposed_values = [] - -func _init(): - self.set_type("output") - self.set_name("Empty Output") diff --git a/Main.tscn b/Main.tscn index 45fbe53..eb7d60a 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,13 +1,12 @@ -[gd_scene load_steps=22 format=3 uid="uid://p3sohjs1pt37"] +[gd_scene load_steps=21 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] [ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] +[ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] +[ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="5_8370q"] [ext_resource type="Script" path="res://Scripts/Menu_buttons.gd" id="7_gussm"] -[ext_resource type="PackedScene" uid="uid://dhor5xf4xd2ul" path="res://Panels/Desk/Desk.tscn" id="8_12iq0"] [ext_resource type="PackedScene" uid="uid://cdg8rr3v7el85" path="res://Panels/Patch Bay/Patch_bay.tscn" id="9_hxqqf"] -[ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="10_e6e26"] -[ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="11_7alyx"] [ext_resource type="PackedScene" uid="uid://nd4u83us3lgo" path="res://Panels/Settings/Settings.tscn" id="27_03pyd"] [ext_resource type="Script" path="res://Scripts/Window.gd" id="27_nmwy1"] @@ -97,24 +96,20 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -current_tab = 3 +current_tab = 1 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true script = ExtResource("3_nk5d5") -[node name="Fixtures" parent="TabContainer" instance=ExtResource("10_e6e26")] -visible = false -layout_mode = 2 - -[node name="Desk" parent="TabContainer" instance=ExtResource("8_12iq0")] +[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] visible = false layout_mode = 2 [node name="Patch Bay" parent="TabContainer" instance=ExtResource("9_hxqqf")] -visible = false layout_mode = 2 -[node name="Virtual Fixtures" parent="TabContainer" instance=ExtResource("11_7alyx")] +[node name="Virtual Fixtures" parent="TabContainer" instance=ExtResource("5_8370q")] +visible = false layout_mode = 2 [node name="Menu Buttons" type="HBoxContainer" parent="."] diff --git a/Panels/Add Fixture/Add_fixture.gd b/Panels/Add Fixture/Add_fixture.gd index f4d0f8d..40952b0 100644 --- a/Panels/Add Fixture/Add_fixture.gd +++ b/Panels/Add Fixture/Add_fixture.gd @@ -24,7 +24,8 @@ var options: Dictionary = { func _ready() -> void: - Globals.subscribe("reload_universes", self._reload_universes) + Core.universe_added.connect(self._reload_universes) + Core.universe_removed.connect(self._reload_universes) _reload_universes() _reload_fixture_tree() @@ -38,14 +39,14 @@ func _reload_fixture_tree() -> void: var root: TreeItem = tree.create_item() tree.hide_root = true - for manufacturer: String in Globals.fixtures.keys(): + for manufacturer: String in Core.fixtures_definitions.keys(): var manufacturer_item: TreeItem = tree.create_item(root) manufacturer_item.set_text(0, manufacturer) manufacturer_item.collapsed = true - for fixture: String in Globals.fixtures[manufacturer].keys(): + for fixture: String in Core.fixtures_definitions[manufacturer].keys(): var fixture_item: TreeItem = tree.create_item(manufacturer_item) - fixture_item.set_text(0, Globals.fixtures[manufacturer][fixture].info.name) + fixture_item.set_text(0, Core.fixtures_definitions[manufacturer][fixture].info.name) func _reload_menu() -> void: @@ -66,13 +67,13 @@ func _reload_menu() -> void: self.get_node(fixture_channel_list).add_item(channel) -func _reload_universes() -> void: +func _reload_universes(_universe=null) -> void: ## Reload the list of universes self.get_node(fixture_universe_option).clear() - for universe: Universe in Globals.universes.values(): - self.get_node(fixture_universe_option).add_item(universe.get_universe_name()) + for universe: Universe in Core.universes.values(): + self.get_node(fixture_universe_option).add_item(universe.name) func _on_fixture_tree_item_selected() -> void: @@ -86,7 +87,7 @@ func _on_fixture_tree_item_selected() -> void: var manufacturer: String = selected.get_parent().get_text(0) var fixture: String = selected.get_text(0) - current_fixture = Globals.fixtures[manufacturer][fixture] + current_fixture = Core.fixtures_definitions[manufacturer][fixture] options.mode = 0 _reload_menu() @@ -101,7 +102,13 @@ func _on_add_fixture_button_pressed() -> void: if self.get_node(fixture_universe_option).selected < 0: return - Globals.universes.values()[self.get_node(fixture_universe_option).selected].new_fixture(current_fixture, options) + Core.universes.values()[self.get_node(fixture_universe_option).selected].new_fixture( + current_fixture, + options.mode, + options.channel, + options.quantity, + options.offset + ) func _on_quantity_value_changed(value: int) -> void: diff --git a/Panels/Fixtures/Fixtures.gd b/Panels/Fixtures/Fixtures.gd index 1e4733c..26b02d6 100644 --- a/Panels/Fixtures/Fixtures.gd +++ b/Panels/Fixtures/Fixtures.gd @@ -11,8 +11,10 @@ var active_fixtures : Array = [] var last_selected_node: Control func _ready() -> void: - Globals.subscribe("reload_fixtures", self.reload_fixtures) - Globals.subscribe("active_fixtures", self.set_active_fixtures) + Core.fixture_added.connect(self._reload_fixtures) + Core.fixture_removed.connect(self._reload_fixtures) + + Core.fixture_selection_changed.connect(self.set_active_fixtures) func delete_request(node:Control) -> void : @@ -25,9 +27,8 @@ func delete_request(node:Control) -> void : func(node): var fixture: Fixture = node.get_meta("fixture") - fixture.config.universe.remove_fixture(fixture) + fixture.universe.remove_fixture(fixture) - Globals.call_subscription("reload_fixtures") ).bind(node)) add_child(confirmation_dialog) @@ -51,28 +52,31 @@ func on_selected(selected_node:Control) -> void: pos_1 = pos_2 pos_2 = x - var fixtures_to_select: Array = [] + var fixtures_to_select: Array[Fixture] = [] for i in range(pos_1, pos_2+1): fixtures_to_select.append(children[i].get_meta("fixture")) - Globals.set_value("active_fixtures", fixtures_to_select) + Core.set_fixture_selection(fixtures_to_select) else: last_selected_node = selected_node - Globals.set_value("active_fixtures", [selected_node.get_meta("fixture")]) + Core.set_fixture_selection([selected_node.get_meta("fixture")]) -func reload_fixtures() -> void: +func _reload_fixtures(_fixture=null) -> void: + ## Reload the list of fixtures + + print("reloading") for node in get_node(physical_fixture_list).get_children(): node.get_parent().remove_child(node) node.queue_free() - for universe in Globals.universes.values(): - for fixture in universe.get_fixtures().values(): + for universe: Universe in Core.universes.values(): + for fixture: Fixture in universe.fixtures.values(): var node_to_add : Control = Globals.components.list_item.instantiate() node_to_add.control_node = self - node_to_add.set_item_name(fixture.meta.fixture_name + " | " + universe.get_universe_name() + " CH: " + str(fixture.channel) + "-" + str(fixture.channel+fixture.length-1)) + node_to_add.set_item_name(fixture.meta.fixture_name + " | " + universe.name + " CH: " + str(fixture.channel) + "-" + str(fixture.channel+fixture.length-1)) node_to_add.name = fixture.uuid node_to_add.set_meta("fixture", fixture) get_node(physical_fixture_list).add_child(node_to_add) @@ -100,13 +104,13 @@ func _on_new_fixture_group_pressed() -> void: func _on_select_all_pressed() -> void: - var fixtures_to_select: Array = [] + var fixtures_to_select: Array[Fixture] = [] for list_item: Control in get_node(physical_fixture_list).get_children(): fixtures_to_select.append(list_item.get_meta("fixture")) - Globals.set_value("active_fixtures", fixtures_to_select) + Core.set_fixture_selection(fixtures_to_select) func _on_select_none_pressed() -> void: - Globals.set_value("active_fixtures", []) + Core.set_fixture_selection([]) diff --git a/Panels/Patch Bay/Patch_bay.gd b/Panels/Patch Bay/Patch_bay.gd index b4d9789..2e1ea05 100644 --- a/Panels/Patch Bay/Patch_bay.gd +++ b/Panels/Patch Bay/Patch_bay.gd @@ -18,21 +18,19 @@ var _current_universe: Universe var _current_io: DataIOPlugin func _ready() -> void: - Globals.subscribe("reload_universes", self._reload_universes) - Globals.subscribe("patch_bay_reload_io", self._reload_io) + Core.universe_added.connect(self._reload_universes) + Core.universe_removed.connect(self._reload_universes) func _new_universe() -> Universe: ## Creates a new Universe, and calls the reload_universes subscription - var new_universe: Universe = Globals.new_universe() - new_universe.set_universe_name("Universe " + str(len(Globals.universes.keys()))) + var new_universe: Universe = Core.new_universe("Universe " + str( len( Core.universes.keys() ) + 1 ) ) - Globals.call_subscription("reload_universes") return new_universe -func _reload_universes() -> void: +func _reload_universes(_universe) -> void: ## Reloads the list of Universes in the UI if not is_instance_valid(_current_universe): @@ -45,23 +43,23 @@ func _reload_universes() -> void: if not _current_universe: _set_universe_controls_enabled(false) - for universe: Universe in Globals.universes.values(): + for universe: Universe in Core.universes.values(): _add_universe_list_item(universe) - - Globals.call_subscription("patch_bay_reload_io") + func _add_universe_list_item(universe: Universe) -> void: ## Adds a list item to the universe list var new_list_item: Control = Globals.components.list_item.instantiate() - new_list_item.set_item_name(universe.get_universe_name()) + + new_list_item.set_item_name(universe.name) new_list_item.control_node = self - new_list_item.name = universe.get_uuid() + new_list_item.name = universe.uuid new_list_item.set_meta("object", universe) - if _current_universe and _current_universe.get_uuid() == universe.get_uuid(): + if _current_universe and _current_universe.uuid == universe.uuid: new_list_item.set_highlighted(true) else: new_list_item.set_highlighted(false) @@ -82,17 +80,10 @@ func _set_universe_controls_enabled(enabled:bool) -> void: self.get_node(universe_name).text = "" -func _new_input() -> void: - ## WIP Function for adding a Universe input - - pass - - func _new_output() -> void: - ## Adds a new output plugin to the currently selected universe, and calls reload_io() + ## Adds a new EmptyOutput plugin to the currently selected universe - _current_universe.new_output() - Globals.call_subscription("patch_bay_reload_io") + _current_universe.new_output(EmptyOutput) func _change_io_config(io: DataIOPlugin = null) -> void: @@ -139,7 +130,7 @@ func _expose_value(value_to_expose: Dictionary) -> void: self.get_node(universe_io_controls).add_child(container) -func _reload_io() -> void: +func _reload_io(_output=null) -> void: ## Reloads the Input and Output lists for the currently selected Universe if not is_instance_valid(_current_io): @@ -152,13 +143,13 @@ func _reload_io() -> void: # If _current_universe is not defined, exit the function now, this will only delete the current IO nodes and leave the list empty if not _current_universe or not _current_io: - _change_io_config() + _change_io_config(null) _set_io_type_option("") if not _current_universe: return # Loop through all outputs in _current_universe, and add them to the list - for output: DataIOPlugin in _current_universe.get_all_outputs().values(): + for output: DataIOPlugin in _current_universe.outputs.values(): _add_output_list_item(output) @@ -166,16 +157,16 @@ func _add_output_list_item(output: DataIOPlugin) -> void: ## Adds a list_item component to the output list var new_list_item: Control = Globals.components.list_item.instantiate() - new_list_item.set_item_name(output.get_name()) + new_list_item.set_item_name(output.name) new_list_item.control_node = self - new_list_item.name = output.get_uuid() + new_list_item.name = output.uuid new_list_item.set_meta("object", output) - if _current_io and _current_io.get_uuid() == output.get_uuid(): + if _current_io and _current_io.uuid == output.uuid: new_list_item.set_highlighted(true) _set_io_type_option("output") - self.get_node(universe_io_type).selected = Globals.output_plugins.keys().find(output.get_name()) + self.get_node(universe_io_type).selected = Globals.output_plugins.keys().find(output.name) _change_io_config(output) else: new_list_item.set_highlighted(false) @@ -189,35 +180,34 @@ func _new_channel_override() -> void: pass -func edit_request(list_item:Control) -> void: +func edit_request(list_item: Control) -> void: ## Called when the edit button is pressed on any IO or Universe if list_item.get_meta("object") is Universe: if _current_universe: - self.get_node(universe_list).get_node(_current_universe.get_uuid()).set_highlighted(false) + self.get_node(universe_list).get_node(_current_universe.uuid).set_highlighted(false) _current_universe = list_item.get_meta("object") - self.get_node(universe_list).get_node(_current_universe.get_uuid()).set_highlighted(true) - self.get_node(universe_name).text = _current_universe.get_universe_name() + _current_universe.output_added.connect(self._reload_io) + _current_universe.output_removed.connect(self._reload_io) + + self.get_node(universe_list).get_node(_current_universe.uuid).set_highlighted(true) + + self.get_node(universe_name).text = _current_universe.name _set_universe_controls_enabled(true) - Globals.call_subscription("patch_bay_reload_io") + _reload_io() elif list_item.get_meta("object") is DataIOPlugin: - match list_item.get_meta("object").get_type(): - "input": - pass - - "output": - if _current_io: - self.get_node(universe_outputs).get_node(_current_io.get_uuid()).set_highlighted(false) - _current_io = list_item.get_meta("object") - self.get_node(universe_outputs).get_node(_current_io.get_uuid()).set_highlighted(true) - - Globals.call_subscription("patch_bay_reload_io") + if _current_io: + self.get_node(universe_outputs).get_node(_current_io.uuid).set_highlighted(false) + _current_io = list_item.get_meta("object") + self.get_node(universe_outputs).get_node(_current_io.uuid).set_highlighted(true) + + _reload_io() -func _set_io_type_option(io_type:String) -> void: +func _set_io_type_option(io_type: String) -> void: ## Updates the list of IO types self.get_node(universe_io_type).clear() @@ -226,12 +216,14 @@ func _set_io_type_option(io_type:String) -> void: # Otherwise dissable the list dropdown if io_type: self.get_node(universe_io_type).disabled = false + match io_type: "input": pass "output": - for name in Globals.output_plugins: + for name in Core.output_plugins: self.get_node(universe_io_type).add_item(name) + else: self.get_node(universe_io_type).disabled = true @@ -245,6 +237,9 @@ func delete_request(list_item:Control) -> void: confirmation_dialog.confirmed.connect(( func(list_item: Control): if list_item.get_meta("object") is Universe: + + print("about to delete") + _delete_universe(list_item.get_meta("object")) elif list_item.get_meta("object") is DataIOPlugin: @@ -257,11 +252,12 @@ func delete_request(list_item:Control) -> void: func _delete_universe(universe: Universe) -> void: ## Deletes a Universe - Globals.delete_universe(universe) + print("deleting universe") + + Core.delete_universe(universe) _current_io = null _current_universe = null - _reload_universes() _set_universe_controls_enabled(false) @@ -269,27 +265,19 @@ func _delete_io(io: DataIOPlugin) -> void: ## Deletes an IO plugin var to_delete: DataIOPlugin = io - match to_delete.get_type(): - "input": - _current_universe.remove_input(to_delete) - "output": - _current_universe.remove_output(to_delete) + _current_universe.remove_output(to_delete) if to_delete == _current_io: _current_io = null - Globals.call_subscription("patch_bay_reload_io") func _on_io_type_item_selected(index:int) -> void: ## Called when the user selects an IO type from the list dropdown - if _current_io: - match _current_io.get_type(): - "input": - _current_io = _current_universe.change_input_type(_current_io.get_uuid(), Globals.input_plugins.values()[index]) - "output": - _current_io = _current_universe.change_output_type(_current_io.get_uuid(), Globals.output_plugins.values()[index]) - Globals.call_subscription("patch_bay_reload_io") + _current_universe.remove_output(_current_io) + _current_io = _current_universe.new_output(Core.output_plugins.values()[index]) + + _reload_io() func _on_new_universe_pressed() -> void: @@ -300,14 +288,10 @@ func _on_new_channel_overide_pressed() -> void: pass -func _on_new_input_pressed() -> void: - pass - - func _on_new_output_pressed() -> void: _new_output() func _on_universe_name_text_changed(new_text) -> void: _current_universe.set_universe_name(new_text) - _reload_universes() + Core.universe_updated.emit(Core.UPDATE_MODE_MODIFY, _current_universe.uuid) diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 4e25bf6..c1ea1b2 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -24,7 +24,7 @@ func _ready() -> void: _add_menu_hbox_button(ResourceLoader.load("res://Assets/Icons/Horizontal_distribute.svg"), self._align.bind(ORIENTATION_HORIZONTAL), "Align the selected fixtures horizontally" ) _add_menu_hbox_button(ResourceLoader.load("res://Assets/Icons/Vertical_distribute.svg"), self._align.bind(ORIENTATION_VERTICAL), "Align the selected fixtures verticality" ) - Globals.subscribe("active_fixtures", self._active_fixtures_changed) + Core.fixture_selection_changed.connect(self._active_fixtures_changed) func _add_menu_hbox_button(content:Variant, method: Callable, tooltip: String = "", disabled: bool = false) -> Button: @@ -48,7 +48,7 @@ func _add_menu_hbox_button(content:Variant, method: Callable, tooltip: String = func _add_fixture() -> void: ## Adds the currently selected virtual fixtures to the view - for fixture: Fixture in Globals.get_value("active_fixtures"): + for fixture: Fixture in Core.selected_fixtures: var node_to_add: Control = Globals.components.virtual_fixture.instantiate() node_to_add.set_fixture(fixture) @@ -118,9 +118,9 @@ func from(config: Dictionary, control_fixture: Fixture) -> void: func _on_virtual_fixture_selected(node) -> void: if node not in _selected_virtual_fixtures: _selected_virtual_fixtures.append(node) - Globals.select_fixture(node.fixture) + Core.select_fixtures([node.fixture]) func _on_virtual_fixture_deselected(node) -> void: _selected_virtual_fixtures.erase(node) - Globals.deselect_fixture(node.fixture) + Core.deselect_fixtures([node.fixture]) diff --git a/Scripts/Global.gd b/Scripts/Global.gd index 055e109..f2641d6 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -182,38 +182,38 @@ var output_plugins : Dictionary } func _ready() -> void: - load_io_plugins() - load_fixtures() + pass + #load_fixtures() -func load_io_plugins() -> void: - var output_plugin_folder : DirAccess = DirAccess.open(io_plugin_path + "Output Plugins") - for plugin in output_plugin_folder.get_files(): - var uninitialized_plugin = ResourceLoader.load(io_plugin_path + "Output Plugins" + "/" + plugin) - var initialized_plugin = uninitialized_plugin.new() - var plugin_name: String = initialized_plugin.get_name() - - if plugin_name in output_plugins.keys(): - plugin_name = plugin_name + " " + new_uuid() - - output_plugins[plugin_name] = uninitialized_plugin - initialized_plugin.free() - -func load_fixtures() -> void: - var access = DirAccess.open(fixture_path) - - for fixture_folder in access.get_directories(): - - for fixture in access.open(fixture_path+"/"+fixture_folder).get_files(): - - var manifest_file = FileAccess.open(fixture_path+fixture_folder+"/"+fixture, FileAccess.READ) - var manifest = JSON.parse_string(manifest_file.get_as_text()) - - manifest.info.file_path = fixture_path+fixture_folder+"/"+fixture - - if fixtures.has(manifest.info.brand): - fixtures[manifest.info.brand][manifest.info.name] = manifest - else: - fixtures[manifest.info.brand] = {manifest.info.name:manifest} +#func load_io_plugins() -> void: + #var output_plugin_folder : DirAccess = DirAccess.open(io_plugin_path + "Output Plugins") + #for plugin in output_plugin_folder.get_files(): + #var uninitialized_plugin = ResourceLoader.load(io_plugin_path + "Output Plugins" + "/" + plugin) + #var initialized_plugin = uninitialized_plugin.new() + #var plugin_name: String = initialized_plugin.get_name() + # + #if plugin_name in output_plugins.keys(): + #plugin_name = plugin_name + " " + new_uuid() + # + #output_plugins[plugin_name] = uninitialized_plugin + #initialized_plugin.free() +# +#func load_fixtures() -> void: + #var access = DirAccess.open(fixture_path) + # + #for fixture_folder in access.get_directories(): + # + #for fixture in access.open(fixture_path+"/"+fixture_folder).get_files(): + # + #var manifest_file = FileAccess.open(fixture_path+fixture_folder+"/"+fixture, FileAccess.READ) + #var manifest = JSON.parse_string(manifest_file.get_as_text()) + # + #manifest.info.file_path = fixture_path+fixture_folder+"/"+fixture + # + #if fixtures.has(manifest.info.brand): + #fixtures[manifest.info.brand][manifest.info.name] = manifest + #else: + #fixtures[manifest.info.brand] = {manifest.info.name:manifest} func show_popup(content: Array[Dictionary] = []) -> void: for i in content: @@ -248,50 +248,50 @@ func call_subscription(value_name:String) -> void: if node_to_update.is_valid(): node_to_update.call() -func new_uuid() -> String: - return UUID_Util.v4() - -func select_fixture(fixture_to_add:Fixture) -> Array: - - var active_fixtures = get_value("active_fixtures") - if fixture_to_add not in active_fixtures: - active_fixtures.append(fixture_to_add) - - set_value("active_fixtures", active_fixtures) - - return active_fixtures - -func deselect_fixture(fixture_to_remove:Fixture) -> Array: - var active_fixtures = get_value("active_fixtures") - active_fixtures.erase(fixture_to_remove) - - set_value("active_fixtures", active_fixtures) - return active_fixtures - -func new_universe() -> Universe: - var new_universe = Universe.new() - universes[new_universe.get_uuid()] = new_universe - return new_universe - -func delete_universe(universe:Universe) -> void: - universe.delete() - universes.erase(universe.get_uuid()) - universe.free() - - call_subscription("reload_universes") - call_subscription("reload_fixtures") - -func serialize_universes() -> Dictionary: - var serialized_universes = {} - for universe_uuid in universes: - serialized_universes[universe_uuid] = universes[universe_uuid].serialize() - return serialized_universes - -func deserialize_universes(new_universes:Dictionary): - for universe_uuid in new_universes: - var universe_to_add = Universe.new() - universe_to_add.from(new_universes[universe_uuid]) - universes[universe_uuid] = universe_to_add +#func new_uuid() -> String: + #return UUID_Util.v4() +# +#func select_fixture(fixture_to_add:Fixture) -> Array: + # + #var active_fixtures = get_value("active_fixtures") + #if fixture_to_add not in active_fixtures: + #active_fixtures.append(fixture_to_add) +# + #set_value("active_fixtures", active_fixtures) +# + #return active_fixtures + # +#func deselect_fixture(fixture_to_remove:Fixture) -> Array: + #var active_fixtures = get_value("active_fixtures") + #active_fixtures.erase(fixture_to_remove) + # + #set_value("active_fixtures", active_fixtures) + #return active_fixtures + # +#func new_universe() -> Universe: + #var new_universe = Universe.new() + #universes[new_universe.get_uuid()] = new_universe + #return new_universe +# +#func delete_universe(universe:Universe) -> void: + #universe.delete() + #universes.erase(universe.get_uuid()) + #universe.free() + # + #call_subscription("reload_universes") + #call_subscription("reload_fixtures") +# +#func serialize_universes() -> Dictionary: + #var serialized_universes = {} + #for universe_uuid in universes: + #serialized_universes[universe_uuid] = universes[universe_uuid].serialize() + #return serialized_universes +# +#func deserialize_universes(new_universes:Dictionary): + #for universe_uuid in new_universes: + #var universe_to_add = Universe.new() + #universe_to_add.from(new_universes[universe_uuid]) + #universes[universe_uuid] = universe_to_add func open_panel_in_window(panel_name:String) -> Variant: if panel_name in panels: diff --git a/core/engine/EngineComponent.gd b/core/components/EngineComponent.gd similarity index 59% rename from core/engine/EngineComponent.gd rename to core/components/EngineComponent.gd index 4552b02..c9b18d0 100644 --- a/core/engine/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -4,31 +4,51 @@ class_name EngineComponent extends Object ## Base class for an engine components, contains functions for storing metadata, and uuid's +signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) ## Emitted when an item is added, edited, or deleted from user_meta, if no value is present it meanes that the key has been deleted +signal name_changed(new_name: String) ## Emitted when the name of this object has changed + var uuid: String = "" ## Uuid of the current component +var name: String = "" ## The name of this object, only use when displaying to users, do not use it as a reference var user_meta: Dictionary ## Infomation that can be stored by other scripts + func _init() -> void: uuid = UUID_Util.v4() + print(self) -func set_user_meta(key: String, value: Variant): +func set_user_meta(key: String, value: Variant, no_signal: bool = false): ## Sets user_meta from the given value user_meta[key] = value + + if not no_signal: + user_meta_changed.emit(self, key, value) -func get_user_meta(key: String, default=null) -> Variant: +func get_user_meta(key: String, default = null) -> Variant: ## Returns user_meta from the given key, if the key is not found, default is returned return user_meta.get(key, default) -func delete_user_meta(key: String) -> bool: +func delete_user_meta(key: String, no_signal: bool = false) -> bool: ## Delets an item from user-meta, returning true if item was found and deleted, and false if not + if not no_signal: + user_meta_changed.emit(self, key) + return user_meta.erase(key) +func change_name(new_name: String, no_signal: bool = false) -> void: + ## Changes the name of this object + name = new_name + + if not no_signal: + name_changed.emit(new_name) + + func serialize() -> Dictionary: ## When this object gets serialize all user metadata that is an Object, will be checked for a uuid propity. ## If one is present it will be used as the serialized version of that object. If none is present, it will be ignored. @@ -43,7 +63,7 @@ func serialize() -> Dictionary: func serialize_meta() -> Dictionary: ## Returnes serialized user_meta - var serialized_user_meta: Dictionary + var serialized_user_meta: Dictionary = {} for key: String in user_meta: if user_meta[key] is Object and "uuid" in user_meta[key]: diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 36ecab2..4bcfb9b 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -4,9 +4,11 @@ class_name Fixture extends EngineComponent ## Engine class to control parameters of fixtures -signal color_changed(color: Color) ## Emmited when the color of this fixture is changed -signal mode_changed(mode: int) ## Emmited when the mode of the fixture is changed -signal channel_changed(new_channel: int) ## Emmited when the channel of the fixture is changed +signal color_changed(color: Color) ## Emitted when the color of this fixture is changed +signal mode_changed(mode: int) ## Emitted when the mode of the fixture is changed +signal channel_changed(new_channel: int) ## Emitted when the channel of the fixture is changed + +signal selected(selected: bool) ## Contains metadata infomation about this fixture var meta: Dictionary = { @@ -24,6 +26,8 @@ var manifest: Dictionary ## Fixture manifest var channels: Array ## Channels this fixture uses, and what they do var channel_ranges: Dictionary ## What happenes at each channel, at each value +var is_selected: bool = false + var _compiled_dmx_data: Dictionary var _parameters: Dictionary @@ -45,6 +49,11 @@ func _init(i: Dictionary = {}) -> void: meta.fixture_brand = i.manifest.info.brand meta.fixture_name = i.manifest.info.name + self.name_changed.connect( + func(new_name: String): + universe.fixture_name_changed.emit(self, new_name) + ) + super._init() func serialize() -> Dictionary: @@ -74,3 +83,14 @@ func set_color_rgb(r,g,b) -> void: _parameters.color = Color(r, g, b) color_changed.emit(_parameters.color) + + +func set_selected(state: bool) -> void: + is_selected = state + selected.emit(state) + + +func delete() -> bool: + ## Called when this fixture is about to be deleted + + return true diff --git a/core/components/Universe.gd b/core/components/Universe.gd new file mode 100644 index 0000000..4bd6f2f --- /dev/null +++ b/core/components/Universe.gd @@ -0,0 +1,176 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name Universe extends EngineComponent +## Enngie class for handling universes, and there outputs + +signal fixture_name_changed(fixture: Fixture, new_name: String) +signal fixture_added(fixtures: Array[Fixture]) +signal fixture_deleted(fixture_uuids: Array[String]) + +signal output_added(output: DataIOPlugin) +signal output_removed(output_uuid: String) + +var fixtures: Dictionary = {} ## Dictionary containing all the fixtures in this universe +var outputs: Dictionary = {} ## Dictionary containing all the outputs in this universe + +var engine: CoreEngine ## The CoreEngine class this universe belongs to + +func new_output(type = EmptyOutput, no_signal: bool = false) -> DataIOPlugin: + ## Adds a new output of type to this universe + + var new_output: DataIOPlugin = type.new() + + outputs[new_output.uuid] = new_output + + if not no_signal: + output_added.emit(new_output) + + return new_output + + +func remove_output(output: DataIOPlugin, no_signal: bool = false) -> void: + ## Removes an output + + var uuid = output.uuid + outputs.erase(uuid) + + output.delete() + output.free() + + if not no_signal: + output_removed.emit(uuid) + + +func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int = 1, offset:int = 0, no_signal: bool = false): + ## Adds a new fixture to this universe, if the channels are already in use false it returned + + if is_channel_used(range(channel, len(manifest.modes.values()[mode].channels))): + return false + + var just_added_fixtures: Array[Fixture] = [] + + for i: int in range(quantity): + var channel_index = channel + offset + channel_index += (len(manifest.modes.values()[mode].channels)) * i + + var new_fixture = Fixture.new({ + "universe": self, + "channel": channel_index, + "mode": mode, + "manifest": manifest + }) + + fixtures[channel_index] = new_fixture + just_added_fixtures.append(new_fixture) + + if not no_signal: + fixture_added.emit(just_added_fixtures) + + +func remove_fixture(fixture: Fixture, no_signal: bool = false): + ## Removes a fixture from this universe + + var fixture_uuid: String = fixture.uuid + + if fixture in engine.selected_fixtures: + engine.deselect_fixtures([fixture]) + + fixtures.erase(fixture.channel) + fixture.delete() + fixture.free() + + if not no_signal: + var uuids: Array[String] = [fixture_uuid] + fixture_deleted.emit(uuids) + + +func is_channel_used(channels: Array) -> bool: + ## Checks if any of the channels in channels are used by another fixture + return false + + +func delete(): + ## Called when this universe is about to be deleted, it will remove all outputs from this universe + + for output in outputs.values(): + remove_output(output) + + + + +#func get_fixtures(): + #return universe.fixtures + # +#func get_fixture(fixture_uuid): + #pass +# +#func set_fixture_data(data): + #universe.fixture_data.merge(data, true) + #_compile_and_send() +# + + + +# +#func set_desk_data(dmx_data): + #universe.desk_data.merge(dmx_data) + #_compile_and_send() +# +#func get_desk_data(): + #return universe.desk_data +# +#func _compile_and_send(): + #var compiled_dmx_data = universe.fixture_data + #compiled_dmx_data.merge(universe.desk_data, true) + #for output in universe.outputs: + #universe.outputs[output].send_packet(compiled_dmx_data) + # +#func serialize(): + #var serialized_outputs = {} + #var serialized_fixtures = {} + # + #for output_uuid in universe.outputs.keys(): + #serialized_outputs[output_uuid] = universe.outputs[output_uuid].serialize() + # + #for fixture_channel in universe.fixtures.keys(): + #var serialized_fixture = universe.fixtures[fixture_channel].serialize() + #if serialized_fixture: + #serialized_fixtures[fixture_channel] = serialized_fixture + # + # + #return { + #"name":universe.name, + #"uuid":universe.uuid, + #"fixtures":serialized_fixtures, + #"inputs":{}, + #"outputs":serialized_outputs, + #"desk_data":universe.desk_data + #} +# +#func from(serialized_universe): + #universe.name = serialized_universe.name + #universe.uuid = serialized_universe.uuid + # + #for fixture_channel in serialized_universe.fixtures: + #var fixture = serialized_universe.fixtures[fixture_channel] + #var options = { + #"channel":int(fixture_channel), + #"mode":fixture.mode, + #"name":fixture.display_name, + #"quantity":1, + #"offset":0, + #"virtual_fixtures":fixture.get("virtual_fixtures", []) + #} + #new_fixture(Globals.fixtures[fixture.fixture_brand][fixture.fixture_name], options) + # + #for output_uuid in serialized_universe.outputs: + #var input = serialized_universe.outputs[output_uuid] + #match input.type: + #"Empty": + #universe.outputs[output_uuid] = EmptyInput.new() + #"Art-Net": + #universe.outputs[output_uuid] = ArtNetOutput.new() + #universe.outputs[output_uuid].from(input) + #universe.outputs[output_uuid].connect_to_host() +# diff --git a/core/components/universe.gd b/core/components/universe.gd deleted file mode 100644 index 09cbf21..0000000 --- a/core/components/universe.gd +++ /dev/null @@ -1,165 +0,0 @@ -class_name Universe extends Object - -var universe = { - "name": "New Universe", - "uuid":Globals.new_uuid(), - "fixtures": { - }, - "inputs": { - }, - "outputs": { - - }, - "fixture_data":{ - - }, - "desk_data":{ - - } -} - -func set_universe_name(new_name): - universe.name = new_name - -func get_universe_name(): - return universe.name - -func get_uuid(): - return universe.uuid - -func get_all_outputs(): - return universe.outputs - -func get_output(uuid=""): - if uuid: - return universe.outputs[uuid] - return - -func new_output(type=EmptyOutput): - var uuid = Globals.new_uuid() - var new_output: DataIOPlugin = type.new() - new_output.set_uuid(uuid) - universe.outputs[uuid] = new_output - return new_output - -func new_fixture(manifest, options): - if options.channel in universe.fixtures: - return false - - for i in range(options.quantity): - - var channel_index = options.channel + options.offset - channel_index += (len(manifest.modes.values()[options.mode].channels)) * i - var uuid = Globals.new_uuid() - var new_fixture = Fixture.new({ - "universe": self, - "channel": options.channel, - "mode": options.mode, - "manifest": manifest - }) - - universe.fixtures[channel_index] = new_fixture - - Globals.call_subscription("reload_fixtures") - -func remove_fixture(fixture): - universe.fixtures.erase(fixture.config.channel) - fixture.delete() - - var active_fixtures = Globals.get_value("active_fixtures") - if active_fixtures: - if fixture in active_fixtures: - active_fixtures.erase(fixture) - Globals.set_value("active_fixtures", active_fixtures) - -func get_fixtures(): - return universe.fixtures - -func get_fixture(fixture_uuid): - pass - -func set_fixture_data(data): - universe.fixture_data.merge(data, true) - _compile_and_send() - -func remove_output(output): - universe.outputs.erase(output.get_uuid()) - output.delete() - output.free() - -func change_output_type(uuid, type): - if not type: type == EmptyOutput - universe.outputs[uuid].delete() - universe.outputs[uuid].free() - universe.outputs[uuid] = type.new() - universe.outputs[uuid].set_uuid(uuid) - return universe.outputs[uuid] - -func set_desk_data(dmx_data): - universe.desk_data.merge(dmx_data) - _compile_and_send() - -func get_desk_data(): - return universe.desk_data - -func _compile_and_send(): - var compiled_dmx_data = universe.fixture_data - compiled_dmx_data.merge(universe.desk_data, true) - for output in universe.outputs: - universe.outputs[output].send_packet(compiled_dmx_data) - -func serialize(): - var serialized_outputs = {} - var serialized_fixtures = {} - - for output_uuid in universe.outputs.keys(): - serialized_outputs[output_uuid] = universe.outputs[output_uuid].serialize() - - for fixture_channel in universe.fixtures.keys(): - var serialized_fixture = universe.fixtures[fixture_channel].serialize() - if serialized_fixture: - serialized_fixtures[fixture_channel] = serialized_fixture - - - return { - "name":universe.name, - "uuid":universe.uuid, - "fixtures":serialized_fixtures, - "inputs":{}, - "outputs":serialized_outputs, - "desk_data":universe.desk_data - } - -func from(serialized_universe): - universe.name = serialized_universe.name - universe.uuid = serialized_universe.uuid - - for fixture_channel in serialized_universe.fixtures: - var fixture = serialized_universe.fixtures[fixture_channel] - var options = { - "channel":int(fixture_channel), - "mode":fixture.mode, - "name":fixture.display_name, - "quantity":1, - "offset":0, - "virtual_fixtures":fixture.get("virtual_fixtures", []) - } - new_fixture(Globals.fixtures[fixture.fixture_brand][fixture.fixture_name], options) - - for output_uuid in serialized_universe.outputs: - var input = serialized_universe.outputs[output_uuid] - match input.type: - "Empty": - universe.outputs[output_uuid] = EmptyInput.new() - "Art-Net": - universe.outputs[output_uuid] = Art_Net_Output.new() - universe.outputs[output_uuid].from(input) - universe.outputs[output_uuid].connect_to_host() - -func delete(): - for fixture in universe.fixtures.values(): - remove_fixture(fixture) - - for output in universe.outputs.values(): - remove_output(output) - diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 08c0a0f..74c2f60 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -4,14 +4,200 @@ class_name CoreEngine extends Node ## The core engine that powers Spectrum +signal universe_name_changed(universe: Universe, new_name: String) ## Emitted when any of the universes in this engine have there name changed +signal universe_output_added(universe: Universe, output: DataIOPlugin) ## Emitted when of the universes +signal universe_output_removed(universe: Universe, output_uuid: String) + +signal universe_added(universe: Universe) +signal universe_removed(universe_uuid: String) + +signal fixture_name_changed(fixture: Fixture, new_name) +signal fixture_added(fixture: Array[Fixture]) +signal fixture_removed(fixture_uuid: Array[String]) +signal fixture_selection_changed(selected_fixtures: Array[Fixture]) + + +var universes: Dictionary = {} +var fixtures_definitions: Dictionary = {} + +var selected_fixtures: Array[Fixture] = [] + +var input_plugins: Dictionary = {} +var output_plugins: Dictionary = {} + +const fixture_path: String = "res://core/fixtures/" +const input_plugin_path: String = "res://core/io_plugins/input_plugins/" +const output_plugin_path: String = "res://core/io_plugins/output_plugins/" + var current_file_name: String = "" var current_file_path: String = "" var _system: System = System.new() -# Called when the node enters the scene tree for the first time. + func _ready() -> void: OS.set_low_processor_usage_mode(true) + reload_io_plugins() + reload_fixtures() + func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: return _system.save(self, file_name, file_path) + + +func new_universe(name: String = "New Universe", no_signal: bool = false) -> Universe: + ## Adds a new universe + + var new_universe: Universe = Universe.new() + new_universe.name = name + new_universe.engine = self + + universes[new_universe.uuid] = new_universe + + if not no_signal: + universe_added.emit(new_universe) + + _connect_universe_signals(new_universe) + + return new_universe + + +func _connect_universe_signals(universe: Universe): + ## Connects all the signals of the new universe to the signals of this engine + + universe.name_changed.connect( + func(new_name: String): + universe_name_changed.emit(universe, new_name) + ) + + universe.output_added.connect( + func(output: DataIOPlugin): + universe_output_added.emit(universe, output) + ) + + universe.output_removed.connect( + func(output_uuid: String): + universe_output_removed.emit(universe, output_uuid) + ) + + universe.fixture_name_changed.connect( + func(fixture: Fixture, new_name: String): + fixture_name_changed.emit(fixture, new_name) + ) + + universe.fixture_added.connect( + func(fixtures: Array[Fixture]): + fixture_added.emit(fixtures) + ) + + universe.fixture_deleted.connect( + func(fixture_uuids: Array[String]): + fixture_removed.emit(fixture_uuids) + ) + + +func delete_universe(universe: Universe, no_signal: bool = false) -> bool: + ## Deletes a universe + + if universe in universes.values(): + + universe.delete() + universes.erase(universe.uuid) + + var uuid: String = universe.uuid + + universe.free() + + if not no_signal: + print("sending signal") + universe_removed.emit(uuid) + + return true + + else: + return false + + +func serialize_universes() -> Dictionary: + ## Serializes all universes and returnes them in a dictnary + + var serialized_universes: Dictionary = {} + + for universe_uuid: String in universes: + serialized_universes[universe_uuid] = universes[universe_uuid].serialize() + + return serialized_universes + + +func reload_io_plugins() -> void: + ## Loads all output plugins from the folder + + output_plugins = {} + + var output_plugin_folder : DirAccess = DirAccess.open(output_plugin_path) + + for plugin in output_plugin_folder.get_files(): + var uninitialized_plugin = ResourceLoader.load(output_plugin_path + plugin) + + var initialized_plugin: DataIOPlugin = uninitialized_plugin.new() + var plugin_name: String = initialized_plugin.name + + if plugin_name in output_plugins.keys(): + plugin_name = plugin_name + " " + UUID_Util.v4() + + output_plugins[plugin_name] = uninitialized_plugin + initialized_plugin.free() + + +func reload_fixtures() -> void: + ## Loads fixture definition files from a folder + + fixtures_definitions = {} + + var access = DirAccess.open(fixture_path) + + for fixture_folder in access.get_directories(): + + for fixture in access.open(fixture_path+"/"+fixture_folder).get_files(): + + var manifest_file = FileAccess.open(fixture_path+fixture_folder+"/"+fixture, FileAccess.READ) + var manifest = JSON.parse_string(manifest_file.get_as_text()) + + manifest.info.file_path = fixture_path+fixture_folder+"/"+fixture + + if fixtures_definitions.has(manifest.info.brand): + fixtures_definitions[manifest.info.brand][manifest.info.name] = manifest + else: + fixtures_definitions[manifest.info.brand] = {manifest.info.name:manifest} + + +func select_fixtures(fixtures: Array[Fixture]) -> void: + ## Selects all the fixtures pass to this function + + for fixture: Fixture in fixtures: + if fixture not in selected_fixtures: + selected_fixtures.append(fixture) + fixture.set_selected(true) + + fixture_selection_changed.emit(selected_fixtures) + + +func set_fixture_selection(fixtures: Array[Fixture]) -> void: + ## Changes the selection to be the fixtures passed to this function + + for fixture: Fixture in selected_fixtures: + fixture.set_selected(false) + + selected_fixtures = [] + + select_fixtures(fixtures) + +func deselect_fixtures(fixtures: Array[Fixture]) -> void: + ## Deselects all the fixtures pass to this function + + for fixture: Fixture in fixtures: + if fixture in selected_fixtures: + selected_fixtures.erase(fixture) + fixture.set_selected(false) + + fixture_selection_changed.emit(selected_fixtures) diff --git a/core/engine/System.gd b/core/engine/System.gd index 8ed2ae7..4632f7a 100644 --- a/core/engine/System.gd +++ b/core/engine/System.gd @@ -9,7 +9,7 @@ var save_file: Dictionary = {} func save(engine: CoreEngine, file_name: String, file_path: String) -> Error: ## Saves the current state of the given engine to a file - save_file.universes = Globals.serialize_universes() + save_file.universes = engine.serialize_universes() return Utils.save_json_to_file(file_path, file_name, save_file) #extends Object diff --git a/core/components/uuid.gd b/core/engine/UUID_Util.gd similarity index 98% rename from core/components/uuid.gd rename to core/engine/UUID_Util.gd index 6c78a6e..8b4621a 100644 --- a/core/components/uuid.gd +++ b/core/engine/UUID_Util.gd @@ -2,7 +2,7 @@ # Note: The code might not be as pretty it could be, since it's written # in a way that maximizes performance. Methods are inlined and loops are avoided. -class_name UUID_Util extends Node +class_name UUID_Util extends Object const BYTE_MASK: int = 0b11111111 diff --git a/Fixtures/generic/cmy-fader.json b/core/fixtures/generic/cmy-fader.json similarity index 100% rename from Fixtures/generic/cmy-fader.json rename to core/fixtures/generic/cmy-fader.json diff --git a/Fixtures/generic/cw-ww-fader.json b/core/fixtures/generic/cw-ww-fader.json similarity index 100% rename from Fixtures/generic/cw-ww-fader.json rename to core/fixtures/generic/cw-ww-fader.json diff --git a/Fixtures/generic/desk-channel.json b/core/fixtures/generic/desk-channel.json similarity index 100% rename from Fixtures/generic/desk-channel.json rename to core/fixtures/generic/desk-channel.json diff --git a/Fixtures/generic/drgb-fader.json b/core/fixtures/generic/drgb-fader.json similarity index 100% rename from Fixtures/generic/drgb-fader.json rename to core/fixtures/generic/drgb-fader.json diff --git a/Fixtures/generic/drgbw-fader.json b/core/fixtures/generic/drgbw-fader.json similarity index 100% rename from Fixtures/generic/drgbw-fader.json rename to core/fixtures/generic/drgbw-fader.json diff --git a/Fixtures/generic/grbw-fader.json b/core/fixtures/generic/grbw-fader.json similarity index 100% rename from Fixtures/generic/grbw-fader.json rename to core/fixtures/generic/grbw-fader.json diff --git a/Fixtures/generic/pan-tilt.json b/core/fixtures/generic/pan-tilt.json similarity index 100% rename from Fixtures/generic/pan-tilt.json rename to core/fixtures/generic/pan-tilt.json diff --git a/Fixtures/generic/rgb-fader.json b/core/fixtures/generic/rgb-fader.json similarity index 100% rename from Fixtures/generic/rgb-fader.json rename to core/fixtures/generic/rgb-fader.json diff --git a/Fixtures/generic/rgba-fader.json b/core/fixtures/generic/rgba-fader.json similarity index 100% rename from Fixtures/generic/rgba-fader.json rename to core/fixtures/generic/rgba-fader.json diff --git a/Fixtures/generic/rgbawuv-fader.json b/core/fixtures/generic/rgbawuv-fader.json similarity index 100% rename from Fixtures/generic/rgbawuv-fader.json rename to core/fixtures/generic/rgbawuv-fader.json diff --git a/Fixtures/generic/rgbd-fader.json b/core/fixtures/generic/rgbd-fader.json similarity index 100% rename from Fixtures/generic/rgbd-fader.json rename to core/fixtures/generic/rgbd-fader.json diff --git a/Fixtures/generic/rgbw-fader.json b/core/fixtures/generic/rgbw-fader.json similarity index 100% rename from Fixtures/generic/rgbw-fader.json rename to core/fixtures/generic/rgbw-fader.json diff --git a/Fixtures/generic/rgbwauv-fader.json b/core/fixtures/generic/rgbwauv-fader.json similarity index 100% rename from Fixtures/generic/rgbwauv-fader.json rename to core/fixtures/generic/rgbwauv-fader.json diff --git a/Fixtures/generic/rgbww-fader.json b/core/fixtures/generic/rgbww-fader.json similarity index 100% rename from Fixtures/generic/rgbww-fader.json rename to core/fixtures/generic/rgbww-fader.json diff --git a/Fixtures/generic/strobe.json b/core/fixtures/generic/strobe.json similarity index 100% rename from Fixtures/generic/strobe.json rename to core/fixtures/generic/strobe.json diff --git a/core/io_plugins/DataIOPlugin.gd b/core/io_plugins/DataIOPlugin.gd new file mode 100644 index 0000000..3118645 --- /dev/null +++ b/core/io_plugins/DataIOPlugin.gd @@ -0,0 +1,19 @@ +extends EngineComponent +class_name DataIOPlugin + +var type: String = "" + +func set_type(new_type:String) -> void: + type = new_type + + +func get_type() -> String: + return type + + +func send_packet(packet) -> void: + return + + +func delete() -> void: + return diff --git a/IO Plugins/Input Plugins/Empty Input.gd b/core/io_plugins/input_plugins/Empty.gd similarity index 100% rename from IO Plugins/Input Plugins/Empty Input.gd rename to core/io_plugins/input_plugins/Empty.gd diff --git a/IO Plugins/Output Plugins/Art Net.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd similarity index 95% rename from IO Plugins/Output Plugins/Art Net.gd rename to core/io_plugins/output_plugins/ArtNetOutput.gd index 1b8f14e..bce5f7b 100644 --- a/IO Plugins/Output Plugins/Art Net.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -1,5 +1,9 @@ extends DataIOPlugin -class_name Art_Net_Output +class_name ArtNetOutput + +var meta = { + "name": "Art Net Output" +} var _udp_peer = PacketPeerUDP.new() @@ -45,7 +49,8 @@ var config = { func _init(): self.set_type("output") - self.set_name("Art-Net") + self.name = meta.name + super._init() func connect_to_host(): _udp_peer.close() diff --git a/core/io_plugins/output_plugins/Empty.gd b/core/io_plugins/output_plugins/Empty.gd new file mode 100644 index 0000000..ff25b75 --- /dev/null +++ b/core/io_plugins/output_plugins/Empty.gd @@ -0,0 +1,14 @@ +class_name EmptyOutput extends DataIOPlugin + +var exposed_values = [] + +func _init(): + self.set_type("output") + self.name = "Empty Output" + + super._init() + +func serialize() -> Dictionary: + return { + "type":"Empty" + } diff --git a/project.godot b/project.godot index dd39df8..7d69aee 100644 --- a/project.godot +++ b/project.godot @@ -35,6 +35,7 @@ Core="*res://core/engine/Engine.gd" [debug] +gdscript/warnings/unused_parameter=0 gdscript/warnings/shadowed_variable=0 gdscript/warnings/shadowed_variable_base_class=0 gdscript/warnings/shadowed_global_identifier=0 @@ -82,4 +83,5 @@ miditest={ [rendering] +renderer/rendering_method="gl_compatibility" textures/vram_compression/import_etc2_astc=true From 8ea78514ff24d66226babb2b9b2679d48450eaa1 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 18 Mar 2024 00:12:27 +1300 Subject: [PATCH 04/20] Added Scenes --- Components/Virtual Fixture/Virtual_fixture.gd | 13 +- Panels/Playback Buttons/PlaybackButtons.gd | 29 +++ Panels/Playback Buttons/PlaybackButtons.tscn | 13 ++ Panels/Programmer/ProgrammerUi.tscn | 153 ++++++++++++++++ Panels/Virtual Fixtures/Virtual_fixtures.gd | 9 +- Panels/Virtual Fixtures/Virtual_fixtures.tscn | 173 ++---------------- core/components/Fixture.gd | 18 +- core/components/Programmer.gd | 33 ++++ core/components/Scene.gd | 24 +++ core/components/Universe.gd | 28 +-- core/engine/Engine.gd | 21 ++- export_presets.cfg | 2 +- 12 files changed, 328 insertions(+), 188 deletions(-) create mode 100644 Panels/Playback Buttons/PlaybackButtons.gd create mode 100644 Panels/Playback Buttons/PlaybackButtons.tscn create mode 100644 Panels/Programmer/ProgrammerUi.tscn create mode 100644 core/components/Programmer.gd create mode 100644 core/components/Scene.gd diff --git a/Components/Virtual Fixture/Virtual_fixture.gd b/Components/Virtual Fixture/Virtual_fixture.gd index ba59680..060f984 100644 --- a/Components/Virtual Fixture/Virtual_fixture.gd +++ b/Components/Virtual Fixture/Virtual_fixture.gd @@ -4,19 +4,20 @@ var fixture: Fixture var color_override = false var is_highlight = false - -func _init(debug_text="") -> void: - print(debug_text) - func _ready(): $"Color Box".add_theme_stylebox_override("panel", $"Color Box".get_theme_stylebox("panel").duplicate()) -func set_color_rgb(color): +func set_color(color): $"Color Box".get_theme_stylebox("panel").bg_color = color func set_fixture(control_fixture: Fixture) -> void: + ## Sets the fixture this virtual fixture is atached to + + if is_instance_valid(fixture): + fixture.color_changed.disconnect(self.set_color) + fixture = control_fixture - fixture.color_changed.connect(self.set_color_rgb) + fixture.color_changed.connect(self.set_color) func serialize(): return { diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd new file mode 100644 index 0000000..2c64727 --- /dev/null +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +extends Control +## Temp ui panel for triggering scenes + +func _ready() -> void: + Core.scene_added.connect(self._reload_buttons) + + +func _reload_buttons(_scene) -> void: + ## Reloads the buttons in the ui + + for old_button: Button in self.get_children(): + self.remove_child(old_button) + old_button.queue_free() + + for scene: Scene in Core.scenes.values(): + var button_to_add: Button = Button.new() + + button_to_add.text = scene.name + button_to_add.custom_minimum_size = Vector2(50, 50) + button_to_add.toggle_mode = true + button_to_add.toggled.connect( + func(state): + scene.enabled = state + ) + + self.add_child(button_to_add) diff --git a/Panels/Playback Buttons/PlaybackButtons.tscn b/Panels/Playback Buttons/PlaybackButtons.tscn new file mode 100644 index 0000000..dd2f6ab --- /dev/null +++ b/Panels/Playback Buttons/PlaybackButtons.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=2 format=3 uid="uid://c5h003o3qi1wl"] + +[ext_resource type="Script" path="res://Panels/Playback Buttons/PlaybackButtons.gd" id="1_0mir5"] + +[node name="PlaybackButtons" type="Control"] +layout_mode = 3 +anchors_preset = 0 + +[node name="PlaybackButtons" type="VBoxContainer" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_0mir5") diff --git a/Panels/Programmer/ProgrammerUi.tscn b/Panels/Programmer/ProgrammerUi.tscn new file mode 100644 index 0000000..8b4d124 --- /dev/null +++ b/Panels/Programmer/ProgrammerUi.tscn @@ -0,0 +1,153 @@ +[gd_scene load_steps=7 format=3 uid="uid://bwxr0mrsrt0iu"] + +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_jp1gn"] +[ext_resource type="Texture2D" uid="uid://be3tq05v1ne7n" path="res://Assets/Icons/Horizontal_distribute.svg" id="2_h3xak"] +[ext_resource type="Texture2D" uid="uid://bn4jkekidjyne" path="res://Assets/Icons/Vertical_distribute.svg" id="3_yvf0x"] +[ext_resource type="Texture2D" uid="uid://vm1u4mv102e3" path="res://Assets/Icons/Grid.svg" id="4_48am0"] +[ext_resource type="Texture2D" uid="uid://th5chd6y3ygu" path="res://Assets/Icons/Rotate.svg" id="5_tu5fs"] +[ext_resource type="PackedScene" uid="uid://ccibt4jo4f1jt" path="res://Components/Knob/Encoder.tscn" id="6_0w05c"] + +[node name="TabContainer" type="TabContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_jp1gn") + +[node name="Programmer" type="HBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +metadata/_edit_use_anchors_ = true + +[node name="PanelContainer2" type="PanelContainer" parent="Programmer"] +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="HBoxContainer" type="HBoxContainer" parent="Programmer/PanelContainer2"] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer/PanelContainer2/HBoxContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 + +[node name="HAlign" type="Button" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +icon = ExtResource("2_h3xak") +icon_alignment = 1 + +[node name="VAlign" type="Button" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +icon = ExtResource("3_yvf0x") +icon_alignment = 1 + +[node name="VBoxContainer2" type="VBoxContainer" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 + +[node name="HAlign" type="Button" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +size_flags_vertical = 3 +icon = ExtResource("4_48am0") +icon_alignment = 1 + +[node name="VAlign" type="Button" parent="Programmer/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +size_flags_vertical = 3 +icon = ExtResource("5_tu5fs") +icon_alignment = 1 + +[node name="VBoxContainer2" type="VBoxContainer" parent="Programmer/PanelContainer2/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer2"] +layout_mode = 2 + +[node name="Encoder" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer2/PanelContainer" instance=ExtResource("6_0w05c")] +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +size_flags_vertical = 3 +rotation_offset = 90 +angle_gap = 0 +wrap_around_value = true + +[node name="SpinBox" type="SpinBox" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +prefix = "Gap:" + +[node name="VBoxContainer3" type="VBoxContainer" parent="Programmer/PanelContainer2/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer3"] +layout_mode = 2 + +[node name="Encoder" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer3/PanelContainer" instance=ExtResource("6_0w05c")] +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +size_flags_vertical = 3 +rotation_offset = 90 +angle_gap = 0 +wrap_around_value = true + +[node name="SpinBox" type="SpinBox" parent="Programmer/PanelContainer2/HBoxContainer/VBoxContainer3"] +layout_mode = 2 +prefix = "Phase:" + +[node name="VSeparator2" type="VSeparator" parent="Programmer"] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="Programmer/PanelContainer"] +layout_mode = 2 + +[node name="VBoxContainer2" type="VBoxContainer" parent="Programmer/PanelContainer/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 + +[node name="Encoder" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer2/PanelContainer" instance=ExtResource("6_0w05c")] +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +size_flags_vertical = 3 +rotation_offset = 90 +angle_gap = 0 +wrap_around_value = true + +[node name="SpinBox" type="SpinBox" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +prefix = "Rotation:" +suffix = "°" + +[node name="VBoxContainer3" type="VBoxContainer" parent="Programmer/PanelContainer/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="PanelContainer" type="PanelContainer" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer3"] +layout_mode = 2 + +[node name="Encoder" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer3/PanelContainer" instance=ExtResource("6_0w05c")] +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +size_flags_vertical = 3 +rotation_offset = 90 +angle_gap = 0 +wrap_around_value = true + +[node name="SpinBox" type="SpinBox" parent="Programmer/PanelContainer/HBoxContainer/VBoxContainer3"] +layout_mode = 2 +prefix = "Phase:" diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index c1ea1b2..0862377 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -65,7 +65,6 @@ func _request_delete() -> void: var to_remove: Array = _selected_virtual_fixtures.duplicate() for virtual_fixture: Control in to_remove: - virtual_fixture.control_node.remove_virtual_fixture(virtual_fixture) virtual_fixture.queue_free() _selected_virtual_fixtures.erase(virtual_fixture) @@ -124,3 +123,11 @@ func _on_virtual_fixture_selected(node) -> void: func _on_virtual_fixture_deselected(node) -> void: _selected_virtual_fixtures.erase(node) Core.deselect_fixtures([node.fixture]) + + +func _on_color_picker_color_changed(color: Color) -> void: + Core.programmer.set_color(Core.selected_fixtures, color) + + +func _on_save_pressed() -> void: + Core.programmer.save_to_scene() diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.tscn b/Panels/Virtual Fixtures/Virtual_fixtures.tscn index fa857a8..36f3e1b 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.tscn +++ b/Panels/Virtual Fixtures/Virtual_fixtures.tscn @@ -1,14 +1,10 @@ -[gd_scene load_steps=10 format=3 uid="uid://dhrijn1m88172"] +[gd_scene load_steps=6 format=3 uid="uid://dhrijn1m88172"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_hwlxv"] [ext_resource type="Script" path="res://Panels/Virtual Fixtures/Virtual_fixtures.gd" id="1_y16fu"] [ext_resource type="Script" path="res://Scripts/Sidebar.gd" id="2_j8tmg"] [ext_resource type="Texture2D" uid="uid://vw0vs7dlct55" path="res://Assets/Icons/menu.svg" id="3_xlq73"] -[ext_resource type="Texture2D" uid="uid://be3tq05v1ne7n" path="res://Assets/Icons/Horizontal_distribute.svg" id="5_0jdj6"] -[ext_resource type="Texture2D" uid="uid://bn4jkekidjyne" path="res://Assets/Icons/Vertical_distribute.svg" id="6_ivvmw"] -[ext_resource type="Texture2D" uid="uid://vm1u4mv102e3" path="res://Assets/Icons/Grid.svg" id="7_krdug"] -[ext_resource type="PackedScene" uid="uid://ccibt4jo4f1jt" path="res://Components/Knob/Encoder.tscn" id="7_ny1u7"] -[ext_resource type="Texture2D" uid="uid://th5chd6y3ygu" path="res://Assets/Icons/Rotate.svg" id="8_8ml5j"] +[ext_resource type="PackedScene" uid="uid://c5h003o3qi1wl" path="res://Panels/Playback Buttons/PlaybackButtons.tscn" id="5_uh5xn"] [node name="Virtual Fixtures" type="Control"] layout_mode = 3 @@ -37,6 +33,7 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_colors/grid_minor = Color(0.101961, 0.101961, 0.101961, 1) theme_override_colors/grid_major = Color(0.0784314, 0.0784314, 0.0784314, 1) +scroll_offset = Vector2(-224, -14) show_minimap_button = false show_arrange_button = false script = ExtResource("1_y16fu") @@ -46,157 +43,6 @@ visible = false custom_minimum_size = Vector2(50, 0) layout_mode = 2 -[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar"] -layout_mode = 2 -theme_override_constants/margin_left = 4 -theme_override_constants/margin_top = 4 -theme_override_constants/margin_right = 4 -theme_override_constants/margin_bottom = 4 - -[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer"] -layout_mode = 2 - -[node name="Open" type="Button" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 0 -icon = ExtResource("3_xlq73") -icon_alignment = 1 - -[node name="Content" type="HBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer" node_paths=PackedStringArray("contence")] -layout_mode = 2 -size_flags_horizontal = 3 -script = ExtResource("2_j8tmg") -contence = NodePath(".") - -[node name="VSeparator" type="VSeparator" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content"] -layout_mode = 2 - -[node name="PanelContainer2" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content"] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer"] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer"] -layout_mode = 2 - -[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer"] -custom_minimum_size = Vector2(100, 0) -layout_mode = 2 - -[node name="HAlign" type="Button" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -icon = ExtResource("5_0jdj6") -icon_alignment = 1 - -[node name="VAlign" type="Button" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -icon = ExtResource("6_ivvmw") -icon_alignment = 1 - -[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer"] -custom_minimum_size = Vector2(100, 0) -layout_mode = 2 - -[node name="HAlign" type="Button" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer2"] -layout_mode = 2 -size_flags_vertical = 3 -icon = ExtResource("7_krdug") -icon_alignment = 1 - -[node name="VAlign" type="Button" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/PanelContainer/HBoxContainer/VBoxContainer2"] -layout_mode = 2 -size_flags_vertical = 3 -icon = ExtResource("8_8ml5j") -icon_alignment = 1 - -[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer2"] -layout_mode = 2 - -[node name="Encoder" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer2/PanelContainer" instance=ExtResource("7_ny1u7")] -custom_minimum_size = Vector2(150, 150) -layout_mode = 2 -size_flags_vertical = 3 -rotation_offset = 90 -angle_gap = 0 -wrap_around_value = true - -[node name="SpinBox" type="SpinBox" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer2"] -layout_mode = 2 -prefix = "Gap:" - -[node name="VBoxContainer3" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer3"] -layout_mode = 2 - -[node name="Encoder" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer3/PanelContainer" instance=ExtResource("7_ny1u7")] -custom_minimum_size = Vector2(150, 150) -layout_mode = 2 -size_flags_vertical = 3 -rotation_offset = 90 -angle_gap = 0 -wrap_around_value = true - -[node name="SpinBox" type="SpinBox" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer2/HBoxContainer/VBoxContainer3"] -layout_mode = 2 -prefix = "Phase:" - -[node name="VSeparator2" type="VSeparator" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content"] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer"] -layout_mode = 2 - -[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer2"] -layout_mode = 2 - -[node name="Encoder" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer2/PanelContainer" instance=ExtResource("7_ny1u7")] -custom_minimum_size = Vector2(150, 150) -layout_mode = 2 -size_flags_vertical = 3 -rotation_offset = 90 -angle_gap = 0 -wrap_around_value = true - -[node name="SpinBox" type="SpinBox" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer2"] -layout_mode = 2 -prefix = "Rotation:" -suffix = "°" - -[node name="VBoxContainer3" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer"] -layout_mode = 2 - -[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer3"] -layout_mode = 2 - -[node name="Encoder" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer3/PanelContainer" instance=ExtResource("7_ny1u7")] -custom_minimum_size = Vector2(150, 150) -layout_mode = 2 -size_flags_vertical = 3 -rotation_offset = 90 -angle_gap = 0 -wrap_around_value = true - -[node name="SpinBox" type="SpinBox" parent="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content/PanelContainer/HBoxContainer/VBoxContainer3"] -layout_mode = 2 -prefix = "Phase:" - [node name="Sidebar" type="PanelContainer" parent="HBoxContainer"] custom_minimum_size = Vector2(50, 0) layout_mode = 2 @@ -217,8 +63,8 @@ icon = ExtResource("3_xlq73") icon_alignment = 1 [node name="Contence" type="VBoxContainer" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer" node_paths=PackedStringArray("contence")] -visible = false layout_mode = 2 +size_flags_vertical = 3 script = ExtResource("2_j8tmg") contence = NodePath(".") @@ -229,7 +75,16 @@ edit_alpha = false picker_shape = 1 color_modes_visible = false +[node name="PlaybackButtons" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence" instance=ExtResource("5_uh5xn")] +layout_mode = 2 + +[node name="Button" type="Button" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence"] +layout_mode = 2 +size_flags_vertical = 10 +text = "Save" + [connection signal="node_deselected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_deselected"] [connection signal="node_selected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_selected"] -[connection signal="pressed" from="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Open" to="HBoxContainer/VBoxContainer/Bottom Bar/MarginContainer/HBoxContainer/Content" method="_on_button_pressed"] [connection signal="pressed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] +[connection signal="color_changed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence/ColorPicker" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_color_picker_color_changed"] +[connection signal="pressed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence/Button" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_save_pressed"] diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 4bcfb9b..2817724 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -69,20 +69,20 @@ func serialize() -> Dictionary: } -func set_color_rgb(r,g,b) -> void: - ## Sets the color of this fixture in 0-255 RBG values - +func set_color(color: Color) -> void: + ## Sets the color of this fixture if "ColorIntensityRed" in channels: - _compiled_dmx_data[int(channels.find("ColorIntensityRed") + channel)] = int(r) + _compiled_dmx_data[int(channels.find("ColorIntensityRed") + channel)] = color.r8 if "ColorIntensityGreen" in channels: - _compiled_dmx_data[int(channels.find("ColorIntensityGreen") + channel)] = int(g) + _compiled_dmx_data[int(channels.find("ColorIntensityGreen") + channel)] = color.g8 if "ColorIntensityBlue" in channels: - _compiled_dmx_data[int(channels.find("ColorIntensityBlue") + channel)] = int(b) - universe.set_fixture_data(_compiled_dmx_data) - - _parameters.color = Color(r, g, b) + _compiled_dmx_data[int(channels.find("ColorIntensityBlue") + channel)] = color.b8 + _parameters.color = color color_changed.emit(_parameters.color) + + universe.set_data(_compiled_dmx_data) + func set_selected(state: bool) -> void: diff --git a/core/components/Programmer.gd b/core/components/Programmer.gd new file mode 100644 index 0000000..09b29ea --- /dev/null +++ b/core/components/Programmer.gd @@ -0,0 +1,33 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name Programmer extends EngineComponent +## Engine class for programming lights, colors, positions, etc. This also handles conversion from Godots color system to dmx colors + +var save_data: Dictionary = {} ## Current data in the programmer + +var engine: CoreEngine ## The CoreEngine this programmer is atached to + +func set_color(fixtures: Array[Fixture], color: Color) -> void: + ## Sets the color of all the fixtures in fixtures, to color + + for fixture: Fixture in fixtures: + fixture.set_color(color) + + if fixture not in save_data: + save_data[fixture] = {} + + save_data[fixture].color = color + + +func save_to_scene(name: String = "New Scene") -> Scene: + ## Saves the current state of this programmer to a scene + + var new_scene: Scene = Scene.new() + + new_scene.save_data = save_data.duplicate(true) + new_scene.name = name + + engine.new_scene(new_scene) + + return new_scene diff --git a/core/components/Scene.gd b/core/components/Scene.gd new file mode 100644 index 0000000..f374000 --- /dev/null +++ b/core/components/Scene.gd @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +class_name Scene extends EngineComponent +## Engine class for creating and recalling saved data + +signal state_changed(is_enabled: bool) ## Emmitted when this scene is enabled or dissabled + +var fade_in_speed: int = 100 ## Fade in speed in ms +var fade_out_speed: int = 100 ## Fade out speed in ms + +var enabled: bool = false: set = set_enabled ## The current state of this scene + +var save_data: Dictionary = {} + +func set_enabled(is_enabled: bool) -> void: + enabled = is_enabled + + print(enabled) + + if is_enabled: + for fixture: Fixture in save_data.keys(): + fixture.set_color(save_data[fixture].color) + diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 4bd6f2f..4ff516a 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -14,6 +14,8 @@ signal output_removed(output_uuid: String) var fixtures: Dictionary = {} ## Dictionary containing all the fixtures in this universe var outputs: Dictionary = {} ## Dictionary containing all the outputs in this universe +var dmx_data: Dictionary = {} + var engine: CoreEngine ## The CoreEngine class this universe belongs to func new_output(type = EmptyOutput, no_signal: bool = false) -> DataIOPlugin: @@ -95,20 +97,29 @@ func delete(): for output in outputs.values(): remove_output(output) - +func set_data(data: Dictionary): + ## Set dmx data, layers will be added soom + dmx_data.merge(data, true) + _compile_and_send() + + +func _compile_and_send(): + ## Will compile all dmx data in a future version, currently just sends dmx data + var compiled_dmx_data = dmx_data + for output: DataIOPlugin in outputs: + output.send_packet(compiled_dmx_data) + + #func get_fixtures(): #return universe.fixtures # #func get_fixture(fixture_uuid): #pass # -#func set_fixture_data(data): - #universe.fixture_data.merge(data, true) - #_compile_and_send() -# + @@ -120,12 +131,7 @@ func delete(): #func get_desk_data(): #return universe.desk_data # -#func _compile_and_send(): - #var compiled_dmx_data = universe.fixture_data - #compiled_dmx_data.merge(universe.desk_data, true) - #for output in universe.outputs: - #universe.outputs[output].send_packet(compiled_dmx_data) - # + #func serialize(): #var serialized_outputs = {} #var serialized_fixtures = {} diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 74c2f60..504d267 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -16,10 +16,13 @@ signal fixture_added(fixture: Array[Fixture]) signal fixture_removed(fixture_uuid: Array[String]) signal fixture_selection_changed(selected_fixtures: Array[Fixture]) +signal scene_added(scene: Scene) +signal scene_removed(scene_uuid: String) + var universes: Dictionary = {} var fixtures_definitions: Dictionary = {} - +var scenes: Dictionary = {} var selected_fixtures: Array[Fixture] = [] var input_plugins: Dictionary = {} @@ -32,10 +35,14 @@ const output_plugin_path: String = "res://core/io_plugins/output_plugins/" var current_file_name: String = "" var current_file_path: String = "" +var programmer = Programmer.new() + var _system: System = System.new() func _ready() -> void: + programmer.engine = self + OS.set_low_processor_usage_mode(true) reload_io_plugins() reload_fixtures() @@ -201,3 +208,15 @@ func deselect_fixtures(fixtures: Array[Fixture]) -> void: fixture.set_selected(false) fixture_selection_changed.emit(selected_fixtures) + + +func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: + ## Adds a scene to this engine, creats a new one if none is passed + + scenes[scene.uuid] = scene + + if not no_signal: + scene_added.emit(scene) + + return scene + diff --git a/export_presets.cfg b/export_presets.cfg index 6434876..2e926f2 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -124,7 +124,7 @@ binary_format/architecture="universal" custom_template/debug="" custom_template/release="" debug/export_console_wrapper=1 -application/icon="res://icon.png" +application/icon="res://Assets/Icon.png" application/icon_interpolation=4 application/bundle_identifier="tech.liamsherwin.spectrum" application/signature="" From 143f1c5a0931d92b5f975ab15cbcdb3a3e935c15 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 18 Mar 2024 11:37:14 +1300 Subject: [PATCH 05/20] Updates Scene Ui --- Assets/Icons/Arrow_back.svg | 59 +++++++++++++++++++ Assets/Icons/Arrow_back.svg.import | 37 ++++++++++++ Assets/Icons/Check.svg | 59 +++++++++++++++++++ Assets/Icons/Check.svg.import | 37 ++++++++++++ Components/Trigger Button/TriggerButton.gd | 14 +++++ Components/Trigger Button/TriggerButton.tscn | 20 +++++++ Panels/Playback Buttons/PlaybackButtons.gd | 4 +- Panels/Playback Buttons/PlaybackButtons.tscn | 16 +++-- Panels/Virtual Fixtures/Virtual_fixtures.tscn | 46 +++++++++++---- Scripts/Global.gd | 3 +- core/components/Universe.gd | 2 +- 11 files changed, 276 insertions(+), 21 deletions(-) create mode 100644 Assets/Icons/Arrow_back.svg create mode 100644 Assets/Icons/Arrow_back.svg.import create mode 100644 Assets/Icons/Check.svg create mode 100644 Assets/Icons/Check.svg.import create mode 100644 Components/Trigger Button/TriggerButton.gd create mode 100644 Components/Trigger Button/TriggerButton.tscn diff --git a/Assets/Icons/Arrow_back.svg b/Assets/Icons/Arrow_back.svg new file mode 100644 index 0000000..aceb02b --- /dev/null +++ b/Assets/Icons/Arrow_back.svg @@ -0,0 +1,59 @@ + + + + + + + + diff --git a/Assets/Icons/Arrow_back.svg.import b/Assets/Icons/Arrow_back.svg.import new file mode 100644 index 0000000..9caefe0 --- /dev/null +++ b/Assets/Icons/Arrow_back.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c1cl6qetwg8st" +path="res://.godot/imported/Arrow_back.svg-a0911a1be2b399f6e203ad85c7bde526.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Icons/Arrow_back.svg" +dest_files=["res://.godot/imported/Arrow_back.svg-a0911a1be2b399f6e203ad85c7bde526.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Assets/Icons/Check.svg b/Assets/Icons/Check.svg new file mode 100644 index 0000000..689ab54 --- /dev/null +++ b/Assets/Icons/Check.svg @@ -0,0 +1,59 @@ + + + + + + + + diff --git a/Assets/Icons/Check.svg.import b/Assets/Icons/Check.svg.import new file mode 100644 index 0000000..7921261 --- /dev/null +++ b/Assets/Icons/Check.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bi4ttx5uklwl7" +path="res://.godot/imported/Check.svg-3fc7cd3289fca542d2045dad8f21839e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Icons/Check.svg" +dest_files=["res://.godot/imported/Check.svg-3fc7cd3289fca542d2045dad8f21839e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Components/Trigger Button/TriggerButton.gd b/Components/Trigger Button/TriggerButton.gd new file mode 100644 index 0000000..9327f37 --- /dev/null +++ b/Components/Trigger Button/TriggerButton.gd @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +extends Button +## Ui button to trigger an action on click + +signal edit_requested(from: Button) + +var control_node: Node + +func _on_gui_input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.pressed and event.button_index == 2: + print("Right Clicked") diff --git a/Components/Trigger Button/TriggerButton.tscn b/Components/Trigger Button/TriggerButton.tscn new file mode 100644 index 0000000..bde1a16 --- /dev/null +++ b/Components/Trigger Button/TriggerButton.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://c2c3t6jriymr6"] + +[ext_resource type="Script" path="res://Components/Trigger Button/TriggerButton.gd" id="1_3rl6v"] +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_v6l20"] + +[node name="TriggerButton" type="Button"] +custom_minimum_size = Vector2(70, 70) +anchors_preset = -1 +anchor_right = 0.0364583 +anchor_bottom = 0.0648148 +theme = ExtResource("1_v6l20") +theme_override_font_sizes/font_size = 9 +toggle_mode = true +text = "Button" +clip_text = true +script = ExtResource("1_3rl6v") +metadata/_edit_use_anchors_ = true + +[connection signal="gui_input" from="." to="." method="_on_gui_input"] +[connection signal="toggled" from="." to="." method="_on_toggled"] diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index 2c64727..c5783ef 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -16,11 +16,9 @@ func _reload_buttons(_scene) -> void: old_button.queue_free() for scene: Scene in Core.scenes.values(): - var button_to_add: Button = Button.new() + var button_to_add: Button = Globals.components.trigger_button.instantiate() button_to_add.text = scene.name - button_to_add.custom_minimum_size = Vector2(50, 50) - button_to_add.toggle_mode = true button_to_add.toggled.connect( func(state): scene.enabled = state diff --git a/Panels/Playback Buttons/PlaybackButtons.tscn b/Panels/Playback Buttons/PlaybackButtons.tscn index dd2f6ab..7804553 100644 --- a/Panels/Playback Buttons/PlaybackButtons.tscn +++ b/Panels/Playback Buttons/PlaybackButtons.tscn @@ -2,12 +2,16 @@ [ext_resource type="Script" path="res://Panels/Playback Buttons/PlaybackButtons.gd" id="1_0mir5"] -[node name="PlaybackButtons" type="Control"] -layout_mode = 3 -anchors_preset = 0 +[node name="PanelContainer" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_vertical = 3 [node name="PlaybackButtons" type="VBoxContainer" parent="."] -layout_mode = 0 -offset_right = 40.0 -offset_bottom = 40.0 +layout_mode = 2 +size_flags_horizontal = 6 script = ExtResource("1_0mir5") +metadata/_edit_use_anchors_ = true diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.tscn b/Panels/Virtual Fixtures/Virtual_fixtures.tscn index 36f3e1b..9ef3bdb 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.tscn +++ b/Panels/Virtual Fixtures/Virtual_fixtures.tscn @@ -23,6 +23,40 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +[node name="Sidebar2" type="PanelContainer" parent="HBoxContainer"] +custom_minimum_size = Vector2(50, 0) +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Sidebar2"] +layout_mode = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 4 + +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/Sidebar2/MarginContainer"] +layout_mode = 2 + +[node name="Side Bar Open" type="Button" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer"] +layout_mode = 2 +icon = ExtResource("3_xlq73") +icon_alignment = 1 + +[node name="Contence" type="VBoxContainer" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer" node_paths=PackedStringArray("contence")] +layout_mode = 2 +size_flags_vertical = 3 +script = ExtResource("2_j8tmg") +contence = NodePath("../../../../Sidebar/MarginContainer/VBoxContainer/Contence") + +[node name="PanelContainer" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence" instance=ExtResource("5_uh5xn")] +layout_mode = 2 +size_flags_vertical = 1 + +[node name="Button" type="Button" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence"] +layout_mode = 2 +size_flags_vertical = 10 +text = "Save" + [node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"] layout_mode = 2 size_flags_horizontal = 3 @@ -33,7 +67,6 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_colors/grid_minor = Color(0.101961, 0.101961, 0.101961, 1) theme_override_colors/grid_major = Color(0.0784314, 0.0784314, 0.0784314, 1) -scroll_offset = Vector2(-224, -14) show_minimap_button = false show_arrange_button = false script = ExtResource("1_y16fu") @@ -75,16 +108,9 @@ edit_alpha = false picker_shape = 1 color_modes_visible = false -[node name="PlaybackButtons" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence" instance=ExtResource("5_uh5xn")] -layout_mode = 2 - -[node name="Button" type="Button" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence"] -layout_mode = 2 -size_flags_vertical = 10 -text = "Save" - +[connection signal="pressed" from="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] +[connection signal="pressed" from="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence/Button" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_save_pressed"] [connection signal="node_deselected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_deselected"] [connection signal="node_selected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_selected"] [connection signal="pressed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] [connection signal="color_changed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence/ColorPicker" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_color_picker_color_changed"] -[connection signal="pressed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence/Button" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_save_pressed"] diff --git a/Scripts/Global.gd b/Scripts/Global.gd index f2641d6..33e58ee 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -33,7 +33,8 @@ var output_plugins : Dictionary "accept_dialog":ResourceLoader.load("res://Components/Accept Dialog/Accept_dialog.tscn"), "channel_slider":ResourceLoader.load("res://Components/Channel Slider/Channel_slider.tscn"), "virtual_fixture":ResourceLoader.load("res://Components/Virtual Fixture/Virtual_fixture.tscn"), - "window":ResourceLoader.load("res://Components/Window/Window.tscn") + "window":ResourceLoader.load("res://Components/Window/Window.tscn"), + "trigger_button":ResourceLoader.load("res://Components/Trigger Button/TriggerButton.tscn") } @onready var panels : Dictionary = { diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 4ff516a..191cb1b 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -109,7 +109,7 @@ func _compile_and_send(): ## Will compile all dmx data in a future version, currently just sends dmx data var compiled_dmx_data = dmx_data - for output: DataIOPlugin in outputs: + for output: DataIOPlugin in outputs.values(): output.send_packet(compiled_dmx_data) From e6b4f3970a3eb855ad441bb9621e1365ea7173eb Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 18 Mar 2024 22:23:56 +1300 Subject: [PATCH 06/20] Fixture HTP blending, scene fading, and basic functions ui --- Components/Trigger Button/TriggerButton.tscn | 1 + Main.tscn | 9 +- Panels/Functions/Functions.gd | 82 +++++----- Panels/Functions/Functions.tscn | 143 ++---------------- Panels/Patch Bay/Patch_bay.gd | 9 +- Panels/Playback Buttons/PlaybackButtons.gd | 1 + Panels/Settings/Settings.gd | 2 +- Panels/Virtual Fixtures/Virtual_fixtures.gd | 4 +- Panels/Virtual Fixtures/Virtual_fixtures.tscn | 2 +- Scripts/Sidebar.gd | 2 +- core/components/EngineComponent.gd | 12 +- core/components/Fixture.gd | 54 +++++-- core/components/Scene.gd | 42 ++++- core/components/Universe.gd | 45 +++--- core/engine/Engine.gd | 46 +++++- core/engine/Utils.gd | 31 +++- core/io_plugins/DataIOPlugin.gd | 14 +- core/io_plugins/input_plugins/Empty.gd | 9 -- .../io_plugins/output_plugins/ArtNetOutput.gd | 14 +- core/io_plugins/output_plugins/Empty.gd | 14 -- 20 files changed, 266 insertions(+), 270 deletions(-) delete mode 100644 core/io_plugins/input_plugins/Empty.gd delete mode 100644 core/io_plugins/output_plugins/Empty.gd diff --git a/Components/Trigger Button/TriggerButton.tscn b/Components/Trigger Button/TriggerButton.tscn index bde1a16..ef86f72 100644 --- a/Components/Trigger Button/TriggerButton.tscn +++ b/Components/Trigger Button/TriggerButton.tscn @@ -11,6 +11,7 @@ anchor_bottom = 0.0648148 theme = ExtResource("1_v6l20") theme_override_font_sizes/font_size = 9 toggle_mode = true +action_mode = 0 text = "Button" clip_text = true script = ExtResource("1_3rl6v") diff --git a/Main.tscn b/Main.tscn index eb7d60a..ac18439 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=21 format=3 uid="uid://p3sohjs1pt37"] +[gd_scene load_steps=22 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] [ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] [ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] +[ext_resource type="PackedScene" uid="uid://cedqo06n6en8u" path="res://Panels/Functions/Functions.tscn" id="4_35sxj"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="5_8370q"] [ext_resource type="Script" path="res://Scripts/Menu_buttons.gd" id="7_gussm"] [ext_resource type="PackedScene" uid="uid://cdg8rr3v7el85" path="res://Panels/Patch Bay/Patch_bay.tscn" id="9_hxqqf"] @@ -96,7 +97,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -current_tab = 1 +current_tab = 2 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true script = ExtResource("3_nk5d5") @@ -105,6 +106,10 @@ script = ExtResource("3_nk5d5") visible = false layout_mode = 2 +[node name="Functions" parent="TabContainer" instance=ExtResource("4_35sxj")] +visible = false +layout_mode = 2 + [node name="Patch Bay" parent="TabContainer" instance=ExtResource("9_hxqqf")] layout_mode = 2 diff --git a/Panels/Functions/Functions.gd b/Panels/Functions/Functions.gd index 3c154dc..2aff934 100644 --- a/Panels/Functions/Functions.gd +++ b/Panels/Functions/Functions.gd @@ -1,53 +1,49 @@ -extends Control +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. -var functions = { - "scenes":{}, - "effects":{}, - "cues":{}, -} +extends Control +## GUI element for managing functions -func _ready(): - Globals.subscribe("edit_mode", self.on_edit_mode_changed) +@export var functions_list: NodePath -func delete_request(node): - node.queue_free() +func _ready() -> void: + Core.scene_added.connect(self._reload_functions) + Core.scene_removed.connect(self._reload_functions) -func edit_request(node): - pass -func on_edit_mode_changed(edit_mode): - for function_item in Globals.nodes.scenes_list.get_children(): - function_item.dissable_buttons(not edit_mode) - - for function_item in Globals.nodes.effects_list.get_children(): - function_item.dissable_buttons(not edit_mode) - - for function_item in Globals.nodes.cues_list.get_children(): - function_item.dissable_buttons(not edit_mode) - -func new_scene(): - var node_to_add = Globals.components.list_item.instantiate() - node_to_add.set_item_name("Scene") - node_to_add.control_node = self - Globals.nodes.scenes_list.add_child(node_to_add) +func delete_request(node:Control) -> void : + ## Called when the delete button is clicked on a function List_Item -func new_effect(): - var node_to_add = Globals.components.list_item.instantiate() - node_to_add.set_item_name("Effect") - node_to_add.control_node = self - Globals.nodes.effects_list.add_child(node_to_add) + var confirmation_dialog: AcceptDialog = Globals.components.accept_dialog.instantiate() + confirmation_dialog.dialog_text = "Are you sure you want to delete this? This action can not be undone" -func new_cue(): - var node_to_add = Globals.components.list_item.instantiate() - node_to_add.set_item_name("Cue") - node_to_add.control_node = self - Globals.nodes.cues_list.add_child(node_to_add) + confirmation_dialog.confirmed.connect(( + func(node): + + var scene: Scene = node.get_meta("function") + scene.engine.remove_scene(scene) + + ).bind(node)) -func _on_new_scene_pressed(): - new_scene() + add_child(confirmation_dialog) + -func _on_new_effect_pressed(): - new_effect() +func edit_request(node:Control) -> void: + ## WIP function to edit a fixture, change channel, type, universe, ect + pass -func _on_new_cue_list_pressed(): - new_cue() +func _reload_functions(_scene=null) -> void: + ## Reload the list of fixtures + + for node in get_node(functions_list).get_children(): + node.get_parent().remove_child(node) + node.queue_free() + + for scene: Scene in Core.scenes.values(): + var node_to_add : Control = Globals.components.list_item.instantiate() + node_to_add.control_node = self + node_to_add.set_item_name(scene.name) + node_to_add.name = scene.uuid + node_to_add.set_meta("function", scene) + get_node(functions_list).add_child(node_to_add) + diff --git a/Panels/Functions/Functions.tscn b/Panels/Functions/Functions.tscn index a0011cd..07c9a3d 100644 --- a/Panels/Functions/Functions.tscn +++ b/Panels/Functions/Functions.tscn @@ -1,9 +1,7 @@ -[gd_scene load_steps=5 format=3 uid="uid://k641v8l2l3wp"] +[gd_scene load_steps=3 format=3 uid="uid://cedqo06n6en8u"] -[ext_resource type="Script" path="res://Panels/Functions/Functions.gd" id="1_uwvo7"] -[ext_resource type="Texture2D" uid="uid://cjx13jidaqjyf" path="res://Assets/Icons/Scene.svg" id="2_iqhgr"] -[ext_resource type="Texture2D" uid="uid://cw7e02n080in3" path="res://Assets/Icons/Effect.svg" id="3_prjry"] -[ext_resource type="Texture2D" uid="uid://dnfqijjcnit7c" path="res://Assets/Icons/Cue_list.svg" id="4_q8830"] +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_un5lg"] +[ext_resource type="Script" path="res://Panels/Functions/Functions.gd" id="2_bfwkh"] [node name="Functions" type="Control"] layout_mode = 3 @@ -12,6 +10,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +theme = ExtResource("1_un5lg") [node name="Functions" type="MarginContainer" parent="."] layout_mode = 1 @@ -24,146 +23,22 @@ theme_override_constants/margin_left = 10 theme_override_constants/margin_top = 10 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 10 -script = ExtResource("1_uwvo7") - -[node name="Panel" type="Panel" parent="Functions"] -layout_mode = 2 - -[node name="Label" type="Label" parent="Functions/Panel"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "Functions are a work in progress and will be available in a future version of Spectrum." -horizontal_alignment = 1 -vertical_alignment = 1 +script = ExtResource("2_bfwkh") +functions_list = NodePath("VBoxContainer/PanelContainer3/ScrollContainer/Functions") [node name="VBoxContainer" type="VBoxContainer" parent="Functions"] -visible = false -layout_mode = 2 - -[node name="MarginContainer" type="MarginContainer" parent="Functions/VBoxContainer"] -layout_mode = 2 -theme_override_constants/margin_bottom = 5 - -[node name="PanelContainer" type="PanelContainer" parent="Functions/VBoxContainer/MarginContainer"] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="Functions/VBoxContainer/MarginContainer/PanelContainer"] layout_mode = 2 -[node name="New Scene" type="Button" parent="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -text = "New Scene" -icon = ExtResource("2_iqhgr") - -[node name="New Effect" type="Button" parent="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -text = "New Effect" -icon = ExtResource("3_prjry") - -[node name="New Cue List" type="Button" parent="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -text = "New Cue List" -icon = ExtResource("4_q8830") - -[node name="PanelContainer2" type="PanelContainer" parent="Functions/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="HBoxContainer" type="HBoxContainer" parent="Functions/VBoxContainer/PanelContainer2"] -layout_mode = 2 - -[node name="Scenes" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes"] +[node name="PanelContainer3" type="PanelContainer" parent="Functions/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="VBoxContainer" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes/ScrollContainer"] +[node name="ScrollContainer" type="ScrollContainer" parent="Functions/VBoxContainer/PanelContainer3"] layout_mode = 2 -size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="Scenes" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes/ScrollContainer/VBoxContainer"] +[node name="Functions" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer3/ScrollContainer"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 - -[node name="HSeparator" type="HSeparator" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes"] -layout_mode = 2 - -[node name="Label" type="Label" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes"] -layout_mode = 2 -text = "Scenes" -horizontal_alignment = 1 - -[node name="VSeparator" type="VSeparator" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer"] -layout_mode = 2 - -[node name="Effects" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="VBoxContainer" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="Effects" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects/ScrollContainer/VBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="HSeparator" type="HSeparator" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects"] -layout_mode = 2 - -[node name="Label" type="Label" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects"] -layout_mode = 2 -text = "Effects" -horizontal_alignment = 1 - -[node name="VSeparator2" type="VSeparator" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer"] -layout_mode = 2 - -[node name="Cues" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="VBoxContainer" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="Cues" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues/ScrollContainer/VBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="HSeparator" type="HSeparator" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues"] -layout_mode = 2 - -[node name="Label" type="Label" parent="Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues"] -layout_mode = 2 -text = "Cues -" -horizontal_alignment = 1 - -[connection signal="pressed" from="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/New Scene" to="Functions" method="_on_new_scene_pressed"] -[connection signal="pressed" from="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/New Effect" to="Functions" method="_on_new_effect_pressed"] -[connection signal="pressed" from="Functions/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/New Cue List" to="Functions" method="_on_new_cue_list_pressed"] diff --git a/Panels/Patch Bay/Patch_bay.gd b/Panels/Patch Bay/Patch_bay.gd index 2e1ea05..df9cbe4 100644 --- a/Panels/Patch Bay/Patch_bay.gd +++ b/Panels/Patch Bay/Patch_bay.gd @@ -81,9 +81,9 @@ func _set_universe_controls_enabled(enabled:bool) -> void: func _new_output() -> void: - ## Adds a new EmptyOutput plugin to the currently selected universe + ## Adds a new ArtNetOutput plugin to the currently selected universe - _current_universe.new_output(EmptyOutput) + _current_universe.new_output(ArtNetOutput) func _change_io_config(io: DataIOPlugin = null) -> void: @@ -275,7 +275,7 @@ func _on_io_type_item_selected(index:int) -> void: ## Called when the user selects an IO type from the list dropdown _current_universe.remove_output(_current_io) - _current_io = _current_universe.new_output(Core.output_plugins.values()[index]) + _current_io = _current_universe.new_output(Core.output_plugins.values()[index].plugin) _reload_io() @@ -293,5 +293,4 @@ func _on_new_output_pressed() -> void: func _on_universe_name_text_changed(new_text) -> void: - _current_universe.set_universe_name(new_text) - Core.universe_updated.emit(Core.UPDATE_MODE_MODIFY, _current_universe.uuid) + _current_universe.name = new_text diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index c5783ef..656ec1c 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -6,6 +6,7 @@ extends Control func _ready() -> void: Core.scene_added.connect(self._reload_buttons) + Core.scene_removed.connect(self._reload_buttons) func _reload_buttons(_scene) -> void: diff --git a/Panels/Settings/Settings.gd b/Panels/Settings/Settings.gd index b77752e..b9c2c76 100644 --- a/Panels/Settings/Settings.gd +++ b/Panels/Settings/Settings.gd @@ -36,7 +36,7 @@ func load_settings() -> void: var section_node := add_section_node(section) for setting in settings[section].keys(): var config : Dictionary = settings[section][setting] - var value : Variant = config_file.get_value(section, setting, null) + var value : Variant = config_file.get_value(section, setting, "") if value: config.function.call(value) var input_node = add_setting_node(section_node, setting, value, config.input, config.signal, config.function, config.setter, config.get("configs", {}), config.get("tooltip", "")) diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 0862377..10fc591 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -56,6 +56,8 @@ func _add_fixture() -> void: node_to_add.position_offset += _position_offset _position_offset += Vector2(5, 5) + fixture.set_user_meta("virtual_fixture", true) + self.add_child(node_to_add) @@ -65,6 +67,7 @@ func _request_delete() -> void: var to_remove: Array = _selected_virtual_fixtures.duplicate() for virtual_fixture: Control in to_remove: + virtual_fixture.fixture.delete_user_meta("virtual_fixture") virtual_fixture.queue_free() _selected_virtual_fixtures.erase(virtual_fixture) @@ -91,7 +94,6 @@ func _align(orientation: int) -> void: return var base_position: Vector2 = _selected_virtual_fixtures[0].position_offset - var i: int = 0 for virtual_fixture: Control in _selected_virtual_fixtures: virtual_fixture.position_offset = base_position diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.tscn b/Panels/Virtual Fixtures/Virtual_fixtures.tscn index 9ef3bdb..ebb3c61 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.tscn +++ b/Panels/Virtual Fixtures/Virtual_fixtures.tscn @@ -46,7 +46,7 @@ icon_alignment = 1 layout_mode = 2 size_flags_vertical = 3 script = ExtResource("2_j8tmg") -contence = NodePath("../../../../Sidebar/MarginContainer/VBoxContainer/Contence") +contence = NodePath(".") [node name="PanelContainer" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence" instance=ExtResource("5_uh5xn")] layout_mode = 2 diff --git a/Scripts/Sidebar.gd b/Scripts/Sidebar.gd index 8d6f962..bca643d 100644 --- a/Scripts/Sidebar.gd +++ b/Scripts/Sidebar.gd @@ -16,4 +16,4 @@ func _on_button_pressed() -> void: #contence.visible = false #else: #contence.visible = true - is_open = not is_open + is_open = not contence.visible diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index c9b18d0..c187cd9 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -8,7 +8,7 @@ signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) # signal name_changed(new_name: String) ## Emitted when the name of this object has changed var uuid: String = "" ## Uuid of the current component -var name: String = "" ## The name of this object, only use when displaying to users, do not use it as a reference +var name: String = "": set = _set_name ## The name of this object, only use when displaying to users, do not use it as a reference var user_meta: Dictionary ## Infomation that can be stored by other scripts @@ -41,6 +41,10 @@ func delete_user_meta(key: String, no_signal: bool = false) -> bool: return user_meta.erase(key) +func _set_name(new_name) -> void: + name = new_name + + func change_name(new_name: String, no_signal: bool = false) -> void: ## Changes the name of this object name = new_name @@ -69,6 +73,10 @@ func serialize_meta() -> Dictionary: if user_meta[key] is Object and "uuid" in user_meta[key]: serialized_user_meta[key] = user_meta[key].uuid else: - serialized_user_meta[key] = user_meta[key] + serialized_user_meta[key] = user_meta[key] return serialized_user_meta + + +func delete() -> void: + pass diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 2817724..9b94fd5 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -15,7 +15,6 @@ var meta: Dictionary = { "fixture_brand":"", "fixture_name":"", "display_name":"", - "file_path":"", } var universe: Universe ## The universe this fixture is patched to @@ -28,6 +27,10 @@ var channel_ranges: Dictionary ## What happenes at each channel, at each value var is_selected: bool = false +## Contains all the parameters inputted by other function in spectrum, ie scenes, programmer, ect. +## Each input it added to this dict with a id for each item, allowing for HTP and LTP calculations +var current_input_data: Dictionary = {} + var _compiled_dmx_data: Dictionary var _parameters: Dictionary @@ -60,17 +63,30 @@ func serialize() -> Dictionary: ## Returnes serialized infomation about this fixture print(uuid) return { - "universe":universe.get_uuid(), + "universe":universe.uuid, "channel":channel, "mode":mode, "meta":meta, "user_meta": serialize_meta(), - "uuid":uuid } -func set_color(color: Color) -> void: - ## Sets the color of this fixture +func recompile_data() -> void: + ## Compiles dmx data from this fixture + + var highest_valued_data: Dictionary + + for input_data_id in current_input_data: + for input_data in current_input_data[input_data_id]: + match input_data: + "color": + highest_valued_data["color"] = Utils.get_htp_color(highest_valued_data.get("color", Color()), current_input_data[input_data_id][input_data]) + + universe.set_data(_compiled_dmx_data) + _set_color(highest_valued_data.get("color", Color.BLACK)) + + +func _set_color(color: Color) -> void: if "ColorIntensityRed" in channels: _compiled_dmx_data[int(channels.find("ColorIntensityRed") + channel)] = color.r8 if "ColorIntensityGreen" in channels: @@ -80,17 +96,31 @@ func set_color(color: Color) -> void: _parameters.color = color color_changed.emit(_parameters.color) + + +func set_color(color: Color, id: String = "overide") -> void: + ## Sets the color of this fixture - universe.set_data(_compiled_dmx_data) + if color == Color.BLACK: + _remove_current_input_data(id, "color") + else: + _add_current_input_data(id, "color", color) + recompile_data() + + +func _add_current_input_data(id: String, key: String, value: Variant) -> void: + if id not in current_input_data: + current_input_data[id] = {} + current_input_data[id][key] = value + + +func _remove_current_input_data(id: String, key: String) -> void: + current_input_data.get("id", {}).erase(key) + if not current_input_data.get("id", false): + current_input_data.erase(id) func set_selected(state: bool) -> void: is_selected = state selected.emit(state) - - -func delete() -> bool: - ## Called when this fixture is about to be deleted - - return true diff --git a/core/components/Scene.gd b/core/components/Scene.gd index f374000..5564887 100644 --- a/core/components/Scene.gd +++ b/core/components/Scene.gd @@ -6,19 +6,47 @@ class_name Scene extends EngineComponent signal state_changed(is_enabled: bool) ## Emmitted when this scene is enabled or dissabled -var fade_in_speed: int = 100 ## Fade in speed in ms -var fade_out_speed: int = 100 ## Fade out speed in ms +var fade_in_speed: int = 2 ## Fade in speed in seconds +var fade_out_speed: int = 2 ## Fade out speed in seconds + +var engine: CoreEngine ## The CoreEngine this scene is a part of var enabled: bool = false: set = set_enabled ## The current state of this scene +var save_data: Dictionary = {} ## Saved data for this scene -var save_data: Dictionary = {} func set_enabled(is_enabled: bool) -> void: - enabled = is_enabled + ## Enabled or dissables this scene - print(enabled) + enabled = is_enabled if is_enabled: - for fixture: Fixture in save_data.keys(): - fixture.set_color(save_data[fixture].color) + for fixture: Fixture in save_data: + Core.animate(func(color): fixture.set_color(color, uuid), Color.BLACK, save_data[fixture].color, fade_in_speed) + else: + for fixture: Fixture in save_data: + Core.animate(func(color): fixture.set_color(color, uuid), fixture.current_input_data[uuid].color, Color.BLACK, fade_out_speed) + + +func serialize() -> Dictionary: + ## Serializes this scene and returnes it in a dictionary + + return { + "name": self.name, + "fade_in_speed": fade_in_speed, + "fade_out_speed": fade_out_speed, + "save_data": serialize_save_data() + } + + +func serialize_save_data() -> Dictionary: + ## Serializes save_data and returnes as a dictionary + + var serialized_save_data: Dictionary = {} + + for fixture: Fixture in save_data: + serialized_save_data[fixture.uuid] = {} + for save_key in save_data[fixture]: + serialized_save_data[fixture.uuid][save_key] = Utils.serialize_variant(save_data[fixture][save_key]) + return serialized_save_data diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 191cb1b..53641d5 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -18,11 +18,12 @@ var dmx_data: Dictionary = {} var engine: CoreEngine ## The CoreEngine class this universe belongs to -func new_output(type = EmptyOutput, no_signal: bool = false) -> DataIOPlugin: +func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: ## Adds a new output of type to this universe var new_output: DataIOPlugin = type.new() + new_output.file_name = engine.output_plugins[new_output.meta.name].file_name outputs[new_output.uuid] = new_output if not no_signal: @@ -113,6 +114,26 @@ func _compile_and_send(): output.send_packet(compiled_dmx_data) +func serialize() -> Dictionary: + ## Serializes this universe + + var serialized_outputs = {} + var serialized_fixtures = {} + + for output: DataIOPlugin in outputs.values(): + serialized_outputs[output.uuid] = output.serialize() + + for fixture: Fixture in fixtures.values(): + serialized_fixtures[fixture.uuid] = fixture.serialize() + + + return { + "name":name, + "fixtures":serialized_fixtures, + "outputs":serialized_outputs, + "user_meta":serialize_meta() + } + #func get_fixtures(): #return universe.fixtures # @@ -132,27 +153,7 @@ func _compile_and_send(): #return universe.desk_data # -#func serialize(): - #var serialized_outputs = {} - #var serialized_fixtures = {} - # - #for output_uuid in universe.outputs.keys(): - #serialized_outputs[output_uuid] = universe.outputs[output_uuid].serialize() - # - #for fixture_channel in universe.fixtures.keys(): - #var serialized_fixture = universe.fixtures[fixture_channel].serialize() - #if serialized_fixture: - #serialized_fixtures[fixture_channel] = serialized_fixture - # - # - #return { - #"name":universe.name, - #"uuid":universe.uuid, - #"fixtures":serialized_fixtures, - #"inputs":{}, - #"outputs":serialized_outputs, - #"desk_data":universe.desk_data - #} + # #func from(serialized_universe): #universe.name = serialized_universe.name diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 504d267..f3a1fa5 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -42,6 +42,7 @@ var _system: System = System.new() func _ready() -> void: programmer.engine = self + OS.set_low_processor_usage_mode(true) reload_io_plugins() @@ -49,7 +50,12 @@ func _ready() -> void: func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: - return _system.save(self, file_name, file_path) + var save_file: Dictionary = {} + + save_file.universes = serialize_universes() + save_file.scenes = serialize_scenes() + + return Utils.save_json_to_file(file_path, file_name, save_file) func new_universe(name: String = "New Universe", no_signal: bool = false) -> Universe: @@ -126,16 +132,27 @@ func delete_universe(universe: Universe, no_signal: bool = false) -> bool: func serialize_universes() -> Dictionary: - ## Serializes all universes and returnes them in a dictnary + ## Serializes all universes and returnes them in a dictionary var serialized_universes: Dictionary = {} - for universe_uuid: String in universes: - serialized_universes[universe_uuid] = universes[universe_uuid].serialize() + for universe: Universe in universes.values(): + serialized_universes[universe.uuid] = universe.serialize() return serialized_universes +func serialize_scenes() -> Dictionary: + ## Serializes all scenes and returnes them in a dictionary + + var serialized_scenes: Dictionary = {} + + for scene: Scene in scenes.values(): + serialized_scenes[scene.uuid] = scene.serialize() + + return serialized_scenes + + func reload_io_plugins() -> void: ## Loads all output plugins from the folder @@ -152,7 +169,7 @@ func reload_io_plugins() -> void: if plugin_name in output_plugins.keys(): plugin_name = plugin_name + " " + UUID_Util.v4() - output_plugins[plugin_name] = uninitialized_plugin + output_plugins[plugin_name] = {"plugin":uninitialized_plugin, "file_name":plugin} initialized_plugin.free() @@ -213,6 +230,7 @@ func deselect_fixtures(fixtures: Array[Fixture]) -> void: func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: ## Adds a scene to this engine, creats a new one if none is passed + scene.engine = self scenes[scene.uuid] = scene if not no_signal: @@ -220,3 +238,21 @@ func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: return scene + +func remove_scene(scene: Scene, no_signal: bool = false) -> void: + ## Removes a scene from this engine + + var uuid: String = scene.uuid + + scenes.erase(uuid) + scene.delete() + scene.free() + + + if not no_signal: + scene_removed.emit(uuid) + + +func animate(function: Callable, from: Variant, to: Variant, duration: int) -> void: + var animation = get_tree().create_tween() + animation.tween_method(function, from, to, duration) diff --git a/core/engine/Utils.gd b/core/engine/Utils.gd index f3b6f70..7f3c52b 100644 --- a/core/engine/Utils.gd +++ b/core/engine/Utils.gd @@ -16,4 +16,33 @@ static func save_json_to_file(file_path: String, file_name: String, json: Dictio file_access.close() return file_access.get_error() - + + +static func serialize_variant(variant: Variant) -> Variant: + print("type: ", typeof(variant)) + match typeof(variant): + TYPE_COLOR: + return variant.to_html() + + return ERR_INVALID_DATA + + +static func get_htp_color(color_1: Color, color_2: Color) -> Color: + # Calculate the intensity of each channel for color1 + var intensity_1_r = color_1.r + var intensity_1_g = color_1.g + var intensity_1_b = color_1.b + + # Calculate the intensity of each channel for color2 + var intensity_2_r = color_2.r + var intensity_2_g = color_2.g + var intensity_2_b = color_2.b + + # Compare the intensities for each channel and return the color with the higher intensity for each channel + var result_color = Color() + result_color.r = intensity_1_r if intensity_1_r > intensity_2_r else intensity_2_r + result_color.g = intensity_1_g if intensity_1_g > intensity_2_g else intensity_2_g + result_color.b = intensity_1_b if intensity_1_b > intensity_2_b else intensity_2_b + + return result_color + diff --git a/core/io_plugins/DataIOPlugin.gd b/core/io_plugins/DataIOPlugin.gd index 3118645..6b15963 100644 --- a/core/io_plugins/DataIOPlugin.gd +++ b/core/io_plugins/DataIOPlugin.gd @@ -1,7 +1,11 @@ -extends EngineComponent -class_name DataIOPlugin +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. -var type: String = "" +class_name DataIOPlugin extends EngineComponent +## Engine base class for all input and output plugins + +var type: String = "" ## Type of this plugin, either input or output +var file_name: String = "" ## File name for this plugins scritp, used when loading a save file func set_type(new_type:String) -> void: type = new_type @@ -11,9 +15,5 @@ func get_type() -> String: return type -func send_packet(packet) -> void: - return - - func delete() -> void: return diff --git a/core/io_plugins/input_plugins/Empty.gd b/core/io_plugins/input_plugins/Empty.gd deleted file mode 100644 index 1eb83c0..0000000 --- a/core/io_plugins/input_plugins/Empty.gd +++ /dev/null @@ -1,9 +0,0 @@ -extends DataIOPlugin -class_name EmptyInput - -var exposed_values = [] - -func _init(): - self.set_type("input") - self.set_name("Empty Input") - diff --git a/core/io_plugins/output_plugins/ArtNetOutput.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd index bce5f7b..686da59 100644 --- a/core/io_plugins/output_plugins/ArtNetOutput.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -1,5 +1,5 @@ -extends DataIOPlugin -class_name ArtNetOutput +class_name ArtNetOutput extends DataIOPlugin + var meta = { "name": "Art Net Output" @@ -45,11 +45,13 @@ var config = { "ip":"172.0.0.1", "port":6454, "universe":0, + "file_name":"" } func _init(): self.set_type("output") self.name = meta.name + super._init() func connect_to_host(): @@ -78,7 +80,13 @@ func get_universe(): return config.universe func serialize(): - return config + return { + "ip": config.ip, + "port": config.port, + "universe": config.universe, + "name": self.name, + "file_name": self.file_name + } func from(serialized_data): config = serialized_data diff --git a/core/io_plugins/output_plugins/Empty.gd b/core/io_plugins/output_plugins/Empty.gd deleted file mode 100644 index ff25b75..0000000 --- a/core/io_plugins/output_plugins/Empty.gd +++ /dev/null @@ -1,14 +0,0 @@ -class_name EmptyOutput extends DataIOPlugin - -var exposed_values = [] - -func _init(): - self.set_type("output") - self.name = "Empty Output" - - super._init() - -func serialize() -> Dictionary: - return { - "type":"Empty" - } From f2de9a4d9eabde73857b3d314f7cd839f26d53c8 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 21 Mar 2024 17:18:04 +1300 Subject: [PATCH 07/20] Added Back File Open Gui --- Components/File Load Menu/FileLoadMenu.gd | 8 +++ Components/File Load Menu/FileLoadMenu.tscn | 17 ++++++ Main.tscn | 1 + Scripts/Global.gd | 66 ++++----------------- Scripts/Menu_buttons.gd | 12 +++- core/engine/Engine.gd | 6 ++ 6 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 Components/File Load Menu/FileLoadMenu.gd create mode 100644 Components/File Load Menu/FileLoadMenu.tscn diff --git a/Components/File Load Menu/FileLoadMenu.gd b/Components/File Load Menu/FileLoadMenu.gd new file mode 100644 index 0000000..1a6fc89 --- /dev/null +++ b/Components/File Load Menu/FileLoadMenu.gd @@ -0,0 +1,8 @@ +extends FileDialog + +func _on_confirmed() -> void: + self.queue_free() + + +func _on_close_requested() -> void: + self.queue_free() diff --git a/Components/File Load Menu/FileLoadMenu.tscn b/Components/File Load Menu/FileLoadMenu.tscn new file mode 100644 index 0000000..3caa06d --- /dev/null +++ b/Components/File Load Menu/FileLoadMenu.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=2 format=3 uid="uid://djm2s80n0ci54"] + +[ext_resource type="Script" path="res://Components/File Load Menu/FileLoadMenu.gd" id="1_bjt7g"] + +[node name="FileLoadMenu" type="FileDialog"] +title = "Open a File" +position = Vector2i(0, 36) +size = Vector2i(582, 449) +visible = true +ok_button_text = "Open" +file_mode = 0 +access = 2 +use_native_dialog = true +script = ExtResource("1_bjt7g") + +[connection signal="close_requested" from="." to="." method="_on_close_requested"] +[connection signal="confirmed" from="." to="." method="_on_confirmed"] diff --git a/Main.tscn b/Main.tscn index ac18439..5e28ef2 100644 --- a/Main.tscn +++ b/Main.tscn @@ -219,5 +219,6 @@ text = "Beta Version 0.4.0 [connection signal="tab_button_pressed" from="TabContainer" to="TabContainer" method="_on_tab_button_pressed"] [connection signal="tab_clicked" from="TabContainer" to="TabContainer" method="_on_tab_clicked"] [connection signal="pressed" from="Menu Buttons/Save" to="Menu Buttons" method="_on_save_pressed"] +[connection signal="pressed" from="Menu Buttons/Load" to="Menu Buttons" method="_on_load_pressed"] [connection signal="pressed" from="Menu Buttons/Settings" to="Settings" method="show"] [connection signal="close_requested" from="Settings" to="Settings" method="_on_close_requested"] diff --git a/Scripts/Global.gd b/Scripts/Global.gd index 33e58ee..fb515a6 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -34,7 +34,8 @@ var output_plugins : Dictionary "channel_slider":ResourceLoader.load("res://Components/Channel Slider/Channel_slider.tscn"), "virtual_fixture":ResourceLoader.load("res://Components/Virtual Fixture/Virtual_fixture.tscn"), "window":ResourceLoader.load("res://Components/Window/Window.tscn"), - "trigger_button":ResourceLoader.load("res://Components/Trigger Button/TriggerButton.tscn") + "trigger_button":ResourceLoader.load("res://Components/Trigger Button/TriggerButton.tscn"), + "file_load_menu": ResourceLoader.load("res://Components/File Load Menu/FileLoadMenu.tscn") } @onready var panels : Dictionary = { @@ -51,49 +52,6 @@ var output_plugins : Dictionary "window_control":ResourceLoader.load("res://Panels/Window Control/Window_control.tscn"), } -@onready var nodes := { - ## General Nodes - #"popup_window":get_tree().root.get_node("Main/Popups"), - #"save_file_dialog":get_tree().root.get_node("Main/Save File Dialog"), - #"add_node_popup":get_tree().root.get_node("Main/TabContainer/Node Editor/Node Editor/Add Node Popup"), - #"add_widget_popup":get_tree().root.get_node("Main/TabContainer/Console/Console/Console Editor/Add Widget Popup"), - #"widget_settings_menu":get_tree().root.get_node("Main/TabContainer/Console/Console/Widget Settings Menu"), - #"edit_mode_toggle":get_tree().root.get_node("Main/Menu Buttons/Edit Mode"), - # - ##Node Editor - #"node_editor":get_tree().root.get_node("Main/TabContainer/Node Editor/Node Editor"), - # - ##Console - #"console_editor":get_tree().root.get_node("Main/TabContainer/Console/Console/Console Editor"), - # - # - ## Functions Tab - #"functions":get_tree().root.get_node("Main/TabContainer/Functions/Functions"), - #"scenes_list":get_tree().root.get_node("Main/TabContainer/Functions/Functions/VBoxContainer/PanelContainer2/HBoxContainer/Scenes/ScrollContainer/VBoxContainer/Scenes"), - #"effects_list":get_tree().root.get_node("Main/TabContainer/Functions/Functions/VBoxContainer/PanelContainer2/HBoxContainer/Effects/ScrollContainer/VBoxContainer/Effects"), - #"cues_list":get_tree().root.get_node("Main/TabContainer/Functions/Functions/VBoxContainer/PanelContainer2/HBoxContainer/Cues/ScrollContainer/VBoxContainer/Cues"), - # - - ## Fixtures Tab - #"fixtures":get_tree().root.get_node("Main/TabContainer/Fixtures/Fixtures/"), - #"physical_fixture_list":get_tree().root.get_node("Main/TabContainer/Fixtures/Fixtures/VBoxContainer/VSplitContainer/PanelContainer3/ScrollContainer/Physical Fixtures"), - #"fixture_groups_list":get_tree().root.get_node("Main/TabContainer/Fixtures/Fixtures/VBoxContainer/VSplitContainer/PanelContainer2/ScrollContainer/Fixture Groups"), - # - ## Add Fixture Menu - #"add_fixture_window":get_tree().root.get_node("Main/Add Fixture"), - #"add_fixture_menu":get_tree().root.get_node("Main/Add Fixture/Add Fixture/"), - #"fixture_tree":get_tree().root.get_node("Main/Add Fixture/Add Fixture/MarginContainer/HSplitContainer/Fixture Tree"), - #"fixture_channel_list":get_tree().root.get_node("Main/Add Fixture/Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/Channel List"), - #"fixture_modes_option":get_tree().root.get_node("Main/Add Fixture/Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4/Modes"), - #"fixture_universe_option":get_tree().root.get_node("Main/Add Fixture/Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3/Fixture Universe Option"), - #"add_fixture_button":get_tree().root.get_node("Main/Add Fixture/Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2/Add Fixture Button"), - # - - ##Virtual Fixtures - #"virtual_fixtures":get_tree().root.get_node("Main/TabContainer/Virtual Fixtures/HBoxContainer/Virtual Fixtures"), - #"virtual_fixtures_sidebar":get_tree().root.get_node("Main/TabContainer/Virtual Fixtures/HBoxContainer/Sidebar"), -} - @onready var icons := { "menue":load("res://Assets/Icons/menu.svg"), "center":load("res://Assets/Icons/Center.svg") @@ -215,16 +173,16 @@ func _ready() -> void: #fixtures[manifest.info.brand][manifest.info.name] = manifest #else: #fixtures[manifest.info.brand] = {manifest.info.name:manifest} - -func show_popup(content: Array[Dictionary] = []) -> void: - for i in content: - var node_to_add = components.warning.instantiate() - node_to_add.get_node("HBoxContainer/VBoxContainer/Title").text = i.type.title - node_to_add.get_node("HBoxContainer/VBoxContainer/Content").text = i.type.content + ". errcode: " + str(i.type.code) + ((" from: " + i.from) if i.has("from") else "") - node_to_add.get_node("HBoxContainer/VBoxContainer/Time").text = Time.get_time_string_from_system() - nodes.popup_window.get_node("VBoxContainer/PanelContainer/ScrollContainer/Content").add_child(node_to_add) - - nodes.popup_window.popup() +# +#func show_popup(content: Array[Dictionary] = []) -> void: + #for i in content: + #var node_to_add = components.warning.instantiate() + #node_to_add.get_node("HBoxContainer/VBoxContainer/Title").text = i.type.title + #node_to_add.get_node("HBoxContainer/VBoxContainer/Content").text = i.type.content + ". errcode: " + str(i.type.code) + ((" from: " + i.from) if i.has("from") else "") + #node_to_add.get_node("HBoxContainer/VBoxContainer/Time").text = Time.get_time_string_from_system() + #nodes.popup_window.get_node("VBoxContainer/PanelContainer/ScrollContainer/Content").add_child(node_to_add) + # + #nodes.popup_window.popup() func subscribe(value_name:String, callback:Callable) -> void: if value_name in subscriptions: diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index 1bbd88f..1e86bbd 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -1,5 +1,15 @@ extends HBoxContainer func _on_save_pressed() -> void: - print(OS.get_environment("HOME")) print(Core.save("Debug_show.spsave", OS.get_environment("HOME"))) + + +func _on_load_pressed() -> void: + var menu: FileDialog = Globals.components.file_load_menu.instantiate() + + menu.confirmed.connect( + func(): + Core.load(menu.current_path) + ) + + get_tree().root.add_child(menu) diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index f3a1fa5..9435bea 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -58,6 +58,12 @@ func save(file_name: String = current_file_name, file_path: String = current_fil return Utils.save_json_to_file(file_path, file_name, save_file) +func load(file_path) -> void: + var saved_file = FileAccess.open(file_path, FileAccess.READ) + var serialized_data = JSON.parse_string(saved_file.get_as_text()) + print(serialized_data) + + func new_universe(name: String = "New Universe", no_signal: bool = false) -> Universe: ## Adds a new universe From f733857dd80fcbc5777a240b8029495b4e672563 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Sun, 31 Mar 2024 19:20:16 +1300 Subject: [PATCH 08/20] Added new list view component --- Assets/Icons/Add.svg | 58 +++++ Assets/Icons/Add.svg.import | 37 ++++ Assets/Icons/Check.svg.import | 2 +- Assets/Icons/Checked.svg | 41 ++++ Assets/Icons/Checked.svg.import | 37 ++++ Assets/Icons/Invert.svg | 50 +++++ Assets/Icons/Invert.svg.import | 37 ++++ Components/ItemListView/ItemListView.gd | 202 ++++++++++++++++++ Components/ItemListView/ItemListView.tscn | 95 ++++++++ Components/Knob/Encoder.gd | 4 +- Components/Knob/Encoder.tscn | 1 + Components/List Item/List_item.gd | 17 +- Components/List Item/List_item.tscn | 16 +- Components/Trigger Button/TriggerButton.gd | 12 +- Components/Trigger Button/TriggerButton.tscn | 16 +- Main.tscn | 9 +- Panels/Add Fixture/Add_fixture.gd | 2 +- Panels/Fixtures/Fixtures.gd | 1 - Panels/Functions/Functions.gd | 42 +--- Panels/Functions/Functions.tscn | 23 +- Panels/Playback Buttons/PlaybackButtons.gd | 8 +- Panels/Playback Buttons/PlaybackButtons.tscn | 18 +- Panels/Universes/Universes.gd | 35 +++ Panels/Universes/Universes.tscn | 25 +++ Panels/Virtual Fixtures/Virtual_fixtures.tscn | 62 ++---- core/components/EngineComponent.gd | 1 - core/components/Universe.gd | 9 + core/engine/Engine.gd | 123 ++++++++--- 28 files changed, 820 insertions(+), 163 deletions(-) create mode 100644 Assets/Icons/Add.svg create mode 100644 Assets/Icons/Add.svg.import create mode 100644 Assets/Icons/Checked.svg create mode 100644 Assets/Icons/Checked.svg.import create mode 100644 Assets/Icons/Invert.svg create mode 100644 Assets/Icons/Invert.svg.import create mode 100644 Components/ItemListView/ItemListView.gd create mode 100644 Components/ItemListView/ItemListView.tscn create mode 100644 Panels/Universes/Universes.gd create mode 100644 Panels/Universes/Universes.tscn diff --git a/Assets/Icons/Add.svg b/Assets/Icons/Add.svg new file mode 100644 index 0000000..3475284 --- /dev/null +++ b/Assets/Icons/Add.svg @@ -0,0 +1,58 @@ + + + + + + + + diff --git a/Assets/Icons/Add.svg.import b/Assets/Icons/Add.svg.import new file mode 100644 index 0000000..aa962d7 --- /dev/null +++ b/Assets/Icons/Add.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bbennjke0ioen" +path="res://.godot/imported/Add.svg-078ad3409bd2c967c3fab28fa9bba462.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Icons/Add.svg" +dest_files=["res://.godot/imported/Add.svg-078ad3409bd2c967c3fab28fa9bba462.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Assets/Icons/Check.svg.import b/Assets/Icons/Check.svg.import index 7921261..a925a22 100644 --- a/Assets/Icons/Check.svg.import +++ b/Assets/Icons/Check.svg.import @@ -32,6 +32,6 @@ process/hdr_as_srgb=false process/hdr_clamp_exposure=false process/size_limit=0 detect_3d/compress_to=1 -svg/scale=2.0 +svg/scale=1.0 editor/scale_with_editor_scale=false editor/convert_colors_with_editor_theme=false diff --git a/Assets/Icons/Checked.svg b/Assets/Icons/Checked.svg new file mode 100644 index 0000000..ef045a8 --- /dev/null +++ b/Assets/Icons/Checked.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/Assets/Icons/Checked.svg.import b/Assets/Icons/Checked.svg.import new file mode 100644 index 0000000..13567af --- /dev/null +++ b/Assets/Icons/Checked.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c6x6e8xi6lupf" +path="res://.godot/imported/Checked.svg-ef4a8ffe3594dc64b1dc900e0809d8c0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Icons/Checked.svg" +dest_files=["res://.godot/imported/Checked.svg-ef4a8ffe3594dc64b1dc900e0809d8c0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Assets/Icons/Invert.svg b/Assets/Icons/Invert.svg new file mode 100644 index 0000000..e351db2 --- /dev/null +++ b/Assets/Icons/Invert.svg @@ -0,0 +1,50 @@ + + + + + + + diff --git a/Assets/Icons/Invert.svg.import b/Assets/Icons/Invert.svg.import new file mode 100644 index 0000000..37f934e --- /dev/null +++ b/Assets/Icons/Invert.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b2nos4alwgqcg" +path="res://.godot/imported/Invert.svg-3001572e5e1f25db4c2b26d0a6c42fb1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Icons/Invert.svg" +dest_files=["res://.godot/imported/Invert.svg-3001572e5e1f25db4c2b26d0a6c42fb1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Components/ItemListView/ItemListView.gd b/Components/ItemListView/ItemListView.gd new file mode 100644 index 0000000..698c1a2 --- /dev/null +++ b/Components/ItemListView/ItemListView.gd @@ -0,0 +1,202 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +@tool +extends Control +## GUI Component for a list view. + +signal edit_requested(items: Array) +signal delete_requested(items: Array) +signal take_requested(items: Array) +signal add_requested() +signal selection_changed(items: Array) + +@export var show_tool_bar: bool = true : set = set_show_tool_bar +@export var show_new: bool = true : set = set_show_new +@export var show_select: bool = true : set = set_show_select +@export var show_invert: bool = true : set = set_show_invert +@export var show_take: bool = true : set = set_show_take +@export var show_edit: bool = true : set = set_show_edit +@export var show_delete: bool = true : set = set_show_delete +@export var show_separators: bool = true : set = set_show_separators + +@export var allow_multi_select: bool = true + +@onready var item_container: VBoxContainer = self.get_node("PanelContainer2/ScrollContainer/ItemContainer") + +var currently_selected_items: Array = [] +var last_selected_item: Control + +var object_refs: Dictionary + +func _ready() -> void: + set_show_tool_bar(show_tool_bar) + set_show_new(show_new) + set_show_select(show_select) + set_show_invert(show_invert) + set_show_take(show_take) + set_show_edit(show_edit) + set_show_delete(show_delete) + set_show_separators(show_separators) + + +func add_items(items: Array) -> void: + ## Adds an item to the list + + for item in items: + if "uuid" in item and "name" in item: + var new_item_node: Control = Globals.components.list_item.instantiate() + new_item_node.set_item_name(item.name) + + new_item_node.control_node = self + new_item_node.name = item.uuid + new_item_node.select_requested.connect(self.on_list_item_select_request) + + item_container.add_child(new_item_node) + object_refs[new_item_node] = item + + +func remove_all() -> void: + ## Removes all items from the list + + for item in item_container.get_children(): + item_container.remove_child(item) + item.queue_free() + + +func on_list_item_select_request(selected_item: Control) -> void: + if Input.is_key_pressed(KEY_SHIFT) and last_selected_item and allow_multi_select: + var children: Array[Node] = item_container.get_children() + var pos_1: int = children.find(last_selected_item) + var pos_2: int = children.find(selected_item) + + if pos_1 > pos_2: + var x = pos_1 + pos_1 = pos_2 + pos_2 = x + + var items_to_select: Array = [] + + for i in range(pos_1, pos_2+1): + items_to_select.append(children[i]) + + currently_selected_items = items_to_select + + else: + last_selected_item = selected_item + currently_selected_items = [selected_item] + + _update_selected() + + +func _update_selected() -> void: + for item: Control in item_container.get_children(): + item.set_highlighted(false) + + for item: Control in currently_selected_items: + item.set_highlighted(true) + + selection_changed.emit(currently_selected_items) + + +func get_objects_from_nodes(items: Array) -> Array: + ## Converts a list of list Item nodes into three objects they are representing + + var object_list: Array = [] + + for item in items: + object_list.append(object_refs[item]) + + return object_list + +#region Button Callbacks + +func _on_new_pressed() -> void: + add_requested.emit() + + +func _on_select_all_pressed() -> void: + currently_selected_items = item_container.get_children() + _update_selected() + + +func _on_select_none_pressed() -> void: + currently_selected_items = [] + _update_selected() + + +func _on_select_invert_pressed() -> void: + var all_items: Array = item_container.get_children() + + for item: Control in currently_selected_items: + all_items.erase(item) + + currently_selected_items = all_items + _update_selected() + + +func _on_take_selection_pressed() -> void: + take_requested.emit(get_objects_from_nodes(currently_selected_items)) + + +func _on_edit_pressed() -> void: + edit_requested.emit(get_objects_from_nodes(currently_selected_items)) + + +func _on_delete_pressed() -> void: + delete_requested.emit(get_objects_from_nodes(currently_selected_items)) + +#endregion + + +#region UI displaying functions +func set_show_tool_bar(is_visible) -> void: + show_tool_bar = is_visible + if is_node_ready(): + $ToolBarContainer.visible = is_visible + + +func set_show_edit(is_visible) -> void: + show_edit = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/Edit.visible = is_visible + + +func set_show_delete(is_visible) -> void: + show_delete = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/Delete.visible = is_visible + + +func set_show_select(is_visible) -> void: + show_select = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/SelectAll.visible = is_visible + $ToolBarContainer/HBoxContainer/SelectNone.visible = is_visible + + +func set_show_invert(is_visible) -> void: + show_invert = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/SelectInvert.visible = is_visible + + +func set_show_new(is_visible) -> void: + show_new = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/New.visible = is_visible + $ToolBarContainer/HBoxContainer/VSeparator1.visible = is_visible + + +func set_show_take(is_visible) -> void: + show_take = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/TakeSelection.visible = is_visible + + +func set_show_separators(is_visible) -> void: + show_separators = is_visible + if is_node_ready(): + $ToolBarContainer/HBoxContainer/VSeparator1.visible = is_visible + $ToolBarContainer/HBoxContainer/VSeparator2.visible = is_visible +#endregion diff --git a/Components/ItemListView/ItemListView.tscn b/Components/ItemListView/ItemListView.tscn new file mode 100644 index 0000000..de429a1 --- /dev/null +++ b/Components/ItemListView/ItemListView.tscn @@ -0,0 +1,95 @@ +[gd_scene load_steps=10 format=3 uid="uid://c6smssfk7gn2w"] + +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_fhj3g"] +[ext_resource type="Script" path="res://Components/ItemListView/ItemListView.gd" id="2_xkuya"] +[ext_resource type="Texture2D" uid="uid://bbennjke0ioen" path="res://Assets/Icons/Add.svg" id="3_kvafp"] +[ext_resource type="Texture2D" uid="uid://c6x6e8xi6lupf" path="res://Assets/Icons/Checked.svg" id="4_21ueo"] +[ext_resource type="Texture2D" uid="uid://su38vnysxa1c" path="res://Assets/Icons/Unchecked.svg" id="5_eti65"] +[ext_resource type="Texture2D" uid="uid://b2nos4alwgqcg" path="res://Assets/Icons/Invert.svg" id="6_xwuqg"] +[ext_resource type="Texture2D" uid="uid://bi4ttx5uklwl7" path="res://Assets/Icons/Check.svg" id="7_g74a1"] +[ext_resource type="Texture2D" uid="uid://rqf8w11gk6ud" path="res://Assets/Icons/Edit.svg" id="8_y732o"] +[ext_resource type="Texture2D" uid="uid://dfrrs2dnvlvsu" path="res://Assets/Icons/Delete.svg" id="9_dwy31"] + +[node name="ItemListView" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = ExtResource("1_fhj3g") +script = ExtResource("2_xkuya") + +[node name="ToolBarContainer" type="PanelContainer" parent="."] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="ToolBarContainer"] +layout_mode = 2 + +[node name="New" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +text = "New" +icon = ExtResource("3_kvafp") + +[node name="VSeparator1" type="VSeparator" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 + +[node name="SelectAll" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select All" +text = "All" +icon = ExtResource("4_21ueo") + +[node name="SelectNone" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select None" +text = "None" +icon = ExtResource("5_eti65") + +[node name="SelectInvert" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select None" +text = "Invert" +icon = ExtResource("6_xwuqg") + +[node name="TakeSelection" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select None" +text = "Take" +icon = ExtResource("7_g74a1") + +[node name="VSeparator2" type="VSeparator" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 + +[node name="Edit" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select None" +text = "Edit" +icon = ExtResource("8_y732o") + +[node name="Delete" type="Button" parent="ToolBarContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Select All" +text = "Delete" +icon = ExtResource("9_dwy31") + +[node name="PanelContainer2" type="PanelContainer" parent="."] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer2"] +layout_mode = 2 + +[node name="ItemContainer" type="VBoxContainer" parent="PanelContainer2/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/New" to="." method="_on_new_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/SelectAll" to="." method="_on_select_all_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/SelectNone" to="." method="_on_select_none_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/SelectInvert" to="." method="_on_select_invert_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/TakeSelection" to="." method="_on_take_selection_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/Edit" to="." method="_on_edit_pressed"] +[connection signal="pressed" from="ToolBarContainer/HBoxContainer/Delete" to="." method="_on_delete_pressed"] diff --git a/Components/Knob/Encoder.gd b/Components/Knob/Encoder.gd index b63de31..db3db2f 100644 --- a/Components/Knob/Encoder.gd +++ b/Components/Knob/Encoder.gd @@ -54,9 +54,7 @@ func set_value_no_signal(value: int) -> int: else: rotation = clampi(remap(value, min_value, max_value, _gap_min, _gap_max), _gap_min, _gap_max) new_value = clampi(value, min_value, max_value) - - print(rotation) - + $TextureRect.rotation_degrees = rotation + rotation_offset $Label.text = str(new_value) diff --git a/Components/Knob/Encoder.tscn b/Components/Knob/Encoder.tscn index 464f193..8d795aa 100644 --- a/Components/Knob/Encoder.tscn +++ b/Components/Knob/Encoder.tscn @@ -11,6 +11,7 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_5y8la") +value = -930 [node name="TextureRect" type="TextureRect" parent="."] layout_mode = 1 diff --git a/Components/List Item/List_item.gd b/Components/List Item/List_item.gd index 5f76662..58c1ef0 100644 --- a/Components/List Item/List_item.gd +++ b/Components/List Item/List_item.gd @@ -1,4 +1,10 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + extends PanelContainer +## GUI component for a list item + +signal select_requested(from: Control) ## Emmited when this control is clicked on var control_node @@ -27,17 +33,8 @@ func dissable_buttons(dissable): $Container/Delete.disabled = dissable $Container/Edit.disabled = dissable -func _on_delete_pressed(): - if control_node.has_method("delete_request"): - control_node.delete_request(self) - -func _on_edit_pressed(): - if control_node.has_method("edit_request"): - control_node.edit_request(self) - func _on_gui_input(event): if event is InputEventMouseButton: if event.pressed == true and event.button_index == MOUSE_BUTTON_LEFT: # Check if the mouse button is released - if control_node.has_method("on_selected"): - control_node.on_selected(self) + select_requested.emit(self) diff --git a/Components/List Item/List_item.tscn b/Components/List Item/List_item.tscn index bf9eb21..a7f751f 100644 --- a/Components/List Item/List_item.tscn +++ b/Components/List Item/List_item.tscn @@ -1,8 +1,6 @@ -[gd_scene load_steps=5 format=3 uid="uid://d0wg6bo67u7cr"] +[gd_scene load_steps=3 format=3 uid="uid://d0wg6bo67u7cr"] [ext_resource type="Script" path="res://Components/List Item/List_item.gd" id="1_plvbh"] -[ext_resource type="Texture2D" uid="uid://dfrrs2dnvlvsu" path="res://Assets/Icons/Delete.svg" id="2_jm4an"] -[ext_resource type="Texture2D" uid="uid://rqf8w11gk6ud" path="res://Assets/Icons/Edit.svg" id="3_02fjg"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_564t2"] content_margin_left = 13.0 @@ -18,6 +16,7 @@ corner_radius_bottom_right = 5 corner_radius_bottom_left = 5 [node name="Item" type="PanelContainer"] +custom_minimum_size = Vector2(0, 50) theme_override_styles/panel = SubResource("StyleBoxFlat_564t2") script = ExtResource("1_plvbh") @@ -31,15 +30,4 @@ layout_mode = 2 layout_mode = 2 text = "Name" -[node name="Delete" type="Button" parent="Container"] -layout_mode = 2 -size_flags_horizontal = 10 -icon = ExtResource("2_jm4an") - -[node name="Edit" type="Button" parent="Container"] -layout_mode = 2 -icon = ExtResource("3_02fjg") - [connection signal="gui_input" from="." to="." method="_on_gui_input"] -[connection signal="pressed" from="Container/Delete" to="." method="_on_delete_pressed"] -[connection signal="pressed" from="Container/Edit" to="." method="_on_edit_pressed"] diff --git a/Components/Trigger Button/TriggerButton.gd b/Components/Trigger Button/TriggerButton.gd index 9327f37..5c0fb11 100644 --- a/Components/Trigger Button/TriggerButton.gd +++ b/Components/Trigger Button/TriggerButton.gd @@ -4,11 +4,17 @@ extends Button ## Ui button to trigger an action on click -signal edit_requested(from: Button) +signal right_clicked(from: Button) + + +func set_label_text(label_text: String) -> void: + ## Sets the text of this button, + ## use this instead of buttons built in set_text methord, as this label supports text wrapping + + $Label.text = label_text -var control_node: Node func _on_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton: if event.pressed and event.button_index == 2: - print("Right Clicked") + right_clicked.emit(self) diff --git a/Components/Trigger Button/TriggerButton.tscn b/Components/Trigger Button/TriggerButton.tscn index ef86f72..1075592 100644 --- a/Components/Trigger Button/TriggerButton.tscn +++ b/Components/Trigger Button/TriggerButton.tscn @@ -8,14 +8,28 @@ custom_minimum_size = Vector2(70, 70) anchors_preset = -1 anchor_right = 0.0364583 anchor_bottom = 0.0648148 +size_flags_horizontal = 3 +size_flags_vertical = 4 theme = ExtResource("1_v6l20") theme_override_font_sizes/font_size = 9 toggle_mode = true action_mode = 0 -text = "Button" clip_text = true script = ExtResource("1_3rl6v") metadata/_edit_use_anchors_ = true +[node name="Label" type="Label" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 14 +horizontal_alignment = 1 +vertical_alignment = 1 +autowrap_mode = 3 +text_overrun_behavior = 3 + [connection signal="gui_input" from="." to="." method="_on_gui_input"] [connection signal="toggled" from="." to="." method="_on_toggled"] diff --git a/Main.tscn b/Main.tscn index 5e28ef2..7d8efd0 100644 --- a/Main.tscn +++ b/Main.tscn @@ -4,10 +4,10 @@ [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] [ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] [ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] +[ext_resource type="PackedScene" uid="uid://03t7su6t2rq2" path="res://Panels/Universes/Universes.tscn" id="4_8kgbc"] [ext_resource type="PackedScene" uid="uid://cedqo06n6en8u" path="res://Panels/Functions/Functions.tscn" id="4_35sxj"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="5_8370q"] [ext_resource type="Script" path="res://Scripts/Menu_buttons.gd" id="7_gussm"] -[ext_resource type="PackedScene" uid="uid://cdg8rr3v7el85" path="res://Panels/Patch Bay/Patch_bay.tscn" id="9_hxqqf"] [ext_resource type="PackedScene" uid="uid://nd4u83us3lgo" path="res://Panels/Settings/Settings.tscn" id="27_03pyd"] [ext_resource type="Script" path="res://Scripts/Window.gd" id="27_nmwy1"] @@ -97,20 +97,19 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -current_tab = 2 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true script = ExtResource("3_nk5d5") [node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] -visible = false layout_mode = 2 -[node name="Functions" parent="TabContainer" instance=ExtResource("4_35sxj")] +[node name="Universes" parent="TabContainer" instance=ExtResource("4_8kgbc")] visible = false layout_mode = 2 -[node name="Patch Bay" parent="TabContainer" instance=ExtResource("9_hxqqf")] +[node name="Functions" parent="TabContainer" instance=ExtResource("4_35sxj")] +visible = false layout_mode = 2 [node name="Virtual Fixtures" parent="TabContainer" instance=ExtResource("5_8370q")] diff --git a/Panels/Add Fixture/Add_fixture.gd b/Panels/Add Fixture/Add_fixture.gd index 40952b0..6a57d64 100644 --- a/Panels/Add Fixture/Add_fixture.gd +++ b/Panels/Add Fixture/Add_fixture.gd @@ -25,7 +25,7 @@ var options: Dictionary = { func _ready() -> void: Core.universe_added.connect(self._reload_universes) - Core.universe_removed.connect(self._reload_universes) + Core.universes_removed.connect(self._reload_universes) _reload_universes() _reload_fixture_tree() diff --git a/Panels/Fixtures/Fixtures.gd b/Panels/Fixtures/Fixtures.gd index 26b02d6..fdcdc17 100644 --- a/Panels/Fixtures/Fixtures.gd +++ b/Panels/Fixtures/Fixtures.gd @@ -91,7 +91,6 @@ func set_active_fixtures(fixtures:Array) -> void: for fixture: Fixture in active_fixtures: get_node(physical_fixture_list).get_node(fixture.uuid).set_highlighted(true) - pass func _on_new_physical_fixture_pressed() -> void: diff --git a/Panels/Functions/Functions.gd b/Panels/Functions/Functions.gd index 2aff934..653c7ac 100644 --- a/Panels/Functions/Functions.gd +++ b/Panels/Functions/Functions.gd @@ -4,46 +4,24 @@ extends Control ## GUI element for managing functions -@export var functions_list: NodePath +@export var item_list_view: NodePath + func _ready() -> void: Core.scene_added.connect(self._reload_functions) - Core.scene_removed.connect(self._reload_functions) + Core.scenes_removed.connect(self._reload_functions) -func delete_request(node:Control) -> void : - ## Called when the delete button is clicked on a function List_Item - - var confirmation_dialog: AcceptDialog = Globals.components.accept_dialog.instantiate() - confirmation_dialog.dialog_text = "Are you sure you want to delete this? This action can not be undone" +func _reload_functions(_scene=null) -> void: + ## Reload the list of fixtures - confirmation_dialog.confirmed.connect(( - func(node): - - var scene: Scene = node.get_meta("function") - scene.engine.remove_scene(scene) - - ).bind(node)) + self.get_node(item_list_view).remove_all() + self.get_node(item_list_view).add_items(Core.scenes.values()) - add_child(confirmation_dialog) -func edit_request(node:Control) -> void: - ## WIP function to edit a fixture, change channel, type, universe, ect - pass - -func _reload_functions(_scene=null) -> void: - ## Reload the list of fixtures +func _on_item_list_view_delete_requested(items: Array) -> void: + ## Called when the delete button is pressed on the ItemListView - for node in get_node(functions_list).get_children(): - node.get_parent().remove_child(node) - node.queue_free() + Core.remove_scenes(items) - for scene: Scene in Core.scenes.values(): - var node_to_add : Control = Globals.components.list_item.instantiate() - node_to_add.control_node = self - node_to_add.set_item_name(scene.name) - node_to_add.name = scene.uuid - node_to_add.set_meta("function", scene) - get_node(functions_list).add_child(node_to_add) - diff --git a/Panels/Functions/Functions.tscn b/Panels/Functions/Functions.tscn index 07c9a3d..fd31c43 100644 --- a/Panels/Functions/Functions.tscn +++ b/Panels/Functions/Functions.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://cedqo06n6en8u"] +[gd_scene load_steps=4 format=3 uid="uid://cedqo06n6en8u"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_un5lg"] [ext_resource type="Script" path="res://Panels/Functions/Functions.gd" id="2_bfwkh"] +[ext_resource type="PackedScene" uid="uid://c6smssfk7gn2w" path="res://Components/ItemListView/ItemListView.tscn" id="3_knoqd"] [node name="Functions" type="Control"] layout_mode = 3 @@ -24,21 +25,11 @@ theme_override_constants/margin_top = 10 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 10 script = ExtResource("2_bfwkh") -functions_list = NodePath("VBoxContainer/PanelContainer3/ScrollContainer/Functions") +item_list_view = NodePath("ItemListView") -[node name="VBoxContainer" type="VBoxContainer" parent="Functions"] +[node name="ItemListView" parent="Functions" instance=ExtResource("3_knoqd")] layout_mode = 2 +show_new = false +allow_multi_select = false -[node name="PanelContainer3" type="PanelContainer" parent="Functions/VBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Functions/VBoxContainer/PanelContainer3"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="Functions" type="VBoxContainer" parent="Functions/VBoxContainer/PanelContainer3/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 +[connection signal="delete_requested" from="Functions/ItemListView" to="Functions" method="_on_item_list_view_delete_requested"] diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index 656ec1c..09fdd99 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -6,7 +6,7 @@ extends Control func _ready() -> void: Core.scene_added.connect(self._reload_buttons) - Core.scene_removed.connect(self._reload_buttons) + Core.scenes_removed.connect(self._reload_buttons) func _reload_buttons(_scene) -> void: @@ -19,10 +19,14 @@ func _reload_buttons(_scene) -> void: for scene: Scene in Core.scenes.values(): var button_to_add: Button = Globals.components.trigger_button.instantiate() - button_to_add.text = scene.name + button_to_add.set_label_text(scene.name) button_to_add.toggled.connect( func(state): scene.enabled = state ) self.add_child(button_to_add) + + +func _on_resized() -> void: + self.columns = int(self.size.x / 110) diff --git a/Panels/Playback Buttons/PlaybackButtons.tscn b/Panels/Playback Buttons/PlaybackButtons.tscn index 7804553..26f237a 100644 --- a/Panels/Playback Buttons/PlaybackButtons.tscn +++ b/Panels/Playback Buttons/PlaybackButtons.tscn @@ -2,16 +2,26 @@ [ext_resource type="Script" path="res://Panels/Playback Buttons/PlaybackButtons.gd" id="1_0mir5"] -[node name="PanelContainer" type="PanelContainer"] +[node name="PlaybackButtons" type="PanelContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_right = -2.0 grow_horizontal = 2 grow_vertical = 2 +size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="PlaybackButtons" type="VBoxContainer" parent="."] +[node name="ScrollContainer" type="ScrollContainer" parent="."] layout_mode = 2 -size_flags_horizontal = 6 +horizontal_scroll_mode = 0 + +[node name="GridContainer" type="GridContainer" parent="ScrollContainer"] +clip_contents = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +columns = 18 script = ExtResource("1_0mir5") -metadata/_edit_use_anchors_ = true + +[connection signal="resized" from="ScrollContainer/GridContainer" to="ScrollContainer/GridContainer" method="_on_resized"] diff --git a/Panels/Universes/Universes.gd b/Panels/Universes/Universes.gd new file mode 100644 index 0000000..96af881 --- /dev/null +++ b/Panels/Universes/Universes.gd @@ -0,0 +1,35 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +extends Control +## GUI element for managing universes + +@export var item_list_view: NodePath + + +func _ready() -> void: + Core.universe_added.connect(self._reload_universes) + Core.universes_removed.connect(self._reload_universes) + Core.universe_name_changed.connect(self._reload_universes) + + +func _reload_universes(_scene=null) -> void: + ## Reload the list of fixtures + + self.get_node(item_list_view).remove_all() + self.get_node(item_list_view).add_items(Core.universes.values()) + + + +func _on_item_list_view_delete_requested(items: Array) -> void: + ## Called when the delete button is pressed on the ItemListView + + Core.remove_universes(items) + + +func _on_item_list_view_add_requested() -> void: + Core.new_universe() + + +func _on_item_list_view_take_requested(items: Array) -> void: + Core.set_universe_selection(items) diff --git a/Panels/Universes/Universes.tscn b/Panels/Universes/Universes.tscn new file mode 100644 index 0000000..e940739 --- /dev/null +++ b/Panels/Universes/Universes.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=4 format=3 uid="uid://03t7su6t2rq2"] + +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_hrdmq"] +[ext_resource type="Script" path="res://Panels/Universes/Universes.gd" id="2_dy1nn"] +[ext_resource type="PackedScene" uid="uid://c6smssfk7gn2w" path="res://Components/ItemListView/ItemListView.tscn" id="2_nny3h"] + +[node name="Universes" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = ExtResource("1_hrdmq") +script = ExtResource("2_dy1nn") +item_list_view = NodePath("ItemListView") + +[node name="ItemListView" parent="." instance=ExtResource("2_nny3h")] +layout_mode = 2 +show_edit = false + +[connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] +[connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] +[connection signal="take_requested" from="ItemListView" to="." method="_on_item_list_view_take_requested"] diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.tscn b/Panels/Virtual Fixtures/Virtual_fixtures.tscn index ebb3c61..89865c9 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.tscn +++ b/Panels/Virtual Fixtures/Virtual_fixtures.tscn @@ -15,7 +15,7 @@ grow_horizontal = 2 grow_vertical = 2 theme = ExtResource("1_hwlxv") -[node name="HBoxContainer" type="HBoxContainer" parent="."] +[node name="HBoxContainer" type="HSplitContainer" parent="."] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -23,45 +23,30 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -[node name="Sidebar2" type="PanelContainer" parent="HBoxContainer"] +[node name="PanelContainer" type="PanelContainer" parent="HBoxContainer"] custom_minimum_size = Vector2(50, 0) layout_mode = 2 -[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Sidebar2"] -layout_mode = 2 -theme_override_constants/margin_left = 4 -theme_override_constants/margin_top = 4 -theme_override_constants/margin_right = 4 -theme_override_constants/margin_bottom = 4 - -[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/Sidebar2/MarginContainer"] -layout_mode = 2 - -[node name="Side Bar Open" type="Button" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer"] -layout_mode = 2 -icon = ExtResource("3_xlq73") -icon_alignment = 1 - -[node name="Contence" type="VBoxContainer" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer" node_paths=PackedStringArray("contence")] +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/PanelContainer"] layout_mode = 2 size_flags_vertical = 3 -script = ExtResource("2_j8tmg") -contence = NodePath(".") -[node name="PanelContainer" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence" instance=ExtResource("5_uh5xn")] +[node name="PlaybackButtons" parent="HBoxContainer/PanelContainer/VBoxContainer" instance=ExtResource("5_uh5xn")] layout_mode = 2 -size_flags_vertical = 1 -[node name="Button" type="Button" parent="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence"] +[node name="Button" type="Button" parent="HBoxContainer/PanelContainer/VBoxContainer"] layout_mode = 2 -size_flags_vertical = 10 +size_flags_vertical = 8 text = "Save" -[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"] +[node name="HSplitContainer" type="HSplitContainer" parent="HBoxContainer"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/HSplitContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="Virtual Fixtures" type="GraphEdit" parent="HBoxContainer/VBoxContainer"] +[node name="Virtual Fixtures" type="GraphEdit" parent="HBoxContainer/HSplitContainer/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -71,46 +56,45 @@ show_minimap_button = false show_arrange_button = false script = ExtResource("1_y16fu") -[node name="Bottom Bar" type="PanelContainer" parent="HBoxContainer/VBoxContainer"] +[node name="Bottom Bar" type="PanelContainer" parent="HBoxContainer/HSplitContainer/VBoxContainer"] visible = false custom_minimum_size = Vector2(50, 0) layout_mode = 2 -[node name="Sidebar" type="PanelContainer" parent="HBoxContainer"] +[node name="Sidebar" type="PanelContainer" parent="HBoxContainer/HSplitContainer"] custom_minimum_size = Vector2(50, 0) layout_mode = 2 -[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/Sidebar"] +[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/HSplitContainer/Sidebar"] layout_mode = 2 theme_override_constants/margin_left = 4 theme_override_constants/margin_top = 4 theme_override_constants/margin_right = 4 theme_override_constants/margin_bottom = 4 -[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/Sidebar/MarginContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/HSplitContainer/Sidebar/MarginContainer"] layout_mode = 2 -[node name="Side Bar Open" type="Button" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer"] +[node name="Side Bar Open" type="Button" parent="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer"] layout_mode = 2 icon = ExtResource("3_xlq73") icon_alignment = 1 -[node name="Contence" type="VBoxContainer" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer" node_paths=PackedStringArray("contence")] +[node name="Contence" type="VBoxContainer" parent="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer" node_paths=PackedStringArray("contence")] layout_mode = 2 size_flags_vertical = 3 script = ExtResource("2_j8tmg") contence = NodePath(".") -[node name="ColorPicker" type="ColorPicker" parent="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence"] +[node name="ColorPicker" type="ColorPicker" parent="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer/Contence"] layout_mode = 2 color = Color(0, 1, 1, 1) edit_alpha = false picker_shape = 1 color_modes_visible = false -[connection signal="pressed" from="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] -[connection signal="pressed" from="HBoxContainer/Sidebar2/MarginContainer/VBoxContainer/Contence/Button" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_save_pressed"] -[connection signal="node_deselected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_deselected"] -[connection signal="node_selected" from="HBoxContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_selected"] -[connection signal="pressed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] -[connection signal="color_changed" from="HBoxContainer/Sidebar/MarginContainer/VBoxContainer/Contence/ColorPicker" to="HBoxContainer/VBoxContainer/Virtual Fixtures" method="_on_color_picker_color_changed"] +[connection signal="pressed" from="HBoxContainer/PanelContainer/VBoxContainer/Button" to="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" method="_on_save_pressed"] +[connection signal="node_deselected" from="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_deselected"] +[connection signal="node_selected" from="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" to="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" method="_on_virtual_fixture_selected"] +[connection signal="pressed" from="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer/Side Bar Open" to="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer/Contence" method="_on_button_pressed"] +[connection signal="color_changed" from="HBoxContainer/HSplitContainer/Sidebar/MarginContainer/VBoxContainer/Contence/ColorPicker" to="HBoxContainer/HSplitContainer/VBoxContainer/Virtual Fixtures" method="_on_color_picker_color_changed"] diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index c187cd9..9956273 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -14,7 +14,6 @@ var user_meta: Dictionary ## Infomation that can be stored by other scripts func _init() -> void: uuid = UUID_Util.v4() - print(self) func set_user_meta(key: String, value: Variant, no_signal: bool = false): diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 53641d5..8d0609d 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -11,11 +11,15 @@ signal fixture_deleted(fixture_uuids: Array[String]) signal output_added(output: DataIOPlugin) signal output_removed(output_uuid: String) +signal selected(is_selected: bool) + var fixtures: Dictionary = {} ## Dictionary containing all the fixtures in this universe var outputs: Dictionary = {} ## Dictionary containing all the outputs in this universe var dmx_data: Dictionary = {} +var is_selected: bool = false + var engine: CoreEngine ## The CoreEngine class this universe belongs to func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: @@ -134,6 +138,11 @@ func serialize() -> Dictionary: "user_meta":serialize_meta() } + +func set_selected(state: bool) -> void: + is_selected = state + selected.emit(state) + #func get_fixtures(): #return universe.fixtures # diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 9435bea..072b071 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -9,7 +9,9 @@ signal universe_output_added(universe: Universe, output: DataIOPlugin) ## Emitte signal universe_output_removed(universe: Universe, output_uuid: String) signal universe_added(universe: Universe) -signal universe_removed(universe_uuid: String) +signal universes_removed(universe_uuids: Array[String]) + +signal universe_selection_changed(selected_universes: Array[Universe]) signal fixture_name_changed(fixture: Fixture, new_name) signal fixture_added(fixture: Array[Fixture]) @@ -17,13 +19,14 @@ signal fixture_removed(fixture_uuid: Array[String]) signal fixture_selection_changed(selected_fixtures: Array[Fixture]) signal scene_added(scene: Scene) -signal scene_removed(scene_uuid: String) +signal scenes_removed(scene_uuids: Array) var universes: Dictionary = {} var fixtures_definitions: Dictionary = {} var scenes: Dictionary = {} var selected_fixtures: Array[Fixture] = [] +var selected_universes: Array[Universe] = [] var input_plugins: Dictionary = {} var output_plugins: Dictionary = {} @@ -42,13 +45,13 @@ var _system: System = System.new() func _ready() -> void: programmer.engine = self - OS.set_low_processor_usage_mode(true) reload_io_plugins() reload_fixtures() +#region Save Load func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: var save_file: Dictionary = {} @@ -62,8 +65,10 @@ func load(file_path) -> void: var saved_file = FileAccess.open(file_path, FileAccess.READ) var serialized_data = JSON.parse_string(saved_file.get_as_text()) print(serialized_data) +#endregion +#region Universes func new_universe(name: String = "New Universe", no_signal: bool = false) -> Universe: ## Adds a new universe @@ -115,27 +120,40 @@ func _connect_universe_signals(universe: Universe): ) -func delete_universe(universe: Universe, no_signal: bool = false) -> bool: - ## Deletes a universe +func remove_universe(universe: Universe, no_signal: bool = false) -> bool: + ## Removes a universe if universe in universes.values(): universe.delete() universes.erase(universe.uuid) + selected_universes.erase(universe) var uuid: String = universe.uuid universe.free() if not no_signal: - print("sending signal") - universe_removed.emit(uuid) + universes_removed.emit([uuid]) return true else: return false - + + +func remove_universes(universes_to_remove: Array, no_signal: bool = false) -> void: + ## Removes mutiple universes at once + + var uuids: Array = [] + + for universe: Universe in universes_to_remove: + uuids.append(universe.uuid) + remove_universe(universe, true) + + if not no_signal: + universes_removed.emit(uuids) + func serialize_universes() -> Dictionary: ## Serializes all universes and returnes them in a dictionary @@ -148,17 +166,40 @@ func serialize_universes() -> Dictionary: return serialized_universes -func serialize_scenes() -> Dictionary: - ## Serializes all scenes and returnes them in a dictionary +func select_universes(universes_to_select: Array, no_signal: bool = false) -> void: + ## Selects all the fixtures passed to this function - var serialized_scenes: Dictionary = {} + for universe: Universe in universes_to_select: + if universe not in selected_universes: + selected_universes.append(universe) + universe.set_selected(true) - for scene: Scene in scenes.values(): - serialized_scenes[scene.uuid] = scene.serialize() + if not no_signal: + universe_selection_changed.emit(selected_universes) + + +func set_universe_selection(universes_to_select: Array) -> void: + ## Changes the selection to be the fixtures passed to this function - return serialized_scenes + deselect_universes(selected_universes, true) + select_universes(universes_to_select) + +func deselect_universes(universes_to_deselect: Array, no_signal: bool = false) -> void: + ## Selects all the fixtures passed to this function + + for universe: Universe in universes_to_deselect: + if universe in selected_universes: + selected_universes.erase(universe) + universe.set_selected(true) + + if not no_signal: + universe_selection_changed.emit(selected_universes) +#endregion + + +#region IO func reload_io_plugins() -> void: ## Loads all output plugins from the folder @@ -177,6 +218,10 @@ func reload_io_plugins() -> void: output_plugins[plugin_name] = {"plugin":uninitialized_plugin, "file_name":plugin} initialized_plugin.free() +#endregion + + +#region Fixtures func reload_fixtures() -> void: @@ -201,28 +246,25 @@ func reload_fixtures() -> void: fixtures_definitions[manifest.info.brand] = {manifest.info.name:manifest} -func select_fixtures(fixtures: Array[Fixture]) -> void: - ## Selects all the fixtures pass to this function +func select_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> void: + ## Selects all the fixtures passed to this function for fixture: Fixture in fixtures: if fixture not in selected_fixtures: selected_fixtures.append(fixture) fixture.set_selected(true) - fixture_selection_changed.emit(selected_fixtures) + if not no_signal: + fixture_selection_changed.emit(selected_fixtures) func set_fixture_selection(fixtures: Array[Fixture]) -> void: ## Changes the selection to be the fixtures passed to this function - for fixture: Fixture in selected_fixtures: - fixture.set_selected(false) - - selected_fixtures = [] - + deselect_fixtures(selected_fixtures, true) select_fixtures(fixtures) -func deselect_fixtures(fixtures: Array[Fixture]) -> void: +func deselect_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> void: ## Deselects all the fixtures pass to this function for fixture: Fixture in fixtures: @@ -230,8 +272,12 @@ func deselect_fixtures(fixtures: Array[Fixture]) -> void: selected_fixtures.erase(fixture) fixture.set_selected(false) - fixture_selection_changed.emit(selected_fixtures) + if not no_signal: + fixture_selection_changed.emit(selected_fixtures) +#endregion + +#region Scenes func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: ## Adds a scene to this engine, creats a new one if none is passed @@ -245,18 +291,35 @@ func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: return scene -func remove_scene(scene: Scene, no_signal: bool = false) -> void: +func remove_scenes(scenes_to_remove: Array, no_signal: bool = false) -> void: ## Removes a scene from this engine - var uuid: String = scene.uuid + var uuids: Array = [] - scenes.erase(uuid) - scene.delete() - scene.free() + for scene: Scene in scenes_to_remove: + uuids.append(scene.uuid) + scenes.erase(scene.uuid) + + scene.delete() + scene.free() if not no_signal: - scene_removed.emit(uuid) + scenes_removed.emit(uuids) + + +func serialize_scenes() -> Dictionary: + ## Serializes all scenes and returnes them in a dictionary + + var serialized_scenes: Dictionary = {} + + for scene: Scene in scenes.values(): + serialized_scenes[scene.uuid] = scene.serialize() + + return serialized_scenes + + +#endregion func animate(function: Callable, from: Variant, to: Variant, duration: int) -> void: From bd066b26be1a234b20aaeffa0179fe45619be977 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Thu, 4 Apr 2024 23:12:05 +1300 Subject: [PATCH 09/20] Updated engine signals, and updated universes --- Components/ItemListView/ItemListView.gd | 15 +++++- Components/ItemListView/ItemListView.tscn | 1 + Main.tscn | 13 ++++-- Panels/Functions/Functions.tscn | 25 ++-------- Panels/IO Controls/IOControls.gd | 52 +++++++++++++++++++++ Panels/IO Controls/IOControls.tscn | 25 ++++++++++ Panels/Patch Bay/Patch_bay.gd | 2 +- Panels/Universes/Universes.gd | 2 +- Panels/Universes/Universes.tscn | 4 +- Panels/Virtual Fixtures/Virtual_fixtures.gd | 9 +++- core/components/EngineComponent.gd | 10 ++++ core/components/Fixture.gd | 10 +--- core/components/Universe.gd | 49 +++++++++++-------- core/engine/Engine.gd | 24 +++------- 14 files changed, 164 insertions(+), 77 deletions(-) create mode 100644 Panels/IO Controls/IOControls.gd create mode 100644 Panels/IO Controls/IOControls.tscn diff --git a/Components/ItemListView/ItemListView.gd b/Components/ItemListView/ItemListView.gd index 698c1a2..cc3f4eb 100644 --- a/Components/ItemListView/ItemListView.gd +++ b/Components/ItemListView/ItemListView.gd @@ -20,6 +20,7 @@ signal selection_changed(items: Array) @export var show_delete: bool = true : set = set_show_delete @export var show_separators: bool = true : set = set_show_separators +@export var buttons_enabled: bool = true : set = set_buttons_enabled @export var allow_multi_select: bool = true @onready var item_container: VBoxContainer = self.get_node("PanelContainer2/ScrollContainer/ItemContainer") @@ -96,11 +97,11 @@ func _update_selected() -> void: for item: Control in currently_selected_items: item.set_highlighted(true) - selection_changed.emit(currently_selected_items) + selection_changed.emit(get_objects_from_nodes(currently_selected_items)) func get_objects_from_nodes(items: Array) -> Array: - ## Converts a list of list Item nodes into three objects they are representing + ## Converts a list of list Item nodes into the objects they are representing var object_list: Array = [] @@ -109,6 +110,16 @@ func get_objects_from_nodes(items: Array) -> Array: return object_list + +func set_buttons_enabled(state: bool): + + buttons_enabled = state + + for node: Node in $ToolBarContainer/HBoxContainer.get_children(): + if node is Button: + node.disabled = not buttons_enabled + + #region Button Callbacks func _on_new_pressed() -> void: diff --git a/Components/ItemListView/ItemListView.tscn b/Components/ItemListView/ItemListView.tscn index de429a1..7d6c9aa 100644 --- a/Components/ItemListView/ItemListView.tscn +++ b/Components/ItemListView/ItemListView.tscn @@ -20,6 +20,7 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme = ExtResource("1_fhj3g") script = ExtResource("2_xkuya") +buttons_enabled = null [node name="ToolBarContainer" type="PanelContainer" parent="."] layout_mode = 2 diff --git a/Main.tscn b/Main.tscn index 7d8efd0..11b142d 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=22 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] +[ext_resource type="PackedScene" uid="uid://cim02rtl7kfpc" path="res://Panels/IO Controls/IOControls.tscn" id="3_k6wx5"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] -[ext_resource type="Script" path="res://Scripts/Tab_container.gd" id="3_nk5d5"] [ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] [ext_resource type="PackedScene" uid="uid://03t7su6t2rq2" path="res://Panels/Universes/Universes.tscn" id="4_8kgbc"] [ext_resource type="PackedScene" uid="uid://cedqo06n6en8u" path="res://Panels/Functions/Functions.tscn" id="4_35sxj"] @@ -99,12 +99,17 @@ grow_horizontal = 2 grow_vertical = 2 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true -script = ExtResource("3_nk5d5") -[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] +[node name="Universes" type="HSplitContainer" parent="TabContainer"] +layout_mode = 2 + +[node name="Universes" parent="TabContainer/Universes" instance=ExtResource("4_8kgbc")] layout_mode = 2 -[node name="Universes" parent="TabContainer" instance=ExtResource("4_8kgbc")] +[node name="IO Controls" parent="TabContainer/Universes" instance=ExtResource("3_k6wx5")] +layout_mode = 2 + +[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] visible = false layout_mode = 2 diff --git a/Panels/Functions/Functions.tscn b/Panels/Functions/Functions.tscn index fd31c43..2a090b4 100644 --- a/Panels/Functions/Functions.tscn +++ b/Panels/Functions/Functions.tscn @@ -1,35 +1,20 @@ -[gd_scene load_steps=4 format=3 uid="uid://cedqo06n6en8u"] +[gd_scene load_steps=3 format=3 uid="uid://cedqo06n6en8u"] -[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_un5lg"] [ext_resource type="Script" path="res://Panels/Functions/Functions.gd" id="2_bfwkh"] [ext_resource type="PackedScene" uid="uid://c6smssfk7gn2w" path="res://Components/ItemListView/ItemListView.tscn" id="3_knoqd"] -[node name="Functions" type="Control"] -layout_mode = 3 +[node name="Functions" type="PanelContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -theme = ExtResource("1_un5lg") - -[node name="Functions" type="MarginContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_constants/margin_left = 10 -theme_override_constants/margin_top = 10 -theme_override_constants/margin_right = 10 -theme_override_constants/margin_bottom = 10 script = ExtResource("2_bfwkh") item_list_view = NodePath("ItemListView") -[node name="ItemListView" parent="Functions" instance=ExtResource("3_knoqd")] +[node name="ItemListView" parent="." instance=ExtResource("3_knoqd")] layout_mode = 2 -show_new = false +buttons_enabled = null allow_multi_select = false -[connection signal="delete_requested" from="Functions/ItemListView" to="Functions" method="_on_item_list_view_delete_requested"] +[connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Panels/IO Controls/IOControls.gd b/Panels/IO Controls/IOControls.gd new file mode 100644 index 0000000..cb50516 --- /dev/null +++ b/Panels/IO Controls/IOControls.gd @@ -0,0 +1,52 @@ +# Copyright (c) 2024 Liam Sherwin +# All rights reserved. + +extends Control +## GUI element for managing universe io devices + +@export var item_list_view: NodePath + +var current_universe: Universe + +func _ready() -> void: + Core.universe_selection_changed.connect(self._reload_universes) + +func _reload_universes(selected_universes: Array[Universe] = [current_universe]) -> void: + + ## Check if mutiple universes (or none) are selected, if so dont update the output list, only clear it + if len(selected_universes) == 1: + current_universe = selected_universes[0] + + current_universe.outputs_added.connect(self._reload_io) + current_universe.outputs_removed.connect(self._reload_io) + + self.get_node(item_list_view).buttons_enabled = true + + else: + if current_universe: + current_universe.outputs_added.disconnect(self._reload_io) + current_universe.outputs_removed.disconnect(self._reload_io) + + current_universe = null + self.get_node(item_list_view).buttons_enabled = false + + _reload_io() + +func _reload_io(_io=null) -> void: + ## Reloads the list of io devices + + self.get_node(item_list_view).remove_all() + + if current_universe: + self.get_node(item_list_view).add_items(current_universe.outputs.values()) + + +func _on_item_list_view_delete_requested(items: Array) -> void: + ## Called when the delete button is pressed on the ItemListView + + current_universe.remove_outputs(items) + + +func _on_item_list_view_add_requested() -> void: + current_universe.new_output() + diff --git a/Panels/IO Controls/IOControls.tscn b/Panels/IO Controls/IOControls.tscn new file mode 100644 index 0000000..2910dcd --- /dev/null +++ b/Panels/IO Controls/IOControls.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=4 format=3 uid="uid://cim02rtl7kfpc"] + +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_je60j"] +[ext_resource type="Script" path="res://Panels/IO Controls/IOControls.gd" id="2_mfak0"] +[ext_resource type="PackedScene" uid="uid://c6smssfk7gn2w" path="res://Components/ItemListView/ItemListView.tscn" id="3_rjw7h"] + +[node name="IO Controls" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = ExtResource("1_je60j") +script = ExtResource("2_mfak0") +item_list_view = NodePath("ItemListView") + +[node name="ItemListView" parent="." instance=ExtResource("3_rjw7h")] +layout_mode = 2 +show_take = false +buttons_enabled = false + +[connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] +[connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Panels/Patch Bay/Patch_bay.gd b/Panels/Patch Bay/Patch_bay.gd index df9cbe4..f3a32bb 100644 --- a/Panels/Patch Bay/Patch_bay.gd +++ b/Panels/Patch Bay/Patch_bay.gd @@ -19,7 +19,7 @@ var _current_io: DataIOPlugin func _ready() -> void: Core.universe_added.connect(self._reload_universes) - Core.universe_removed.connect(self._reload_universes) + Core.universes_removed.connect(self._reload_universes) func _new_universe() -> Universe: diff --git a/Panels/Universes/Universes.gd b/Panels/Universes/Universes.gd index 96af881..4119d4d 100644 --- a/Panels/Universes/Universes.gd +++ b/Panels/Universes/Universes.gd @@ -31,5 +31,5 @@ func _on_item_list_view_add_requested() -> void: Core.new_universe() -func _on_item_list_view_take_requested(items: Array) -> void: +func _on_item_list_view_selection_changed(items: Array) -> void: Core.set_universe_selection(items) diff --git a/Panels/Universes/Universes.tscn b/Panels/Universes/Universes.tscn index e940739..834a7de 100644 --- a/Panels/Universes/Universes.tscn +++ b/Panels/Universes/Universes.tscn @@ -18,8 +18,8 @@ item_list_view = NodePath("ItemListView") [node name="ItemListView" parent="." instance=ExtResource("2_nny3h")] layout_mode = 2 -show_edit = false +buttons_enabled = null [connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] -[connection signal="take_requested" from="ItemListView" to="." method="_on_item_list_view_take_requested"] +[connection signal="selection_changed" from="ItemListView" to="." method="_on_item_list_view_selection_changed"] diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 10fc591..72d35ca 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -15,6 +15,8 @@ var _add_fixture_button: Button var _position_offset: Vector2 = Vector2(100, 100) +var last_execution_time = 0 + # Called when the node enters the scene tree for the first time. func _ready() -> void: ## Add extra buttons to GraphEdit menu, and subscribe to global variables @@ -128,7 +130,12 @@ func _on_virtual_fixture_deselected(node) -> void: func _on_color_picker_color_changed(color: Color) -> void: - Core.programmer.set_color(Core.selected_fixtures, color) + var current_time = Time.get_ticks_msec() / 1000.0 + + if current_time - last_execution_time >= Core.min_interval: + Core.programmer.set_color(Core.selected_fixtures, color) + print(color) + last_execution_time = current_time func _on_save_pressed() -> void: diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index 9956273..054868e 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -6,16 +6,26 @@ class_name EngineComponent extends Object signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) ## Emitted when an item is added, edited, or deleted from user_meta, if no value is present it meanes that the key has been deleted signal name_changed(new_name: String) ## Emitted when the name of this object has changed +signal selected(is_selected: bool) var uuid: String = "" ## Uuid of the current component var name: String = "": set = _set_name ## The name of this object, only use when displaying to users, do not use it as a reference var user_meta: Dictionary ## Infomation that can be stored by other scripts +var is_selected: bool = false: set = set_selected + func _init() -> void: uuid = UUID_Util.v4() +func set_selected(state: bool) -> void: + ## Sets the selection state of this component + + is_selected = state + selected.emit(state) + + func set_user_meta(key: String, value: Variant, no_signal: bool = false): ## Sets user_meta from the given value diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 9b94fd5..06e8c0b 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -8,8 +8,6 @@ signal color_changed(color: Color) ## Emitted when the color of this fixture is signal mode_changed(mode: int) ## Emitted when the mode of the fixture is changed signal channel_changed(new_channel: int) ## Emitted when the channel of the fixture is changed -signal selected(selected: bool) - ## Contains metadata infomation about this fixture var meta: Dictionary = { "fixture_brand":"", @@ -25,7 +23,6 @@ var manifest: Dictionary ## Fixture manifest var channels: Array ## Channels this fixture uses, and what they do var channel_ranges: Dictionary ## What happenes at each channel, at each value -var is_selected: bool = false ## Contains all the parameters inputted by other function in spectrum, ie scenes, programmer, ect. ## Each input it added to this dict with a id for each item, allowing for HTP and LTP calculations @@ -118,9 +115,4 @@ func _add_current_input_data(id: String, key: String, value: Variant) -> void: func _remove_current_input_data(id: String, key: String) -> void: current_input_data.get("id", {}).erase(key) if not current_input_data.get("id", false): - current_input_data.erase(id) - - -func set_selected(state: bool) -> void: - is_selected = state - selected.emit(state) + current_input_data.erase(id) diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 8d0609d..0f002fe 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -5,23 +5,21 @@ class_name Universe extends EngineComponent ## Enngie class for handling universes, and there outputs signal fixture_name_changed(fixture: Fixture, new_name: String) -signal fixture_added(fixtures: Array[Fixture]) -signal fixture_deleted(fixture_uuids: Array[String]) +signal fixtures_added(fixtures: Array[Fixture]) +signal fixtures_deleted(fixture_uuids: Array[String]) -signal output_added(output: DataIOPlugin) -signal output_removed(output_uuid: String) - -signal selected(is_selected: bool) +signal outputs_added(outputs: Array[DataIOPlugin]) +signal outputs_removed(output_uuids: Array[String]) var fixtures: Dictionary = {} ## Dictionary containing all the fixtures in this universe var outputs: Dictionary = {} ## Dictionary containing all the outputs in this universe var dmx_data: Dictionary = {} -var is_selected: bool = false - var engine: CoreEngine ## The CoreEngine class this universe belongs to +var _last_execution_time: int = 0 + func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: ## Adds a new output of type to this universe @@ -31,7 +29,7 @@ func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: outputs[new_output.uuid] = new_output if not no_signal: - output_added.emit(new_output) + outputs_added.emit([new_output]) return new_output @@ -46,7 +44,20 @@ func remove_output(output: DataIOPlugin, no_signal: bool = false) -> void: output.free() if not no_signal: - output_removed.emit(uuid) + outputs_removed.emit([uuid]) + + +func remove_outputs(outputs_to_remove: Array, no_signal: bool = false): + ## Remove more than one output at once + + var uuids: Array[String] = [] + + for output: DataIOPlugin in outputs_to_remove: + uuids.append(output.uuid) + remove_output(output, true) + + if not no_signal: + outputs_removed.emit(uuids) func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int = 1, offset:int = 0, no_signal: bool = false): @@ -72,7 +83,7 @@ func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int just_added_fixtures.append(new_fixture) if not no_signal: - fixture_added.emit(just_added_fixtures) + fixtures_added.emit(just_added_fixtures) func remove_fixture(fixture: Fixture, no_signal: bool = false): @@ -89,7 +100,7 @@ func remove_fixture(fixture: Fixture, no_signal: bool = false): if not no_signal: var uuids: Array[String] = [fixture_uuid] - fixture_deleted.emit(uuids) + fixtures_deleted.emit(uuids) func is_channel_used(channels: Array) -> bool: @@ -111,11 +122,14 @@ func set_data(data: Dictionary): func _compile_and_send(): - ## Will compile all dmx data in a future version, currently just sends dmx data - var compiled_dmx_data = dmx_data + var current_time = Time.get_ticks_msec() / 1000.0 - for output: DataIOPlugin in outputs.values(): - output.send_packet(compiled_dmx_data) + if current_time - _last_execution_time >= engine.min_interval: + var compiled_dmx_data: Dictionary = dmx_data + for output in outputs.values(): + output.send_packet(compiled_dmx_data) + + _last_execution_time = current_time func serialize() -> Dictionary: @@ -139,9 +153,6 @@ func serialize() -> Dictionary: } -func set_selected(state: bool) -> void: - is_selected = state - selected.emit(state) #func get_fixtures(): #return universe.fixtures diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 072b071..c1eb170 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -5,12 +5,8 @@ class_name CoreEngine extends Node ## The core engine that powers Spectrum signal universe_name_changed(universe: Universe, new_name: String) ## Emitted when any of the universes in this engine have there name changed -signal universe_output_added(universe: Universe, output: DataIOPlugin) ## Emitted when of the universes -signal universe_output_removed(universe: Universe, output_uuid: String) - signal universe_added(universe: Universe) signal universes_removed(universe_uuids: Array[String]) - signal universe_selection_changed(selected_universes: Array[Universe]) signal fixture_name_changed(fixture: Fixture, new_name) @@ -40,8 +36,10 @@ var current_file_path: String = "" var programmer = Programmer.new() -var _system: System = System.new() +var frequency = 45.0 +var min_interval = 1.0 / frequency +var _system: System = System.new() func _ready() -> void: programmer.engine = self @@ -94,27 +92,17 @@ func _connect_universe_signals(universe: Universe): universe_name_changed.emit(universe, new_name) ) - universe.output_added.connect( - func(output: DataIOPlugin): - universe_output_added.emit(universe, output) - ) - - universe.output_removed.connect( - func(output_uuid: String): - universe_output_removed.emit(universe, output_uuid) - ) - universe.fixture_name_changed.connect( func(fixture: Fixture, new_name: String): fixture_name_changed.emit(fixture, new_name) ) - universe.fixture_added.connect( + universe.fixtures_added.connect( func(fixtures: Array[Fixture]): fixture_added.emit(fixtures) ) - universe.fixture_deleted.connect( + universe.fixtures_deleted.connect( func(fixture_uuids: Array[String]): fixture_removed.emit(fixture_uuids) ) @@ -179,7 +167,7 @@ func select_universes(universes_to_select: Array, no_signal: bool = false) -> vo func set_universe_selection(universes_to_select: Array) -> void: - ## Changes the selection to be the fixtures passed to this function + ## Changes the selection to be the universes passed to this function deselect_universes(selected_universes, true) select_universes(universes_to_select) From a38ea857b57bbb26b0462b81d1eb293cea314fb0 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 17:02:33 +1200 Subject: [PATCH 10/20] Fixed issues with IO Creation --- Components/File Load Menu/FileLoadMenu.gd | 6 +- Components/File Load Menu/FileLoadMenu.tscn | 13 +- Components/File Save Menu/FileSaveMenu.gd | 4 + Components/File Save Menu/FileSaveMenu.tscn | 18 +++ Components/ItemListView/ItemListView.gd | 118 +++++++++++------- Components/ItemListView/ItemListView.tscn | 1 - Components/List Item/List_item.tscn | 2 +- Panels/Functions/Functions.tscn | 1 - Panels/IO Controls/IOControls.gd | 16 ++- Panels/IO Controls/IOControls.tscn | 1 + Panels/Universes/Universes.gd | 10 +- Panels/Universes/Universes.tscn | 1 - Scripts/Global.gd | 3 +- Scripts/Menu_buttons.gd | 11 +- core/components/Fixture.gd | 2 +- core/engine/Engine.gd | 9 +- .../io_plugins/output_plugins/ArtNetOutput.gd | 4 +- 17 files changed, 149 insertions(+), 71 deletions(-) create mode 100644 Components/File Save Menu/FileSaveMenu.gd create mode 100644 Components/File Save Menu/FileSaveMenu.tscn diff --git a/Components/File Load Menu/FileLoadMenu.gd b/Components/File Load Menu/FileLoadMenu.gd index 1a6fc89..3db950a 100644 --- a/Components/File Load Menu/FileLoadMenu.gd +++ b/Components/File Load Menu/FileLoadMenu.gd @@ -1,8 +1,4 @@ extends FileDialog -func _on_confirmed() -> void: - self.queue_free() - - -func _on_close_requested() -> void: +func _any_close_signal() -> void: self.queue_free() diff --git a/Components/File Load Menu/FileLoadMenu.tscn b/Components/File Load Menu/FileLoadMenu.tscn index 3caa06d..c88df0a 100644 --- a/Components/File Load Menu/FileLoadMenu.tscn +++ b/Components/File Load Menu/FileLoadMenu.tscn @@ -1,17 +1,20 @@ -[gd_scene load_steps=2 format=3 uid="uid://djm2s80n0ci54"] +[gd_scene load_steps=3 format=3 uid="uid://djm2s80n0ci54"] [ext_resource type="Script" path="res://Components/File Load Menu/FileLoadMenu.gd" id="1_bjt7g"] +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_ulnoa"] [node name="FileLoadMenu" type="FileDialog"] title = "Open a File" -position = Vector2i(0, 36) -size = Vector2i(582, 449) +initial_position = 5 +size = Vector2i(778, 449) visible = true +theme = ExtResource("1_ulnoa") ok_button_text = "Open" file_mode = 0 access = 2 use_native_dialog = true script = ExtResource("1_bjt7g") -[connection signal="close_requested" from="." to="." method="_on_close_requested"] -[connection signal="confirmed" from="." to="." method="_on_confirmed"] +[connection signal="canceled" from="." to="." method="_any_close_signal"] +[connection signal="close_requested" from="." to="." method="_any_close_signal"] +[connection signal="confirmed" from="." to="." method="_any_close_signal"] diff --git a/Components/File Save Menu/FileSaveMenu.gd b/Components/File Save Menu/FileSaveMenu.gd new file mode 100644 index 0000000..3db950a --- /dev/null +++ b/Components/File Save Menu/FileSaveMenu.gd @@ -0,0 +1,4 @@ +extends FileDialog + +func _any_close_signal() -> void: + self.queue_free() diff --git a/Components/File Save Menu/FileSaveMenu.tscn b/Components/File Save Menu/FileSaveMenu.tscn new file mode 100644 index 0000000..c6d7792 --- /dev/null +++ b/Components/File Save Menu/FileSaveMenu.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=3 format=3 uid="uid://cfgsds74efvse"] + +[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_56t30"] +[ext_resource type="Script" path="res://Components/File Save Menu/FileSaveMenu.gd" id="1_st57w"] + +[node name="FileSaveMenu" type="FileDialog"] +initial_position = 5 +size = Vector2i(903, 449) +visible = true +theme = ExtResource("1_56t30") +ok_button_text = "Save" +access = 2 +use_native_dialog = true +script = ExtResource("1_st57w") + +[connection signal="canceled" from="." to="." method="_any_close_signal"] +[connection signal="close_requested" from="." to="." method="_any_close_signal"] +[connection signal="confirmed" from="." to="." method="_any_close_signal"] diff --git a/Components/ItemListView/ItemListView.gd b/Components/ItemListView/ItemListView.gd index cc3f4eb..47949c4 100644 --- a/Components/ItemListView/ItemListView.gd +++ b/Components/ItemListView/ItemListView.gd @@ -45,13 +45,17 @@ func add_items(items: Array) -> void: ## Adds an item to the list for item in items: - if "uuid" in item and "name" in item: + if _is_valid_object(item): var new_item_node: Control = Globals.components.list_item.instantiate() new_item_node.set_item_name(item.name) new_item_node.control_node = self new_item_node.name = item.uuid - new_item_node.select_requested.connect(self.on_list_item_select_request) + new_item_node.select_requested.connect(self._on_list_item_select_request) + + if item.get("is_selected") == true: + new_item_node.set_highlighted(item.is_selected) + currently_selected_items.append(item) item_container.add_child(new_item_node) object_refs[new_item_node] = item @@ -60,12 +64,52 @@ func add_items(items: Array) -> void: func remove_all() -> void: ## Removes all items from the list + object_refs = {} + last_selected_item = null + currently_selected_items = [] + for item in item_container.get_children(): item_container.remove_child(item) item.queue_free() -func on_list_item_select_request(selected_item: Control) -> void: +func get_objects_from_nodes(items: Array) -> Array: + ## Converts a list of list Item nodes into the objects they are representing + + var object_list: Array = [] + + for item in items: + object_list.append(object_refs[item]) + + return object_list + + +func set_buttons_enabled(state: bool): + + buttons_enabled = state + + for node: Node in $ToolBarContainer/HBoxContainer.get_children(): + if node is Button: + node.disabled = not buttons_enabled + + +func set_selected(items: Array) -> void: + ## Sets the selected list items + + currently_selected_items = [] + + for item in items: + if _is_valid_object(item): + if item_container.has_node(item.uuid): + currently_selected_items.append(item) + + if currently_selected_items and not last_selected_item: + last_selected_item = item_container.get_node(currently_selected_items[-1].uuid) + + _update_selected() + + +func _on_list_item_select_request(selected_item: Control) -> void: if Input.is_key_pressed(KEY_SHIFT) and last_selected_item and allow_multi_select: var children: Array[Node] = item_container.get_children() var pos_1: int = children.find(last_selected_item) @@ -81,43 +125,29 @@ func on_list_item_select_request(selected_item: Control) -> void: for i in range(pos_1, pos_2+1): items_to_select.append(children[i]) - currently_selected_items = items_to_select + selection_changed.emit(get_objects_from_nodes(items_to_select)) else: last_selected_item = selected_item - currently_selected_items = [selected_item] - - _update_selected() + selection_changed.emit(get_objects_from_nodes([selected_item])) -func _update_selected() -> void: + +func _update_selected(no_signal: bool = false) -> void: for item: Control in item_container.get_children(): item.set_highlighted(false) - for item: Control in currently_selected_items: - item.set_highlighted(true) - - selection_changed.emit(get_objects_from_nodes(currently_selected_items)) - - -func get_objects_from_nodes(items: Array) -> Array: - ## Converts a list of list Item nodes into the objects they are representing - - var object_list: Array = [] - - for item in items: - object_list.append(object_refs[item]) - - return object_list + for item: Object in currently_selected_items: + item_container.get_node(item.uuid).set_highlighted(true) -func set_buttons_enabled(state: bool): - - buttons_enabled = state +func _is_valid_object(object: Variant) -> bool: + ## Checks if an object is valid for use in an item list, object must have a uuid and name - for node: Node in $ToolBarContainer/HBoxContainer.get_children(): - if node is Button: - node.disabled = not buttons_enabled + if object is Object and "uuid" in object and "name" in object: + return true + else: + return false #region Button Callbacks @@ -127,35 +157,39 @@ func _on_new_pressed() -> void: func _on_select_all_pressed() -> void: - currently_selected_items = item_container.get_children() - _update_selected() + if object_refs: + print("_on_select_all_pressed") + selection_changed.emit(get_objects_from_nodes( item_container.get_children())) func _on_select_none_pressed() -> void: - currently_selected_items = [] - _update_selected() + if object_refs: + selection_changed.emit([]) func _on_select_invert_pressed() -> void: - var all_items: Array = item_container.get_children() - - for item: Control in currently_selected_items: - all_items.erase(item) + if object_refs: + var all_items: Array = object_refs.values() - currently_selected_items = all_items - _update_selected() + for item: Object in currently_selected_items: + all_items.erase(item) + + selection_changed.emit(all_items) func _on_take_selection_pressed() -> void: - take_requested.emit(get_objects_from_nodes(currently_selected_items)) + if currently_selected_items: + take_requested.emit(currently_selected_items) func _on_edit_pressed() -> void: - edit_requested.emit(get_objects_from_nodes(currently_selected_items)) + if currently_selected_items: + edit_requested.emit(currently_selected_items) func _on_delete_pressed() -> void: - delete_requested.emit(get_objects_from_nodes(currently_selected_items)) + if currently_selected_items: + delete_requested.emit(currently_selected_items) #endregion diff --git a/Components/ItemListView/ItemListView.tscn b/Components/ItemListView/ItemListView.tscn index 7d6c9aa..de429a1 100644 --- a/Components/ItemListView/ItemListView.tscn +++ b/Components/ItemListView/ItemListView.tscn @@ -20,7 +20,6 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme = ExtResource("1_fhj3g") script = ExtResource("2_xkuya") -buttons_enabled = null [node name="ToolBarContainer" type="PanelContainer" parent="."] layout_mode = 2 diff --git a/Components/List Item/List_item.tscn b/Components/List Item/List_item.tscn index a7f751f..7923037 100644 --- a/Components/List Item/List_item.tscn +++ b/Components/List Item/List_item.tscn @@ -8,7 +8,7 @@ content_margin_top = 5.0 content_margin_right = 5.0 content_margin_bottom = 5.0 bg_color = Color(0.0862745, 0.0862745, 0.0862745, 0.466667) -border_width_left = 10 +border_width_left = 5 border_color = Color(1, 1, 1, 1) corner_radius_top_left = 5 corner_radius_top_right = 5 diff --git a/Panels/Functions/Functions.tscn b/Panels/Functions/Functions.tscn index 2a090b4..8e8cd4c 100644 --- a/Panels/Functions/Functions.tscn +++ b/Panels/Functions/Functions.tscn @@ -14,7 +14,6 @@ item_list_view = NodePath("ItemListView") [node name="ItemListView" parent="." instance=ExtResource("3_knoqd")] layout_mode = 2 -buttons_enabled = null allow_multi_select = false [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Panels/IO Controls/IOControls.gd b/Panels/IO Controls/IOControls.gd index cb50516..906ae77 100644 --- a/Panels/IO Controls/IOControls.gd +++ b/Panels/IO Controls/IOControls.gd @@ -15,6 +15,10 @@ func _reload_universes(selected_universes: Array[Universe] = [current_universe]) ## Check if mutiple universes (or none) are selected, if so dont update the output list, only clear it if len(selected_universes) == 1: + + if current_universe: + _dissconnect() + current_universe = selected_universes[0] current_universe.outputs_added.connect(self._reload_io) @@ -24,14 +28,19 @@ func _reload_universes(selected_universes: Array[Universe] = [current_universe]) else: if current_universe: - current_universe.outputs_added.disconnect(self._reload_io) - current_universe.outputs_removed.disconnect(self._reload_io) + _dissconnect() current_universe = null self.get_node(item_list_view).buttons_enabled = false _reload_io() + +func _dissconnect() -> void: + current_universe.outputs_added.disconnect(self._reload_io) + current_universe.outputs_removed.disconnect(self._reload_io) + + func _reload_io(_io=null) -> void: ## Reloads the list of io devices @@ -50,3 +59,6 @@ func _on_item_list_view_delete_requested(items: Array) -> void: func _on_item_list_view_add_requested() -> void: current_universe.new_output() + +func _on_item_list_view_selection_changed(items: Array) -> void: + self.get_node(item_list_view).set_selected(items) diff --git a/Panels/IO Controls/IOControls.tscn b/Panels/IO Controls/IOControls.tscn index 2910dcd..cd86324 100644 --- a/Panels/IO Controls/IOControls.tscn +++ b/Panels/IO Controls/IOControls.tscn @@ -23,3 +23,4 @@ buttons_enabled = false [connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] +[connection signal="selection_changed" from="ItemListView" to="." method="_on_item_list_view_selection_changed"] diff --git a/Panels/Universes/Universes.gd b/Panels/Universes/Universes.gd index 4119d4d..3a4c004 100644 --- a/Panels/Universes/Universes.gd +++ b/Panels/Universes/Universes.gd @@ -8,9 +8,11 @@ extends Control func _ready() -> void: + print(item_list_view) Core.universe_added.connect(self._reload_universes) Core.universes_removed.connect(self._reload_universes) Core.universe_name_changed.connect(self._reload_universes) + Core.universe_selection_changed.connect(self._universe_selection_changed) func _reload_universes(_scene=null) -> void: @@ -18,14 +20,16 @@ func _reload_universes(_scene=null) -> void: self.get_node(item_list_view).remove_all() self.get_node(item_list_view).add_items(Core.universes.values()) - +func _universe_selection_changed(selected_universes: Array) -> void: + self.get_node(item_list_view).set_selected(selected_universes) + + func _on_item_list_view_delete_requested(items: Array) -> void: ## Called when the delete button is pressed on the ItemListView - Core.remove_universes(items) - + func _on_item_list_view_add_requested() -> void: Core.new_universe() diff --git a/Panels/Universes/Universes.tscn b/Panels/Universes/Universes.tscn index 834a7de..eb182e1 100644 --- a/Panels/Universes/Universes.tscn +++ b/Panels/Universes/Universes.tscn @@ -18,7 +18,6 @@ item_list_view = NodePath("ItemListView") [node name="ItemListView" parent="." instance=ExtResource("2_nny3h")] layout_mode = 2 -buttons_enabled = null [connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Scripts/Global.gd b/Scripts/Global.gd index fb515a6..4c41b00 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -35,7 +35,8 @@ var output_plugins : Dictionary "virtual_fixture":ResourceLoader.load("res://Components/Virtual Fixture/Virtual_fixture.tscn"), "window":ResourceLoader.load("res://Components/Window/Window.tscn"), "trigger_button":ResourceLoader.load("res://Components/Trigger Button/TriggerButton.tscn"), - "file_load_menu": ResourceLoader.load("res://Components/File Load Menu/FileLoadMenu.tscn") + "file_load_menu": ResourceLoader.load("res://Components/File Load Menu/FileLoadMenu.tscn"), + "file_save_menu": ResourceLoader.load("res://Components/File Save Menu/FileSaveMenu.tscn") } @onready var panels : Dictionary = { diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index 1e86bbd..8290052 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -1,7 +1,16 @@ extends HBoxContainer func _on_save_pressed() -> void: - print(Core.save("Debug_show.spsave", OS.get_environment("HOME"))) + + var menu: FileDialog = Globals.components.file_save_menu.instantiate() + + menu.confirmed.connect( + func(): + print(Core.save(menu.current_file, menu.current_dir)) + ) + + get_tree().root.add_child(menu) + func _on_load_pressed() -> void: diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 06e8c0b..1434f31 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -71,7 +71,7 @@ func serialize() -> Dictionary: func recompile_data() -> void: ## Compiles dmx data from this fixture - var highest_valued_data: Dictionary + var highest_valued_data: Dictionary = {} for input_data_id in current_input_data: for input_data in current_input_data[input_data_id]: diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index c1eb170..a08f768 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -39,8 +39,6 @@ var programmer = Programmer.new() var frequency = 45.0 var min_interval = 1.0 / frequency -var _system: System = System.new() - func _ready() -> void: programmer.engine = self @@ -137,6 +135,7 @@ func remove_universes(universes_to_remove: Array, no_signal: bool = false) -> vo for universe: Universe in universes_to_remove: uuids.append(universe.uuid) + deselect_universes([universe], no_signal) remove_universe(universe, true) if not no_signal: @@ -168,7 +167,7 @@ func select_universes(universes_to_select: Array, no_signal: bool = false) -> vo func set_universe_selection(universes_to_select: Array) -> void: ## Changes the selection to be the universes passed to this function - + deselect_universes(selected_universes, true) select_universes(universes_to_select) @@ -176,10 +175,10 @@ func set_universe_selection(universes_to_select: Array) -> void: func deselect_universes(universes_to_deselect: Array, no_signal: bool = false) -> void: ## Selects all the fixtures passed to this function - for universe: Universe in universes_to_deselect: + for universe: Universe in universes_to_deselect.duplicate(): if universe in selected_universes: selected_universes.erase(universe) - universe.set_selected(true) + universe.set_selected(false) if not no_signal: universe_selection_changed.emit(selected_universes) diff --git a/core/io_plugins/output_plugins/ArtNetOutput.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd index 686da59..0e19124 100644 --- a/core/io_plugins/output_plugins/ArtNetOutput.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -14,7 +14,7 @@ var exposed_values = [ "signal":"text_submitted", "function":self.set_ip_addr, "parameters":{ - "placeholder_text":"172.0.0.1", + "placeholder_text":"127.0.0.1", "text":self.get_ip_addr } }, @@ -42,7 +42,7 @@ var exposed_values = [ ] var config = { - "ip":"172.0.0.1", + "ip":"127.0.0.1", "port":6454, "universe":0, "file_name":"" From a4f7cba312d5107c76d3147bedffc34d9eb4a2fb Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 20:06:52 +1200 Subject: [PATCH 11/20] Fixed file loading --- Panels/Functions/Functions.gd | 2 +- Panels/Playback Buttons/PlaybackButtons.gd | 2 +- Scripts/Menu_buttons.gd | 5 ++ core/components/EngineComponent.gd | 4 +- core/components/Fixture.gd | 3 ++ core/components/Scene.gd | 28 ++++++++++ core/components/Universe.gd | 52 +++++++++++++++++-- core/engine/Engine.gd | 49 ++++++++++++++--- core/engine/Utils.gd | 14 ++++- .../{desk-channel.json => dimmer.json} | 0 core/io_plugins/DataIOPlugin.gd | 1 - .../io_plugins/output_plugins/ArtNetOutput.gd | 25 ++++----- 12 files changed, 156 insertions(+), 29 deletions(-) rename core/fixtures/generic/{desk-channel.json => dimmer.json} (100%) diff --git a/Panels/Functions/Functions.gd b/Panels/Functions/Functions.gd index 653c7ac..b692816 100644 --- a/Panels/Functions/Functions.gd +++ b/Panels/Functions/Functions.gd @@ -8,7 +8,7 @@ extends Control func _ready() -> void: - Core.scene_added.connect(self._reload_functions) + Core.scenes_added.connect(self._reload_functions) Core.scenes_removed.connect(self._reload_functions) diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index 09fdd99..e45782b 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -5,7 +5,7 @@ extends Control ## Temp ui panel for triggering scenes func _ready() -> void: - Core.scene_added.connect(self._reload_buttons) + Core.scenes_added.connect(self._reload_buttons) Core.scenes_removed.connect(self._reload_buttons) diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index 8290052..3a12f68 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -1,5 +1,10 @@ extends HBoxContainer + +func _ready(): + Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") + + func _on_save_pressed() -> void: var menu: FileDialog = Globals.components.file_save_menu.instantiate() diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index 054868e..243a110 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -16,7 +16,9 @@ var is_selected: bool = false: set = set_selected func _init() -> void: - uuid = UUID_Util.v4() + + if not uuid: + uuid = UUID_Util.v4() func set_selected(state: bool) -> void: diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 1434f31..b6b69e8 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -49,6 +49,9 @@ func _init(i: Dictionary = {}) -> void: meta.fixture_brand = i.manifest.info.brand meta.fixture_name = i.manifest.info.name + if "uuid" in i: + self.uuid = i.uuid + self.name_changed.connect( func(new_name: String): universe.fixture_name_changed.emit(self, new_name) diff --git a/core/components/Scene.gd b/core/components/Scene.gd index 5564887..ed5dd75 100644 --- a/core/components/Scene.gd +++ b/core/components/Scene.gd @@ -39,6 +39,16 @@ func serialize() -> Dictionary: } +func load_from(serialized_data: Dictionary) -> void: + + self.name = serialized_data.get("name", "") + + fade_in_speed = serialized_data.get("fade_in_speed", fade_in_speed) + fade_out_speed = serialized_data.get("fade_out_speed", fade_out_speed) + + save_data = deserialize_save_data(serialized_data.get("save_data", {})) + + func serialize_save_data() -> Dictionary: ## Serializes save_data and returnes as a dictionary @@ -50,3 +60,21 @@ func serialize_save_data() -> Dictionary: serialized_save_data[fixture.uuid][save_key] = Utils.serialize_variant(save_data[fixture][save_key]) return serialized_save_data + + +func deserialize_save_data(serialized_data: Dictionary) -> Dictionary: + ## Deserializes save_data and returnes as a dictionary + + var deserialized_save_data: Dictionary = {} + + for fixture_uuid: String in serialized_data: + var fixture_save: Dictionary = serialized_data[fixture_uuid] + + var deserialized_fixture_save = {} + + for saved_property: String in fixture_save: + deserialized_fixture_save[saved_property] = Utils.deserialize_variant(fixture_save[saved_property]) + + deserialized_save_data[engine.fixtures[fixture_uuid]] = deserialized_fixture_save + + return deserialized_save_data diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 0f002fe..4a22dd0 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -25,7 +25,6 @@ func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: var new_output: DataIOPlugin = type.new() - new_output.file_name = engine.output_plugins[new_output.meta.name].file_name outputs[new_output.uuid] = new_output if not no_signal: @@ -60,7 +59,7 @@ func remove_outputs(outputs_to_remove: Array, no_signal: bool = false): outputs_removed.emit(uuids) -func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int = 1, offset:int = 0, no_signal: bool = false): +func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int = 1, offset:int = 0, uuid: String = "", no_signal: bool = false) -> bool: ## Adds a new fixture to this universe, if the channels are already in use false it returned if is_channel_used(range(channel, len(manifest.modes.values()[mode].channels))): @@ -78,13 +77,16 @@ func new_fixture(manifest: Dictionary, mode:int, channel: int = -1, quantity:int "mode": mode, "manifest": manifest }) + fixtures[channel_index] = new_fixture + engine.fixtures[new_fixture.uuid] = new_fixture just_added_fixtures.append(new_fixture) if not no_signal: fixtures_added.emit(just_added_fixtures) - + + return true func remove_fixture(fixture: Fixture, no_signal: bool = false): ## Removes a fixture from this universe @@ -95,6 +97,7 @@ func remove_fixture(fixture: Fixture, no_signal: bool = false): engine.deselect_fixtures([fixture]) fixtures.erase(fixture.channel) + engine.fixtures.erase(fixture.uuid) fixture.delete() fixture.free() @@ -153,6 +156,49 @@ func serialize() -> Dictionary: } +func load_from(serialised_data: Dictionary) -> void: + ## Loads this universe from a serialised universe + + self.name = serialised_data.get("name", "") + + fixtures = {} + outputs = {} + + for fixture_uuid: String in serialised_data.get("fixtures", {}): + var serialised_fixture: Dictionary = serialised_data.fixtures[fixture_uuid] + + var fixture_brand: String = serialised_fixture.get("meta", {}).get("fixture_brand", "Generic") + var fixture_name: String = serialised_fixture.get("meta", {}).get("fixture_name", "Dimmer") + + var fixture_manifest: Dictionary = Core.fixtures_definitions[fixture_brand][fixture_name] + var channel: int = serialised_fixture.get("channel", 1) + + var new_fixture = Fixture.new({ + "universe": self, + "channel": channel, + "mode": serialised_fixture.get("mode", 0), + "manifest": fixture_manifest, + "uuid": fixture_uuid + }) + + + fixtures[channel] = new_fixture + engine.fixtures[new_fixture.uuid] = new_fixture + + + fixtures_added.emit(fixtures.values()) + + + for output_uuid: String in serialised_data.get("outputs"): + var serialised_output: Dictionary = serialised_data.outputs[output_uuid] + + var new_output: DataIOPlugin = engine.output_plugins[serialised_output.file].plugin.new(serialised_output) + new_output.uuid = output_uuid + + outputs[new_output.uuid] = new_output + + outputs_added.emit(outputs.values()) + #func get_fixtures(): #return universe.fixtures diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index a08f768..05de5b2 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -14,11 +14,12 @@ signal fixture_added(fixture: Array[Fixture]) signal fixture_removed(fixture_uuid: Array[String]) signal fixture_selection_changed(selected_fixtures: Array[Fixture]) -signal scene_added(scene: Scene) +signal scenes_added(scene: Array[Scene]) signal scenes_removed(scene_uuids: Array) var universes: Dictionary = {} +var fixtures: Dictionary = {} var fixtures_definitions: Dictionary = {} var scenes: Dictionary = {} var selected_fixtures: Array[Fixture] = [] @@ -47,6 +48,7 @@ func _ready() -> void: reload_fixtures() + #region Save Load func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: var save_file: Dictionary = {} @@ -58,20 +60,43 @@ func save(file_name: String = current_file_name, file_path: String = current_fil func load(file_path) -> void: + ## Loads a save file and deserialize the data + var saved_file = FileAccess.open(file_path, FileAccess.READ) - var serialized_data = JSON.parse_string(saved_file.get_as_text()) - print(serialized_data) + var serialized_data: Dictionary = JSON.parse_string(saved_file.get_as_text()) + + ## Loops through each universe in the save file (if any), and loads them into the engine + for universe_uuid: String in serialized_data.get("universes", {}): + var serialized_universe: Dictionary = serialized_data.universes[universe_uuid] + + var new_universe: Universe = new_universe(serialized_universe.name, false, serialized_universe, universe_uuid) + universes[new_universe.uuid] = new_universe + + for scene_uuid: String in serialized_data.get("scenes", {}): + var serialized_scene: Dictionary = serialized_data.scenes[scene_uuid] + + var new_scene: Scene = new_scene(Scene.new(), true, serialized_scene, scene_uuid) + + scenes_added.emit(scenes) #endregion #region Universes -func new_universe(name: String = "New Universe", no_signal: bool = false) -> Universe: +func new_universe(name: String = "New Universe", no_signal: bool = false, serialised_data: Dictionary = {}, uuid: String = "") -> Universe: ## Adds a new universe var new_universe: Universe = Universe.new() - new_universe.name = name + new_universe.engine = self + if serialised_data: + new_universe.load_from(serialised_data) + else: + new_universe.name = name + + if uuid: + new_universe.uuid = uuid + universes[new_universe.uuid] = new_universe if not no_signal: @@ -203,7 +228,7 @@ func reload_io_plugins() -> void: if plugin_name in output_plugins.keys(): plugin_name = plugin_name + " " + UUID_Util.v4() - output_plugins[plugin_name] = {"plugin":uninitialized_plugin, "file_name":plugin} + output_plugins[plugin] = {"plugin":uninitialized_plugin, "plugin_name":plugin_name} initialized_plugin.free() #endregion @@ -266,14 +291,22 @@ func deselect_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> voi #region Scenes -func new_scene(scene: Scene = Scene.new(), no_signal: bool = false) -> Scene: +func new_scene(scene: Scene = Scene.new(), no_signal: bool = false, serialized_data: Dictionary = {}, uuid: String = "") -> Scene: ## Adds a scene to this engine, creats a new one if none is passed + if uuid: + scene.uuid = uuid + scene.engine = self + + if serialized_data: + scene.load_from(serialized_data) + + scenes[scene.uuid] = scene if not no_signal: - scene_added.emit(scene) + scenes_added.emit([scene]) return scene diff --git a/core/engine/Utils.gd b/core/engine/Utils.gd index 7f3c52b..8cc155a 100644 --- a/core/engine/Utils.gd +++ b/core/engine/Utils.gd @@ -19,14 +19,24 @@ static func save_json_to_file(file_path: String, file_name: String, json: Dictio static func serialize_variant(variant: Variant) -> Variant: - print("type: ", typeof(variant)) match typeof(variant): TYPE_COLOR: - return variant.to_html() + return "#" + variant.to_html() return ERR_INVALID_DATA +static func deserialize_variant(variant: Variant) -> Variant: + match typeof(variant): + TYPE_STRING: + match variant[0]: + "#": + print(variant.right(8)) + return Color.from_string(variant.right(8), Color.BLACK) + + return ERR_INVALID_DATA + + static func get_htp_color(color_1: Color, color_2: Color) -> Color: # Calculate the intensity of each channel for color1 var intensity_1_r = color_1.r diff --git a/core/fixtures/generic/desk-channel.json b/core/fixtures/generic/dimmer.json similarity index 100% rename from core/fixtures/generic/desk-channel.json rename to core/fixtures/generic/dimmer.json diff --git a/core/io_plugins/DataIOPlugin.gd b/core/io_plugins/DataIOPlugin.gd index 6b15963..cc81656 100644 --- a/core/io_plugins/DataIOPlugin.gd +++ b/core/io_plugins/DataIOPlugin.gd @@ -5,7 +5,6 @@ class_name DataIOPlugin extends EngineComponent ## Engine base class for all input and output plugins var type: String = "" ## Type of this plugin, either input or output -var file_name: String = "" ## File name for this plugins scritp, used when loading a save file func set_type(new_type:String) -> void: type = new_type diff --git a/core/io_plugins/output_plugins/ArtNetOutput.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd index 0e19124..46a86a7 100644 --- a/core/io_plugins/output_plugins/ArtNetOutput.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -1,10 +1,5 @@ class_name ArtNetOutput extends DataIOPlugin - -var meta = { - "name": "Art Net Output" -} - var _udp_peer = PacketPeerUDP.new() var exposed_values = [ @@ -45,12 +40,15 @@ var config = { "ip":"127.0.0.1", "port":6454, "universe":0, - "file_name":"" } -func _init(): +func _init(serialised_data: Dictionary = {}): self.set_type("output") - self.name = meta.name + + self.name = serialised_data.get("name", "Art Net Output") + config.ip = serialised_data.get("config", {}).get("ip", config.ip) + config.port = serialised_data.get("config", {}).get("port", config.port) + config.universe = serialised_data.get("config", {}).get("univeres", config.universe) super._init() @@ -81,11 +79,14 @@ func get_universe(): func serialize(): return { - "ip": config.ip, - "port": config.port, - "universe": config.universe, + "config":{ + "ip": config.ip, + "port": config.port, + "universe": config.universe, + }, "name": self.name, - "file_name": self.file_name + "file": self.get_script().get_path().split("/")[-1], + "user_meta": self.serialize_meta() } func from(serialized_data): From 3d72c2f4acbbde79024cf70547c7a04189f48553 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 20:40:51 +1200 Subject: [PATCH 12/20] Fixed scenes and fixture ui --- Main.tscn | 6 +- Panels/Add Fixture/Add_fixture.gd | 4 +- Panels/Fixtures/Fixtures.gd | 108 ++++------------------- Panels/Fixtures/Fixtures.tscn | 135 ++--------------------------- Panels/Functions/Functions.gd | 4 + Panels/Functions/Functions.tscn | 1 + Panels/Universes/Universes.gd | 4 +- Scripts/Menu_buttons.gd | 4 +- core/components/EngineComponent.gd | 3 +- core/components/Fixture.gd | 2 + core/components/Programmer.gd | 2 +- core/components/Scene.gd | 9 +- core/components/Universe.gd | 13 +++ core/engine/Engine.gd | 12 +-- 14 files changed, 71 insertions(+), 236 deletions(-) diff --git a/Main.tscn b/Main.tscn index 11b142d..3251cf2 100644 --- a/Main.tscn +++ b/Main.tscn @@ -3,7 +3,7 @@ [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="PackedScene" uid="uid://cim02rtl7kfpc" path="res://Panels/IO Controls/IOControls.tscn" id="3_k6wx5"] [ext_resource type="Script" path="res://Scripts/fps.gd" id="3_l3bnx"] -[ext_resource type="PackedScene" uid="uid://pe1tet2410en" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] +[ext_resource type="PackedScene" uid="uid://d12eb0smjpwuk" path="res://Panels/Fixtures/Fixtures.tscn" id="3_u55oi"] [ext_resource type="PackedScene" uid="uid://03t7su6t2rq2" path="res://Panels/Universes/Universes.tscn" id="4_8kgbc"] [ext_resource type="PackedScene" uid="uid://cedqo06n6en8u" path="res://Panels/Functions/Functions.tscn" id="4_35sxj"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="5_8370q"] @@ -109,11 +109,11 @@ layout_mode = 2 [node name="IO Controls" parent="TabContainer/Universes" instance=ExtResource("3_k6wx5")] layout_mode = 2 -[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] +[node name="Functions" parent="TabContainer" instance=ExtResource("4_35sxj")] visible = false layout_mode = 2 -[node name="Functions" parent="TabContainer" instance=ExtResource("4_35sxj")] +[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] visible = false layout_mode = 2 diff --git a/Panels/Add Fixture/Add_fixture.gd b/Panels/Add Fixture/Add_fixture.gd index 6a57d64..c97eede 100644 --- a/Panels/Add Fixture/Add_fixture.gd +++ b/Panels/Add Fixture/Add_fixture.gd @@ -24,7 +24,7 @@ var options: Dictionary = { func _ready() -> void: - Core.universe_added.connect(self._reload_universes) + Core.universes_added.connect(self._reload_universes) Core.universes_removed.connect(self._reload_universes) _reload_universes() _reload_fixture_tree() @@ -67,7 +67,7 @@ func _reload_menu() -> void: self.get_node(fixture_channel_list).add_item(channel) -func _reload_universes(_universe=null) -> void: +func _reload_universes(_universes=null) -> void: ## Reload the list of universes self.get_node(fixture_universe_option).clear() diff --git a/Panels/Fixtures/Fixtures.gd b/Panels/Fixtures/Fixtures.gd index fdcdc17..693efaa 100644 --- a/Panels/Fixtures/Fixtures.gd +++ b/Panels/Fixtures/Fixtures.gd @@ -2,114 +2,38 @@ # All rights reserved. extends Control -## GUI element for managing fixtures, and fixture groups +## GUI element for managing fixtures -@export var physical_fixture_list: NodePath -@export var fixture_groups_list: NodePath +@export var item_list_view: NodePath -var active_fixtures : Array = [] -var last_selected_node: Control func _ready() -> void: Core.fixture_added.connect(self._reload_fixtures) Core.fixture_removed.connect(self._reload_fixtures) - - Core.fixture_selection_changed.connect(self.set_active_fixtures) - + Core.universes_added.connect(self._reload_fixtures) + Core.universes_removed.connect(self._reload_fixtures) + Core.fixture_selection_changed.connect(self._reload_fixtures) -func delete_request(node:Control) -> void : - ## Called when the delete button is clicked on a fixture List_Item - - var confirmation_dialog: AcceptDialog = Globals.components.accept_dialog.instantiate() - confirmation_dialog.dialog_text = "Are you sure you want to delete this? This action can not be undone" - - confirmation_dialog.confirmed.connect(( - func(node): - - var fixture: Fixture = node.get_meta("fixture") - fixture.universe.remove_fixture(fixture) - - ).bind(node)) - - add_child(confirmation_dialog) - - -func edit_request(node:Control) -> void: - ## WIP function to edit a fixture, change channel, type, universe, ect - pass - - -func on_selected(selected_node:Control) -> void: - ## Called when the user clicks on a fixture List_Item - - if Input.is_key_pressed(KEY_SHIFT) and last_selected_node: - var children: Array[Node] = self.get_node(physical_fixture_list).get_children() - var pos_1: int = children.find(last_selected_node) - var pos_2: int = children.find(selected_node) - - if pos_1 > pos_2: - var x = pos_1 - pos_1 = pos_2 - pos_2 = x - - var fixtures_to_select: Array[Fixture] = [] - - for i in range(pos_1, pos_2+1): - fixtures_to_select.append(children[i].get_meta("fixture")) - - Core.set_fixture_selection(fixtures_to_select) - - else: - last_selected_node = selected_node - Core.set_fixture_selection([selected_node.get_meta("fixture")]) - -func _reload_fixtures(_fixture=null) -> void: +func _reload_fixtures(_scene=null) -> void: ## Reload the list of fixtures - print("reloading") - for node in get_node(physical_fixture_list).get_children(): - node.get_parent().remove_child(node) - node.queue_free() + self.get_node(item_list_view).remove_all() + self.get_node(item_list_view).add_items(Core.fixtures.values()) - for universe: Universe in Core.universes.values(): - for fixture: Fixture in universe.fixtures.values(): - var node_to_add : Control = Globals.components.list_item.instantiate() - node_to_add.control_node = self - node_to_add.set_item_name(fixture.meta.fixture_name + " | " + universe.name + " CH: " + str(fixture.channel) + "-" + str(fixture.channel+fixture.length-1)) - node_to_add.name = fixture.uuid - node_to_add.set_meta("fixture", fixture) - get_node(physical_fixture_list).add_child(node_to_add) - - set_active_fixtures(active_fixtures) -func set_active_fixtures(fixtures:Array) -> void: - for fixture in get_node(physical_fixture_list).get_children(): - fixture.set_highlighted(false) - active_fixtures = fixtures +func _on_item_list_view_delete_requested(items: Array) -> void: + ## Called when the delete button is pressed on the ItemListView - for fixture: Fixture in active_fixtures: - get_node(physical_fixture_list).get_node(fixture.uuid).set_highlighted(true) - - -func _on_new_physical_fixture_pressed() -> void: - Globals.open_panel_in_window("add_fixture") - + for fixture: Fixture in items: + fixture.universe.remove_fixture(fixture) -func _on_new_fixture_group_pressed() -> void: - pass -func _on_select_all_pressed() -> void: - - var fixtures_to_select: Array[Fixture] = [] - - for list_item: Control in get_node(physical_fixture_list).get_children(): - fixtures_to_select.append(list_item.get_meta("fixture")) - - Core.set_fixture_selection(fixtures_to_select) +func _on_item_list_view_add_requested() -> void: + Globals.open_panel_in_window("add_fixture") -func _on_select_none_pressed() -> void: - Core.set_fixture_selection([]) +func _on_item_list_view_selection_changed(items: Array) -> void: + Core.set_fixture_selection(items) diff --git a/Panels/Fixtures/Fixtures.tscn b/Panels/Fixtures/Fixtures.tscn index 19ccbdb..3a5f07d 100644 --- a/Panels/Fixtures/Fixtures.tscn +++ b/Panels/Fixtures/Fixtures.tscn @@ -1,138 +1,21 @@ -[gd_scene load_steps=11 format=3 uid="uid://pe1tet2410en"] +[gd_scene load_steps=3 format=3 uid="uid://d12eb0smjpwuk"] -[ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_g8n3l"] [ext_resource type="Script" path="res://Panels/Fixtures/Fixtures.gd" id="1_xjo7n"] -[ext_resource type="Texture2D" uid="uid://dis005hfepinf" path="res://Assets/Icons/Fixture.svg" id="2_tonwl"] -[ext_resource type="Texture2D" uid="uid://ds5mmj3a0ukl4" path="res://Assets/Icons/Fixture_group.svg" id="3_dj1r6"] -[ext_resource type="Texture2D" uid="uid://cwv0ml7wy07au" path="res://Assets/Icons/Checklist.svg" id="5_7ecew"] -[ext_resource type="Texture2D" uid="uid://su38vnysxa1c" path="res://Assets/Icons/Unchecked.svg" id="6_c3kim"] +[ext_resource type="PackedScene" uid="uid://c6smssfk7gn2w" path="res://Components/ItemListView/ItemListView.tscn" id="2_o0s47"] -[sub_resource type="InputEventKey" id="InputEventKey_6ywj7"] -device = -1 -ctrl_pressed = true -keycode = 65 -unicode = 97 - -[sub_resource type="Shortcut" id="Shortcut_svqby"] -events = [SubResource("InputEventKey_6ywj7")] - -[sub_resource type="InputEventKey" id="InputEventKey_jvtdl"] -device = -1 -shift_pressed = true -ctrl_pressed = true -keycode = 65 -unicode = 65 - -[sub_resource type="Shortcut" id="Shortcut_vy8ba"] -events = [SubResource("InputEventKey_jvtdl")] - -[node name="Fixtures" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -theme = ExtResource("1_g8n3l") - -[node name="Fixtures" type="MarginContainer" parent="."] -layout_mode = 1 +[node name="Fixtures" type="PanelContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -theme_override_constants/margin_left = 10 -theme_override_constants/margin_top = 10 -theme_override_constants/margin_right = 10 -theme_override_constants/margin_bottom = 10 script = ExtResource("1_xjo7n") -physical_fixture_list = NodePath("VBoxContainer/VSplitContainer/PanelContainer3/ScrollContainer/Physical Fixtures") -fixture_groups_list = NodePath("VBoxContainer/VSplitContainer/PanelContainer2/ScrollContainer/Fixture Groups") - -[node name="VBoxContainer" type="VBoxContainer" parent="Fixtures"] -layout_mode = 2 - -[node name="MarginContainer" type="MarginContainer" parent="Fixtures/VBoxContainer"] -layout_mode = 2 -theme_override_constants/margin_bottom = 5 - -[node name="PanelContainer" type="PanelContainer" parent="Fixtures/VBoxContainer/MarginContainer"] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="Fixtures/VBoxContainer/MarginContainer/PanelContainer"] -layout_mode = 2 - -[node name="New Physical Fixture" type="Button" parent="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -tooltip_text = "Open fixture creation window" -text = "New Fixture" -icon = ExtResource("2_tonwl") - -[node name="New Fixture Group" type="Button" parent="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -tooltip_text = "Work in progress, Create a new fixture group" -text = "New Fixture Group" -icon = ExtResource("3_dj1r6") - -[node name="Select All" type="Button" parent="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -tooltip_text = "Select All" -shortcut = SubResource("Shortcut_svqby") -icon = ExtResource("5_7ecew") - -[node name="Select None" type="Button" parent="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer"] -layout_mode = 2 -tooltip_text = "Select All" -shortcut = SubResource("Shortcut_vy8ba") -icon = ExtResource("6_c3kim") - -[node name="VSplitContainer" type="VSplitContainer" parent="Fixtures/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="PanelContainer3" type="PanelContainer" parent="Fixtures/VBoxContainer/VSplitContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Fixtures/VBoxContainer/VSplitContainer/PanelContainer3"] -layout_mode = 2 -size_flags_vertical = 3 +item_list_view = NodePath("ItemListView") -[node name="Physical Fixtures" type="VBoxContainer" parent="Fixtures/VBoxContainer/VSplitContainer/PanelContainer3/ScrollContainer"] +[node name="ItemListView" parent="." instance=ExtResource("2_o0s47")] layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="PanelContainer2" type="PanelContainer" parent="Fixtures/VBoxContainer/VSplitContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="Fixtures/VBoxContainer/VSplitContainer/PanelContainer2"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="Fixture Groups" type="VBoxContainer" parent="Fixtures/VBoxContainer/VSplitContainer/PanelContainer2/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="Panel" type="Panel" parent="Fixtures"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="Fixtures/Panel"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "Fixtures are a work in progress and will be available in a future version of Spectrum." -horizontal_alignment = 1 -vertical_alignment = 1 +allow_multi_select = false -[connection signal="pressed" from="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/New Physical Fixture" to="Fixtures" method="_on_new_physical_fixture_pressed"] -[connection signal="pressed" from="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/Select All" to="Fixtures" method="_on_select_all_pressed"] -[connection signal="pressed" from="Fixtures/VBoxContainer/MarginContainer/PanelContainer/HBoxContainer/Select None" to="Fixtures" method="_on_select_none_pressed"] +[connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] +[connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] +[connection signal="selection_changed" from="ItemListView" to="." method="_on_item_list_view_selection_changed"] diff --git a/Panels/Functions/Functions.gd b/Panels/Functions/Functions.gd index b692816..8bde6e6 100644 --- a/Panels/Functions/Functions.gd +++ b/Panels/Functions/Functions.gd @@ -25,3 +25,7 @@ func _on_item_list_view_delete_requested(items: Array) -> void: Core.remove_scenes(items) + + +func _on_item_list_view_selection_changed(items: Array) -> void: + self.get_node(item_list_view).set_selected(items) diff --git a/Panels/Functions/Functions.tscn b/Panels/Functions/Functions.tscn index 8e8cd4c..029f8e0 100644 --- a/Panels/Functions/Functions.tscn +++ b/Panels/Functions/Functions.tscn @@ -17,3 +17,4 @@ layout_mode = 2 allow_multi_select = false [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] +[connection signal="selection_changed" from="ItemListView" to="." method="_on_item_list_view_selection_changed"] diff --git a/Panels/Universes/Universes.gd b/Panels/Universes/Universes.gd index 3a4c004..0ddb52d 100644 --- a/Panels/Universes/Universes.gd +++ b/Panels/Universes/Universes.gd @@ -9,13 +9,13 @@ extends Control func _ready() -> void: print(item_list_view) - Core.universe_added.connect(self._reload_universes) + Core.universes_added.connect(self._reload_universes) Core.universes_removed.connect(self._reload_universes) Core.universe_name_changed.connect(self._reload_universes) Core.universe_selection_changed.connect(self._universe_selection_changed) -func _reload_universes(_scene=null) -> void: +func _reload_universes(_universes=null) -> void: ## Reload the list of fixtures self.get_node(item_list_view).remove_all() diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index 3a12f68..1ae91ea 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -2,8 +2,8 @@ extends HBoxContainer func _ready(): - Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") - + #Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") + pass func _on_save_pressed() -> void: diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index 243a110..15ea43d 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -7,6 +7,7 @@ class_name EngineComponent extends Object signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) ## Emitted when an item is added, edited, or deleted from user_meta, if no value is present it meanes that the key has been deleted signal name_changed(new_name: String) ## Emitted when the name of this object has changed signal selected(is_selected: bool) +signal delete_request(from: EngineComponent) var uuid: String = "" ## Uuid of the current component var name: String = "": set = _set_name ## The name of this object, only use when displaying to users, do not use it as a reference @@ -90,4 +91,4 @@ func serialize_meta() -> Dictionary: func delete() -> void: - pass + delete_request.emit(self) diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index b6b69e8..8999758 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -49,6 +49,8 @@ func _init(i: Dictionary = {}) -> void: meta.fixture_brand = i.manifest.info.brand meta.fixture_name = i.manifest.info.name + self.name = i.manifest.info.brand + " | " + i.manifest.info.name + if "uuid" in i: self.uuid = i.uuid diff --git a/core/components/Programmer.gd b/core/components/Programmer.gd index 09b29ea..f54550a 100644 --- a/core/components/Programmer.gd +++ b/core/components/Programmer.gd @@ -25,7 +25,7 @@ func save_to_scene(name: String = "New Scene") -> Scene: var new_scene: Scene = Scene.new() - new_scene.save_data = save_data.duplicate(true) + new_scene.set_save_data(save_data.duplicate(true)) new_scene.name = name engine.new_scene(new_scene) diff --git a/core/components/Scene.gd b/core/components/Scene.gd index ed5dd75..997dd2f 100644 --- a/core/components/Scene.gd +++ b/core/components/Scene.gd @@ -28,6 +28,13 @@ func set_enabled(is_enabled: bool) -> void: Core.animate(func(color): fixture.set_color(color, uuid), fixture.current_input_data[uuid].color, Color.BLACK, fade_out_speed) +func set_save_data(saved_data: Dictionary) -> void: + save_data = saved_data + + for fixture: Fixture in save_data.keys(): + fixture.delete_request.connect(func(deleted_fixture: Fixture): save_data.erase(deleted_fixture)) + + func serialize() -> Dictionary: ## Serializes this scene and returnes it in a dictionary @@ -46,7 +53,7 @@ func load_from(serialized_data: Dictionary) -> void: fade_in_speed = serialized_data.get("fade_in_speed", fade_in_speed) fade_out_speed = serialized_data.get("fade_out_speed", fade_out_speed) - save_data = deserialize_save_data(serialized_data.get("save_data", {})) + set_save_data(deserialize_save_data(serialized_data.get("save_data", {}))) func serialize_save_data() -> Dictionary: diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 4a22dd0..2ad9768 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -106,6 +106,19 @@ func remove_fixture(fixture: Fixture, no_signal: bool = false): fixtures_deleted.emit(uuids) +func remove_fixtures(fixtures_to_remove: Array, no_signal: bool = false) -> void: + ## Removes mutiple fixtures at once + + var uuids: Array = [] + + for fixture: Fixture in fixtures_to_remove: + uuids.append(fixture.uuid) + remove_fixture(fixture, true) + + if not no_signal: + fixtures_deleted.emit(uuids) + + func is_channel_used(channels: Array) -> bool: ## Checks if any of the channels in channels are used by another fixture return false diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 05de5b2..ba240a0 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -5,7 +5,7 @@ class_name CoreEngine extends Node ## The core engine that powers Spectrum signal universe_name_changed(universe: Universe, new_name: String) ## Emitted when any of the universes in this engine have there name changed -signal universe_added(universe: Universe) +signal universes_added(universe: Array[Universe]) signal universes_removed(universe_uuids: Array[String]) signal universe_selection_changed(selected_universes: Array[Universe]) @@ -100,7 +100,7 @@ func new_universe(name: String = "New Universe", no_signal: bool = false, serial universes[new_universe.uuid] = new_universe if not no_signal: - universe_added.emit(new_universe) + universes_added.emit([new_universe]) _connect_universe_signals(new_universe) @@ -258,7 +258,7 @@ func reload_fixtures() -> void: fixtures_definitions[manifest.info.brand] = {manifest.info.name:manifest} -func select_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> void: +func select_fixtures(fixtures: Array, no_signal: bool = false) -> void: ## Selects all the fixtures passed to this function for fixture: Fixture in fixtures: @@ -270,16 +270,16 @@ func select_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> void: fixture_selection_changed.emit(selected_fixtures) -func set_fixture_selection(fixtures: Array[Fixture]) -> void: +func set_fixture_selection(fixtures: Array) -> void: ## Changes the selection to be the fixtures passed to this function deselect_fixtures(selected_fixtures, true) select_fixtures(fixtures) -func deselect_fixtures(fixtures: Array[Fixture], no_signal: bool = false) -> void: +func deselect_fixtures(fixtures: Array, no_signal: bool = false) -> void: ## Deselects all the fixtures pass to this function - for fixture: Fixture in fixtures: + for fixture: Fixture in fixtures.duplicate(): if fixture in selected_fixtures: selected_fixtures.erase(fixture) fixture.set_selected(false) From 2de3836f78c19a46116f00c35c93e07b15d5ac13 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 20:51:55 +1200 Subject: [PATCH 13/20] Fixed output timing, so you dont ddos your artnet node --- Panels/Virtual Fixtures/Virtual_fixtures.gd | 9 +++++---- core/components/Universe.gd | 9 +++++---- core/engine/Engine.gd | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 72d35ca..579133f 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -15,7 +15,7 @@ var _add_fixture_button: Button var _position_offset: Vector2 = Vector2(100, 100) -var last_execution_time = 0 +var last_call_time: float = 0.0 # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -130,12 +130,13 @@ func _on_virtual_fixture_deselected(node) -> void: func _on_color_picker_color_changed(color: Color) -> void: - var current_time = Time.get_ticks_msec() / 1000.0 + var current_time = Time.get_ticks_msec() / 1000.0 # Convert milliseconds to seconds - if current_time - last_execution_time >= Core.min_interval: + if current_time - last_call_time >= Core.call_interval: Core.programmer.set_color(Core.selected_fixtures, color) print(color) - last_execution_time = current_time + + last_call_time = current_time func _on_save_pressed() -> void: diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 2ad9768..9a7710b 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -18,7 +18,7 @@ var dmx_data: Dictionary = {} var engine: CoreEngine ## The CoreEngine class this universe belongs to -var _last_execution_time: int = 0 +var last_call_time: float = 0.0 func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: ## Adds a new output of type to this universe @@ -138,14 +138,15 @@ func set_data(data: Dictionary): func _compile_and_send(): - var current_time = Time.get_ticks_msec() / 1000.0 + var current_time = Time.get_ticks_msec() / 1000.0 # Convert milliseconds to seconds - if current_time - _last_execution_time >= engine.min_interval: + if current_time - last_call_time >= Core.call_interval: var compiled_dmx_data: Dictionary = dmx_data for output in outputs.values(): output.send_packet(compiled_dmx_data) - _last_execution_time = current_time + + last_call_time = current_time func serialize() -> Dictionary: diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index ba240a0..7f04b08 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -37,8 +37,9 @@ var current_file_path: String = "" var programmer = Programmer.new() -var frequency = 45.0 -var min_interval = 1.0 / frequency +var call_interval: float = 1.0 / 45.0 # 1 second divided by 45 + +var last_call_time: float = 0.0 func _ready() -> void: programmer.engine = self From 190f23a23b0cb2584a1d0b12306eb273dc323bb5 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 22:17:49 +1200 Subject: [PATCH 14/20] Virtual fixture positions save to file (wont load yet tho) --- Components/Virtual Fixture/Virtual_fixture.gd | 6 ++++ .../Virtual Fixture/Virtual_fixture.tscn | 1 + Panels/Virtual Fixtures/Virtual_fixtures.gd | 29 +++++++++++-------- Scripts/Menu_buttons.gd | 2 +- core/components/Fixture.gd | 7 +++++ core/engine/Utils.gd | 28 +++++++++--------- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Components/Virtual Fixture/Virtual_fixture.gd b/Components/Virtual Fixture/Virtual_fixture.gd index 060f984..bbc06ff 100644 --- a/Components/Virtual Fixture/Virtual_fixture.gd +++ b/Components/Virtual Fixture/Virtual_fixture.gd @@ -3,6 +3,7 @@ extends GraphElement var fixture: Fixture var color_override = false var is_highlight = false +var virtual_fixture_index: int = 0 func _ready(): $"Color Box".add_theme_stylebox_override("panel", $"Color Box".get_theme_stylebox("panel").duplicate()) @@ -18,6 +19,7 @@ func set_fixture(control_fixture: Fixture) -> void: fixture = control_fixture fixture.color_changed.connect(self.set_color) + fixture.selected.connect(self.set_highlighted) func serialize(): return { @@ -47,3 +49,7 @@ func _on_node_deselected(): color_override = false if is_highlight:set_highlighted(true) else:$"Color Box".get_theme_stylebox("panel").border_color = Color.BLACK + + +func _on_dragged(from: Vector2, to: Vector2) -> void: + fixture.user_meta.virtual_fixtures[virtual_fixture_index] = to diff --git a/Components/Virtual Fixture/Virtual_fixture.tscn b/Components/Virtual Fixture/Virtual_fixture.tscn index e18e11f..7dd2951 100644 --- a/Components/Virtual Fixture/Virtual_fixture.tscn +++ b/Components/Virtual Fixture/Virtual_fixture.tscn @@ -27,5 +27,6 @@ layout_mode = 2 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_0nr4c") +[connection signal="dragged" from="." to="." method="_on_dragged"] [connection signal="node_deselected" from="." to="." method="_on_node_deselected"] [connection signal="node_selected" from="." to="." method="_on_node_selected"] diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 579133f..42bf0b5 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -55,38 +55,42 @@ func _add_fixture() -> void: node_to_add.set_fixture(fixture) node_to_add.set_highlighted(true) + + if not fixture.user_meta.get("virtual_fixtures"): + fixture.user_meta.virtual_fixtures = [] + + node_to_add.virtual_fixture_index = len(fixture.user_meta.virtual_fixtures) node_to_add.position_offset += _position_offset _position_offset += Vector2(5, 5) - fixture.set_user_meta("virtual_fixture", true) + fixture.user_meta.virtual_fixtures.append(node_to_add.position_offset) self.add_child(node_to_add) func _request_delete() -> void: ## Deletes a virtual fixtures from the current view - var to_remove: Array = _selected_virtual_fixtures.duplicate() for virtual_fixture: Control in to_remove: - virtual_fixture.fixture.delete_user_meta("virtual_fixture") + virtual_fixture.fixture.user_meta.virtual_fixtures.remove_at(virtual_fixture.virtual_fixture_index) virtual_fixture.queue_free() _selected_virtual_fixtures.erase(virtual_fixture) - + # func _active_fixtures_changed(new_active_fixtures: Array) -> void: ## Function to update highlighting on virtual fixtures, when their corresponding fixture is selected _add_fixture_button.disabled = true if new_active_fixtures == [] else false - for virtual_fixture: Control in get_children(): - virtual_fixture.set_highlighted(false) - - for active_fixture: Fixture in new_active_fixtures: - for virtual_fixture in active_fixture.get_user_meta("virtual_fixtures", []): - virtual_fixture.set_highlighted(true) - - _old_active_fixtures = new_active_fixtures + #for virtual_fixture: Control in get_children(): + #virtual_fixture.set_highlighted(false) + # + #for active_fixture: Fixture in new_active_fixtures: + #for virtual_fixture in active_fixture.get_user_meta("virtual_fixtures", []): + #virtual_fixture.set_highlighted(true) + # + #_old_active_fixtures = new_active_fixtures func _align(orientation: int) -> void: @@ -99,6 +103,7 @@ func _align(orientation: int) -> void: for virtual_fixture: Control in _selected_virtual_fixtures: virtual_fixture.position_offset = base_position + virtual_fixture.fixture.user_meta.virtual_fixtures[virtual_fixture.virtual_fixture_index] = base_position if orientation: base_position.x += 100 diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index 1ae91ea..eec0a20 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -2,7 +2,7 @@ extends HBoxContainer func _ready(): - #Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") + Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") pass func _on_save_pressed() -> void: diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index 8999758..a6b2687 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -23,6 +23,8 @@ var manifest: Dictionary ## Fixture manifest var channels: Array ## Channels this fixture uses, and what they do var channel_ranges: Dictionary ## What happenes at each channel, at each value +var position: Vector2 = Vector2.ZERO + ## Contains all the parameters inputted by other function in spectrum, ie scenes, programmer, ect. ## Each input it added to this dict with a id for each item, allowing for HTP and LTP calculations @@ -46,6 +48,10 @@ func _init(i: Dictionary = {}) -> void: channel_ranges = i.manifest.get("channels", {}) channels = i.manifest.modes.values()[mode].channels + var p = Utils.deserialize_variant(i.get("position", "")) + if p is Vector2: + position = p + meta.fixture_brand = i.manifest.info.brand meta.fixture_name = i.manifest.info.name @@ -68,6 +74,7 @@ func serialize() -> Dictionary: "universe":universe.uuid, "channel":channel, "mode":mode, + "position":Utils.serialize_variant(position), "meta":meta, "user_meta": serialize_meta(), } diff --git a/core/engine/Utils.gd b/core/engine/Utils.gd index 8cc155a..c7e22f6 100644 --- a/core/engine/Utils.gd +++ b/core/engine/Utils.gd @@ -19,22 +19,24 @@ static func save_json_to_file(file_path: String, file_name: String, json: Dictio static func serialize_variant(variant: Variant) -> Variant: - match typeof(variant): - TYPE_COLOR: - return "#" + variant.to_html() - - return ERR_INVALID_DATA + return var_to_str(variant) + #match typeof(variant): + #TYPE_COLOR: + #return "#" + variant.to_html() + # + #return ERR_INVALID_DATA static func deserialize_variant(variant: Variant) -> Variant: - match typeof(variant): - TYPE_STRING: - match variant[0]: - "#": - print(variant.right(8)) - return Color.from_string(variant.right(8), Color.BLACK) - - return ERR_INVALID_DATA + return str_to_var(variant) + #match typeof(variant): + #TYPE_STRING: + #match variant[0]: + #"#": + #print(variant.right(8)) + #return Color.from_string(variant.right(8), Color.BLACK) + # + #return ERR_INVALID_DATA static func get_htp_color(color_1: Color, color_2: Color) -> Color: From d461a061cf30819ea972b8654e0a9b01c6831d88 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Mon, 8 Apr 2024 22:37:29 +1200 Subject: [PATCH 15/20] Fixes --- Panels/Fixtures/Fixtures.tscn | 1 - Panels/Playback Buttons/PlaybackButtons.gd | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Panels/Fixtures/Fixtures.tscn b/Panels/Fixtures/Fixtures.tscn index 3a5f07d..8576dd9 100644 --- a/Panels/Fixtures/Fixtures.tscn +++ b/Panels/Fixtures/Fixtures.tscn @@ -14,7 +14,6 @@ item_list_view = NodePath("ItemListView") [node name="ItemListView" parent="." instance=ExtResource("2_o0s47")] layout_mode = 2 -allow_multi_select = false [connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index e45782b..f9bab14 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -29,4 +29,4 @@ func _reload_buttons(_scene) -> void: func _on_resized() -> void: - self.columns = int(self.size.x / 110) + self.columns = clamp(int(self.size.x / 110), 1, INF) From e0064844903cb9c9dfa08d8cf9e70652402ce804 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Tue, 9 Apr 2024 18:51:10 +1200 Subject: [PATCH 16/20] Artnet will now auto connect --- {core/io_plugins/output_plugins => Panels}/ArtNetOutput.gd | 2 ++ 1 file changed, 2 insertions(+) rename {core/io_plugins/output_plugins => Panels}/ArtNetOutput.gd (99%) diff --git a/core/io_plugins/output_plugins/ArtNetOutput.gd b/Panels/ArtNetOutput.gd similarity index 99% rename from core/io_plugins/output_plugins/ArtNetOutput.gd rename to Panels/ArtNetOutput.gd index 46a86a7..f781782 100644 --- a/core/io_plugins/output_plugins/ArtNetOutput.gd +++ b/Panels/ArtNetOutput.gd @@ -51,6 +51,8 @@ func _init(serialised_data: Dictionary = {}): config.universe = serialised_data.get("config", {}).get("univeres", config.universe) super._init() + + connect_to_host() func connect_to_host(): _udp_peer.close() From e10020bc2aec770e2ccb176d3b78f8e881ed368a Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Tue, 9 Apr 2024 18:51:16 +1200 Subject: [PATCH 17/20] Removed auto load --- Scripts/Menu_buttons.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Menu_buttons.gd b/Scripts/Menu_buttons.gd index eec0a20..1ae91ea 100644 --- a/Scripts/Menu_buttons.gd +++ b/Scripts/Menu_buttons.gd @@ -2,7 +2,7 @@ extends HBoxContainer func _ready(): - Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") + #Core.load(OS.get_environment("HOME") + "/Documents/Spectrum/Test1.spshow") pass func _on_save_pressed() -> void: From 143300611da9f307d8ea9c3f2c76eedf50d82c73 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Tue, 9 Apr 2024 18:51:45 +1200 Subject: [PATCH 18/20] Updated fixtures page, temp as touch input is broken for external windows --- Main.tscn | 15 ++++- Panels/Add Fixture/Add_fixture.tscn | 86 ++++++++++++----------------- 2 files changed, 47 insertions(+), 54 deletions(-) diff --git a/Main.tscn b/Main.tscn index 3251cf2..48e7408 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=22 format=3 uid="uid://p3sohjs1pt37"] +[gd_scene load_steps=23 format=3 uid="uid://p3sohjs1pt37"] [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_lygr6"] [ext_resource type="PackedScene" uid="uid://cim02rtl7kfpc" path="res://Panels/IO Controls/IOControls.tscn" id="3_k6wx5"] @@ -7,6 +7,7 @@ [ext_resource type="PackedScene" uid="uid://03t7su6t2rq2" path="res://Panels/Universes/Universes.tscn" id="4_8kgbc"] [ext_resource type="PackedScene" uid="uid://cedqo06n6en8u" path="res://Panels/Functions/Functions.tscn" id="4_35sxj"] [ext_resource type="PackedScene" uid="uid://dhrijn1m88172" path="res://Panels/Virtual Fixtures/Virtual_fixtures.tscn" id="5_8370q"] +[ext_resource type="PackedScene" uid="uid://c3lrdtiw05qft" path="res://Panels/Add Fixture/Add_fixture.tscn" id="6_wm8dh"] [ext_resource type="Script" path="res://Scripts/Menu_buttons.gd" id="7_gussm"] [ext_resource type="PackedScene" uid="uid://nd4u83us3lgo" path="res://Panels/Settings/Settings.tscn" id="27_03pyd"] [ext_resource type="Script" path="res://Scripts/Window.gd" id="27_nmwy1"] @@ -97,10 +98,12 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +current_tab = 2 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true [node name="Universes" type="HSplitContainer" parent="TabContainer"] +visible = false layout_mode = 2 [node name="Universes" parent="TabContainer/Universes" instance=ExtResource("4_8kgbc")] @@ -113,8 +116,14 @@ layout_mode = 2 visible = false layout_mode = 2 -[node name="Fixtures" parent="TabContainer" instance=ExtResource("3_u55oi")] -visible = false +[node name="Fixtures" type="HSplitContainer" parent="TabContainer"] +layout_mode = 2 + +[node name="Fixtures" parent="TabContainer/Fixtures" instance=ExtResource("3_u55oi")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Add Fixture" parent="TabContainer/Fixtures" instance=ExtResource("6_wm8dh")] layout_mode = 2 [node name="Virtual Fixtures" parent="TabContainer" instance=ExtResource("5_8370q")] diff --git a/Panels/Add Fixture/Add_fixture.tscn b/Panels/Add Fixture/Add_fixture.tscn index ae28f2c..d0670db 100644 --- a/Panels/Add Fixture/Add_fixture.tscn +++ b/Panels/Add Fixture/Add_fixture.tscn @@ -3,16 +3,7 @@ [ext_resource type="Theme" uid="uid://cyua45ur0ijqo" path="res://Assets/Main.theme" id="1_460tm"] [ext_resource type="Script" path="res://Panels/Add Fixture/Add_fixture.gd" id="2_q8wav"] -[node name="Add Fixture" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="Add Fixture" type="PanelContainer" parent="."] -layout_mode = 1 +[node name="Add Fixture" type="PanelContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 @@ -22,72 +13,65 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme = ExtResource("1_460tm") script = ExtResource("2_q8wav") -fixture_tree = NodePath("MarginContainer/HSplitContainer/Fixture Tree") -fixture_channel_list = NodePath("MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/Channel List") -fixture_modes_option = NodePath("MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4/Modes") -fixture_universe_option = NodePath("MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3/Fixture Universe Option") -add_fixture_button = NodePath("MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2/Add Fixture Button") - -[node name="MarginContainer" type="MarginContainer" parent="Add Fixture"] -layout_mode = 2 -theme_override_constants/margin_left = 10 -theme_override_constants/margin_top = 10 -theme_override_constants/margin_right = 10 -theme_override_constants/margin_bottom = 10 +fixture_tree = NodePath("HSplitContainer/Fixture Tree") +fixture_channel_list = NodePath("HSplitContainer/PanelContainer/VBoxContainer/Channel List") +fixture_modes_option = NodePath("HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4/Modes") +fixture_universe_option = NodePath("HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3/Fixture Universe Option") +add_fixture_button = NodePath("HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2/Add Fixture Button") -[node name="HSplitContainer" type="HSplitContainer" parent="Add Fixture/MarginContainer"] +[node name="HSplitContainer" type="HSplitContainer" parent="."] layout_mode = 2 split_offset = 100 -[node name="Fixture Tree" type="Tree" parent="Add Fixture/MarginContainer/HSplitContainer"] +[node name="Fixture Tree" type="Tree" parent="HSplitContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="PanelContainer" type="PanelContainer" parent="Add Fixture/MarginContainer/HSplitContainer"] +[node name="PanelContainer" type="PanelContainer" parent="HSplitContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="VBoxContainer" type="VBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="HSplitContainer/PanelContainer"] layout_mode = 2 -[node name="HBoxContainer" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 -[node name="Label" type="Label" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer"] +[node name="Label" type="Label" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer"] layout_mode = 2 text = "Channel" -[node name="Channel" type="SpinBox" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer"] +[node name="Channel" type="SpinBox" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer"] layout_mode = 2 size_flags_horizontal = 10 min_value = 1.0 max_value = 512.0 value = 1.0 -[node name="HBoxContainer3" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer3" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 -[node name="Label" type="Label" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3"] +[node name="Label" type="Label" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3"] layout_mode = 2 text = "Universe" -[node name="Fixture Universe Option" type="OptionButton" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3"] +[node name="Fixture Universe Option" type="OptionButton" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer3"] custom_minimum_size = Vector2(200, 40) layout_mode = 2 size_flags_horizontal = 10 -[node name="HSeparator" type="HSeparator" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HSeparator" type="HSeparator" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 -[node name="HBoxContainer4" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer4" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 -[node name="Label" type="Label" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4"] +[node name="Label" type="Label" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4"] layout_mode = 2 text = "Mode " -[node name="Modes" type="OptionButton" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4"] +[node name="Modes" type="OptionButton" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4"] custom_minimum_size = Vector2(200, 0) layout_mode = 2 size_flags_horizontal = 10 @@ -97,50 +81,50 @@ fit_to_longest_item = false popup/item_0/text = " " popup/item_0/id = 0 -[node name="Channel List" type="ItemList" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="Channel List" type="ItemList" parent="HSplitContainer/PanelContainer/VBoxContainer"] custom_minimum_size = Vector2(0, 200) layout_mode = 2 allow_search = false -[node name="HBoxContainer5" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer5" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 size_flags_vertical = 10 -[node name="Label" type="Label" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5"] +[node name="Label" type="Label" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5"] layout_mode = 2 text = "Quantity" -[node name="Quantity" type="SpinBox" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5"] +[node name="Quantity" type="SpinBox" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5"] layout_mode = 2 size_flags_horizontal = 10 min_value = 1.0 max_value = 512.0 value = 1.0 -[node name="HBoxContainer6" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer6" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 size_flags_vertical = 8 -[node name="Label" type="Label" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6"] +[node name="Label" type="Label" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6"] layout_mode = 2 text = "Offset" -[node name="Offset" type="SpinBox" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6"] +[node name="Offset" type="SpinBox" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6"] layout_mode = 2 size_flags_horizontal = 10 -[node name="HBoxContainer2" type="HBoxContainer" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer"] +[node name="HBoxContainer2" type="HBoxContainer" parent="HSplitContainer/PanelContainer/VBoxContainer"] layout_mode = 2 size_flags_vertical = 8 -[node name="Add Fixture Button" type="Button" parent="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2"] +[node name="Add Fixture Button" type="Button" parent="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2"] layout_mode = 2 size_flags_horizontal = 3 text = "Add Fixture" -[connection signal="item_selected" from="Add Fixture/MarginContainer/HSplitContainer/Fixture Tree" to="Add Fixture" method="_on_fixture_tree_item_selected"] -[connection signal="value_changed" from="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer/Channel" to="Add Fixture" method="_on_channel_value_changed"] -[connection signal="item_selected" from="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4/Modes" to="Add Fixture" method="_on_modes_item_selected"] -[connection signal="value_changed" from="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5/Quantity" to="Add Fixture" method="_on_quantity_value_changed"] -[connection signal="value_changed" from="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6/Offset" to="Add Fixture" method="_on_offset_value_changed"] -[connection signal="pressed" from="Add Fixture/MarginContainer/HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2/Add Fixture Button" to="Add Fixture" method="_on_add_fixture_button_pressed"] +[connection signal="item_selected" from="HSplitContainer/Fixture Tree" to="." method="_on_fixture_tree_item_selected"] +[connection signal="value_changed" from="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer/Channel" to="." method="_on_channel_value_changed"] +[connection signal="item_selected" from="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer4/Modes" to="." method="_on_modes_item_selected"] +[connection signal="value_changed" from="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer5/Quantity" to="." method="_on_quantity_value_changed"] +[connection signal="value_changed" from="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer6/Offset" to="." method="_on_offset_value_changed"] +[connection signal="pressed" from="HSplitContainer/PanelContainer/VBoxContainer/HBoxContainer2/Add Fixture Button" to="." method="_on_add_fixture_button_pressed"] From 024b873684aaf322c469b4b3a89e6f94294d041d Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Tue, 9 Apr 2024 20:09:30 +1200 Subject: [PATCH 19/20] Bug fixes --- Components/Virtual Fixture/Virtual_fixture.gd | 2 + Main.tscn | 3 +- Panels/Fixtures/Fixtures.tscn | 1 + Panels/Playback Buttons/PlaybackButtons.gd | 2 + Panels/Virtual Fixtures/Virtual_fixtures.gd | 1 - core/components/EngineComponent.gd | 4 +- core/components/Fixture.gd | 11 ++- core/components/Universe.gd | 18 ++-- core/engine/Engine.gd | 15 +++- .../output_plugins}/ArtNetOutput.gd | 86 ++++++++++++------- 10 files changed, 93 insertions(+), 50 deletions(-) rename {Panels => core/io_plugins/output_plugins}/ArtNetOutput.gd (89%) diff --git a/Components/Virtual Fixture/Virtual_fixture.gd b/Components/Virtual Fixture/Virtual_fixture.gd index bbc06ff..3715da6 100644 --- a/Components/Virtual Fixture/Virtual_fixture.gd +++ b/Components/Virtual Fixture/Virtual_fixture.gd @@ -20,6 +20,7 @@ func set_fixture(control_fixture: Fixture) -> void: fixture = control_fixture fixture.color_changed.connect(self.set_color) fixture.selected.connect(self.set_highlighted) + fixture.delete_request.connect(self.delete) func serialize(): return { @@ -38,6 +39,7 @@ func set_highlighted(highlight): $"Color Box".get_theme_stylebox("panel").border_color = Color.BLACK func delete(): + self.get_parent()._selected_virtual_fixtures.erase(self) self.queue_free() diff --git a/Main.tscn b/Main.tscn index 48e7408..81e8573 100644 --- a/Main.tscn +++ b/Main.tscn @@ -98,12 +98,10 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -current_tab = 2 drag_to_rearrange_enabled = true use_hidden_tabs_for_min_size = true [node name="Universes" type="HSplitContainer" parent="TabContainer"] -visible = false layout_mode = 2 [node name="Universes" parent="TabContainer/Universes" instance=ExtResource("4_8kgbc")] @@ -117,6 +115,7 @@ visible = false layout_mode = 2 [node name="Fixtures" type="HSplitContainer" parent="TabContainer"] +visible = false layout_mode = 2 [node name="Fixtures" parent="TabContainer/Fixtures" instance=ExtResource("3_u55oi")] diff --git a/Panels/Fixtures/Fixtures.tscn b/Panels/Fixtures/Fixtures.tscn index 8576dd9..13c5b38 100644 --- a/Panels/Fixtures/Fixtures.tscn +++ b/Panels/Fixtures/Fixtures.tscn @@ -14,6 +14,7 @@ item_list_view = NodePath("ItemListView") [node name="ItemListView" parent="." instance=ExtResource("2_o0s47")] layout_mode = 2 +show_new = false [connection signal="add_requested" from="ItemListView" to="." method="_on_item_list_view_add_requested"] [connection signal="delete_requested" from="ItemListView" to="." method="_on_item_list_view_delete_requested"] diff --git a/Panels/Playback Buttons/PlaybackButtons.gd b/Panels/Playback Buttons/PlaybackButtons.gd index f9bab14..9edb0e4 100644 --- a/Panels/Playback Buttons/PlaybackButtons.gd +++ b/Panels/Playback Buttons/PlaybackButtons.gd @@ -25,6 +25,8 @@ func _reload_buttons(_scene) -> void: scene.enabled = state ) + button_to_add.set_pressed_no_signal(scene.enabled) + self.add_child(button_to_add) diff --git a/Panels/Virtual Fixtures/Virtual_fixtures.gd b/Panels/Virtual Fixtures/Virtual_fixtures.gd index 42bf0b5..050f822 100644 --- a/Panels/Virtual Fixtures/Virtual_fixtures.gd +++ b/Panels/Virtual Fixtures/Virtual_fixtures.gd @@ -139,7 +139,6 @@ func _on_color_picker_color_changed(color: Color) -> void: if current_time - last_call_time >= Core.call_interval: Core.programmer.set_color(Core.selected_fixtures, color) - print(color) last_call_time = current_time diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index 15ea43d..b91bb1e 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -7,7 +7,7 @@ class_name EngineComponent extends Object signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) ## Emitted when an item is added, edited, or deleted from user_meta, if no value is present it meanes that the key has been deleted signal name_changed(new_name: String) ## Emitted when the name of this object has changed signal selected(is_selected: bool) -signal delete_request(from: EngineComponent) +signal delete_request() var uuid: String = "" ## Uuid of the current component var name: String = "": set = _set_name ## The name of this object, only use when displaying to users, do not use it as a reference @@ -91,4 +91,4 @@ func serialize_meta() -> Dictionary: func delete() -> void: - delete_request.emit(self) + delete_request.emit() diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index a6b2687..fa8fff0 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -31,7 +31,6 @@ var position: Vector2 = Vector2.ZERO var current_input_data: Dictionary = {} var _compiled_dmx_data: Dictionary -var _parameters: Dictionary func _init(i: Dictionary = {}) -> void: @@ -89,10 +88,11 @@ func recompile_data() -> void: for input_data in current_input_data[input_data_id]: match input_data: "color": - highest_valued_data["color"] = Utils.get_htp_color(highest_valued_data.get("color", Color()), current_input_data[input_data_id][input_data]) - - universe.set_data(_compiled_dmx_data) + highest_valued_data["color"] = Utils.get_htp_color(highest_valued_data.get("color", Color()), current_input_data[input_data_id].color) + _set_color(highest_valued_data.get("color", Color.BLACK)) + + universe.set_data(_compiled_dmx_data) func _set_color(color: Color) -> void: @@ -103,8 +103,7 @@ func _set_color(color: Color) -> void: if "ColorIntensityBlue" in channels: _compiled_dmx_data[int(channels.find("ColorIntensityBlue") + channel)] = color.b8 - _parameters.color = color - color_changed.emit(_parameters.color) + color_changed.emit(color) func set_color(color: Color, id: String = "overide") -> void: diff --git a/core/components/Universe.gd b/core/components/Universe.gd index 9a7710b..cf68f23 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -25,6 +25,8 @@ func new_output(type = ArtNetOutput, no_signal: bool = false) -> DataIOPlugin: var new_output: DataIOPlugin = type.new() + engine.output_timer.connect(new_output.send_packet) + outputs[new_output.uuid] = new_output if not no_signal: @@ -138,15 +140,15 @@ func set_data(data: Dictionary): func _compile_and_send(): - var current_time = Time.get_ticks_msec() / 1000.0 # Convert milliseconds to seconds - - if current_time - last_call_time >= Core.call_interval: - var compiled_dmx_data: Dictionary = dmx_data - for output in outputs.values(): - output.send_packet(compiled_dmx_data) + #var current_time = Time.get_ticks_msec() / 1000.0 # Convert milliseconds to seconds + # + #if current_time - last_call_time >= Core.call_interval: + var compiled_dmx_data: Dictionary = dmx_data + for output in outputs.values(): + output.set_data(compiled_dmx_data) - last_call_time = current_time + #last_call_time = current_time func serialize() -> Dictionary: @@ -208,6 +210,8 @@ func load_from(serialised_data: Dictionary) -> void: var new_output: DataIOPlugin = engine.output_plugins[serialised_output.file].plugin.new(serialised_output) new_output.uuid = output_uuid + engine.output_timer.connect(new_output.send_packet) + outputs[new_output.uuid] = new_output diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index 7f04b08..a46ac47 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -17,6 +17,7 @@ signal fixture_selection_changed(selected_fixtures: Array[Fixture]) signal scenes_added(scene: Array[Scene]) signal scenes_removed(scene_uuids: Array) +signal output_timer() ## Emited [call_interval] number of times per second var universes: Dictionary = {} var fixtures: Dictionary = {} @@ -39,7 +40,7 @@ var programmer = Programmer.new() var call_interval: float = 1.0 / 45.0 # 1 second divided by 45 -var last_call_time: float = 0.0 +var accumulated_time: float = 0.0 func _ready() -> void: programmer.engine = self @@ -49,6 +50,18 @@ func _ready() -> void: reload_fixtures() +func _process(delta: float) -> void: + # Accumulate the time + accumulated_time += delta + + # Check if enough time has passed since the last function call + if accumulated_time >= call_interval: + # Call the function + output_timer.emit() + + # Subtract the interval from the accumulated time + accumulated_time -= call_interval + #region Save Load func save(file_name: String = current_file_name, file_path: String = current_file_name) -> Error: diff --git a/Panels/ArtNetOutput.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd similarity index 89% rename from Panels/ArtNetOutput.gd rename to core/io_plugins/output_plugins/ArtNetOutput.gd index f781782..b2a3ac3 100644 --- a/Panels/ArtNetOutput.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -2,6 +2,8 @@ class_name ArtNetOutput extends DataIOPlugin var _udp_peer = PacketPeerUDP.new() +var _current_data: Dictionary = {} + var exposed_values = [ { "name":"Ip Address", @@ -54,30 +56,19 @@ func _init(serialised_data: Dictionary = {}): connect_to_host() + func connect_to_host(): _udp_peer.close() _udp_peer.connect_to_host(config.ip, config.port) -func set_ip_addr(new_ip_address): - config.ip = new_ip_address - connect_to_host() - -func set_port(new_port): - config.port = new_port - connect_to_host() -func set_universe(new_universe): - config.universe = new_universe - connect_to_host() +func _disconnect(): + _udp_peer.close() -func get_ip_addr(): - return config.ip -func get_port(): - return config.port +func set_data(data) -> void : + _current_data = data -func get_universe(): - return config.universe func serialize(): return { @@ -90,40 +81,45 @@ func serialize(): "file": self.get_script().get_path().split("/")[-1], "user_meta": self.serialize_meta() } +# +#func from(serialized_data): + #config = serialized_data -func from(serialized_data): - config = serialized_data - -func _disconnect(): - _udp_peer.close() func delete(): _disconnect() -func send_packet(dmx_data) -> void: + +func send_packet() -> void: + + print(_current_data) + if not _current_data: + return + + # Construct Art-Net packet var packet = PackedByteArray() - + # Art-Net ID ('Art-Net') packet.append_array([65, 114, 116, 45, 78, 101, 116, 0]) - + # OpCode: ArtDMX (0x5000) packet.append_array([0, 80]) - + # Protocol Version: 14 (0x000e) packet.append_array([0, 14]) - + # ArtDMX packet # Sequence Number packet.append(0) - + # Physical Port (Set to 0 if not needed) packet.append(0) - + # Universe (16-bit) packet.append(int(config.universe) % 256) # Lower 8 bits packet.append(int(config.universe) / 256) # Upper 8 bits - + # Length (16-bit) # packet.append_array([512 % 256, int(512 / 255)]) packet.append(02) @@ -131,9 +127,37 @@ func send_packet(dmx_data) -> void: # DMX Channels for channel in range(1, 513): - packet.append(dmx_data.get(channel, 0)) - + packet.append(_current_data.get(channel, 0)) + # Send the packet # _udp_peer.set_dest_address(ip, port) _udp_peer.put_packet(packet) + _current_data = {} + + +func set_ip_addr(new_ip_address): + config.ip = new_ip_address + connect_to_host() + + +func set_port(new_port): + config.port = new_port + connect_to_host() + + +func set_universe(new_universe): + config.universe = new_universe + connect_to_host() + + +func get_ip_addr(): + return config.ip + + +func get_port(): + return config.port + + +func get_universe(): + return config.universe From 8371492d07334eea66940e617157213fe0984339 Mon Sep 17 00:00:00 2001 From: Liam Sherwin Date: Tue, 9 Apr 2024 20:29:05 +1200 Subject: [PATCH 20/20] Fixed crash when universe deleted --- Components/Virtual Fixture/Virtual_fixture.gd | 2 +- Panels/Fixtures/Fixtures.gd | 2 +- core/components/EngineComponent.gd | 4 ++-- core/components/Fixture.gd | 11 +++++++++++ core/components/Universe.gd | 11 +++++------ core/engine/Engine.gd | 4 ++-- core/io_plugins/output_plugins/ArtNetOutput.gd | 2 +- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Components/Virtual Fixture/Virtual_fixture.gd b/Components/Virtual Fixture/Virtual_fixture.gd index 3715da6..842f3b1 100644 --- a/Components/Virtual Fixture/Virtual_fixture.gd +++ b/Components/Virtual Fixture/Virtual_fixture.gd @@ -38,7 +38,7 @@ func set_highlighted(highlight): else: $"Color Box".get_theme_stylebox("panel").border_color = Color.BLACK -func delete(): +func delete(_fixture = null): self.get_parent()._selected_virtual_fixtures.erase(self) self.queue_free() diff --git a/Panels/Fixtures/Fixtures.gd b/Panels/Fixtures/Fixtures.gd index 693efaa..8629c20 100644 --- a/Panels/Fixtures/Fixtures.gd +++ b/Panels/Fixtures/Fixtures.gd @@ -15,7 +15,7 @@ func _ready() -> void: Core.fixture_selection_changed.connect(self._reload_fixtures) -func _reload_fixtures(_scene=null) -> void: +func _reload_fixtures(_fixture=null) -> void: ## Reload the list of fixtures self.get_node(item_list_view).remove_all() diff --git a/core/components/EngineComponent.gd b/core/components/EngineComponent.gd index b91bb1e..bb779a5 100644 --- a/core/components/EngineComponent.gd +++ b/core/components/EngineComponent.gd @@ -7,7 +7,7 @@ class_name EngineComponent extends Object signal user_meta_changed(origin: EngineComponent, key: String, value: Variant) ## Emitted when an item is added, edited, or deleted from user_meta, if no value is present it meanes that the key has been deleted signal name_changed(new_name: String) ## Emitted when the name of this object has changed signal selected(is_selected: bool) -signal delete_request() +signal delete_request(origin: EngineComponent) var uuid: String = "" ## Uuid of the current component var name: String = "": set = _set_name ## The name of this object, only use when displaying to users, do not use it as a reference @@ -91,4 +91,4 @@ func serialize_meta() -> Dictionary: func delete() -> void: - delete_request.emit() + delete_request.emit(self) diff --git a/core/components/Fixture.gd b/core/components/Fixture.gd index fa8fff0..2bd8a86 100644 --- a/core/components/Fixture.gd +++ b/core/components/Fixture.gd @@ -95,6 +95,17 @@ func recompile_data() -> void: universe.set_data(_compiled_dmx_data) +func delete() -> void: + delete_request.emit(self) + + var empty_data: Dictionary = {} + + for i in _compiled_dmx_data: + empty_data[i] = 0 + + universe.set_data(empty_data) + + func _set_color(color: Color) -> void: if "ColorIntensityRed" in channels: _compiled_dmx_data[int(channels.find("ColorIntensityRed") + channel)] = color.r8 diff --git a/core/components/Universe.gd b/core/components/Universe.gd index cf68f23..13b682b 100644 --- a/core/components/Universe.gd +++ b/core/components/Universe.gd @@ -6,7 +6,7 @@ class_name Universe extends EngineComponent signal fixture_name_changed(fixture: Fixture, new_name: String) signal fixtures_added(fixtures: Array[Fixture]) -signal fixtures_deleted(fixture_uuids: Array[String]) +signal fixtures_deleted(fixture_uuids: Array) signal outputs_added(outputs: Array[DataIOPlugin]) signal outputs_removed(output_uuids: Array[String]) @@ -104,8 +104,7 @@ func remove_fixture(fixture: Fixture, no_signal: bool = false): fixture.free() if not no_signal: - var uuids: Array[String] = [fixture_uuid] - fixtures_deleted.emit(uuids) + fixtures_deleted.emit([fixture_uuid]) func remove_fixtures(fixtures_to_remove: Array, no_signal: bool = false) -> void: @@ -127,10 +126,10 @@ func is_channel_used(channels: Array) -> bool: func delete(): - ## Called when this universe is about to be deleted, it will remove all outputs from this universe + ## Called when this universe is about to be deleted, it will remove all outputs and fixtures from this universe - for output in outputs.values(): - remove_output(output) + remove_fixtures(fixtures.values()) + remove_outputs(outputs.values()) func set_data(data: Dictionary): diff --git a/core/engine/Engine.gd b/core/engine/Engine.gd index a46ac47..b109c1a 100644 --- a/core/engine/Engine.gd +++ b/core/engine/Engine.gd @@ -11,7 +11,7 @@ signal universe_selection_changed(selected_universes: Array[Universe]) signal fixture_name_changed(fixture: Fixture, new_name) signal fixture_added(fixture: Array[Fixture]) -signal fixture_removed(fixture_uuid: Array[String]) +signal fixture_removed(fixture_uuid: Array) signal fixture_selection_changed(selected_fixtures: Array[Fixture]) signal scenes_added(scene: Array[Scene]) @@ -140,7 +140,7 @@ func _connect_universe_signals(universe: Universe): ) universe.fixtures_deleted.connect( - func(fixture_uuids: Array[String]): + func(fixture_uuids: Array): fixture_removed.emit(fixture_uuids) ) diff --git a/core/io_plugins/output_plugins/ArtNetOutput.gd b/core/io_plugins/output_plugins/ArtNetOutput.gd index b2a3ac3..caa3ad1 100644 --- a/core/io_plugins/output_plugins/ArtNetOutput.gd +++ b/core/io_plugins/output_plugins/ArtNetOutput.gd @@ -92,10 +92,10 @@ func delete(): func send_packet() -> void: - print(_current_data) if not _current_data: return + print(_current_data) # Construct Art-Net packet var packet = PackedByteArray()