Skip to content

Commit f4eeb85

Browse files
author
Liam Sherwin
committed
Multi Zone Fixtures
1 parent 26b1a47 commit f4eeb85

File tree

18 files changed

+738
-149
lines changed

18 files changed

+738
-149
lines changed

core/components/FixtureManifest.gd

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func create_zone(p_mode: String, p_zone: String) -> bool:
5858

5959

6060
## Creates a parameter in the given mode and zone
61-
func add_parameter(p_mode: String, p_zone: String, p_parameter: String, p_channels: Array[int], p_categorys: String = "Control") -> bool:
61+
func add_parameter(p_mode: String, p_zone: String, p_parameter: String, p_channels: Array[int], p_category: String = "") -> bool:
6262
if not _modes.has(p_mode) or not _modes[p_mode].zones.has(p_zone):
6363
return false
6464

@@ -67,20 +67,44 @@ func add_parameter(p_mode: String, p_zone: String, p_parameter: String, p_channe
6767
"offsets": p_channels.duplicate(),
6868
"functions": {}
6969
}
70-
_categorys.get_or_add(p_mode, {}).get_or_add(p_zone, {})[p_parameter] = p_categorys
70+
71+
_categorys.get_or_add(p_mode, {}).get_or_add(p_zone, {})[p_parameter] = p_category
7172

7273
return true
7374

7475

76+
## Duplicates a parameter to another zone
77+
func duplicate_parameter(p_mode: String, p_parameter: String, p_from_zone: String, p_to_zone: String, p_channels: Array[int]) -> bool:
78+
if not _modes.has(p_mode) or not _modes[p_mode].zones.has(p_from_zone):
79+
return false
80+
81+
var new_parameter: Dictionary = _modes[p_mode].zones[p_from_zone][p_parameter].duplicate(true)
82+
create_zone(p_mode, p_to_zone)
83+
84+
new_parameter.offsets = p_channels
85+
_modes[p_mode].zones[p_to_zone][p_parameter] = new_parameter
86+
87+
return true
88+
89+
90+
## Removes a parameter
91+
func remove_parameter(p_mode: String, p_zone: String, p_parameter: String) -> bool:
92+
if not _modes.has(p_mode) or not _modes[p_mode].zones.has(p_zone):
93+
return false
94+
95+
return _modes[p_mode].zones[p_zone].erase(p_parameter)
96+
97+
7598
## Adds a funtion to the given parameter
76-
func add_parameter_function(p_mode: String, p_zone: String, p_parameter: String, p_function: String, p_name: String, p_default: int, p_range: Array[int]) -> bool:
99+
func add_parameter_function(p_mode: String, p_zone: String, p_parameter: String, p_function: String, p_name: String, p_default: int, p_range: Array[int], p_can_fade: bool) -> bool:
77100
if not _modes.has(p_mode) or not _modes[p_mode].zones.has(p_zone) or not _modes[p_mode].zones[p_zone].has(p_parameter):
78101
return false
79102

