1 extends DialogicSubsystem
3 ## Subsystem that manages loading layouts with specific styles applied.
5 signal style_changed(info:Dictionary)
9 ####################################################################################################
11 func clear_game_state(_clear_flag := DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
15 func load_game_state(load_flag := LoadFlags.FULL_LOAD) -> void:
16 if load_flag == LoadFlags.ONLY_DNODES:
18 load_style(dialogic.current_state_info.get('style', ''))
24 ####################################################################################################
26 ## This helper method calls load_style, but with the [parameter state_reload] as true,
27 ## which is commonly wanted if you expect a game to already be in progress.
28 func change_style(style_name := "", is_base_style := true) -> Node:
29 return load_style(style_name, null, is_base_style, true)
32 ## Loads a style. Consider using the simpler [method change_style] if you want to change the style while another style is already in use.
33 ## [br] If [param state_reload] is true, the current state will be loaded into a new layout scenes nodes.
34 ## That should not be done before calling start() or load() as it would be unnecessary or cause double-loading.
35 func load_style(style_name := "", parent: Node = null, is_base_style := true, state_reload := false) -> Node:
36 var style := DialogicUtil.get_style_by_name(style_name)
38 var signal_info := {'style':style_name}
39 dialogic.current_state_info['style'] = style_name
41 # is_base_style should only be wrong on temporary changes like character styles
43 dialogic.current_state_info['base_style'] = style_name
45 var previous_layout := get_layout_node()
46 if is_instance_valid(previous_layout) and previous_layout.has_meta('style'):
47 signal_info['previous'] = previous_layout.get_meta('style').name
49 # If this is the same style and scene, do nothing
50 if previous_layout.get_meta('style') == style:
51 return previous_layout
53 # If this has the same scene setup, just apply the new overrides
54 elif previous_layout.get_meta('style') == style.get_inheritance_root():
55 DialogicUtil.apply_scene_export_overrides(previous_layout, style.get_layer_inherited_info("").overrides)
57 for layer in previous_layout.get_layers():
58 DialogicUtil.apply_scene_export_overrides(
60 style.get_layer_inherited_info(style.get_layer_id_at_index(index)).overrides)
63 previous_layout.set_meta('style', style)
64 style_changed.emit(signal_info)
68 parent = previous_layout.get_parent()
70 previous_layout.get_parent().remove_child(previous_layout)
71 previous_layout.queue_free()
73 # if this is another style:
74 var new_layout := create_layout(style, parent)
76 # Preserve process_mode on style changes
78 new_layout.process_mode = previous_layout.process_mode
80 new_layout.ready.connect(reload_current_info_into_new_style)
82 style_changed.emit(signal_info)
87 ## Method that adds a layout scene with all the necessary layers.
88 ## The layout scene will be added to the tree root and returned.
89 func create_layout(style: DialogicStyle, parent: Node = null) -> DialogicLayoutBase:
92 var base_scene: DialogicLayoutBase
93 var base_layer_info := style.get_layer_inherited_info("")
94 if base_layer_info.path.is_empty():
95 base_scene = DialogicUtil.get_default_layout_base().instantiate()
97 base_scene = load(base_layer_info.path).instantiate()
99 base_scene.name = "DialogicLayout_"+style.name.to_pascal_case()
101 # Apply base scene overrides
102 DialogicUtil.apply_scene_export_overrides(base_scene, base_layer_info.overrides)
105 for layer_id in style.get_layer_inherited_list():
106 var layer := style.get_layer_inherited_info(layer_id)
108 if not ResourceLoader.exists(layer.path):
111 var layer_scene: DialogicLayoutLayer = null
113 if ResourceLoader.load_threaded_get_status(layer.path) == ResourceLoader.THREAD_LOAD_LOADED:
114 layer_scene = ResourceLoader.load_threaded_get(layer.path).instantiate()
116 layer_scene = load(layer.path).instantiate()
118 base_scene.add_layer(layer_scene)
120 # Apply layer overrides
121 DialogicUtil.apply_scene_export_overrides(layer_scene, layer.overrides)
123 base_scene.set_meta('style', style)
126 parent = dialogic.get_parent()
127 parent.call_deferred("add_child", base_scene)
129 dialogic.get_tree().set_meta('dialogic_layout_node', base_scene)
134 ## When changing to a different layout scene,
135 ## we have to load all the info from the current_state_info (basically
136 func reload_current_info_into_new_style() -> void:
137 for subsystem in dialogic.get_children():
138 subsystem.load_game_state(LoadFlags.ONLY_DNODES)
141 ## Returns the style currently in use
142 func get_current_style() -> String:
143 if has_active_layout_node():
144 var style: DialogicStyle = get_layout_node().get_meta('style', null)
150 func has_active_layout_node() -> bool:
152 get_tree().has_meta('dialogic_layout_node')
153 and is_instance_valid(get_tree().get_meta('dialogic_layout_node'))
154 and not get_tree().get_meta('dialogic_layout_node').is_queued_for_deletion()
158 func get_layout_node() -> DialogicLayoutBase:
159 if has_active_layout_node():
160 return get_tree().get_meta('dialogic_layout_node')
164 ## Similar to get_tree().get_first_node_in_group('group_name') but filtered to the active layout node subtree
165 func get_first_node_in_layout(group_name: String) -> Node:
166 var layout_node := get_layout_node()
167 if null == layout_node:
169 var nodes := get_tree().get_nodes_in_group(group_name)
171 if layout_node.is_ancestor_of(node):