]> Untitled Git - wolf-seeking-sheep.git/blob - addons/dialogic/Resources/dialogic_style.gd
Squashed commit of the following:
[wolf-seeking-sheep.git] / addons / dialogic / Resources / dialogic_style.gd
1 @tool
2 extends Resource
3 class_name DialogicStyle
4
5 ## A style represents a collection of layers and settings.
6 ## A style can inherit from another style.
7
8
9 @export var name := "Style":
10         get:
11                 if name.is_empty():
12                         return "Unkown Style"
13                 return name
14
15 @export var inherits: DialogicStyle = null
16
17 ## Stores the layer order
18 @export var layer_list: Array[String] = []
19 ## Stores the layer infos
20 @export var layer_info := {
21         "" : DialogicStyleLayer.new()
22 }
23
24
25
26
27 func _init(_name := "") -> void:
28         if not _name.is_empty():
29                 name = _name
30
31
32
33 #region BASE METHODS
34 # These methods are local, meaning they do NOT take inheritance into account.
35
36
37 ## Returns the amount of layers (the base layer is not included).
38 func get_layer_count() -> int:
39         return layer_list.size()
40
41
42 ## Returns the index of the layer with [param id] in the layer list.
43 ## Returns -1 for the base layer (id=="") which is not in the layer list.
44 func get_layer_index(id:String) -> int:
45         return layer_list.find(id)
46
47
48 ## Returns `true` if [param id] is a valid id for a layer.
49 func has_layer(id:String) -> bool:
50         return id in layer_info or id == ""
51
52
53 ## Returns `true` if [param index] is a valid index for a layer.
54 func has_layer_index(index:int) -> bool:
55         return index < layer_list.size()
56
57
58 ## Returns the id of the layer at [param index].
59 func get_layer_id_at_index(index:int) -> String:
60         if index == -1:
61                 return ""
62         if has_layer_index(index):
63                 return layer_list[index]
64         return ""
65
66
67 func get_layer_info(id:String) -> Dictionary:
68         var info := {"id": id, "path": "", "overrides": {}}
69
70         if has_layer(id):
71                 var layer_resource: DialogicStyleLayer = layer_info[id]
72
73                 if layer_resource.scene != null:
74                         info.path = layer_resource.scene.resource_path
75                 elif id == "":
76                         info.path = DialogicUtil.get_default_layout_base().resource_path
77
78                 info.overrides = layer_resource.overrides.duplicate()
79
80         return info
81
82 #endregion
83
84
85 #region MODIFICATION METHODS
86 # These methods modify the layers of this style.
87
88
89 ## Returns a new layer id not yet in use.
90 func get_new_layer_id() -> String:
91         var i := 16
92         while String.num_int64(i, 16) in layer_info:
93                 i += 1
94         return String.num_int64(i, 16)
95
96
97 ## Adds a layer with the given scene and overrides.
98 ## Returns the new layers id.
99 func add_layer(scene:String, overrides:Dictionary = {}, id:= "##") -> String:
100         if id == "##":
101                 id = get_new_layer_id()
102         layer_info[id] = DialogicStyleLayer.new(scene, overrides)
103         layer_list.append(id)
104         changed.emit()
105         return id
106
107
108 ## Deletes the layer with the given id.
109 ## Deleting the base layer is not allowed.
110 func delete_layer(id:String) -> void:
111         if not has_layer(id) or id == "":
112                 return
113
114         layer_info.erase(id)
115         layer_list.erase(id)
116
117         changed.emit()
118
119
120 ## Moves the layer at [param from_index] to [param to_index].
121 func move_layer(from_index:int, to_index:int) -> void:
122         if not has_layer_index(from_index) or not has_layer_index(to_index-1):
123                 return
124
125         var id := layer_list.pop_at(from_index)
126         layer_list.insert(to_index, id)
127
128         changed.emit()
129
130
131 ## Changes the scene property of the DialogicStyleLayer resource at [param layer_id].
132 func set_layer_scene(layer_id:String, scene:String) -> void:
133         if not has_layer(layer_id):
134                 return
135         layer_info[layer_id].scene = load(scene)
136         changed.emit()
137
138
139 func set_layer_overrides(layer_id:String, overrides:Dictionary) -> void:
140         if not has_layer(layer_id):
141                 return
142
143         layer_info[layer_id].overrides = overrides
144         changed.emit()
145
146
147 ## Changes an override of the DialogicStyleLayer resource at [param layer_id].
148 func set_layer_setting(layer_id:String, setting:String, value:Variant) -> void:
149         if not has_layer(layer_id):
150                 return
151
152         layer_info[layer_id].overrides[setting] = value
153         changed.emit()
154
155
156 ## Resets (removes) an override of the DialogicStyleLayer resource at [param layer_id].
157 func remove_layer_setting(layer_id:String, setting:String) -> void:
158         if not has_layer(layer_id):
159                 return
160
161         layer_info[layer_id].overrides.erase(setting)
162         changed.emit()
163
164 #
165 #endregion
166
167
168 #region INHERITANCE METHODS
169 # These methods are what you should usually use to get info about this style.
170
171
172 ## Returns `true` if this style is inheriting from another style.
173 func inherits_anything() -> bool:
174         return inherits != null
175
176
177 ## Returns the base style of this style.
178 func get_inheritance_root() -> DialogicStyle:
179         if not inherits_anything():
180                 return self
181
182         var style: DialogicStyle = self
183         while style.inherits_anything():
184                 style = style.inherits
185
186         return style
187
188
189 ## This merges some [param layer_info] with it's param ancestors layer info.
190 func merge_layer_infos(layer_info:Dictionary, ancestor_info:Dictionary) -> Dictionary:
191         var combined := layer_info.duplicate(true)
192
193         combined.path = ancestor_info.path
194         combined.overrides.merge(ancestor_info.overrides)
195
196         return combined
197
198
199 ## Returns the layer info of the layer at [param id] taking into account inherited info.
200 ## If [param inherited_only] is `true`, the local info is not included.
201 func get_layer_inherited_info(id:String, inherited_only := false) -> Dictionary:
202         var style := self
203         var info := {"id": id, "path": "", "overrides": {}}
204
205         if not inherited_only:
206                 info = get_layer_info(id)
207
208         while style.inherits_anything():
209                 style = style.inherits
210                 info = merge_layer_infos(info, style.get_layer_info(id))
211
212         return info
213
214
215 ## Returns the layer list of the root style.
216 func get_layer_inherited_list() -> Array:
217         var list := layer_list
218
219         if inherits_anything():
220                 list = get_inheritance_root().layer_list
221
222         return list
223
224
225 ## Applies inherited info to the local layers.
226 ## Then removes inheritance.
227 func realize_inheritance() -> void:
228         layer_list = get_layer_inherited_list()
229
230         var new_layer_info := {}
231         for id in layer_info:
232                 var info := get_layer_inherited_info(id)
233                 new_layer_info[id] = DialogicStyleLayer.new(info.get("path", ""), info.get("overrides", {}))
234
235         layer_info = new_layer_info
236         inherits = null
237         changed.emit()
238
239
240 #endregion
241
242 ## Creates a fresh new style with the same settings.
243 func clone() -> DialogicStyle:
244         var style := DialogicStyle.new()
245         style.name = name
246         style.inherits = inherits
247
248         var base_info := get_layer_info("")
249         style.set_layer_scene("", base_info.path)
250         style.set_layer_overrides("", base_info.overrides)
251
252         for id in layer_list:
253                 var info := get_layer_info(id)
254                 style.add_layer(info.path, info.overrides, id)
255
256         return style
257
258
259 ## Starts preloading all the scenes used by this style.
260 func prepare() -> void:
261         for id in layer_info:
262                 if layer_info[id].scene:
263                         ResourceLoader.load_threaded_request(layer_info[id].scene.resource_path)
264
265
266 #region UPDATE OLD STYLES
267 # TODO deprecated when going into beta
268
269 # TODO  Deprecated, only for Styles before alpha 16!
270 @export var base_scene: PackedScene = null
271 # TODO Deprecated, only for Styles before alpha 16!
272 @export var base_overrides := {}
273 # TODO Deprecated, only for Styles before alpha 16!
274 @export var layers: Array[DialogicStyleLayer] = []
275
276 func update_from_pre_alpha16() -> void:
277         if not layers.is_empty():
278                 var idx := 0
279                 for layer in layers:
280                         var id := "##"
281                         if inherits_anything():
282                                 id = get_layer_inherited_list()[idx]
283                         if layer.scene:
284                                 add_layer(layer.scene.resource_path, layer.overrides, id)
285                         else:
286                                 add_layer("", layer.overrides, id)
287                         idx += 1
288                 layers.clear()
289
290         if not base_scene == null:
291                 set_layer_scene("", base_scene.resource_path)
292                 base_scene = null
293         if not base_overrides.is_empty():
294                 set_layer_overrides("", base_overrides)
295                 base_overrides.clear()
296
297
298 #endregion