You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
4.4 KiB

6 months ago
@tool
extends Resource
class_name DialogicStyle
## A style represents a collection of layers and settings.
## A style can inherit from another style.
@export var name := "Style":
get:
if name.is_empty():
return "Unkown Style"
return name
@export var inherits: DialogicStyle = null
@export var base_scene: PackedScene = null
@export var base_overrides := {}
@export var layers: Array[DialogicStyleLayer] = []
func _init(_name:="") -> void:
if not _name.is_empty():
name = _name
## This always returns the inheritance root's scene!
func get_base_scene() -> PackedScene:
if base_scene == null:
return DialogicUtil.get_default_layout_base()
return get_inheritance_root().base_scene
## This always returns the full inherited roots layers!
func get_layer_list() -> PackedStringArray:
return PackedStringArray(get_inheritance_root().layers.map(func(x:DialogicStyleLayer): return x.scene.resource_path))
func get_layer_count() -> int:
return layers.size()
func get_layer_info(index:int) -> Dictionary:
if index == -1:
return {'path':get_base_scene().resource_path, 'overrides':base_overrides.duplicate()}
if index < layers.size():
if layers[index].scene != null:
return {'path':layers[index].scene.resource_path, 'overrides':layers[index].overrides.duplicate()}
else:
return {'path':'', 'overrides':layers[index].overrides.duplicate()}
return {'path':'', 'overrides':{}}
func get_layer_inherited_info(index:int, inherited_only:=false) -> Dictionary:
var style := self
var info := {'path':'', 'overrides':{}}
if not inherited_only:
info = get_layer_info(index)
while style.inherits != null:
style = style.inherits
info = merge_layer_infos(info, style.get_layer_info(index))
return info
func add_layer(scene:String, overrides:Dictionary = {}) -> void:
layers.append(DialogicStyleLayer.new(scene, overrides))
changed.emit()
func delete_layer(layer_index:int) -> void:
if not has_layer(layer_index):
return
layers.remove_at(layer_index)
changed.emit()
func move_layer(from_index:int, to_index:int) -> void:
if not has_layer(from_index) or not has_layer(to_index-1):
return
var info: Resource = layers.pop_at(from_index)
layers.insert(to_index, info)
changed.emit()
func set_layer_scene(layer_index:int, scene:String) -> void:
if not has_layer(layer_index):
return
if layer_index == -1:
base_scene = load(scene)
else:
layers[layer_index].scene = load(scene)
changed.emit()
func set_layer_setting(layer:int, setting:String, value:Variant) -> void:
if not has_layer(layer):
return
if layer == -1:
base_overrides[setting] = value
else:
layers[layer].overrides[setting] = value
changed.emit()
func remove_layer_setting(layer:int, setting:String) -> void:
if not has_layer(layer):
return
if layer == -1:
base_overrides.erase(setting)
else:
layers[layer].overrides.erase(setting)
changed.emit()
## This merges two layers (mainly their overrides). Layer a has priority!
func merge_layer_infos(layer_a:Dictionary, layer_b:Dictionary) -> Dictionary:
var combined := layer_a.duplicate(true)
combined.path = layer_b.path
combined.overrides.merge(layer_b.overrides)
return combined
func has_layer(index:int) -> bool:
return index < layers.size()
func inherits_anything() -> bool:
return inherits != null
func get_inheritance_root() -> DialogicStyle:
if inherits == null:
return self
var style: DialogicStyle = self
while style.inherits != null:
style = style.inherits
return style
func realize_inheritance() -> void:
base_scene = get_base_scene()
base_overrides = get_layer_inherited_info(-1)
var _layers: Array[DialogicStyleLayer] = []
for i in range(get_layer_count()):
var info := get_layer_inherited_info(i)
_layers.append(DialogicStyleLayer.new(info.get("path", ""), info.get("overrides", {})))
layers = _layers
inherits = null
changed.emit()
func clone() -> DialogicStyle:
var style := DialogicStyle.new()
style.name = name
if base_scene != null:
style.base_scene = base_scene
style.inherits = inherits
style.base_overrides = base_overrides
for layer_idx in range(get_layer_count()):
var info := get_layer_info(layer_idx)
style.add_layer(info.path, info.overrides)
return style
func prepare() -> void:
if base_scene:
ResourceLoader.load_threaded_request(base_scene.resource_path)
for layer in layers:
if layer.scene:
ResourceLoader.load_threaded_request(layer.scene.resource_path)