80103
_modes[p_mode].zones[p_zone][p_parameter].functions[p_function] = {
81104
"attribute": p_function,
82105
"name": p_name,
83106
"default": p_default,
107+
"can_fade": p_can_fade,
84108
"dmx_range": p_range.duplicate(),
85109
"sets": []
86110
}
@@ -126,14 +150,24 @@ func has_function(p_mode: String, p_zone: String, p_parameter: String, p_functio
126150
return _modes.get(p_mode, {}).get("zones", {}).get(p_zone, {}).get(p_parameter, {}).get("functions", {}).has(p_function)
127151

128152

153+
## Checks if this FixtureManifest has a function that can fade
154+
func function_can_fade(p_mode: String, p_zone: String, p_parameter: String, p_function: String) -> bool:
155+
return _modes.get(p_mode, {}).get("zones", {}).get(p_zone, {}).get(p_parameter, {}).get("functions", {}).get(p_function, {}).get("can_fade", false)
156+
157+
129158
## Returns the given mode
130159
func get_mode(p_mode: String) -> Dictionary:
131160
return _modes.get(p_mode, {}).duplicate(true)
132161

133162

134163
## Returns all the modes in this manifest
135-
func get_modes() -> Array:
136-
return _modes.keys()
164+
func get_modes() -> Array[String]:
165+
return Array(_modes.keys(), TYPE_STRING, "", null)
166+
167+
168+
## Returns all zones in this manifest
169+
func get_zones(p_mode) -> Array[String]:
170+
return Array(_modes[p_mode].zones.keys(), TYPE_STRING, "", null)
137171

138172

139173
## Gets all the categorys in a mode and zone
@@ -148,7 +182,6 @@ func get_parameter_functions(p_mode: String, p_zone: String, p_parameter: String
148182

149183
return _modes[p_mode].zones[p_zone][p_parameter].functions.keys()
150184

151-
152185
## Overide this function to serialize your object
153186
func _serialize_request() -> Dictionary:
154187
return {

core/components/fixtures/DMXFixture.gd

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var _channel: int = 0
1515
## The mode of this fixture
1616
var _mode: String = ""
1717

18-
## Current override values of this fixture, post precedence calculation
19-
## { "zone": { "parameter": value } }##
20-
var _current_override: Dictionary = {}
18+
## All the input value overrides as raw values
19+
## { "zone": { "parameter": { "value": float, "function": String } } }
20+
var _raw_override_layers: Dictionary[String, Dictionary] = {}
2121

2222
## The FixtureManifest for this fixture
2323
var _manifest: FixtureManifest = null
@@ -31,30 +31,22 @@ func _component_ready() -> void:
3131

3232

3333
## Internal: Sets a parameter override to a float value
34-
func _set_override(parameter: String, value: float, zone: String = "root") -> void:
35-
var split: PackedStringArray = parameter.split(".", true, 1)
36-
if len(split) == 2:
37-
var logical: String = split[0]
38-
39-
_current_override.get_or_add(zone, {})[logical] = value
40-
override_changed.emit(parameter, value, zone)
34+
func _set_override(p_parameter: String, p_function: String, p_value: float, p_zone: String = "root") -> void:
35+
_raw_override_layers.get_or_add(p_zone, {})[p_parameter] = {"value": p_value, "function": p_function}
36+
override_changed.emit(p_parameter, p_function, p_value, p_zone)
4137

4238

43-
#Internal: Erases the parameter override
44-
func _erase_override(parameter: String, zone: String = "root") -> void:
45-
var split: PackedStringArray = parameter.split(".", true, 1)
46-
if len(split) == 2:
47-
var logical: String = split[0]
48-
49-
if _current_override.get_or_add(zone, {}).erase(logical) and not _current_override[zone]:
50-
_current_override.erase(zone)
39+
## Internal: Erases the parameter override
40+
func _erase_override(p_parameter: String, p_zone: String = "root") -> void:
41+
if _raw_override_layers.get_or_add(p_zone, {}).erase(p_parameter) and not _raw_override_layers[p_zone]:
42+
_raw_override_layers.erase(p_zone)
5143

52-
override_erased.emit(parameter, zone)
44+
override_erased.emit(p_parameter, p_zone)
5345

5446

5547
## Internal: Erases all overrides
5648
func _erase_all_overrides() -> void:
57-
_current_override.clear()
49+
_raw_override_layers.clear()
5850
all_override_removed.emit()
5951

6052

@@ -87,12 +79,17 @@ func _set_manifest(p_manifest: FixtureManifest, p_mode: String) -> void:
8779

8880
## Gets all the override values
8981
func get_all_override_values() -> Dictionary:
90-
return _current_override.duplicate(true)
82+
return _raw_override_layers.duplicate(true)
9183

9284

9385
## Checks if this DMXFixture has any overrides
9486
func has_overrides() -> bool:
95-
return _current_override != {}
87+
return _raw_override_layers != {}
88+
89+
90+
## Gets all the zones
91+
func get_zones() -> Array[String]:
92+
return _manifest.get_zones(_mode)
9693

9794

9895
## Gets all the parameters and there category from a zone
@@ -105,6 +102,11 @@ func get_parameter_functions(p_zone: String, p_parameter: String) -> Array:
105102
return _manifest.get_parameter_functions(_mode, p_zone, p_parameter)
106103

107104

105+
## Checks if this DMXFixture has a function that can fade
106+
func function_can_fade(p_zone: String, p_parameter: String, p_function: String) -> bool:
107+
return _manifest.function_can_fade(_mode, p_zone, p_parameter, p_function)
108+
109+
108110
## Saves this DMXFixture to a dictonary
109111
func _serialize_request() -> Dictionary:
110112
return {
@@ -122,3 +124,5 @@ func _load_request(p_serialized_data: Dictionary) -> void:
122124
FixtureLibrary.request_manifest(manifest_uuid).then(func (manifest: FixtureManifest):
123125
_set_manifest(manifest, _mode)
124126
)
127+
128+
_raw_override_layers = Dictionary(type_convert(p_serialized_data.get("raw_override_layers", {}), TYPE_DICTIONARY), TYPE_STRING, "", null, TYPE_DICTIONARY, "", null)

core/components/fixtures/Fixture.gd

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ class_name Fixture extends EngineComponent
66

77

88
## Emitted when parameters are changed
9-
signal parameter_changed(parameter: String, value: Variant, zone: String)
9+
signal parameter_changed(parameter: String, function: String, value: Variant, zone: String)
1010

1111
## Emitted when a parameter is erased
1212
signal parameter_erased(parameter: String, zone: String)
1313

1414
## Emited when a parameter override is changed or added
15-
signal override_changed(parameter: String, value: Variant, zone: String)
15+
signal override_changed(parameter: String, function: String, value: Variant, zone: String)
1616

1717
## Emitted when a parameter override is removed
1818
signal override_erased(parameter: String, zone: String)
@@ -35,42 +35,42 @@ func _init(p_uuid: String = UUID_Util.v4(), p_name: String = name) -> void:
3535

3636

3737
## Sets a parameter to a float value
38-
func set_parameter(parameter: String, value: float, layer_id: String, zone: String = "root") -> Promise:
39-
return rpc("set_parameter", [parameter, value, layer_id, zone])
38+
func set_parameter(p_parameter: String, p_function: String, p_value: float, p_layer_id: String, p_zone: String = "root") -> Promise:
39+
return rpc("set_parameter", [p_parameter, p_function, p_value, p_layer_id, p_zone])
4040

4141

4242
## Internal: Sets a parameter to a float value
43-
func _set_parameter(parameter: String, value: float, layer_id: String, zone: String = "root") -> void:
43+
func _set_parameter(p_parameter: String, p_value: float, p_layer_id: String, p_zone: String = "root") -> void:
4444
return
4545

4646

4747
## Erases the parameter on the given layer
48-
func erase_parameter(parameter: String, layer_id: String, zone: String = "root") -> Promise:
49-
return rpc("erase_parameter", [parameter, layer_id, zone])
48+
func erase_parameter(p_parameter: String, p_layer_id: String, p_zone: String = "root") -> Promise:
49+
return rpc("erase_parameter", [p_parameter, p_layer_id, p_zone])
5050

5151

5252
## Internal: Erases the parameter on the given layer
53-
func _erase_parameter(parameter: String, layer_id: String, zone: String = "root") -> void:
53+
func _erase_parameter(p_parameter: String, p_layer_id: String, p_zone: String = "root") -> void:
5454
return
5555

5656

5757
## Sets a parameter override to a float value
58-
func set_override(parameter: String, value: float, zone: String = "root") -> Promise:
59-
return rpc("set_override", [parameter, value, zone])
58+
func set_override(p_parameter: String, p_function: String, p_value: float, p_zone: String = "root") -> Promise:
59+
return rpc("set_override", [p_parameter, p_function, p_value, p_zone])
6060

6161

6262
## Internal: Sets a parameter override to a float value
63-
func _set_override(parameter: String, value: float, zone: String = "root") -> void:
63+
func _set_override(p_parameter: String, p_function: String, p_value: float, p_zone: String = "root") -> void:
6464
return
6565

6666

6767
## Erases the parameter override
68-
func erase_override(parameter: String, zone: String = "root") -> Promise:
69-
return rpc("erase_override", [parameter, zone])
68+
func erase_override(p_parameter: String, p_zone: String = "root") -> Promise:
69+
return rpc("erase_override", [p_parameter, p_zone])
7070

7171

7272
## Internal: Erases the parameter override
73-
func _erase_override(parameter: String, zone: String = "root") -> void:
73+
func _erase_override(p_parameter: String, p_zone: String = "root") -> void:
7474
return
7575

7676

@@ -94,6 +94,11 @@ func has_overrides() -> bool:
9494
return false
9595

9696

97+
## Gets all the zones
98+
func get_zones() -> Array[String]:
99+
return []
100+
101+
97102
## Gets all the parameters and there category from a zone
98103
func get_parameter_categories(p_zone: String) -> Dictionary:
99104
return {}
@@ -102,3 +107,8 @@ func get_parameter_categories(p_zone: String) -> Dictionary:
102107
## Gets all the parameter functions
103108
func get_parameter_functions(p_zone: String, p_parameter: String) -> Array:
104109
return []
110+
111+
112+
## Checks if this Fixture has a function that can fade
113+
func function_can_fade(p_zone: String, p_parameter: String, p_function: String) -> bool:
114+
return false

core/engine/Engine.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ var EngineConfig = {
4646
},
4747
{
4848
"object": (Programmer),
49-
"name": "programmer"
49+
"name": "Programmer"
5050
},
5151
{
5252
"object": (FixtureLibrary),

core/global/Programmer.gd

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,57 @@ class_name CoreProgrammer extends Node
55
## Engine class for programming lights, colors, positions, etc.
66

77

8+
## Emitted when the programmer is cleared
9+
signal cleared()
10+
11+
812
## Save Modes
9-
enum SAVE_MODE {
13+
enum SaveMode {
1014
MODIFIED, ## Only save fixtures that have been changed in the programmer
1115
ALL, ## Save all values of the fixtures
1216
ALL_NONE_ZERO ## Save all values of the fixtures, as long as they are not the zero value for that channel
1317
}
1418

19+
## Random parameter modes
20+
enum RandomMode {
21+
All, ## Sets all fixture's parameter to the same random value
22+
Individual ## Uses a differnt random value for each fixture
23+
}
24+
25+
26+
## Network Config:
27+
var network_config: Dictionary = {
28+
"callbacks": {
29+
"on_cleared": _clear,
30+
}
31+
}
32+
1533

1634
## Clears the programmer
17-
func clear() -> void:
18-
Client.send_command("Programmer", "clear")
35+
func clear() -> Promise:
36+
return Client.send_command("Programmer", "clear")
37+
38+
39+
## Called when the programmer is cleared on the server
40+
func _clear() -> void:
41+
cleared.emit()
1942

2043

2144
## Function to set the fixture data at the given chanel key
22-
func set_parameter(p_fixtures: Array, p_parameter: String, p_value: float, p_zone: String) -> void:
23-
Client.send_command("Programmer", "set_parameter", [p_fixtures, p_parameter, p_value, p_zone])
45+
func set_parameter(p_fixtures: Array, p_parameter: String, p_function: String, p_value: float, p_zone: String) -> Promise:
46+
return Client.send_command("Programmer", "set_parameter", [p_fixtures, p_parameter, p_function, p_value, p_zone])
47+
48+
49+
## Sets a fixture parameter to a random value
50+
func set_parameter_random(p_fixtures: Array, p_parameter: String, p_function: String, p_zone: String, p_mode: RandomMode) -> Promise:
51+
return Client.send_command("Programmer", "set_parameter_random", [p_fixtures, p_parameter, p_function, p_zone, p_mode])
52+
53+
54+
## Erases a parameter
55+
func erase_parameter(p_fixtures: Array, p_parameter: String, p_zone: String) -> Promise:
56+
return Client.send_command("Programmer", "erase_parameter", [p_fixtures, p_parameter, p_zone])
57+
58+
59+
## Saves the current state of this programmer to a scene
60+
func save_to_scene(fixtures: Array, mode: SaveMode = SaveMode.MODIFIED) -> Promise:
61+
return Client.send_command("Programmer", "save_to_scene", [fixtures, mode])

core/static/Utils.gd

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,40 @@ static func sum_array(array: Array) -> Variant:
162162
return sum
163163

164164

165+
## Sorts all the text in an array
166+
static func sort_text(arr: Array) -> Array:
167+
arr.sort_custom(func(a, b): return a.naturalnocasecmp_to(b) < 0)
168+
return arr
169+
170+
171+
## Sorts all the text in an array, with numbers
172+
static func sort_text_and_numbers(arr: Array) -> Array:
173+
arr.sort_custom(func(a, b): return _split_sort_key(a) < _split_sort_key(b))
174+
return arr
175+
176+
177+
## Helper function for sort_text_and_numbers
178+
static func _split_sort_key(s: String) -> Array:
179+
var regex = RegEx.new()
180+
regex.compile(r"\d+|\D+")
181+
182+
var parts = []
183+
for match in regex.search_all(s):
184+
var sub = match.get_string()
185+
parts.append(int(sub) if sub.is_valid_int() else sub)
186+
187+
return parts
188+
189+
190+
## Moves an item to the start of an array
191+
static func array_move_to_start(arr: Array, item) -> Array:
192+
var i = arr.find(item)
193+
if i > 0: # Ensures "root" is found and isn't already at index 0
194+
arr.remove_at(i)
195+
arr.insert(0, item)
196+
return arr
197+
198+
165199
## Connects all the callables to the signals in the dictionary. Stored as {"SignalName": Callable}
166200
static func connect_signals(signals: Dictionary, object: Object) -> void:
167201
if is_instance_valid(object):

0 commit comments

Comments
 (0)