Updated dialogic

This commit is contained in:
MaddoScientisto 2026-01-05 16:00:41 +01:00
commit cbb82512ee
483 changed files with 5743 additions and 2177 deletions

View file

@ -9,7 +9,9 @@ class_name DialogicUtil
## This method should be used instead of EditorInterface.get_editor_scale(), because if you use that
## it will run perfectly fine from the editor, but crash when the game is exported.
static func get_editor_scale() -> float:
return get_dialogic_plugin().get_editor_interface().get_editor_scale()
if Engine.is_editor_hint():
return get_dialogic_plugin().get_editor_interface().get_editor_scale()
return 1.0
## Although this does in fact always return a EditorPlugin node,
@ -77,11 +79,19 @@ static func _update_autoload_subsystem_access() -> void:
var script: Script = load("res://addons/dialogic/Core/DialogicGameHandler.gd")
var new_subsystem_access_list := "#region SUBSYSTEMS\n"
var subsystems_sorted := []
for indexer: DialogicIndexer in get_indexers(true, true):
for subsystem: Dictionary in indexer._get_subsystems().duplicate(true):
new_subsystem_access_list += '\nvar {name} := preload("{script}").new():\n\tget: return get_subsystem("{name}")\n'.format(subsystem)
subsystems_sorted.append(subsystem)
subsystems_sorted.sort_custom(func (a: Dictionary, b: Dictionary) -> bool:
return a.name < b.name
)
for subsystem: Dictionary in subsystems_sorted:
new_subsystem_access_list += '\nvar {name} := preload("{script}").new():\n\tget: return get_subsystem("{name}")\n'.format(subsystem)
new_subsystem_access_list += "\n#endregion"
script.source_code = RegEx.create_from_string(r"#region SUBSYSTEMS\n#*\n((?!#endregion)(.*\n))*#endregion").sub(script.source_code, new_subsystem_access_list)
@ -90,11 +100,10 @@ static func _update_autoload_subsystem_access() -> void:
static func get_indexers(include_custom := true, force_reload := false) -> Array[DialogicIndexer]:
if Engine.get_main_loop().has_meta('dialogic_indexers') and !force_reload:
if Engine.get_main_loop().has_meta('dialogic_indexers') and not force_reload:
return Engine.get_main_loop().get_meta('dialogic_indexers')
var indexers: Array[DialogicIndexer] = []
for file in listdir(DialogicUtil.get_module_path(''), false):
var possible_script: String = DialogicUtil.get_module_path(file).path_join("index.gd")
if ResourceLoader.exists(possible_script):
@ -287,40 +296,6 @@ static func _get_value_in_dictionary(path:String, dictionary:Dictionary, default
#endregion
#region STYLES
################################################################################
static func get_default_layout_base() -> PackedScene:
return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Base_Default/default_layout_base.tscn"))
static func get_fallback_style() -> DialogicStyle:
return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Style_VN_Default/default_vn_style.tres"))
static func get_default_style() -> DialogicStyle:
var default: String = ProjectSettings.get_setting('dialogic/layout/default_style', '')
if !ResourceLoader.exists(default):
return get_fallback_style()
return load(default)
static func get_style_by_name(name:String) -> DialogicStyle:
if name.is_empty():
return get_default_style()
var styles: Array = ProjectSettings.get_setting('dialogic/layout/style_list', [])
for style in styles:
if not ResourceLoader.exists(style):
continue
if load(style).name == name:
return load(style)
return get_default_style()
#endregion
#region SCENE EXPORT OVERRIDES
################################################################################
@ -458,39 +433,53 @@ static func setup_script_property_edit_node(property_info: Dictionary, value:Var
input.select(value)
input.item_selected.connect(DialogicUtil._on_export_int_enum_submitted.bind(property_info.name, property_changed))
else:
input = SpinBox.new()
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed))
if property_info.hint_string == 'int':
input.step = 1
input.allow_greater = true
input.allow_lesser = true
elif ',' in property_info.hint_string:
input = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate()
input.property_name = property_info['name']
input.use_int_mode()
if ',' in property_info.hint_string:
input.min_value = int(property_info.hint_string.get_slice(',', 0))
input.max_value = int(property_info.hint_string.get_slice(',', 1))
if property_info.hint_string.count(',') > 1:
input.step = int(property_info.hint_string.get_slice(',', 2))
else:
input.step = 1
input.max_value = INF
input.min_value = -INF
if value != null:
input.value = value
input.set_value(value)
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_changed))
TYPE_FLOAT:
input = SpinBox.new()
input = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate()
input.property_name = property_info['name']
input.use_float_mode()
input.step = 0.01
if ',' in property_info.hint_string:
input.min_value = float(property_info.hint_string.get_slice(',', 0))
input.max_value = float(property_info.hint_string.get_slice(',', 1))
if property_info.hint_string.count(',') > 1:
input.step = float(property_info.hint_string.get_slice(',', 2))
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed))
if value != null:
input.value = value
input.set_value(value)
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_changed))
TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4:
var vectorSize: String = type_string(typeof(value))[-1]
input = load("res://addons/dialogic/Editor/Events/Fields/field_vector" + vectorSize + ".tscn").instantiate()
input.property_name = property_info['name']
input.set_value(value)
input.value_changed.connect(DialogicUtil._on_export_vector_submitted.bind(property_changed))
TYPE_VECTOR2I, TYPE_VECTOR3I, TYPE_VECTOR4I:
var vectorSize: String = type_string(typeof(value))[-2]
input = load("res://addons/dialogic/Editor/Events/Fields/field_vector" + vectorSize + ".tscn").instantiate()
input.step = 1
input.property_name = property_info['name']
input.set_value(value)
input.value_changed.connect(DialogicUtil._on_export_vectori_submitted.bind(property_changed))
TYPE_STRING:
if property_info['hint'] & PROPERTY_HINT_FILE or property_info['hint'] & PROPERTY_HINT_DIR:
input = load("res://addons/dialogic/Editor/Events/Fields/field_file.tscn").instantiate()
input.show_editing_button = true
input.file_filter = property_info['hint_string']
input.file_mode = FileDialog.FILE_MODE_OPEN_FILE
if property_info['hint'] == PROPERTY_HINT_DIR:
@ -518,6 +507,7 @@ static func setup_script_property_edit_node(property_info: Dictionary, value:Var
TYPE_DICTIONARY:
input = load("res://addons/dialogic/Editor/Events/Fields/field_dictionary.tscn").instantiate()
input.property_name = property_info["name"]
input.set_value(value)
input.value_changed.connect(_on_export_dict_submitted.bind(property_changed))
TYPE_OBJECT:
input = load("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn").instantiate()
@ -543,7 +533,7 @@ static func _on_export_color_submitted(color:Color, property_name:String, callab
static func _on_export_int_enum_submitted(item:int, property_name:String, callable: Callable) -> void:
callable.call(property_name, var_to_str(item))
static func _on_export_number_submitted(value:float, property_name:String, callable: Callable) -> void:
static func _on_export_number_submitted(property_name:String, value:float, callable: Callable) -> void:
callable.call(property_name, var_to_str(value))
static func _on_export_file_submitted(property_name:String, value:String, callable: Callable) -> void:
@ -555,6 +545,13 @@ static func _on_export_string_enum_submitted(value:int, property_name:String, li
static func _on_export_vector_submitted(property_name:String, value:Variant, callable: Callable) -> void:
callable.call(property_name, var_to_str(value))
static func _on_export_vectori_submitted(property_name:String, value:Variant, callable: Callable) -> void:
match typeof(value):
TYPE_VECTOR2: value = Vector2i(value)
TYPE_VECTOR3: value = Vector3i(value)
TYPE_VECTOR4: value = Vector4i(value)
callable.call(property_name, var_to_str(value))
static func _on_export_dict_submitted(property_name:String, value:Variant, callable: Callable) -> void:
callable.call(property_name, var_to_str(value))
@ -674,3 +671,133 @@ static func get_portrait_position_suggestions(search_text := "") -> Dictionary:
suggestions.erase(search_text)
return suggestions
static func get_autoload_suggestions(filter:String="") -> Dictionary:
var suggestions := {}
for prop in ProjectSettings.get_property_list():
if prop.name.begins_with('autoload/'):
var some_autoload: String = prop.name.trim_prefix('autoload/')
suggestions[some_autoload] = {'value': some_autoload, 'tooltip':some_autoload, 'editor_icon': ["Node", "EditorIcons"]}
if filter.begins_with(some_autoload):
suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]}
return suggestions
static func get_autoload_script_resource(autoload_name:String) -> Script:
var script: Script
if autoload_name and ProjectSettings.has_setting('autoload/'+autoload_name):
var loaded_autoload := load(ProjectSettings.get_setting('autoload/'+autoload_name).trim_prefix('*'))
if loaded_autoload is PackedScene:
var packed_scene: PackedScene = loaded_autoload
script = packed_scene.instantiate().get_script()
else:
script = loaded_autoload
return script
static func get_autoload_method_suggestions(filter:String, autoload_name:String) -> Dictionary:
var suggestions := {}
var script := get_autoload_script_resource(autoload_name)
if script:
for script_method in script.get_script_method_list():
if script_method.name.begins_with('@') or script_method.name.begins_with('_'):
continue
suggestions[script_method.name] = {'value': script_method.name, 'tooltip':script_method.name, 'editor_icon': ["Callable", "EditorIcons"]}
if not filter.is_empty():
suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]}
return suggestions
static func get_autoload_property_suggestions(_filter:String, autoload_name:String) -> Dictionary:
var suggestions := {}
var script := get_autoload_script_resource(autoload_name)
if script:
for property in script.get_script_property_list():
if property.name.ends_with('.gd') or property.name.begins_with('_'):
continue
suggestions[property.name] = {'value': property.name, 'tooltip':property.name, 'editor_icon': ["MemberProperty", "EditorIcons"]}
return suggestions
static func get_audio_bus_suggestions(_filter:= "") -> Dictionary:
var bus_name_list := {}
for i in range(AudioServer.bus_count):
if i == 0:
bus_name_list[AudioServer.get_bus_name(i)] = {'value':''}
else:
bus_name_list[AudioServer.get_bus_name(i)] = {'value':AudioServer.get_bus_name(i)}
return bus_name_list
static func get_audio_channel_suggestions(_search_text:String) -> Dictionary:
var suggestions := {}
var channel_defaults := DialogicUtil.get_audio_channel_defaults()
var cached_names := DialogicResourceUtil.get_channel_list()
for i in channel_defaults.keys():
if not cached_names.has(i):
cached_names.append(i)
cached_names.sort()
for i in cached_names:
if i.is_empty():
continue
suggestions[i] = {'value': i}
if i in channel_defaults.keys():
suggestions[i]["editor_icon"] = ["ProjectList", "EditorIcons"]
suggestions[i]["tooltip"] = "A default channel defined in the settings."
else:
suggestions[i]["editor_icon"] = ["AudioStreamPlayer", "EditorIcons"]
suggestions[i]["tooltip"] = "A temporary channel without defaults."
return suggestions
static func get_audio_channel_defaults() -> Dictionary:
return ProjectSettings.get_setting('dialogic/audio/channel_defaults', {
"": {
'volume': 0.0,
'audio_bus': '',
'fade_length': 0.0,
'loop': false,
},
"music": {
'volume': 0.0,
'audio_bus': '',
'fade_length': 0.0,
'loop': true,
}})
static func validate_audio_channel_name(text: String) -> Dictionary:
var result := {}
var channel_name_regex := RegEx.create_from_string(r'(?<dash_only>^-$)|(?<invalid>[^\w-]{1})')
var matches := channel_name_regex.search_all(text)
var invalid_chars := []
for regex_match in matches:
if regex_match.get_string('dash_only'):
result['error_tooltip'] = "Channel name cannot be '-'."
result['valid_text'] = ''
else:
var invalid_char = regex_match.get_string('invalid')
if not invalid_char in invalid_chars:
invalid_chars.append(invalid_char)
if invalid_chars:
result['valid_text'] = channel_name_regex.sub(text, '', true)
result['error_tooltip'] = "Channel names cannot contain the following characters: " + "".join(invalid_chars)
return result