3 class_name DialogicStyle
5 ## A style represents a collection of layers and settings.
6 ## A style can inherit from another style.
9 @export var name := "Style":
15 @export var inherits: DialogicStyle = null
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()
27 func _init(_name := "") -> void:
28 if not _name.is_empty():
34 # These methods are local, meaning they do NOT take inheritance into account.
37 ## Returns the amount of layers (the base layer is not included).
38 func get_layer_count() -> int:
39 return layer_list.size()
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)
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 == ""
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()
58 ## Returns the id of the layer at [param index].
59 func get_layer_id_at_index(index:int) -> String:
62 if has_layer_index(index):
63 return layer_list[index]
67 func get_layer_info(id:String) -> Dictionary:
68 var info := {"id": id, "path": "", "overrides": {}}
71 var layer_resource: DialogicStyleLayer = layer_info[id]
73 if layer_resource.scene != null:
74 info.path = layer_resource.scene.resource_path
76 info.path = DialogicUtil.get_default_layout_base().resource_path
78 info.overrides = layer_resource.overrides.duplicate()
85 #region MODIFICATION METHODS
86 # These methods modify the layers of this style.
89 ## Returns a new layer id not yet in use.
90 func get_new_layer_id() -> String:
92 while String.num_int64(i, 16) in layer_info:
94 return String.num_int64(i, 16)
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:
101 id = get_new_layer_id()
102 layer_info[id] = DialogicStyleLayer.new(scene, overrides)
103 layer_list.append(id)
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 == "":
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):
125 var id := layer_list.pop_at(from_index)
126 layer_list.insert(to_index, id)
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):
135 layer_info[layer_id].scene = load(scene)
139 func set_layer_overrides(layer_id:String, overrides:Dictionary) -> void:
140 if not has_layer(layer_id):
143 layer_info[layer_id].overrides = overrides
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):
152 layer_info[layer_id].overrides[setting] = value
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):
161 layer_info[layer_id].overrides.erase(setting)
168 #region INHERITANCE METHODS
169 # These methods are what you should usually use to get info about this style.
172 ## Returns `true` if this style is inheriting from another style.
173 func inherits_anything() -> bool:
174 return inherits != null
177 ## Returns the base style of this style.
178 func get_inheritance_root() -> DialogicStyle:
179 if not inherits_anything():
182 var style: DialogicStyle = self
183 while style.inherits_anything():
184 style = style.inherits
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)
193 combined.path = ancestor_info.path
194 combined.overrides.merge(ancestor_info.overrides)
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:
203 var info := {"id": id, "path": "", "overrides": {}}
205 if not inherited_only:
206 info = get_layer_info(id)
208 while style.inherits_anything():
209 style = style.inherits
210 info = merge_layer_infos(info, style.get_layer_info(id))
215 ## Returns the layer list of the root style.
216 func get_layer_inherited_list() -> Array:
217 var list := layer_list
219 if inherits_anything():
220 list = get_inheritance_root().layer_list
225 ## Applies inherited info to the local layers.
226 ## Then removes inheritance.
227 func realize_inheritance() -> void:
228 layer_list = get_layer_inherited_list()
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", {}))
235 layer_info = new_layer_info
242 ## Creates a fresh new style with the same settings.
243 func clone() -> DialogicStyle:
244 var style := DialogicStyle.new()
246 style.inherits = inherits
248 var base_info := get_layer_info("")
249 style.set_layer_scene("", base_info.path)
250 style.set_layer_overrides("", base_info.overrides)
252 for id in layer_list:
253 var info := get_layer_info(id)
254 style.add_layer(info.path, info.overrides, id)
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)
266 #region UPDATE OLD STYLES
267 # TODO deprecated when going into beta
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] = []
276 func update_from_pre_alpha16() -> void:
277 if not layers.is_empty():
281 if inherits_anything():
282 id = get_layer_inherited_list()[idx]
284 add_layer(layer.scene.resource_path, layer.overrides, id)
286 add_layer("", layer.overrides, id)
290 if not base_scene == null:
291 set_layer_scene("", base_scene.resource_path)
293 if not base_overrides.is_empty():
294 set_layer_overrides("", base_overrides)
295 base_overrides.clear()