First work on dialogic, resized guild, and started implementing portraits.
This commit is contained in:
13
addons/dialogic/Editor/Settings/HintLabelStylingScript.gd
Normal file
13
addons/dialogic/Editor/Settings/HintLabelStylingScript.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
@tool
|
||||
extends Label
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# don't load the label settings when opening as a scene
|
||||
# prevents HUGE diffs
|
||||
if owner.get_parent() is SubViewport:
|
||||
return
|
||||
label_settings = LabelSettings.new()
|
||||
label_settings.font = get_theme_font("doc_italic", "EditorFonts")
|
||||
label_settings.font_size = get_theme_font_size('font_size', 'Label')
|
||||
label_settings.font_color = get_theme_color("accent_color", "Editor")
|
||||
@@ -0,0 +1 @@
|
||||
uid://ds8mckibk1a8t
|
||||
356
addons/dialogic/Editor/Settings/csv_file.gd
Normal file
356
addons/dialogic/Editor/Settings/csv_file.gd
Normal file
@@ -0,0 +1,356 @@
|
||||
class_name DialogicCsvFile
|
||||
extends RefCounted
|
||||
## Handles translation of a [class DialogicTimeline] to a CSV file.
|
||||
|
||||
var lines: Array[PackedStringArray] = []
|
||||
## Dictionary of lines from the original file.
|
||||
## Key: String, Value: PackedStringArray
|
||||
var old_lines: Dictionary = {}
|
||||
|
||||
## The amount of columns the CSV file has after loading it.
|
||||
## Used to add trailing commas to new lines.
|
||||
var column_count := 0
|
||||
|
||||
## Whether this CSV file was able to be loaded a defined
|
||||
## file path.
|
||||
var is_new_file: bool = false
|
||||
|
||||
## The underlying file used to read and write the CSV file.
|
||||
var file: FileAccess
|
||||
|
||||
## File path used to load the CSV file.
|
||||
var used_file_path: String
|
||||
|
||||
## The amount of events that were updated in the CSV file.
|
||||
var updated_rows: int = 0
|
||||
|
||||
## The amount of events that were added to the CSV file.
|
||||
var new_rows: int = 0
|
||||
|
||||
## Whether this CSV handler should add newlines as a separator between sections.
|
||||
## A section may be a new character, new timeline, or new glossary item inside
|
||||
## a per-project file.
|
||||
var add_separator: bool = false
|
||||
|
||||
enum PropertyType {
|
||||
String = 0,
|
||||
Array = 1,
|
||||
Other = 2,
|
||||
}
|
||||
|
||||
## The translation property used for the glossary item translation.
|
||||
const TRANSLATION_ID := DialogicGlossary.TRANSLATION_PROPERTY
|
||||
|
||||
## Attempts to load the CSV file from [param file_path].
|
||||
## If the file does not exist, a single entry is added to the [member lines]
|
||||
## array.
|
||||
## The [param separator_enabled] enables adding newlines as a separator to
|
||||
## per-project files. This is useful for readability.
|
||||
func _init(file_path: String, original_locale: String, separator_enabled: bool) -> void:
|
||||
used_file_path = file_path
|
||||
add_separator = separator_enabled
|
||||
|
||||
# The first entry must be the locale row.
|
||||
# [method collect_lines_from_timeline] will add the other locales, if any.
|
||||
var locale_array_line := PackedStringArray(["keys", original_locale])
|
||||
lines.append(locale_array_line)
|
||||
|
||||
if not ResourceLoader.exists(file_path):
|
||||
is_new_file = true
|
||||
|
||||
# The "keys" and original locale are the only columns in a new file.
|
||||
# For example: "keys, en"
|
||||
column_count = 2
|
||||
return
|
||||
|
||||
file = FileAccess.open(file_path, FileAccess.READ)
|
||||
|
||||
var locale_csv_row := file.get_csv_line()
|
||||
column_count = locale_csv_row.size()
|
||||
var locale_key := locale_csv_row[0]
|
||||
|
||||
old_lines[locale_key] = locale_csv_row
|
||||
|
||||
_read_file_into_lines()
|
||||
|
||||
|
||||
## Private function to read the CSV file into the [member lines] array.
|
||||
## Cannot be called on a new file.
|
||||
func _read_file_into_lines() -> void:
|
||||
while not file.eof_reached():
|
||||
var line := file.get_csv_line()
|
||||
var row_key := line[0]
|
||||
|
||||
old_lines[row_key] = line
|
||||
|
||||
|
||||
## Collects names from the given [param characters] and adds them to the
|
||||
## [member lines].
|
||||
##
|
||||
## If this is the character name CSV file, use this method to
|
||||
## take previously collected characters from other [class DialogicCsvFile]s.
|
||||
func collect_lines_from_characters(characters: Dictionary) -> void:
|
||||
for character: DialogicCharacter in characters.values():
|
||||
# Add row for display names.
|
||||
var name_property := DialogicCharacter.TranslatedProperties.NAME
|
||||
var display_name_key: String = character.get_property_translation_key(name_property)
|
||||
var line_value: String = character.display_name
|
||||
var array_line := PackedStringArray([display_name_key, line_value])
|
||||
lines.append(array_line)
|
||||
|
||||
var nicknames: Array = character.nicknames
|
||||
|
||||
if not nicknames.is_empty():
|
||||
var nick_name_property := DialogicCharacter.TranslatedProperties.NICKNAMES
|
||||
var nickname_string: String = ",".join(nicknames)
|
||||
var nickname_name_line_key: String = character.get_property_translation_key(nick_name_property)
|
||||
var nick_array_line := PackedStringArray([nickname_name_line_key, nickname_string])
|
||||
lines.append(nick_array_line)
|
||||
|
||||
# New character item, if needed, add a separator.
|
||||
if add_separator:
|
||||
_append_empty()
|
||||
|
||||
|
||||
## Appends an empty line to the [member lines] array.
|
||||
func _append_empty() -> void:
|
||||
var empty_line := PackedStringArray(["", ""])
|
||||
lines.append(empty_line)
|
||||
|
||||
|
||||
## Returns the property type for the given [param key].
|
||||
func _get_key_type(key: String) -> PropertyType:
|
||||
if key.ends_with(DialogicGlossary.NAME_PROPERTY):
|
||||
return PropertyType.String
|
||||
|
||||
if key.ends_with(DialogicGlossary.ALTERNATIVE_PROPERTY):
|
||||
return PropertyType.Array
|
||||
|
||||
return PropertyType.Other
|
||||
|
||||
|
||||
func _process_line_into_array(csv_values: PackedStringArray, property_type: PropertyType) -> Array[String]:
|
||||
const KEY_VALUE_INDEX := 0
|
||||
var values_as_array: Array[String] = []
|
||||
|
||||
for i in csv_values.size():
|
||||
|
||||
if i == KEY_VALUE_INDEX:
|
||||
continue
|
||||
|
||||
var csv_value := csv_values[i]
|
||||
|
||||
if csv_value.is_empty():
|
||||
continue
|
||||
|
||||
match property_type:
|
||||
PropertyType.String:
|
||||
values_as_array = [csv_value]
|
||||
|
||||
PropertyType.Array:
|
||||
var split_values := csv_value.split(",")
|
||||
|
||||
for value in split_values:
|
||||
values_as_array.append(value)
|
||||
|
||||
return values_as_array
|
||||
|
||||
|
||||
func _add_keys_to_glossary(glossary: DialogicGlossary, names: Array) -> void:
|
||||
var glossary_prefix_key := glossary._get_glossary_translation_id_prefix()
|
||||
var glossary_translation_id_prefix := _get_glossary_translation_key_prefix(glossary)
|
||||
|
||||
for glossary_line: PackedStringArray in names:
|
||||
|
||||
if glossary_line.is_empty():
|
||||
continue
|
||||
|
||||
var csv_key := glossary_line[0]
|
||||
|
||||
# CSV line separators will be empty.
|
||||
if not csv_key.begins_with(glossary_prefix_key):
|
||||
continue
|
||||
|
||||
var value_type := _get_key_type(csv_key)
|
||||
|
||||
# String and Array are the only valid types.
|
||||
if (value_type == PropertyType.Other
|
||||
or not csv_key.begins_with(glossary_translation_id_prefix)):
|
||||
continue
|
||||
|
||||
var new_line_to_add := _process_line_into_array(glossary_line, value_type)
|
||||
|
||||
for name_to_add: String in new_line_to_add:
|
||||
glossary._translation_keys[name_to_add.strip_edges()] = csv_key
|
||||
|
||||
|
||||
|
||||
## Reads all [member lines] and adds them to the given [param glossary]'s
|
||||
## internal collection of words-to-translation-key mappings.
|
||||
##
|
||||
## Populate the CSV's lines with the method [method collect_lines_from_glossary]
|
||||
## before.
|
||||
func add_translation_keys_to_glossary(glossary: DialogicGlossary) -> void:
|
||||
glossary._translation_keys.clear()
|
||||
_add_keys_to_glossary(glossary, lines)
|
||||
_add_keys_to_glossary(glossary, old_lines.values())
|
||||
|
||||
|
||||
## Returns the translation key prefix for the given [param glossary_translation_id].
|
||||
## The resulting format will look like this: Glossary/a2/
|
||||
## You can use this to find entries in [member lines] that to a glossary.
|
||||
func _get_glossary_translation_key_prefix(glossary: DialogicGlossary) -> String:
|
||||
return (
|
||||
DialogicGlossary.RESOURCE_NAME
|
||||
.path_join(glossary._translation_id)
|
||||
)
|
||||
|
||||
|
||||
## Returns whether [param value_b] is greater than [param value_a].
|
||||
##
|
||||
## This method helps to sort glossary entry properties by their importance
|
||||
## matching the order in the editor.
|
||||
##
|
||||
## TODO: Allow Dialogic users to define their own order.
|
||||
func _sort_glossary_entry_property_keys(property_key_a: String, property_key_b: String) -> bool:
|
||||
const GLOSSARY_CSV_LINE_ORDER := {
|
||||
DialogicGlossary.NAME_PROPERTY: 0,
|
||||
DialogicGlossary.ALTERNATIVE_PROPERTY: 1,
|
||||
DialogicGlossary.TEXT_PROPERTY: 2,
|
||||
DialogicGlossary.EXTRA_PROPERTY: 3,
|
||||
}
|
||||
const UNKNOWN_PROPERTY_ORDER := 100
|
||||
|
||||
var value_a: int = GLOSSARY_CSV_LINE_ORDER.get(property_key_a, UNKNOWN_PROPERTY_ORDER)
|
||||
var value_b: int = GLOSSARY_CSV_LINE_ORDER.get(property_key_b, UNKNOWN_PROPERTY_ORDER)
|
||||
|
||||
return value_a < value_b
|
||||
|
||||
|
||||
## Collects properties from glossary entries from the given [param glossary] and
|
||||
## adds them to the [member lines].
|
||||
func collect_lines_from_glossary(glossary: DialogicGlossary) -> void:
|
||||
|
||||
for glossary_value: Variant in glossary.entries.values():
|
||||
|
||||
if glossary_value is String:
|
||||
continue
|
||||
|
||||
var glossary_entry: Dictionary = glossary_value
|
||||
var glossary_entry_name: String = glossary_entry[DialogicGlossary.NAME_PROPERTY]
|
||||
|
||||
var _glossary_translation_id := glossary.get_set_glossary_translation_id()
|
||||
var entry_translation_id := glossary.get_set_glossary_entry_translation_id(glossary_entry_name)
|
||||
|
||||
var entry_property_keys := glossary_entry.keys().duplicate()
|
||||
entry_property_keys.sort_custom(_sort_glossary_entry_property_keys)
|
||||
|
||||
var entry_name_property: String = glossary_entry[DialogicGlossary.NAME_PROPERTY]
|
||||
|
||||
for entry_key: String in entry_property_keys:
|
||||
# Ignore private keys.
|
||||
if entry_key.begins_with(DialogicGlossary.PRIVATE_PROPERTY_PREFIX):
|
||||
continue
|
||||
|
||||
var item_value: Variant = glossary_entry[entry_key]
|
||||
var item_value_str := ""
|
||||
|
||||
if item_value is Array:
|
||||
var item_array := item_value as Array
|
||||
# We use a space after the comma to make it easier to read.
|
||||
item_value_str = " ,".join(item_array)
|
||||
|
||||
elif not item_value is String or item_value.is_empty():
|
||||
continue
|
||||
|
||||
else:
|
||||
item_value_str = item_value
|
||||
|
||||
var glossary_csv_key := glossary._get_glossary_translation_key(entry_translation_id, entry_key)
|
||||
|
||||
if (entry_key == DialogicGlossary.NAME_PROPERTY
|
||||
or entry_key == DialogicGlossary.ALTERNATIVE_PROPERTY):
|
||||
glossary.entries[glossary_csv_key] = entry_name_property
|
||||
|
||||
var glossary_line := PackedStringArray([glossary_csv_key, item_value_str])
|
||||
|
||||
lines.append(glossary_line)
|
||||
|
||||
# New glossary item, if needed, add a separator.
|
||||
if add_separator:
|
||||
_append_empty()
|
||||
|
||||
|
||||
|
||||
## Collects translatable events from the given [param timeline] and adds
|
||||
## them to the [member lines].
|
||||
func collect_lines_from_timeline(timeline: DialogicTimeline) -> void:
|
||||
for event: DialogicEvent in timeline.events:
|
||||
|
||||
if event.can_be_translated():
|
||||
|
||||
if event._translation_id.is_empty():
|
||||
event.add_translation_id()
|
||||
event.update_text_version()
|
||||
|
||||
var properties: Array = event._get_translatable_properties()
|
||||
|
||||
for property: String in properties:
|
||||
var line_key: String = event.get_property_translation_key(property)
|
||||
var line_value: String = event._get_property_original_translation(property)
|
||||
var array_line := PackedStringArray([line_key, line_value])
|
||||
lines.append(array_line)
|
||||
|
||||
# End of timeline, if needed, add a separator.
|
||||
if add_separator:
|
||||
_append_empty()
|
||||
|
||||
|
||||
## Clears the CSV file on disk and writes the current [member lines] array to it.
|
||||
## Uses the [member old_lines] dictionary to update existing translations.
|
||||
## If a translation row misses a column, a trailing comma will be added to
|
||||
## conform to the CSV file format.
|
||||
##
|
||||
## If the locale CSV line was collected only, a new file won't be created and
|
||||
## already existing translations won't be updated.
|
||||
func update_csv_file_on_disk() -> void:
|
||||
# None or locale row only.
|
||||
if lines.size() < 2:
|
||||
print_rich("[color=yellow]No lines for the CSV file, skipping: " + used_file_path)
|
||||
|
||||
return
|
||||
|
||||
# Clear the current CSV file.
|
||||
file = FileAccess.open(used_file_path, FileAccess.WRITE)
|
||||
|
||||
for line in lines:
|
||||
var row_key := line[0]
|
||||
|
||||
# In case there might be translations for this line already,
|
||||
# add them at the end again (orig locale text is replaced).
|
||||
if row_key in old_lines:
|
||||
var old_line: PackedStringArray = old_lines[row_key]
|
||||
var updated_line: PackedStringArray = line + old_line.slice(2)
|
||||
|
||||
var line_columns: int = updated_line.size()
|
||||
var line_columns_to_add := column_count - line_columns
|
||||
|
||||
# Add trailing commas to match the amount of columns.
|
||||
for _i in range(line_columns_to_add):
|
||||
updated_line.append("")
|
||||
|
||||
file.store_csv_line(updated_line)
|
||||
updated_rows += 1
|
||||
|
||||
else:
|
||||
var line_columns: int = line.size()
|
||||
var line_columns_to_add := column_count - line_columns
|
||||
|
||||
# Add trailing commas to match the amount of columns.
|
||||
for _i in range(line_columns_to_add):
|
||||
line.append("")
|
||||
|
||||
file.store_csv_line(line)
|
||||
new_rows += 1
|
||||
|
||||
file.close()
|
||||
1
addons/dialogic/Editor/Settings/csv_file.gd.uid
Normal file
1
addons/dialogic/Editor/Settings/csv_file.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://q7qb1gsp5nyj
|
||||
169
addons/dialogic/Editor/Settings/settings_editor.gd
Normal file
169
addons/dialogic/Editor/Settings/settings_editor.gd
Normal file
@@ -0,0 +1,169 @@
|
||||
@tool
|
||||
extends DialogicEditor
|
||||
|
||||
## Editor that contains all settings
|
||||
|
||||
var button_group := ButtonGroup.new()
|
||||
var registered_sections: Array[DialogicSettingsPage] = []
|
||||
|
||||
|
||||
func _get_title() -> String:
|
||||
return "Settings"
|
||||
|
||||
|
||||
func _get_icon() -> Texture:
|
||||
return get_theme_icon("PluginScript", "EditorIcons")
|
||||
|
||||
|
||||
func _register() -> void:
|
||||
editors_manager.register_simple_editor(self)
|
||||
self.alternative_text = "Customize dialogic and it's behaviour"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if get_parent() is SubViewport:
|
||||
return
|
||||
|
||||
register_settings_section("res://addons/dialogic/Editor/Settings/settings_general.tscn")
|
||||
register_settings_section("res://addons/dialogic/Editor/Settings/settings_translation.tscn")
|
||||
register_settings_section("res://addons/dialogic/Editor/Settings/settings_modules.tscn")
|
||||
|
||||
for indexer in DialogicUtil.get_indexers():
|
||||
for settings_page in indexer._get_settings_pages():
|
||||
register_settings_section(settings_page)
|
||||
|
||||
add_registered_sections()
|
||||
%SettingsTabs.get_child(0).button_pressed = true
|
||||
%SettingsContent.get_child(0).show()
|
||||
|
||||
|
||||
func register_settings_section(path:String) -> void:
|
||||
var section: Control = load(path).instantiate()
|
||||
registered_sections.append(section)
|
||||
|
||||
|
||||
func add_registered_sections() -> void:
|
||||
for i in %SettingsTabs.get_children():
|
||||
i.queue_free()
|
||||
for i in %FeatureTabs.get_children():
|
||||
i.queue_free()
|
||||
|
||||
for i in %SettingsContent.get_children():
|
||||
i.queue_free()
|
||||
|
||||
|
||||
registered_sections.sort_custom(section_sort)
|
||||
for section in registered_sections:
|
||||
|
||||
section.name = section._get_title()
|
||||
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.set_meta('section', section)
|
||||
vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
vbox.name = section.name
|
||||
var hbox := HBoxContainer.new()
|
||||
|
||||
var title := Label.new()
|
||||
title.text = section.name
|
||||
title.theme_type_variation = 'DialogicSectionBig'
|
||||
hbox.add_child(title)
|
||||
vbox.add_child(hbox)
|
||||
|
||||
|
||||
if !section.short_info.is_empty():
|
||||
var tooltip_hint: Control = load("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn").instantiate()
|
||||
tooltip_hint.hint_text = section.short_info
|
||||
hbox.add_child(tooltip_hint)
|
||||
|
||||
|
||||
var scroll := ScrollContainer.new()
|
||||
scroll.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
var inner_vbox := VBoxContainer.new()
|
||||
inner_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
inner_vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
scroll.add_child(inner_vbox)
|
||||
var panel := PanelContainer.new()
|
||||
panel.theme_type_variation = "DialogicPanelA"
|
||||
panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
if section.size_flags_vertical == Control.SIZE_EXPAND_FILL:
|
||||
panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
inner_vbox.add_child(panel)
|
||||
|
||||
|
||||
var info_section: Control = section._get_info_section()
|
||||
if info_section != null:
|
||||
inner_vbox.add_child(Control.new())
|
||||
inner_vbox.get_child(-1).custom_minimum_size.y = 50
|
||||
|
||||
inner_vbox.add_child(title.duplicate())
|
||||
inner_vbox.get_child(-1).text = "Information"
|
||||
var info_panel := panel.duplicate()
|
||||
info_panel.theme_type_variation = "DialogicPanelDarkA"
|
||||
|
||||
inner_vbox.add_child(info_panel)
|
||||
info_section.get_parent().remove_child(info_section)
|
||||
info_panel.add_child(info_section)
|
||||
|
||||
panel.add_child(section)
|
||||
vbox.add_child(scroll)
|
||||
|
||||
|
||||
var button := Button.new()
|
||||
button.text = " "+section.name
|
||||
button.tooltip_text = section.name
|
||||
button.toggle_mode = true
|
||||
button.button_group = button_group
|
||||
button.expand_icon = true
|
||||
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
button.flat = true
|
||||
button.add_theme_color_override('font_pressed_color', get_theme_color("property_color_z", "Editor"))
|
||||
button.add_theme_color_override('font_hover_color', get_theme_color('warning_color', 'Editor'))
|
||||
button.add_theme_color_override('font_focus_color', get_theme_color('warning_color', 'Editor'))
|
||||
button.add_theme_stylebox_override('focus', StyleBoxEmpty.new())
|
||||
button.pressed.connect(open_tab.bind(vbox))
|
||||
if section._is_feature_tab():
|
||||
%FeatureTabs.add_child(button)
|
||||
else:
|
||||
%SettingsTabs.add_child(button)
|
||||
|
||||
vbox.hide()
|
||||
# if section.has_method('_get_icon'):
|
||||
# icon.texture = section._get_icon()
|
||||
%SettingsContent.add_child(vbox)
|
||||
|
||||
|
||||
func open_tab(tab_to_show:Control) -> void:
|
||||
for tab in %SettingsContent.get_children():
|
||||
tab.hide()
|
||||
|
||||
tab_to_show.show()
|
||||
|
||||
|
||||
func section_sort(item1:DialogicSettingsPage, item2:DialogicSettingsPage) -> bool:
|
||||
if !item1._is_feature_tab() and item2._is_feature_tab():
|
||||
return true
|
||||
if item1._get_priority() > item2._get_priority():
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
|
||||
func _open(extra_information:Variant = null) -> void:
|
||||
refresh()
|
||||
if typeof(extra_information) == TYPE_STRING:
|
||||
if %SettingsContent.has_node(extra_information):
|
||||
open_tab(%SettingsContent.get_node(extra_information))
|
||||
|
||||
|
||||
func _close() -> void:
|
||||
for child in %SettingsContent.get_children():
|
||||
if child.get_meta('section').has_method('_about_to_close'):
|
||||
child.get_meta('section')._about_to_close()
|
||||
|
||||
|
||||
func refresh() -> void:
|
||||
for child in %SettingsContent.get_children():
|
||||
if child.get_meta('section').has_method('_refresh'):
|
||||
child.get_meta('section')._refresh()
|
||||
|
||||
1
addons/dialogic/Editor/Settings/settings_editor.gd.uid
Normal file
1
addons/dialogic/Editor/Settings/settings_editor.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ddt0uutspr055
|
||||
59
addons/dialogic/Editor/Settings/settings_editor.tscn
Normal file
59
addons/dialogic/Editor/Settings/settings_editor.tscn
Normal file
@@ -0,0 +1,59 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dganirw26brfb"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Editor/Settings/settings_editor.gd" id="1"]
|
||||
|
||||
[node name="Settings" type="HSplitContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="TabList" type="ScrollContainer" parent="."]
|
||||
layout_mode = 2
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="TabList"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_top = 3
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="TabList/Margin"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="Title" type="Label" parent="TabList/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSection"
|
||||
text = "Settings"
|
||||
|
||||
[node name="SettingsTabs" type="VBoxContainer" parent="TabList/Margin/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="Control" type="Control" parent="TabList/Margin/VBox"]
|
||||
custom_minimum_size = Vector2(0, 30)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title2" type="Label" parent="TabList/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSection"
|
||||
text = "Features"
|
||||
|
||||
[node name="FeatureTabs" type="VBoxContainer" parent="TabList/Margin/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="SettingsContent" type="VBoxContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
247
addons/dialogic/Editor/Settings/settings_general.gd
Normal file
247
addons/dialogic/Editor/Settings/settings_general.gd
Normal file
@@ -0,0 +1,247 @@
|
||||
@tool
|
||||
extends DialogicSettingsPage
|
||||
|
||||
## Settings tab that holds genreal dialogic settings.
|
||||
|
||||
|
||||
func _get_title() -> String:
|
||||
return "General"
|
||||
|
||||
|
||||
func _get_priority() -> int:
|
||||
return 99
|
||||
|
||||
func _ready() -> void:
|
||||
var s := DCSS.inline({
|
||||
'padding': 5,
|
||||
'background': Color(0.545098, 0.545098, 0.545098, 0.211765)
|
||||
})
|
||||
%ExtensionsFolderPicker.resource_icon = get_theme_icon("Folder", "EditorIcons")
|
||||
|
||||
# Signals
|
||||
%ExtensionsFolderPicker.value_changed.connect(_on_ExtensionsFolder_value_changed)
|
||||
%PhysicsTimerButton.toggled.connect(_on_physics_timer_button_toggled)
|
||||
|
||||
# Colors
|
||||
%ResetColorsButton.icon = get_theme_icon("Reload", "EditorIcons")
|
||||
%ResetColorsButton.button_up.connect(_on_reset_colors_button)
|
||||
|
||||
# Extension creator
|
||||
%ExtensionCreator.hide()
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
%PhysicsTimerButton.button_pressed = DialogicUtil.is_physics_timer()
|
||||
%LayoutNodeEndBehaviour.select(ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0))
|
||||
%ExtensionsFolderPicker.set_value(ProjectSettings.get_setting('dialogic/extensions_folder', 'res://addons/dialogic_additions'))
|
||||
|
||||
update_color_palette()
|
||||
|
||||
%SectionList.clear()
|
||||
%SectionList.create_item()
|
||||
var cached_events := DialogicResourceUtil.get_event_cache()
|
||||
var sections := []
|
||||
var section_order: Array = DialogicUtil.get_editor_setting('event_section_order', ['Main', 'Logic', 'Flow', 'Audio', 'Visuals','Other', 'Helper'])
|
||||
for ev in cached_events:
|
||||
if !ev.event_category in sections:
|
||||
sections.append(ev.event_category)
|
||||
var item: TreeItem = %SectionList.create_item(null)
|
||||
item.set_text(0, ev.event_category)
|
||||
item.add_button(0, get_theme_icon("ArrowUp", "EditorIcons"))
|
||||
item.add_button(0, get_theme_icon("ArrowDown", "EditorIcons"))
|
||||
if ev.event_category in section_order:
|
||||
|
||||
item.move_before(item.get_parent().get_child(min(section_order.find(ev.event_category),item.get_parent().get_child_count()-1)))
|
||||
|
||||
%SectionList.get_root().get_child(0).set_button_disabled(0, 0, true)
|
||||
%SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true)
|
||||
|
||||
|
||||
func _on_section_list_button_clicked(item:TreeItem, column, id, mouse_button_index):
|
||||
if id == 0:
|
||||
item.move_before(item.get_parent().get_child(item.get_index()-1))
|
||||
else:
|
||||
item.move_after(item.get_parent().get_child(item.get_index()+1))
|
||||
|
||||
for child in %SectionList.get_root().get_children():
|
||||
child.set_button_disabled(0, 0, false)
|
||||
child.set_button_disabled(0, 1, false)
|
||||
|
||||
%SectionList.get_root().get_child(0).set_button_disabled(0, 0, true)
|
||||
%SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true)
|
||||
|
||||
var sections := []
|
||||
for child in %SectionList.get_root().get_children():
|
||||
sections.append(child.get_text(0))
|
||||
|
||||
DialogicUtil.set_editor_setting('event_section_order', sections)
|
||||
force_event_button_list_reload()
|
||||
|
||||
|
||||
func force_event_button_list_reload() -> void:
|
||||
find_parent('EditorsManager').editors['Timeline'].node.get_node('%VisualEditor').load_event_buttons()
|
||||
|
||||
|
||||
func update_color_palette() -> void:
|
||||
# Color Palette
|
||||
for child in %Colors.get_children():
|
||||
child.queue_free()
|
||||
for color in DialogicUtil.get_color_palette():
|
||||
var button := ColorPickerButton.new()
|
||||
button.custom_minimum_size = Vector2(50 ,50) * DialogicUtil.get_editor_scale()
|
||||
%Colors.add_child(button)
|
||||
button.color = DialogicUtil.get_color(color)
|
||||
button.color_changed.connect(_on_color_change)
|
||||
|
||||
|
||||
func _on_color_change(color:Color) -> void:
|
||||
var new_palette := {}
|
||||
for i in %Colors.get_children():
|
||||
new_palette['Color'+str(i.get_index()+1)] = i.color
|
||||
DialogicUtil.set_editor_setting('color_palette', new_palette)
|
||||
|
||||
|
||||
|
||||
func _on_reset_colors_button() -> void:
|
||||
DialogicUtil.set_editor_setting('color_palette', null)
|
||||
update_color_palette()
|
||||
|
||||
|
||||
func _on_physics_timer_button_toggled(is_toggled: bool) -> void:
|
||||
ProjectSettings.set_setting('dialogic/timer/process_in_physics', is_toggled)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_ExtensionsFolder_value_changed(property:String, value:String) -> void:
|
||||
if value == null or value.is_empty():
|
||||
value = 'res://addons/dialogic_additions'
|
||||
ProjectSettings.set_setting('dialogic/extensions_folder', value)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_layout_node_end_behaviour_item_selected(index:int) -> void:
|
||||
ProjectSettings.set_setting('dialogic/layout/end_behaviour', index)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
################################################################################
|
||||
## EXTENSION CREATOR
|
||||
################################################################################
|
||||
|
||||
func _on_create_extension_button_pressed() -> void:
|
||||
%CreateExtensionButton.hide()
|
||||
%ExtensionCreator.show()
|
||||
|
||||
%NameEdit.text = ""
|
||||
%NameEdit.grab_focus()
|
||||
|
||||
|
||||
func _on_submit_extension_button_pressed() -> void:
|
||||
if %NameEdit.text.is_empty():
|
||||
return
|
||||
|
||||
var extensions_folder: String = ProjectSettings.get_setting('dialogic/extensions_folder', 'res://addons/dialogic_additions')
|
||||
|
||||
extensions_folder = extensions_folder.path_join(%NameEdit.text.to_pascal_case())
|
||||
DirAccess.make_dir_recursive_absolute(extensions_folder)
|
||||
var mode: int = %ExtensionMode.selected
|
||||
|
||||
var file: FileAccess
|
||||
var indexer_content := "@tool\nextends DialogicIndexer\n\n"
|
||||
if mode != 2: # don't add event in Subsystem Only mode
|
||||
indexer_content += """func _get_events() -> Array:
|
||||
return [this_folder.path_join('event_"""+%NameEdit.text.to_snake_case()+""".gd')]\n\n"""
|
||||
file = FileAccess.open(extensions_folder.path_join('event_'+%NameEdit.text.to_snake_case()+'.gd'), FileAccess.WRITE)
|
||||
file.store_string(
|
||||
|
||||
#region EXTENDED EVENT SCRIPT
|
||||
"""@tool
|
||||
extends DialogicEvent
|
||||
class_name Dialogic"""+%NameEdit.text.to_pascal_case()+"""Event
|
||||
|
||||
# Define properties of the event here
|
||||
|
||||
func _execute() -> void:
|
||||
# This will execute when the event is reached
|
||||
finish() # called to continue with the next event
|
||||
|
||||
|
||||
#region INITIALIZE
|
||||
################################################################################
|
||||
# Set fixed settings of this event
|
||||
func _init() -> void:
|
||||
event_name = \""""+%NameEdit.text.capitalize()+"""\"
|
||||
event_category = "Other"
|
||||
|
||||
\n
|
||||
#endregion
|
||||
|
||||
#region SAVING/LOADING
|
||||
################################################################################
|
||||
func get_shortcode() -> String:
|
||||
return \""""+%NameEdit.text.to_snake_case()+"""\"
|
||||
|
||||
func get_shortcode_parameters() -> Dictionary:
|
||||
return {
|
||||
#param_name : property_info
|
||||
#"my_parameter" : {"property": "property", "default": "Default"},
|
||||
}
|
||||
|
||||
# You can alternatively overwrite these 3 functions: to_text(), from_text(), is_valid_event()
|
||||
#endregion
|
||||
|
||||
|
||||
#region EDITOR REPRESENTATION
|
||||
################################################################################
|
||||
|
||||
func build_event_editor() -> void:
|
||||
pass
|
||||
|
||||
#endregion
|
||||
""")
|
||||
|
||||
#endregion
|
||||
if mode != 0: # don't add subsystem in event only mode
|
||||
indexer_content += """func _get_subsystems() -> Array:
|
||||
return [{'name':'"""+%NameEdit.text.to_pascal_case()+"""', 'script':this_folder.path_join('subsystem_"""+%NameEdit.text.to_snake_case()+""".gd')}]"""
|
||||
file = FileAccess.open(extensions_folder.path_join('subsystem_'+%NameEdit.text.to_snake_case()+'.gd'), FileAccess.WRITE)
|
||||
file.store_string(
|
||||
|
||||
# region EXTENDED SUBSYSTEM SCRIPT
|
||||
"""extends DialogicSubsystem
|
||||
|
||||
## Describe the subsystems purpose here.
|
||||
|
||||
|
||||
#region STATE
|
||||
####################################################################################################
|
||||
|
||||
func clear_game_state(clear_flag:=Dialogic.ClearFlags.FULL_CLEAR) -> void:
|
||||
pass
|
||||
|
||||
func load_game_state(load_flag:=LoadFlags.FULL_LOAD) -> void:
|
||||
pass
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MAIN METHODS
|
||||
####################################################################################################
|
||||
|
||||
# Add some useful methods here.
|
||||
|
||||
#endregion
|
||||
""")
|
||||
file = FileAccess.open(extensions_folder.path_join('index.gd'), FileAccess.WRITE)
|
||||
file.store_string(indexer_content)
|
||||
|
||||
%ExtensionCreator.hide()
|
||||
%CreateExtensionButton.show()
|
||||
|
||||
find_parent('EditorView').plugin_reference.get_editor_interface().get_resource_filesystem().scan_sources()
|
||||
force_event_button_list_reload()
|
||||
|
||||
|
||||
|
||||
func _on_reload_pressed() -> void:
|
||||
DialogicUtil._update_autoload_subsystem_access()
|
||||
1
addons/dialogic/Editor/Settings/settings_general.gd.uid
Normal file
1
addons/dialogic/Editor/Settings/settings_general.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dd68ldgly88gk
|
||||
283
addons/dialogic/Editor/Settings/settings_general.tscn
Normal file
283
addons/dialogic/Editor/Settings/settings_general.tscn
Normal file
@@ -0,0 +1,283 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://b873ho41sklv8"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Editor/Settings/settings_general.gd" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_kqhx5"]
|
||||
[ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="3_i7rug"]
|
||||
|
||||
[sub_resource type="Image" id="Image_e1gle"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_4wgbv"]
|
||||
image = SubResource("Image_e1gle")
|
||||
|
||||
[node name="General" type="VBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="PaletteTitle" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SectionPaletteTitle" type="Label" parent="PaletteTitle"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Color Palette"
|
||||
|
||||
[node name="HintTooltip" parent="PaletteTitle" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "These colors are used for the events."
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "These colors are used for the events."
|
||||
|
||||
[node name="ResetColorsButton" type="Button" parent="PaletteTitle"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
tooltip_text = "Reset Colors to default"
|
||||
icon = SubResource("ImageTexture_4wgbv")
|
||||
flat = true
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="."]
|
||||
layout_mode = 2
|
||||
horizontal_scroll_mode = 3
|
||||
vertical_scroll_mode = 0
|
||||
|
||||
[node name="Colors" type="HBoxContainer" parent="ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SectionBehaviourTitle" type="Label" parent="HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Layout Node Behaviour"
|
||||
|
||||
[node name="HintTooltip" parent="HBoxContainer2" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "The layout scene configured in the Layout editor is automatically
|
||||
instanced when calling Dialogic.start(). Depending on your game,
|
||||
you might want it to be deleted after the dialogue, be hidden
|
||||
(as reinstancing often is wasting resources) or kept visible. "
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "The layout scene configured in the Layout editor is automatically
|
||||
instanced when calling Dialogic.start(). Depending on your game,
|
||||
you might want it to be deleted after the dialogue, be hidden
|
||||
(as reinstancing often is wasting resources) or kept visible. "
|
||||
|
||||
[node name="HBoxContainer3" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer3"]
|
||||
layout_mode = 2
|
||||
text = "On timeline end"
|
||||
|
||||
[node name="LayoutNodeEndBehaviour" type="OptionButton" parent="HBoxContainer3"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
item_count = 3
|
||||
selected = 0
|
||||
fit_to_longest_item = false
|
||||
popup/item_0/text = "Delete Layout Node"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Hide Layout Node"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Keep Layout Node"
|
||||
popup/item_2/id = 2
|
||||
|
||||
[node name="HSeparator4" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer6" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer4" type="VBoxContainer" parent="HBoxContainer6"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="HBoxContainer5" type="HBoxContainer" parent="HBoxContainer6/HBoxContainer4"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SectionExtensionsTitle" type="Label" parent="HBoxContainer6/HBoxContainer4/HBoxContainer5"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Extensions"
|
||||
|
||||
[node name="HintTooltip" parent="HBoxContainer6/HBoxContainer4/HBoxContainer5" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Configure where dialogic looks for custom modules.
|
||||
|
||||
You will have to restart the project to see the change take action."
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "Configure where dialogic looks for custom modules.
|
||||
|
||||
You will have to restart the project to see the change take action."
|
||||
|
||||
[node name="Reload" type="Button" parent="HBoxContainer6/HBoxContainer4/HBoxContainer5"]
|
||||
layout_mode = 2
|
||||
text = "Reload"
|
||||
flat = true
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer6/HBoxContainer4"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer6/HBoxContainer4/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Extensions folder"
|
||||
|
||||
[node name="ExtensionsFolderPicker" parent="HBoxContainer6/HBoxContainer4/HBoxContainer" instance=ExtResource("3_i7rug")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
placeholder = "res://addons/dialogic_additions/Events"
|
||||
file_mode = 2
|
||||
resource_icon = SubResource("ImageTexture_4wgbv")
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="HBoxContainer6"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ExtensionsPanel" type="PanelContainer" parent="HBoxContainer6"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_type_variation = &"DialogicPanelA"
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="HBoxContainer6/ExtensionsPanel"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="HBoxContainer6" type="HBoxContainer" parent="HBoxContainer6/ExtensionsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer6/ExtensionsPanel/VBox/HBoxContainer6"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSubTitle"
|
||||
text = "Extension Creator "
|
||||
|
||||
[node name="HintTooltip" parent="HBoxContainer6/ExtensionsPanel/VBox/HBoxContainer6" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Use the Exension Creator to quickly setup custom modules!"
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "Use the Exension Creator to quickly setup custom modules!"
|
||||
|
||||
[node name="CreateExtensionButton" type="Button" parent="HBoxContainer6/ExtensionsPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Create New Extension"
|
||||
|
||||
[node name="ExtensionCreator" type="VBoxContainer" parent="HBoxContainer6/ExtensionsPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ExtensionCreatorOptions" type="GridContainer" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator"]
|
||||
layout_mode = 2
|
||||
columns = 2
|
||||
|
||||
[node name="NameLabel" type="Label" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/ExtensionCreatorOptions"]
|
||||
layout_mode = 2
|
||||
text = "Name:"
|
||||
|
||||
[node name="NameEdit" type="LineEdit" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/ExtensionCreatorOptions"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
placeholder_text = "e.g. \"Print\", \"Item\", \"Door\", \"Quest\""
|
||||
|
||||
[node name="ModeLabel" type="Label" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/ExtensionCreatorOptions"]
|
||||
layout_mode = 2
|
||||
text = "Setup mode:"
|
||||
|
||||
[node name="ExtensionMode" type="OptionButton" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/ExtensionCreatorOptions"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
item_count = 4
|
||||
selected = 0
|
||||
popup/item_0/text = "Event only"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Event+Subsystem"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Subsystem only"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "Complex"
|
||||
popup/item_3/id = 3
|
||||
|
||||
[node name="SubmitExtensionButton" type="Button" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Create"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer7" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TimerTitle" type="Label" parent="HBoxContainer7"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Timer processing"
|
||||
|
||||
[node name="HintTooltip" parent="HBoxContainer7" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Change whether dialogics timers process in physics_process (frame-rate independent) or process."
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "Change whether dialogics timers process in physics_process (frame-rate independent) or process."
|
||||
|
||||
[node name="HBoxContainer4" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer4"]
|
||||
layout_mode = 2
|
||||
text = "Process timers in physics_process"
|
||||
|
||||
[node name="PhysicsTimerButton" type="CheckBox" parent="HBoxContainer4"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator5" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SectionSections" type="Label" parent="HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Section Order"
|
||||
|
||||
[node name="HintTooltip" parent="HBoxContainer" instance=ExtResource("2_kqhx5")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "You can change the order of the event sections here. "
|
||||
texture = SubResource("ImageTexture_4wgbv")
|
||||
hint_text = "You can change the order of the event sections here. "
|
||||
|
||||
[node name="SectionList" type="Tree" parent="."]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 150)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/button_margin = 0
|
||||
allow_reselect = true
|
||||
allow_rmb_select = true
|
||||
hide_folding = true
|
||||
hide_root = true
|
||||
drop_mode_flags = 1
|
||||
|
||||
[connection signal="item_selected" from="HBoxContainer3/LayoutNodeEndBehaviour" to="." method="_on_layout_node_end_behaviour_item_selected"]
|
||||
[connection signal="pressed" from="HBoxContainer6/HBoxContainer4/HBoxContainer5/Reload" to="." method="_on_reload_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer6/ExtensionsPanel/VBox/CreateExtensionButton" to="." method="_on_create_extension_button_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/SubmitExtensionButton" to="." method="_on_submit_extension_button_pressed"]
|
||||
[connection signal="button_clicked" from="SectionList" to="." method="_on_section_list_button_clicked"]
|
||||
443
addons/dialogic/Editor/Settings/settings_modules.gd
Normal file
443
addons/dialogic/Editor/Settings/settings_modules.gd
Normal file
@@ -0,0 +1,443 @@
|
||||
@tool
|
||||
extends DialogicSettingsPage
|
||||
|
||||
|
||||
func _get_title() -> String:
|
||||
return "Modules"
|
||||
|
||||
func _get_priority() -> int:
|
||||
return 0
|
||||
|
||||
func _is_feature_tab() -> bool:
|
||||
return true
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if get_parent() is SubViewport:
|
||||
return
|
||||
%Refresh.icon = get_theme_icon("Loop", "EditorIcons")
|
||||
%Search.right_icon = get_theme_icon("Search", "EditorIcons")
|
||||
|
||||
%Filter_Events.icon = get_theme_icon("Favorites", "EditorIcons")
|
||||
%Filter_Subsystems.icon = get_theme_icon("Callable", "EditorIcons")
|
||||
%Filter_Styles.icon = get_theme_icon("PopupMenu", "EditorIcons")
|
||||
%Filter_EffectsAndModifiers.icon = get_theme_icon("RichTextEffect", "EditorIcons")
|
||||
%Filter_Editors.icon = get_theme_icon("ConfirmationDialog", "EditorIcons")
|
||||
%Filter_Settings.icon = get_theme_icon("PluginScript", "EditorIcons")
|
||||
%Collapse.icon = get_theme_icon("CollapseTree", "EditorIcons")
|
||||
|
||||
%EventDefaultsPanel.add_theme_stylebox_override('panel', get_theme_stylebox("Background", "EditorStyles"))
|
||||
|
||||
%ExternalLink.icon = get_theme_icon("Help", "EditorIcons")
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
%EventDefaultsPanel.hide()
|
||||
load_modules_tree()
|
||||
|
||||
|
||||
func _on_refresh_pressed() -> void:
|
||||
DialogicUtil.get_indexers(true, true)
|
||||
DialogicResourceUtil.update_event_cache()
|
||||
load_modules_tree()
|
||||
|
||||
|
||||
func filters_updated(fake_arg:Variant) -> void:
|
||||
load_modules_tree()
|
||||
|
||||
|
||||
func _on_collapse_toggled(button_pressed:bool) -> void:
|
||||
for item in %Tree.get_root().get_children():
|
||||
item.collapsed = button_pressed
|
||||
|
||||
if button_pressed:
|
||||
%Collapse.icon = get_theme_icon("ExpandTree", "EditorIcons")
|
||||
%Collapse.tooltip_text = "Expand All"
|
||||
else:
|
||||
%Collapse.icon = get_theme_icon("CollapseTree", "EditorIcons")
|
||||
%Collapse.tooltip_text = "Collapse All"
|
||||
|
||||
|
||||
func _on_search_text_changed(new_text:String) -> void:
|
||||
for filter in [%Filter_Events, %Filter_Subsystems, %Filter_Editors, %Filter_EffectsAndModifiers, %Filter_Settings, %Filter_Styles]:
|
||||
filter.text = ""
|
||||
filter.set_meta("counter", 0)
|
||||
|
||||
var hidden_events: Array = DialogicUtil.get_editor_setting('hidden_event_buttons', [])
|
||||
|
||||
for child in %Tree.get_root().get_children():
|
||||
if new_text.to_lower() in child.get_text(0).to_lower() or new_text.is_empty():
|
||||
for sub_child in child.get_children():
|
||||
sub_child.visible = sub_child.get_meta('filter_button').button_pressed
|
||||
sub_child.get_meta('filter_button').set_meta('counter', sub_child.get_meta('filter_button').get_meta('counter')+1)
|
||||
sub_child.get_meta('filter_button').text = str(sub_child.get_meta('filter_button').get_meta('counter'))
|
||||
child.visible = true
|
||||
else:
|
||||
for sub_child in child.get_children():
|
||||
sub_child.visible = sub_child.get_meta('filter_button').button_pressed and new_text.to_lower() in sub_child.get_text(0).to_lower()
|
||||
|
||||
if new_text.to_lower() in sub_child.get_text(0).to_lower():
|
||||
sub_child.get_meta('filter_button').set_meta('counter', sub_child.get_meta('filter_button').get_meta('counter')+1)
|
||||
sub_child.get_meta('filter_button').text = str(sub_child.get_meta('filter_button').get_meta('counter'))
|
||||
|
||||
for i in range(child.get_button_count(0)):
|
||||
child.erase_button(0, child.get_button_count(0)-1)
|
||||
var any_visible := false
|
||||
var counter := 0
|
||||
for sub_child in child.get_children():
|
||||
if sub_child.visible:
|
||||
child.add_button(0, sub_child.get_icon(0), counter, false, sub_child.get_text(0))
|
||||
if sub_child.get_metadata(0) and sub_child.get_metadata(0)['type'] == 'Event' and sub_child.get_metadata(0)['hidden']:
|
||||
var color: Color = sub_child.get_icon_modulate(0)
|
||||
color.a = 0.5
|
||||
child.set_button_color(0, counter, color)
|
||||
else:
|
||||
child.set_button_color(0, counter, sub_child.get_icon_modulate(0))
|
||||
counter += 1
|
||||
any_visible = true
|
||||
child.visible = any_visible
|
||||
|
||||
|
||||
|
||||
func load_modules_tree() -> void:
|
||||
%Tree.clear()
|
||||
var root: TreeItem = %Tree.create_item()
|
||||
var cached_events := DialogicResourceUtil.get_event_cache()
|
||||
var hidden_events: Array = DialogicUtil.get_editor_setting('hidden_event_buttons', [])
|
||||
var indexers := DialogicUtil.get_indexers()
|
||||
for i in indexers:
|
||||
var module_item: TreeItem = %Tree.create_item(root)
|
||||
module_item.set_text(0, i.get_script().resource_path.trim_suffix('/index.gd').get_file())
|
||||
module_item.set_metadata(0, {'type':'Module'})
|
||||
|
||||
# Events
|
||||
for ev in i._get_events():
|
||||
if not ResourceLoader.exists(ev):
|
||||
continue
|
||||
var event_item: TreeItem = %Tree.create_item(module_item)
|
||||
event_item.set_icon(0, get_theme_icon("Favorites", "EditorIcons"))
|
||||
for cached_event in cached_events:
|
||||
if cached_event.get_script().resource_path == ev:
|
||||
event_item.set_text(0, cached_event.event_name + " Event")
|
||||
event_item.set_icon_modulate(0, cached_event.event_color)
|
||||
var hidden: bool = cached_event.event_name in hidden_events
|
||||
event_item.set_metadata(0, {'type':'Event', 'event':cached_event, 'hidden':hidden})
|
||||
event_item.add_button(0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"), 0, false, "Toggle Event Button Visibility")
|
||||
if hidden:
|
||||
event_item.set_button(0, 0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"))
|
||||
event_item.set_meta('filter_button', %Filter_Events)
|
||||
event_item.visible = %Filter_Events.button_pressed
|
||||
|
||||
# Subsystems
|
||||
for subsys in i._get_subsystems():
|
||||
var subsys_item: TreeItem = %Tree.create_item(module_item)
|
||||
subsys_item.set_icon(0, get_theme_icon("Callable", "EditorIcons"))
|
||||
subsys_item.set_text(0, subsys.name + " Subsystem")
|
||||
subsys_item.set_icon_modulate(0, get_theme_color("readonly_color", "Editor"))
|
||||
subsys_item.set_metadata(0, {'type':'Subsystem', 'info':subsys})
|
||||
subsys_item.set_meta('filter_button', %Filter_Subsystems)
|
||||
subsys_item.visible = %Filter_Subsystems.button_pressed
|
||||
|
||||
# Style scenes
|
||||
for style in i._get_layout_parts():
|
||||
var style_item: TreeItem = %Tree.create_item(module_item)
|
||||
style_item.set_icon(0, get_theme_icon("PopupMenu", "EditorIcons"))
|
||||
style_item.set_text(0, style.name)
|
||||
style_item.set_icon_modulate(0, get_theme_color("property_color_x", "Editor"))
|
||||
style_item.set_metadata(0, {'type':'Style', 'info':style})
|
||||
style_item.set_meta('filter_button', %Filter_Styles)
|
||||
style_item.visible = %Filter_Styles.button_pressed
|
||||
|
||||
# Text Effects
|
||||
for effect in i._get_text_effects():
|
||||
var effect_item: TreeItem = %Tree.create_item(module_item)
|
||||
effect_item.set_icon(0, get_theme_icon("RichTextEffect", "EditorIcons"))
|
||||
effect_item.set_text(0, "Text effect ["+effect.command+"]")
|
||||
effect_item.set_icon_modulate(0, get_theme_color("property_color_z", "Editor"))
|
||||
effect_item.set_metadata(0, {'type':'Effect', 'info':effect})
|
||||
effect_item.set_meta('filter_button', %Filter_EffectsAndModifiers)
|
||||
effect_item.visible = %Filter_EffectsAndModifiers.button_pressed
|
||||
|
||||
# Text Modifiers
|
||||
for mod in i._get_text_modifiers():
|
||||
var mod_item: TreeItem = %Tree.create_item(module_item)
|
||||
mod_item.set_icon(0, get_theme_icon("RichTextEffect", "EditorIcons"))
|
||||
mod_item.set_text(0, mod.method.capitalize())
|
||||
mod_item.set_icon_modulate(0, get_theme_color("property_color_z", "Editor"))
|
||||
mod_item.set_metadata(0, {'type':'Modifier', 'info':mod})
|
||||
mod_item.set_meta('filter_button', %Filter_EffectsAndModifiers)
|
||||
mod_item.visible = %Filter_EffectsAndModifiers.button_pressed
|
||||
|
||||
# Settings
|
||||
for settings in i._get_settings_pages():
|
||||
var settings_item: TreeItem = %Tree.create_item(module_item)
|
||||
settings_item.set_icon(0, get_theme_icon("PluginScript", "EditorIcons"))
|
||||
settings_item.set_text(0, module_item.get_text(0) + " Settings")
|
||||
settings_item.set_icon_modulate(0, get_theme_color("readonly_color", "Editor"))
|
||||
settings_item.set_metadata(0, {'type':'Settings', 'info':settings})
|
||||
settings_item.set_meta('filter_button', %Filter_Settings)
|
||||
settings_item.visible = %Filter_Settings.button_pressed
|
||||
|
||||
# Editors
|
||||
for editor in i._get_editors():
|
||||
var editor_item: TreeItem = %Tree.create_item(module_item)
|
||||
editor_item.set_icon(0, get_theme_icon("ConfirmationDialog", "EditorIcons"))
|
||||
editor_item.set_text(0, editor.get_file().trim_suffix('.tscn').capitalize())
|
||||
editor_item.set_icon_modulate(0, get_theme_color("readonly_color", "Editor"))
|
||||
editor_item.set_metadata(0, {'type':'Editor', 'info':editor})
|
||||
editor_item.set_meta('filter_button', %Filter_Editors)
|
||||
editor_item.visible = %Filter_Editors.button_pressed
|
||||
|
||||
module_item.collapsed = %Collapse.button_pressed
|
||||
|
||||
_on_search_text_changed(%Search.text)
|
||||
if %Tree.get_root().get_child_count(): %Tree.set_selected(%Tree.get_root().get_child(0), 0)
|
||||
|
||||
|
||||
func _on_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int) -> void:
|
||||
match item.get_metadata(0)['type']:
|
||||
'Module':
|
||||
item.collapsed = false
|
||||
%Tree.set_selected(item.get_child(id), 0)
|
||||
'Event':
|
||||
# Visibility item clicked
|
||||
if id == 0:
|
||||
var meta: Dictionary= item.get_metadata(0)
|
||||
if meta['hidden']:
|
||||
item.set_button(0, 0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"))
|
||||
item.get_parent().set_button_color(0, item.get_index(), item.get_icon_modulate(0))
|
||||
if item == %Tree.get_selected():
|
||||
%VisibilityToggle.button_pressed = true
|
||||
else:
|
||||
item.set_button(0, 0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"))
|
||||
var color: Color = item.get_icon_modulate(0)
|
||||
color.a = 0.5
|
||||
item.get_parent().set_button_color(0, item.get_index(), color)
|
||||
if item == %Tree.get_selected():
|
||||
%VisibilityToggle.button_pressed = false
|
||||
meta['hidden'] = !meta['hidden']
|
||||
item.set_metadata(0, meta)
|
||||
change_event_visibility(meta['event'], !meta['hidden'])
|
||||
|
||||
|
||||
func _on_tree_item_selected() -> void:
|
||||
var selected_item: TreeItem = %Tree.get_selected()
|
||||
|
||||
var metadata: Variant = selected_item.get_metadata(0)
|
||||
|
||||
%Title.text = selected_item.get_text(0)
|
||||
%EventDefaultsPanel.hide()
|
||||
%Icon.texture = null
|
||||
%ExternalLink.hide()
|
||||
%VisibilityToggle.hide()
|
||||
|
||||
if metadata is Dictionary:
|
||||
match metadata.type:
|
||||
'Event':
|
||||
%GeneralInfo.text = "Events can be used in timelines and do all kinds of things. They often interact with subsystems and dialogic nodes."
|
||||
|
||||
load_event_settings(metadata.event)
|
||||
if %EventDefaults.get_child_count():
|
||||
%EventDefaultsPanel.show()
|
||||
|
||||
if metadata.event.help_page_path:
|
||||
%ExternalLink.show()
|
||||
%ExternalLink.set_meta('url', metadata.event.help_page_path)
|
||||
%Icon.texture = metadata.event._get_icon()
|
||||
if !metadata.event.disable_editor_button:
|
||||
%VisibilityToggle.show()
|
||||
%VisibilityToggle.button_pressed = !metadata.event.event_name in DialogicUtil.get_editor_setting('hidden_event_buttons', [])
|
||||
if %VisibilityToggle.button_pressed:
|
||||
%VisibilityToggle.icon = get_theme_icon("GuiVisibilityVisible", "EditorIcons")
|
||||
else:
|
||||
%VisibilityToggle.icon = get_theme_icon("GuiVisibilityHidden", "EditorIcons")
|
||||
# -------------------------------------------------
|
||||
'Subsystem':
|
||||
%GeneralInfo.text = "Subsystems hold specialized functionality. They mostly manage communication between events and dialogic nodes. Often they provide handy methods that can be accessed by the user like this: Dialogic.Subsystem.a_method()."
|
||||
# -------------------------------------------------
|
||||
'Effect':
|
||||
%GeneralInfo.text = "Text effects can be used in text events. They will be executed once reached and can take a single argument."
|
||||
# -------------------------------------------------
|
||||
'Modifier':
|
||||
%GeneralInfo.text = "Modifiers can modify text from text events before it is shown."
|
||||
# -------------------------------------------------
|
||||
'Style':
|
||||
%GeneralInfo.text = "Style presets can be activated and modified in the Styles editor. They provide the design of the dialog interface in your game."
|
||||
# -------------------------------------------------
|
||||
'Editor':
|
||||
%GeneralInfo.text = "Editors provide a user interface for editing dialogic data."
|
||||
# -------------------------------------------------
|
||||
'Settings':
|
||||
%GeneralInfo.text = "Settings pages provide settings that are usually used by subsystems, events and dialogic nodes."
|
||||
# -------------------------------------------------
|
||||
'_':
|
||||
%GeneralInfo.text = ""
|
||||
|
||||
|
||||
func _on_external_link_pressed() -> void:
|
||||
if %ExternalLink.has_meta('url'):
|
||||
OS.shell_open(%ExternalLink.get_meta('url'))
|
||||
|
||||
|
||||
func change_event_visibility(event:DialogicEvent, visibility:bool) -> void:
|
||||
if event:
|
||||
var list: Array= DialogicUtil.get_editor_setting('hidden_event_buttons', [])
|
||||
if visibility:
|
||||
list.erase(event.event_name)
|
||||
else:
|
||||
list.append(event.event_name)
|
||||
DialogicUtil.set_editor_setting('hidden_event_buttons', list)
|
||||
force_event_button_list_update()
|
||||
|
||||
|
||||
func _on_visibility_toggle_toggled(button_pressed:bool) -> void:
|
||||
change_event_visibility(%Tree.get_selected().get_metadata(0).event, button_pressed)
|
||||
|
||||
if button_pressed:
|
||||
%VisibilityToggle.icon = get_theme_icon("GuiVisibilityVisible", "EditorIcons")
|
||||
%Tree.get_selected().set_button(0, 0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"))
|
||||
%Tree.get_selected().get_parent().set_button_color(0, %Tree.get_selected().get_index(), %Tree.get_selected().get_icon_modulate(0))
|
||||
else:
|
||||
%VisibilityToggle.icon = get_theme_icon("GuiVisibilityHidden", "EditorIcons")
|
||||
%Tree.get_selected().set_button(0, 0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"))
|
||||
var color: Color = %Tree.get_selected().get_icon_modulate(0)
|
||||
color.a = 0.5
|
||||
%Tree.get_selected().get_parent().set_button_color(0, %Tree.get_selected().get_index(), color)
|
||||
|
||||
|
||||
|
||||
func force_event_button_list_update() -> void:
|
||||
find_parent('EditorsManager').editors['Timeline'].node.get_node('%VisualEditor').load_event_buttons()
|
||||
|
||||
################################################################################
|
||||
## EVENT DEFAULT SETTINGS
|
||||
################################################################################
|
||||
func load_event_settings(event:DialogicEvent) -> void:
|
||||
for child in %EventDefaults.get_children():
|
||||
child.queue_free()
|
||||
|
||||
var event_default_overrides: Dictionary = ProjectSettings.get_setting('dialogic/event_default_overrides', {})
|
||||
|
||||
var params := event.get_shortcode_parameters()
|
||||
for prop in params:
|
||||
var current_value: Variant = params[prop].default
|
||||
if event_default_overrides.get(event.event_name, {}).has(params[prop].property):
|
||||
current_value = event_default_overrides.get(event.event_name, {}).get(params[prop].property)
|
||||
|
||||
# Label
|
||||
var label := Label.new()
|
||||
label.text = prop.capitalize()
|
||||
%EventDefaults.add_child(label)
|
||||
|
||||
var reset := Button.new()
|
||||
reset.icon = get_theme_icon("Clear", "EditorIcons")
|
||||
reset.flat = true
|
||||
|
||||
%EventDefaults.add_child(reset)
|
||||
|
||||
# Editing field
|
||||
var editor_node: Node = null
|
||||
match typeof(event.get(params[prop].property)):
|
||||
TYPE_STRING:
|
||||
editor_node = LineEdit.new()
|
||||
editor_node.custom_minimum_size.x = 150
|
||||
editor_node.text = str(current_value)
|
||||
editor_node.text_changed.connect(_on_event_default_string_submitted.bind(params[prop].property))
|
||||
TYPE_INT, TYPE_FLOAT:
|
||||
if params[prop].has('suggestions'):
|
||||
editor_node = OptionButton.new()
|
||||
for i in params[prop].suggestions.call():
|
||||
editor_node.add_item(i, int(params[prop].suggestions.call()[i].value))
|
||||
editor_node.select(int(current_value))
|
||||
editor_node.item_selected.connect(_on_event_default_option_selected.bind(editor_node, params[prop].property))
|
||||
else:
|
||||
editor_node = SpinBox.new()
|
||||
|
||||
editor_node.allow_greater = true
|
||||
editor_node.allow_lesser = true
|
||||
if typeof(event.get(params[prop].property)) == TYPE_INT:
|
||||
editor_node.step = 1
|
||||
else:
|
||||
editor_node.step = 0.001
|
||||
|
||||
editor_node.value = float(current_value)
|
||||
editor_node.value_changed.connect(_on_event_default_number_changed.bind(params[prop].property))
|
||||
|
||||
TYPE_VECTOR2:
|
||||
editor_node = load("res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn").instantiate()
|
||||
editor_node.set_value(current_value)
|
||||
editor_node.property_name = params[prop].property
|
||||
editor_node.value_changed.connect(_on_event_default_value_changed)
|
||||
|
||||
TYPE_BOOL:
|
||||
editor_node = CheckBox.new()
|
||||
editor_node.button_pressed = bool(current_value)
|
||||
editor_node.toggled.connect(_on_event_default_bool_toggled.bind(params[prop].property))
|
||||
|
||||
TYPE_ARRAY:
|
||||
editor_node = load("res://addons/dialogic/Editor/Events/Fields/field_array.tscn").instantiate()
|
||||
editor_node.set_value(current_value)
|
||||
editor_node.property_name = params[prop].property
|
||||
editor_node.value_changed.connect(_on_event_default_value_changed)
|
||||
|
||||
TYPE_DICTIONARY:
|
||||
editor_node = load("res://addons/dialogic/Editor/Events/Fields/field_dictionary.tscn").instantiate()
|
||||
editor_node.set_value(current_value)
|
||||
editor_node.property_name = params[prop].property
|
||||
editor_node.value_changed.connect(_on_event_default_value_changed)
|
||||
%EventDefaults.add_child(editor_node)
|
||||
reset.pressed.connect(reset_event_default_override.bind(prop, editor_node, params[prop].default))
|
||||
|
||||
|
||||
func set_event_default_override(prop:String, value:Variant) -> void:
|
||||
var event_default_overrides: Dictionary = ProjectSettings.get_setting('dialogic/event_default_overrides', {})
|
||||
var event: DialogicEvent = %Tree.get_selected().get_metadata(0).event
|
||||
|
||||
if not event_default_overrides.has(event.event_name):
|
||||
event_default_overrides[event.event_name] = {}
|
||||
|
||||
event_default_overrides[event.event_name][prop] = value
|
||||
|
||||
ProjectSettings.set_setting('dialogic/event_default_overrides', event_default_overrides)
|
||||
|
||||
|
||||
func reset_event_default_override(prop:String, node:Node, default:Variant) -> void:
|
||||
var event_default_overrides: Dictionary = ProjectSettings.get_setting('dialogic/event_default_overrides', {})
|
||||
var event: DialogicEvent = %Tree.get_selected().get_metadata(0).event
|
||||
|
||||
if not event_default_overrides.has(event.event_name):
|
||||
return
|
||||
|
||||
event_default_overrides[event.event_name].erase(prop)
|
||||
|
||||
ProjectSettings.set_setting('dialogic/event_default_overrides', event_default_overrides)
|
||||
|
||||
if node is CheckBox:
|
||||
node.button_pressed = default
|
||||
elif node is LineEdit:
|
||||
node.text = default
|
||||
elif node.has_method('set_value'):
|
||||
node.set_value(default)
|
||||
elif node is ColorPickerButton:
|
||||
node.color = default
|
||||
elif node is OptionButton:
|
||||
node.select(default)
|
||||
elif node is SpinBox:
|
||||
node.value = default
|
||||
|
||||
|
||||
func _on_event_default_string_submitted(text:String, prop:String) -> void:
|
||||
set_event_default_override(prop, text)
|
||||
|
||||
func _on_event_default_option_selected(index:int, option_button:OptionButton, prop:String) -> void:
|
||||
set_event_default_override(prop, option_button.get_item_id(index))
|
||||
|
||||
func _on_event_default_number_changed(value:float, prop:String) -> void:
|
||||
set_event_default_override(prop, value)
|
||||
|
||||
func _on_event_default_value_changed(prop:String, value:Variant) -> void:
|
||||
set_event_default_override(prop, value)
|
||||
|
||||
func _on_event_default_bool_toggled(value:bool, prop:String) -> void:
|
||||
set_event_default_override(prop, value)
|
||||
|
||||
1
addons/dialogic/Editor/Settings/settings_modules.gd.uid
Normal file
1
addons/dialogic/Editor/Settings/settings_modules.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bpyif5ki478i2
|
||||
236
addons/dialogic/Editor/Settings/settings_modules.tscn
Normal file
236
addons/dialogic/Editor/Settings/settings_modules.tscn
Normal file
@@ -0,0 +1,236 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://o7ljiritpgap"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Editor/Settings/settings_modules.gd" id="1_l2hk0"]
|
||||
|
||||
[sub_resource type="Image" id="Image_570p8"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_lce2m"]
|
||||
image = SubResource("Image_570p8")
|
||||
|
||||
[sub_resource type="Image" id="Image_ihhvm"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_137g7"]
|
||||
image = SubResource("Image_ihhvm")
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_315cl"]
|
||||
content_margin_left = 4.0
|
||||
content_margin_top = 4.0
|
||||
content_margin_right = 4.0
|
||||
content_margin_bottom = 4.0
|
||||
bg_color = Color(1, 0.365, 0.365, 1)
|
||||
draw_center = false
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
corner_detail = 1
|
||||
|
||||
[node name="ModuleManagement" type="HSplitContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_bottom = -157.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 0
|
||||
script = ExtResource("1_l2hk0")
|
||||
short_info = "Here you can manage modules:
|
||||
- change event defaults
|
||||
- hide events from the event list"
|
||||
|
||||
[node name="Overview" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="Overview"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
follow_focus = true
|
||||
horizontal_scroll_mode = 3
|
||||
vertical_scroll_mode = 0
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="Overview/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 8
|
||||
alignment = 2
|
||||
|
||||
[node name="Filter_Events" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Events"
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Filter_Subsystems" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Subsystems"
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Filter_EffectsAndModifiers" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Text Effects and Modifiers"
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Filter_Styles" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Preset Style Scenes"
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Filter_Settings" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Settings Pages"
|
||||
toggle_mode = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Filter_Editors" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Include Editors"
|
||||
toggle_mode = true
|
||||
text = "0"
|
||||
flat = true
|
||||
icon_alignment = 2
|
||||
|
||||
[node name="Search" type="LineEdit" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
layout_mode = 2
|
||||
placeholder_text = "Search"
|
||||
clear_button_enabled = true
|
||||
|
||||
[node name="Refresh" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Refresh"
|
||||
|
||||
[node name="Collapse" type="Button" parent="Overview/ScrollContainer/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Collapse All"
|
||||
toggle_mode = true
|
||||
|
||||
[node name="Tree" type="Tree" parent="Overview"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
allow_reselect = true
|
||||
hide_root = true
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="."]
|
||||
show_behind_parent = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
size_flags_stretch_ratio = 0.75
|
||||
horizontal_scroll_mode = 3
|
||||
vertical_scroll_mode = 0
|
||||
|
||||
[node name="Settings" type="VBoxContainer" parent="Scroll"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="Scroll/Settings"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="Scroll/Settings/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
expand_mode = 3
|
||||
|
||||
[node name="Title" type="Label" parent="Scroll/Settings/HBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSubTitle"
|
||||
|
||||
[node name="ExternalLink" type="Button" parent="Scroll/Settings/HBox"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
icon = SubResource("ImageTexture_lce2m")
|
||||
flat = true
|
||||
|
||||
[node name="VisibilityToggle" type="Button" parent="Scroll/Settings/HBox"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
icon = SubResource("ImageTexture_137g7")
|
||||
flat = true
|
||||
|
||||
[node name="EventDefaultsPanel" type="PanelContainer" parent="Scroll/Settings"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_315cl")
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="Scroll/Settings/EventDefaultsPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title" type="Label" parent="Scroll/Settings/EventDefaultsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Edit event defaults:"
|
||||
|
||||
[node name="EventDefaults" type="GridContainer" parent="Scroll/Settings/EventDefaultsPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
columns = 3
|
||||
|
||||
[node name="GeneralInfo" type="Label" parent="Scroll/Settings"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicHintText2"
|
||||
autowrap_mode = 3
|
||||
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_Events" to="." method="filters_updated"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_Subsystems" to="." method="filters_updated"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_EffectsAndModifiers" to="." method="filters_updated"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_Styles" to="." method="filters_updated"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_Settings" to="." method="filters_updated"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Filter_Editors" to="." method="filters_updated"]
|
||||
[connection signal="text_changed" from="Overview/ScrollContainer/HBox/Search" to="." method="_on_search_text_changed"]
|
||||
[connection signal="pressed" from="Overview/ScrollContainer/HBox/Refresh" to="." method="_on_refresh_pressed"]
|
||||
[connection signal="toggled" from="Overview/ScrollContainer/HBox/Collapse" to="." method="_on_collapse_toggled"]
|
||||
[connection signal="button_clicked" from="Overview/Tree" to="." method="_on_tree_button_clicked"]
|
||||
[connection signal="item_selected" from="Overview/Tree" to="." method="_on_tree_item_selected"]
|
||||
[connection signal="pressed" from="Scroll/Settings/HBox/ExternalLink" to="." method="_on_external_link_pressed"]
|
||||
[connection signal="toggled" from="Scroll/Settings/HBox/VisibilityToggle" to="." method="_on_visibility_toggle_toggled"]
|
||||
35
addons/dialogic/Editor/Settings/settings_page.gd
Normal file
35
addons/dialogic/Editor/Settings/settings_page.gd
Normal file
@@ -0,0 +1,35 @@
|
||||
@tool
|
||||
extends Control
|
||||
class_name DialogicSettingsPage
|
||||
|
||||
@export_multiline var short_info := ""
|
||||
|
||||
## Called to get the title of the page
|
||||
func _get_title() -> String:
|
||||
return name
|
||||
|
||||
|
||||
## Called to get the ordering of the page
|
||||
func _get_priority() -> int:
|
||||
return 0
|
||||
|
||||
|
||||
## Called to know whether to put this in the features section
|
||||
func _is_feature_tab() -> bool:
|
||||
return false
|
||||
|
||||
|
||||
## Called when the settings editor is opened
|
||||
func _refresh() -> void:
|
||||
pass
|
||||
|
||||
|
||||
## Called before the settings editor closes (another editor is opened)
|
||||
## Can be used to safe stuff
|
||||
func _about_to_close() -> void:
|
||||
pass
|
||||
|
||||
|
||||
## Return a section with information.
|
||||
func _get_info_section() -> Control:
|
||||
return null
|
||||
1
addons/dialogic/Editor/Settings/settings_page.gd.uid
Normal file
1
addons/dialogic/Editor/Settings/settings_page.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dlk077afvj4jy
|
||||
660
addons/dialogic/Editor/Settings/settings_translation.gd
Normal file
660
addons/dialogic/Editor/Settings/settings_translation.gd
Normal file
@@ -0,0 +1,660 @@
|
||||
@tool
|
||||
extends DialogicSettingsPage
|
||||
|
||||
## Settings tab that allows enabeling and updating translation csv-files.
|
||||
|
||||
|
||||
enum TranslationModes {PER_PROJECT, PER_TIMELINE, NONE}
|
||||
enum SaveLocationModes {INSIDE_TRANSLATION_FOLDER, NEXT_TO_TIMELINE, NONE}
|
||||
|
||||
var loading := false
|
||||
@onready var settings_editor: Control = find_parent('Settings')
|
||||
|
||||
## The default CSV filename that contains the translations for character
|
||||
## properties.
|
||||
const DEFAULT_CHARACTER_CSV_NAME := "dialogic_character_translations.csv"
|
||||
## The default CSV filename that contains the translations for timelines.
|
||||
## Only used when all timelines are supposed to be translated in one file.
|
||||
const DEFAULT_TIMELINE_CSV_NAME := "dialogic_timeline_translations.csv"
|
||||
|
||||
const DEFAULT_GLOSSARY_CSV_NAME := "dialogic_glossary_translations.csv"
|
||||
|
||||
const _USED_LOCALES_SETTING := "dialogic/translation/locales"
|
||||
|
||||
## Contains translation changes that were made during the last update.
|
||||
|
||||
## Unique locales that will be set after updating the CSV files.
|
||||
var _unique_locales := []
|
||||
|
||||
func _get_icon() -> Texture2D:
|
||||
return get_theme_icon("Translation", "EditorIcons")
|
||||
|
||||
|
||||
func _is_feature_tab() -> bool:
|
||||
return true
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
%TransEnabled.toggled.connect(store_changes)
|
||||
%OrigLocale.get_suggestions_func = get_locales
|
||||
%OrigLocale.resource_icon = get_theme_icon("Translation", "EditorIcons")
|
||||
%OrigLocale.value_changed.connect(store_changes)
|
||||
%TestingLocale.get_suggestions_func = get_locales
|
||||
%TestingLocale.resource_icon = get_theme_icon("Translation", "EditorIcons")
|
||||
%TestingLocale.value_changed.connect(store_changes)
|
||||
%TransFolderPicker.value_changed.connect(store_changes)
|
||||
%AddSeparatorEnabled.toggled.connect(store_changes)
|
||||
|
||||
%SaveLocationMode.item_selected.connect(store_changes)
|
||||
%TransMode.item_selected.connect(store_changes)
|
||||
|
||||
%UpdateCsvFiles.pressed.connect(_on_update_translations_pressed)
|
||||
%UpdateCsvFiles.icon = get_theme_icon("Add", "EditorIcons")
|
||||
|
||||
%CollectTranslations.pressed.connect(collect_translations)
|
||||
%CollectTranslations.icon = get_theme_icon("File", "EditorIcons")
|
||||
|
||||
%TransRemove.pressed.connect(_on_erase_translations_pressed)
|
||||
%TransRemove.icon = get_theme_icon("Remove", "EditorIcons")
|
||||
|
||||
%UpdateConfirmationDialog.add_button("Keep old & Generate new", false, "generate_new")
|
||||
|
||||
%UpdateConfirmationDialog.custom_action.connect(_on_custom_action)
|
||||
|
||||
_verify_translation_file()
|
||||
|
||||
|
||||
func _on_custom_action(action: String) -> void:
|
||||
if action == "generate_new":
|
||||
update_csv_files()
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
loading = true
|
||||
|
||||
%TransEnabled.button_pressed = ProjectSettings.get_setting('dialogic/translation/enabled', false)
|
||||
%TranslationSettings.visible = %TransEnabled.button_pressed
|
||||
%OrigLocale.set_value(ProjectSettings.get_setting('dialogic/translation/original_locale', TranslationServer.get_tool_locale()))
|
||||
%TransMode.select(ProjectSettings.get_setting('dialogic/translation/file_mode', 1))
|
||||
%TransFolderPicker.set_value(ProjectSettings.get_setting('dialogic/translation/translation_folder', ''))
|
||||
%TestingLocale.set_value(ProjectSettings.get_setting('internationalization/locale/test', ''))
|
||||
%AddSeparatorEnabled.button_pressed = ProjectSettings.get_setting('dialogic/translation/add_separator', false)
|
||||
|
||||
_verify_translation_file()
|
||||
|
||||
loading = false
|
||||
|
||||
|
||||
func store_changes(_fake_arg: Variant = null, _fake_arg2: Variant = null) -> void:
|
||||
if loading:
|
||||
return
|
||||
|
||||
_verify_translation_file()
|
||||
|
||||
ProjectSettings.set_setting('dialogic/translation/enabled', %TransEnabled.button_pressed)
|
||||
%TranslationSettings.visible = %TransEnabled.button_pressed
|
||||
ProjectSettings.set_setting('dialogic/translation/original_locale', %OrigLocale.current_value)
|
||||
ProjectSettings.set_setting('dialogic/translation/file_mode', %TransMode.selected)
|
||||
ProjectSettings.set_setting('dialogic/translation/translation_folder', %TransFolderPicker.current_value)
|
||||
ProjectSettings.set_setting('internationalization/locale/test', %TestingLocale.current_value)
|
||||
ProjectSettings.set_setting('dialogic/translation/save_mode', %SaveLocationMode.selected)
|
||||
ProjectSettings.set_setting('dialogic/translation/add_separator', %AddSeparatorEnabled.button_pressed)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
## Checks whether the translation folder path is required.
|
||||
## If it is, disables the "Update CSV files" button and shows a warning.
|
||||
##
|
||||
## The translation folder path is required when either of the following is true:
|
||||
## - The translation mode is set to "Per Project".
|
||||
## - The save location mode is set to "Inside Translation Folder".
|
||||
func _verify_translation_file() -> void:
|
||||
var translation_folder: String = %TransFolderPicker.current_value
|
||||
var file_mode: TranslationModes = %TransMode.selected
|
||||
|
||||
if file_mode == TranslationModes.PER_PROJECT:
|
||||
%SaveLocationMode.disabled = true
|
||||
else:
|
||||
%SaveLocationMode.disabled = false
|
||||
|
||||
var valid_translation_folder := (!translation_folder.is_empty()
|
||||
and DirAccess.dir_exists_absolute(translation_folder))
|
||||
|
||||
%UpdateCsvFiles.disabled = not valid_translation_folder
|
||||
|
||||
var status_message := ""
|
||||
|
||||
if not valid_translation_folder:
|
||||
status_message += "⛔ Requires valid translation folder to translate character names"
|
||||
|
||||
if file_mode == TranslationModes.PER_PROJECT:
|
||||
status_message += " and the project CSV file."
|
||||
else:
|
||||
status_message += "."
|
||||
|
||||
%StatusMessage.text = status_message
|
||||
|
||||
|
||||
func get_locales(_filter: String) -> Dictionary:
|
||||
var suggestions := {}
|
||||
suggestions['Default'] = {'value':'', 'tooltip':"Will use the fallback locale set in the project settings."}
|
||||
suggestions[TranslationServer.get_tool_locale()] = {'value':TranslationServer.get_tool_locale()}
|
||||
|
||||
var used_locales: Array = ProjectSettings.get_setting(_USED_LOCALES_SETTING, TranslationServer.get_all_languages())
|
||||
|
||||
for locale: String in used_locales:
|
||||
var language_name := TranslationServer.get_language_name(locale)
|
||||
|
||||
# Invalid locales return an empty String.
|
||||
if language_name.is_empty():
|
||||
continue
|
||||
|
||||
suggestions[locale] = { 'value': locale, 'tooltip': language_name }
|
||||
|
||||
return suggestions
|
||||
|
||||
|
||||
func _on_update_translations_pressed() -> void:
|
||||
var save_mode: SaveLocationModes = %SaveLocationMode.selected
|
||||
var file_mode: TranslationModes = %TransMode.selected
|
||||
var translation_folder: String = %TransFolderPicker.current_value
|
||||
|
||||
var old_save_mode: SaveLocationModes = ProjectSettings.get_setting('dialogic/translation/intern/save_mode', save_mode)
|
||||
var old_file_mode: TranslationModes = ProjectSettings.get_setting('dialogic/translation/intern/file_mode', file_mode)
|
||||
var old_translation_folder: String = ProjectSettings.get_setting('dialogic/translation/intern/translation_folder', translation_folder)
|
||||
|
||||
if (old_save_mode == save_mode
|
||||
and old_file_mode == file_mode
|
||||
and old_translation_folder == translation_folder):
|
||||
update_csv_files()
|
||||
return
|
||||
|
||||
%UpdateConfirmationDialog.popup_centered()
|
||||
|
||||
|
||||
## Used by the dialog to inform that the settings were changed.
|
||||
func _delete_and_update() -> void:
|
||||
erase_translations()
|
||||
update_csv_files()
|
||||
|
||||
|
||||
## Creates or updates the glossary CSV files.
|
||||
func _handle_glossary_translation(
|
||||
csv_data: CsvUpdateData,
|
||||
save_location_mode: SaveLocationModes,
|
||||
translation_mode: TranslationModes,
|
||||
translation_folder_path: String,
|
||||
orig_locale: String) -> void:
|
||||
|
||||
var glossary_csv: DialogicCsvFile = null
|
||||
var glossary_paths: Array = ProjectSettings.get_setting('dialogic/glossary/glossary_files', [])
|
||||
var add_separator_lines: bool = ProjectSettings.get_setting('dialogic/translation/add_separator', false)
|
||||
|
||||
for glossary_path: String in glossary_paths:
|
||||
|
||||
if glossary_csv == null:
|
||||
var csv_name := ""
|
||||
|
||||
# Get glossary CSV file name.
|
||||
match translation_mode:
|
||||
TranslationModes.PER_PROJECT:
|
||||
csv_name = DEFAULT_GLOSSARY_CSV_NAME
|
||||
|
||||
TranslationModes.PER_TIMELINE:
|
||||
var glossary_name: String = glossary_path.trim_suffix('.tres')
|
||||
var path_parts := glossary_name.split("/")
|
||||
var file_name := path_parts[-1]
|
||||
csv_name = "dialogic_" + file_name + '_translation.csv'
|
||||
|
||||
var glossary_csv_path := ""
|
||||
# Get glossary CSV file path.
|
||||
match save_location_mode:
|
||||
SaveLocationModes.INSIDE_TRANSLATION_FOLDER:
|
||||
glossary_csv_path = translation_folder_path.path_join(csv_name)
|
||||
|
||||
SaveLocationModes.NEXT_TO_TIMELINE:
|
||||
glossary_csv_path = glossary_path.get_base_dir().path_join(csv_name)
|
||||
|
||||
# Create or update glossary CSV file.
|
||||
glossary_csv = DialogicCsvFile.new(glossary_csv_path, orig_locale, add_separator_lines)
|
||||
|
||||
if (glossary_csv.is_new_file):
|
||||
csv_data.new_glossaries += 1
|
||||
else:
|
||||
csv_data.updated_glossaries += 1
|
||||
|
||||
var glossary: DialogicGlossary = load(glossary_path)
|
||||
glossary_csv.collect_lines_from_glossary(glossary)
|
||||
glossary_csv.add_translation_keys_to_glossary(glossary)
|
||||
ResourceSaver.save(glossary)
|
||||
|
||||
#If per-file mode is used, save this csv and begin a new one
|
||||
if translation_mode == TranslationModes.PER_TIMELINE:
|
||||
glossary_csv.update_csv_file_on_disk()
|
||||
glossary_csv = null
|
||||
|
||||
# If a Per-Project glossary is still open, we need to save it.
|
||||
if glossary_csv != null:
|
||||
glossary_csv.update_csv_file_on_disk()
|
||||
glossary_csv = null
|
||||
|
||||
|
||||
## Keeps information about the amount of new and updated CSV rows and what
|
||||
## resources were populated with translation IDs.
|
||||
## The final data can be used to display a status message.
|
||||
class CsvUpdateData:
|
||||
var new_events := 0
|
||||
var updated_events := 0
|
||||
|
||||
var new_timelines := 0
|
||||
var updated_timelines := 0
|
||||
|
||||
var new_names := 0
|
||||
var updated_names := 0
|
||||
|
||||
var new_glossaries := 0
|
||||
var updated_glossaries := 0
|
||||
|
||||
var new_glossary_entries := 0
|
||||
var updated_glossary_entries := 0
|
||||
|
||||
|
||||
func update_csv_files() -> void:
|
||||
_unique_locales = []
|
||||
var orig_locale: String = ProjectSettings.get_setting('dialogic/translation/original_locale', '').strip_edges()
|
||||
var save_location_mode: SaveLocationModes = ProjectSettings.get_setting('dialogic/translation/save_mode', SaveLocationModes.NEXT_TO_TIMELINE)
|
||||
var translation_mode: TranslationModes = ProjectSettings.get_setting('dialogic/translation/file_mode', TranslationModes.PER_PROJECT)
|
||||
var translation_folder_path: String = ProjectSettings.get_setting('dialogic/translation/translation_folder', 'res://')
|
||||
var add_separator_lines: bool = ProjectSettings.get_setting('dialogic/translation/add_separator', false)
|
||||
|
||||
var csv_data := CsvUpdateData.new()
|
||||
|
||||
if orig_locale.is_empty():
|
||||
orig_locale = ProjectSettings.get_setting('internationalization/locale/fallback')
|
||||
|
||||
ProjectSettings.set_setting('dialogic/translation/intern/save_mode', save_location_mode)
|
||||
ProjectSettings.set_setting('dialogic/translation/intern/file_mode', translation_mode)
|
||||
ProjectSettings.set_setting('dialogic/translation/intern/translation_folder', translation_folder_path)
|
||||
|
||||
var current_timeline := _close_active_timeline()
|
||||
|
||||
var csv_per_project: DialogicCsvFile = null
|
||||
var per_project_csv_path := translation_folder_path.path_join(DEFAULT_TIMELINE_CSV_NAME)
|
||||
|
||||
if translation_mode == TranslationModes.PER_PROJECT:
|
||||
csv_per_project = DialogicCsvFile.new(per_project_csv_path, orig_locale, add_separator_lines)
|
||||
|
||||
if (csv_per_project.is_new_file):
|
||||
csv_data.new_timelines += 1
|
||||
else:
|
||||
csv_data.updated_timelines += 1
|
||||
|
||||
# Iterate over all timelines.
|
||||
# Create or update CSV files.
|
||||
# Transform the timeline into translatable lines and collect into the CSV file.
|
||||
for timeline_path: String in DialogicResourceUtil.list_resources_of_type('.dtl'):
|
||||
var csv_file: DialogicCsvFile = csv_per_project
|
||||
|
||||
# Swap the CSV file to the Per Timeline one.
|
||||
if translation_mode == TranslationModes.PER_TIMELINE:
|
||||
var per_timeline_path: String = timeline_path.trim_suffix('.dtl')
|
||||
var path_parts := per_timeline_path.split("/")
|
||||
var timeline_name: String = path_parts[-1]
|
||||
|
||||
# Adjust the file path to the translation location mode.
|
||||
if save_location_mode == SaveLocationModes.INSIDE_TRANSLATION_FOLDER:
|
||||
var prefixed_timeline_name := "dialogic_" + timeline_name
|
||||
per_timeline_path = translation_folder_path.path_join(prefixed_timeline_name)
|
||||
|
||||
|
||||
per_timeline_path += '_translation.csv'
|
||||
csv_file = DialogicCsvFile.new(per_timeline_path, orig_locale, false)
|
||||
csv_data.new_timelines += 1
|
||||
|
||||
# Load and process timeline, turn events into resources.
|
||||
var timeline: DialogicTimeline = load(timeline_path)
|
||||
|
||||
if timeline.events.size() == 0:
|
||||
print_rich("[color=yellow]Empty timeline, skipping: " + timeline_path + "[/color]")
|
||||
continue
|
||||
|
||||
timeline.process()
|
||||
|
||||
# Collect timeline into CSV.
|
||||
csv_file.collect_lines_from_timeline(timeline)
|
||||
|
||||
# in case new translation_id's were added, we save the timeline again
|
||||
timeline.set_meta("timeline_not_saved", true)
|
||||
ResourceSaver.save(timeline, timeline_path)
|
||||
|
||||
if translation_mode == TranslationModes.PER_TIMELINE:
|
||||
csv_file.update_csv_file_on_disk()
|
||||
|
||||
csv_data.new_events += csv_file.new_rows
|
||||
csv_data.updated_events += csv_file.updated_rows
|
||||
|
||||
_handle_glossary_translation(
|
||||
csv_data,
|
||||
save_location_mode,
|
||||
translation_mode,
|
||||
translation_folder_path,
|
||||
orig_locale
|
||||
)
|
||||
|
||||
_handle_character_names(
|
||||
csv_data,
|
||||
orig_locale,
|
||||
translation_folder_path,
|
||||
add_separator_lines
|
||||
)
|
||||
|
||||
if translation_mode == TranslationModes.PER_PROJECT:
|
||||
csv_per_project.update_csv_file_on_disk()
|
||||
|
||||
_silently_open_timeline(current_timeline)
|
||||
|
||||
# Trigger reimport.
|
||||
find_parent('EditorView').plugin_reference.get_editor_interface().get_resource_filesystem().scan_sources()
|
||||
|
||||
var status_message := "Events created {new_events} found {updated_events}
|
||||
Names created {new_names} found {updated_names}
|
||||
CSVs created {new_timelines} found {updated_timelines}
|
||||
Glossary created {new_glossaries} found {updated_glossaries}
|
||||
Entries created {new_glossary_entries} found {updated_glossary_entries}"
|
||||
|
||||
var status_message_args := {
|
||||
'new_events': csv_data.new_events,
|
||||
'updated_events': csv_data.updated_events,
|
||||
'new_timelines': csv_data.new_timelines,
|
||||
'updated_timelines': csv_data.updated_timelines,
|
||||
'new_glossaries': csv_data.new_glossaries,
|
||||
'updated_glossaries': csv_data.updated_glossaries,
|
||||
'new_names': csv_data.new_names,
|
||||
'updated_names': csv_data.updated_names,
|
||||
'new_glossary_entries': csv_data.new_glossary_entries,
|
||||
'updated_glossary_entries': csv_data.updated_glossary_entries,
|
||||
}
|
||||
|
||||
%StatusMessage.text = status_message.format(status_message_args)
|
||||
ProjectSettings.set_setting(_USED_LOCALES_SETTING, _unique_locales)
|
||||
|
||||
|
||||
## Iterates over all character resource files and creates or updates CSV files
|
||||
## that contain the translations for character properties.
|
||||
## This will save each character resource file to disk.
|
||||
func _handle_character_names(
|
||||
csv_data: CsvUpdateData,
|
||||
original_locale: String,
|
||||
translation_folder_path: String,
|
||||
add_separator_lines: bool) -> void:
|
||||
var names_csv_path := translation_folder_path.path_join(DEFAULT_CHARACTER_CSV_NAME)
|
||||
var character_name_csv: DialogicCsvFile = DialogicCsvFile.new(names_csv_path,
|
||||
original_locale,
|
||||
add_separator_lines
|
||||
)
|
||||
|
||||
var all_characters := {}
|
||||
|
||||
for character_path: String in DialogicResourceUtil.list_resources_of_type('.dch'):
|
||||
var character: DialogicCharacter = load(character_path)
|
||||
|
||||
if character._translation_id.is_empty():
|
||||
csv_data.new_names += 1
|
||||
|
||||
else:
|
||||
csv_data.updated_names += 1
|
||||
|
||||
var translation_id := character.get_set_translation_id()
|
||||
all_characters[translation_id] = character
|
||||
|
||||
ResourceSaver.save(character)
|
||||
|
||||
character_name_csv.collect_lines_from_characters(all_characters)
|
||||
character_name_csv.update_csv_file_on_disk()
|
||||
|
||||
|
||||
func collect_translations() -> void:
|
||||
var translation_files := []
|
||||
var translation_mode: TranslationModes = ProjectSettings.get_setting('dialogic/translation/file_mode', TranslationModes.PER_PROJECT)
|
||||
|
||||
if translation_mode == TranslationModes.PER_TIMELINE:
|
||||
|
||||
for timeline_path: String in DialogicResourceUtil.list_resources_of_type('.translation'):
|
||||
|
||||
for file: String in DialogicUtil.listdir(timeline_path.get_base_dir()):
|
||||
file = timeline_path.get_base_dir().path_join(file)
|
||||
|
||||
if file.ends_with('.translation'):
|
||||
|
||||
if not file in translation_files:
|
||||
translation_files.append(file)
|
||||
|
||||
if translation_mode == TranslationModes.PER_PROJECT:
|
||||
var translation_folder: String = ProjectSettings.get_setting('dialogic/translation/translation_folder', 'res://')
|
||||
|
||||
for file: String in DialogicUtil.listdir(translation_folder):
|
||||
file = translation_folder.path_join(file)
|
||||
|
||||
if file.ends_with('.translation'):
|
||||
|
||||
if not file in translation_files:
|
||||
translation_files.append(file)
|
||||
|
||||
var all_translation_files: Array = ProjectSettings.get_setting('internationalization/locale/translations', [])
|
||||
var orig_file_amount := len(all_translation_files)
|
||||
|
||||
# This array keeps track of valid translation file paths.
|
||||
var found_file_paths := []
|
||||
var removed_translation_files := 0
|
||||
|
||||
for file_path: String in translation_files:
|
||||
# If the file path is not valid, we must clean it up.
|
||||
if ResourceLoader.exists(file_path):
|
||||
found_file_paths.append(file_path)
|
||||
else:
|
||||
removed_translation_files += 1
|
||||
continue
|
||||
|
||||
if not file_path in all_translation_files:
|
||||
all_translation_files.append(file_path)
|
||||
|
||||
var path_without_suffix := file_path.trim_suffix('.translation')
|
||||
var locale_part := path_without_suffix.split(".")[-1]
|
||||
_collect_locale(locale_part)
|
||||
|
||||
|
||||
var valid_translation_files := PackedStringArray(all_translation_files)
|
||||
ProjectSettings.set_setting('internationalization/locale/translations', valid_translation_files)
|
||||
ProjectSettings.save()
|
||||
|
||||
%StatusMessage.text = (
|
||||
"Added translation files: " + str(len(all_translation_files)-orig_file_amount)
|
||||
+ "\nRemoved translation files: " + str(removed_translation_files)
|
||||
+ "\nTotal translation files: " + str(len(all_translation_files)))
|
||||
|
||||
|
||||
func _on_erase_translations_pressed() -> void:
|
||||
%EraseConfirmationDialog.popup_centered()
|
||||
|
||||
|
||||
## Deletes translation files generated by [param csv_name].
|
||||
## The [param csv_name] may not contain the file extension (.csv).
|
||||
##
|
||||
## Returns a vector, value 1 is amount of deleted translation files.
|
||||
## Value
|
||||
func delete_translations_files(translation_files: Array, csv_name: String) -> int:
|
||||
var deleted_files := 0
|
||||
|
||||
for file_path: String in DialogicResourceUtil.list_resources_of_type('.translation'):
|
||||
var base_name: String = file_path.get_basename()
|
||||
var path_parts := base_name.split("/")
|
||||
var translation_name: String = path_parts[-1]
|
||||
|
||||
if translation_name.begins_with(csv_name):
|
||||
|
||||
if OK == DirAccess.remove_absolute(file_path):
|
||||
var project_translation_file_index := translation_files.find(file_path)
|
||||
|
||||
if project_translation_file_index > -1:
|
||||
translation_files.remove_at(project_translation_file_index)
|
||||
|
||||
deleted_files += 1
|
||||
print_rich("[color=green]Deleted translation file: " + file_path + "[/color]")
|
||||
else:
|
||||
print_rich("[color=yellow]Failed to delete translation file: " + file_path + "[/color]")
|
||||
|
||||
|
||||
return deleted_files
|
||||
|
||||
|
||||
## Iterates over all timelines and deletes their CSVs and timeline
|
||||
## translation IDs.
|
||||
## Deletes the Per-Project CSV file and the character name CSV file.
|
||||
func erase_translations() -> void:
|
||||
var files: PackedStringArray = ProjectSettings.get_setting('internationalization/locale/translations', [])
|
||||
var translation_files := Array(files)
|
||||
ProjectSettings.set_setting(_USED_LOCALES_SETTING, [])
|
||||
|
||||
var deleted_csv_files := 0
|
||||
var deleted_translation_files := 0
|
||||
var cleaned_timelines := 0
|
||||
var cleaned_characters := 0
|
||||
var cleaned_events := 0
|
||||
var cleaned_glossaries := 0
|
||||
|
||||
var current_timeline := _close_active_timeline()
|
||||
|
||||
# Delete all Dialogic CSV files and their translation files.
|
||||
for csv_path: String in DialogicResourceUtil.list_resources_of_type(".csv"):
|
||||
var csv_path_parts: PackedStringArray = csv_path.split("/")
|
||||
var csv_name: String = csv_path_parts[-1].trim_suffix(".csv")
|
||||
|
||||
# Handle Dialogic CSVs only.
|
||||
if not csv_name.begins_with("dialogic_"):
|
||||
continue
|
||||
|
||||
# Delete the CSV file.
|
||||
if OK == DirAccess.remove_absolute(csv_path):
|
||||
deleted_csv_files += 1
|
||||
print_rich("[color=green]Deleted CSV file: " + csv_path + "[/color]")
|
||||
|
||||
deleted_translation_files += delete_translations_files(translation_files, csv_name)
|
||||
else:
|
||||
print_rich("[color=yellow]Failed to delete CSV file: " + csv_path + "[/color]")
|
||||
|
||||
# Clean timelines.
|
||||
for timeline_path: String in DialogicResourceUtil.list_resources_of_type(".dtl"):
|
||||
|
||||
# Process the timeline.
|
||||
var timeline: DialogicTimeline = load(timeline_path)
|
||||
timeline.process()
|
||||
cleaned_timelines += 1
|
||||
|
||||
# Remove event translation IDs.
|
||||
for event: DialogicEvent in timeline.events:
|
||||
|
||||
if event._translation_id and not event._translation_id.is_empty():
|
||||
event.remove_translation_id()
|
||||
event.update_text_version()
|
||||
cleaned_events += 1
|
||||
|
||||
if "character" in event:
|
||||
# Remove character translation IDs.
|
||||
var character: DialogicCharacter = event.character
|
||||
|
||||
if character != null and not character._translation_id.is_empty():
|
||||
character.remove_translation_id()
|
||||
cleaned_characters += 1
|
||||
|
||||
timeline.set_meta("timeline_not_saved", true)
|
||||
ResourceSaver.save(timeline, timeline_path)
|
||||
|
||||
_erase_glossary_translation_ids()
|
||||
_erase_character_name_translation_ids()
|
||||
|
||||
ProjectSettings.set_setting('dialogic/translation/id_counter', 16)
|
||||
ProjectSettings.set_setting('internationalization/locale/translations', PackedStringArray(translation_files))
|
||||
ProjectSettings.save()
|
||||
|
||||
find_parent('EditorView').plugin_reference.get_editor_interface().get_resource_filesystem().scan_sources()
|
||||
|
||||
var status_message := "Timelines cleaned {cleaned_timelines}
|
||||
Events cleaned {cleaned_events}
|
||||
Characters cleaned {cleaned_characters}
|
||||
Glossaries cleaned {cleaned_glossaries}
|
||||
|
||||
CSVs erased {erased_csv_files}
|
||||
Translations erased {erased_translation_files}"
|
||||
|
||||
var status_message_args := {
|
||||
'cleaned_timelines': cleaned_timelines,
|
||||
'cleaned_characters': cleaned_characters,
|
||||
'cleaned_events': cleaned_events,
|
||||
'cleaned_glossaries': cleaned_glossaries,
|
||||
'erased_csv_files': deleted_csv_files,
|
||||
'erased_translation_files': deleted_translation_files,
|
||||
}
|
||||
|
||||
_silently_open_timeline(current_timeline)
|
||||
|
||||
# Trigger reimport.
|
||||
find_parent('EditorView').plugin_reference.get_editor_interface().get_resource_filesystem().scan_sources()
|
||||
|
||||
# Clear the internal settings.
|
||||
ProjectSettings.clear('dialogic/translation/intern/save_mode')
|
||||
ProjectSettings.clear('dialogic/translation/intern/file_mode')
|
||||
ProjectSettings.clear('dialogic/translation/intern/translation_folder')
|
||||
|
||||
_verify_translation_file()
|
||||
%StatusMessage.text = status_message.format(status_message_args)
|
||||
|
||||
|
||||
func _erase_glossary_translation_ids() -> void:
|
||||
# Clean glossary.
|
||||
var glossary_paths: Array = ProjectSettings.get_setting('dialogic/glossary/glossary_files', [])
|
||||
|
||||
for glossary_path: String in glossary_paths:
|
||||
var glossary: DialogicGlossary = load(glossary_path)
|
||||
glossary.remove_translation_id()
|
||||
glossary.remove_entry_translation_ids()
|
||||
glossary.clear_translation_keys()
|
||||
ResourceSaver.save(glossary, glossary_path)
|
||||
print_rich("[color=green]Cleaned up glossary file: " + glossary_path + "[/color]")
|
||||
|
||||
|
||||
func _erase_character_name_translation_ids() -> void:
|
||||
for character_path: String in DialogicResourceUtil.list_resources_of_type('.dch'):
|
||||
var character: DialogicCharacter = load(character_path)
|
||||
|
||||
character.remove_translation_id()
|
||||
ResourceSaver.save(character)
|
||||
|
||||
|
||||
## Closes the current timeline in the Dialogic Editor and returns the timeline
|
||||
## as a resource.
|
||||
## If no timeline has been opened, returns null.
|
||||
func _close_active_timeline() -> Resource:
|
||||
var timeline_node: DialogicEditor = settings_editor.editors_manager.editors['Timeline']['node']
|
||||
# We will close this timeline to ensure it will properly update.
|
||||
# By saving this reference, we can open it again.
|
||||
var current_timeline := timeline_node.current_resource
|
||||
# Clean the current editor, this will also close the timeline.
|
||||
settings_editor.editors_manager.clear_editor(timeline_node)
|
||||
|
||||
return current_timeline
|
||||
|
||||
|
||||
## Opens the timeline resource into the Dialogic Editor.
|
||||
## If the timeline is null, does nothing.
|
||||
func _silently_open_timeline(timeline_to_open: Resource) -> void:
|
||||
if timeline_to_open != null:
|
||||
settings_editor.editors_manager.edit_resource(timeline_to_open, true, true)
|
||||
|
||||
|
||||
## Checks [param locale] for unique locales that have not been added
|
||||
## to the [_unique_locales] array yet.
|
||||
func _collect_locale(locale: String) -> void:
|
||||
if _unique_locales.has(locale):
|
||||
return
|
||||
|
||||
_unique_locales.append(locale)
|
||||
@@ -0,0 +1 @@
|
||||
uid://b1w1n8qm57s4b
|
||||
368
addons/dialogic/Editor/Settings/settings_translation.tscn
Normal file
368
addons/dialogic/Editor/Settings/settings_translation.tscn
Normal file
@@ -0,0 +1,368 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://chpb1mj03xjxv"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Editor/Settings/settings_translation.gd" id="1_dvmyi"]
|
||||
[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_k2lou"]
|
||||
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_dq4j2"]
|
||||
[ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="4_kvsma"]
|
||||
|
||||
[sub_resource type="Image" id="Image_g2hic"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_xbph7"]
|
||||
image = SubResource("Image_g2hic")
|
||||
|
||||
[node name="Translations" type="VBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_top = -101.0
|
||||
offset_bottom = 102.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_dvmyi")
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Basics" type="VBoxContainer" parent="HBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Title" type="Label" parent="HBox/Basics"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Basics"
|
||||
|
||||
[node name="VBox4" type="HBoxContainer" parent="HBox/Basics"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HBox/Basics/VBox4"]
|
||||
layout_mode = 2
|
||||
text = "Enable translations"
|
||||
|
||||
[node name="TransEnabled" type="CheckBox" parent="HBox/Basics/VBox4"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator5" type="VSeparator" parent="HBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Testing" type="VBoxContainer" parent="HBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Title2" type="Label" parent="HBox/Testing"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Testing"
|
||||
|
||||
[node name="VBox3" type="HBoxContainer" parent="HBox/Testing"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label3" type="Label" parent="HBox/Testing/VBox3"]
|
||||
layout_mode = 2
|
||||
text = "Testing locale"
|
||||
|
||||
[node name="HintTooltip8" parent="HBox/Testing/VBox3" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Change this locale to test your game in a different language (only in-editor).
|
||||
Equivalent of the testing local project setting. "
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Change this locale to test your game in a different language (only in-editor).
|
||||
Equivalent of the testing local project setting.
|
||||
|
||||
Update dropdown list via \"Collect Translation\"."
|
||||
|
||||
[node name="TestingLocale" parent="HBox/Testing/VBox3" instance=ExtResource("3_dq4j2")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator4" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TranslationSettings" type="HBoxContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="TranslationSettings"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="SettingsTitle" type="Label" parent="TranslationSettings/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Settings"
|
||||
|
||||
[node name="Grid" type="GridContainer" parent="TranslationSettings/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
columns = 2
|
||||
|
||||
[node name="VBox" type="HBoxContainer" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label3" type="Label" parent="TranslationSettings/VBoxContainer/Grid/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Default locale"
|
||||
|
||||
[node name="HintTooltip" parent="TranslationSettings/VBoxContainer/Grid/VBox" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "The locale of the language your timelines are written in."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "The locale of the language your timelines are written in."
|
||||
|
||||
[node name="OrigLocale" parent="TranslationSettings/VBoxContainer/Grid" instance=ExtResource("3_dq4j2")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TransFile" type="HBoxContainer" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="TranslationSettings/VBoxContainer/Grid/TransFile"]
|
||||
layout_mode = 2
|
||||
text = "Translation folder"
|
||||
|
||||
[node name="HintTooltip3" parent="TranslationSettings/VBoxContainer/Grid/TransFile" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Choose a folder to let Dialogic save CSV files in.
|
||||
Also used when saving \"Inside Translation Folder\""
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Choose a folder to let Dialogic save CSV files in.
|
||||
Also used when saving \"Inside Translation Folder\""
|
||||
|
||||
[node name="TransFolderPicker" parent="TranslationSettings/VBoxContainer/Grid" instance=ExtResource("4_kvsma")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
file_mode = 2
|
||||
|
||||
[node name="VBox2" type="HBoxContainer" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="OutputModeLabel" type="Label" parent="TranslationSettings/VBoxContainer/Grid/VBox2"]
|
||||
layout_mode = 2
|
||||
text = "Output mode"
|
||||
|
||||
[node name="OutputModeTooltip" parent="TranslationSettings/VBoxContainer/Grid/VBox2" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Decides how many CSV files will be created.
|
||||
|
||||
• \"Per Type\": Uses one CSV file for each type of resource: Timelines, characters, and glossaries.
|
||||
For example, 10 timelines will be combined into 1 CSV file.
|
||||
|
||||
• \"Per File\": Uses one CSV file for each resource file.
|
||||
For example, 10 timelines will result in 10 CSV files.
|
||||
|
||||
The \"Per File\" option utilises \"Output location\", in contrast, the \"Per Type\" will always use the Translation folder."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Decides how many CSV files will be created.
|
||||
|
||||
• \"Per Type\": Uses one CSV file for each type of resource: Timelines, characters, and glossaries.
|
||||
For example, 10 timelines will be combined into 1 CSV file.
|
||||
|
||||
• \"Per File\": Uses one CSV file for each resource file.
|
||||
For example, 10 timelines will result in 10 CSV files.
|
||||
|
||||
The \"Per File\" option utilises \"Output location\", in contrast, the \"Per Type\" will always use the Translation folder."
|
||||
|
||||
[node name="TransMode" type="OptionButton" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
item_count = 2
|
||||
selected = 0
|
||||
popup/item_0/text = "Per Type"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Per File"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="OutputLocation" type="HBoxContainer" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="OutputLocationLabel" type="Label" parent="TranslationSettings/VBoxContainer/Grid/OutputLocation"]
|
||||
layout_mode = 2
|
||||
text = "Output location"
|
||||
|
||||
[node name="OutputLocationTooltip" parent="TranslationSettings/VBoxContainer/Grid/OutputLocation" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Decides where to save the generated CSV files.
|
||||
|
||||
• \"Inside Translation Folder\": Uses the \"Translation folder\".
|
||||
|
||||
• \"Next To Timeline\": Places them in the resource type's folder.
|
||||
|
||||
This button requires the \"Per File\" Output mode.
|
||||
A resource type can be: Timelines, characters, and glossaries."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Decides where to save the generated CSV files.
|
||||
|
||||
• \"Inside Translation Folder\": Uses the \"Translation folder\".
|
||||
|
||||
• \"Next To Timeline\": Places them in the resource type's folder.
|
||||
|
||||
This button requires the \"Per File\" Output mode.
|
||||
A resource type can be: Timelines, characters, and glossaries."
|
||||
|
||||
[node name="SaveLocationMode" type="OptionButton" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
disabled = true
|
||||
item_count = 2
|
||||
selected = 0
|
||||
popup/item_0/text = "Inside Translation Folder"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Next to File"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="Control" type="Control" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AddSeparatorHBox" type="HBoxContainer" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AddSeparatorLabel" type="Label" parent="TranslationSettings/VBoxContainer/Grid/AddSeparatorHBox"]
|
||||
layout_mode = 2
|
||||
text = "Add Separator Lines"
|
||||
|
||||
[node name="HintAddSeparatorEnabled" parent="TranslationSettings/VBoxContainer/Grid/AddSeparatorHBox" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Adds an empty line into per-project CSVs to differentiate between sections.
|
||||
|
||||
For example, when a new glossary item or timeline starts, an empty line will be added."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Adds an empty line into per-project CSVs to differentiate between sections.
|
||||
|
||||
For example, when a new glossary item or timeline starts, an empty line will be added."
|
||||
|
||||
[node name="AddSeparatorEnabled" type="CheckBox" parent="TranslationSettings/VBoxContainer/Grid"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator6" type="VSeparator" parent="TranslationSettings"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer2" type="VBoxContainer" parent="TranslationSettings"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="TranslationSettings/VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title3" type="Label" parent="TranslationSettings/VBoxContainer2/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Actions"
|
||||
|
||||
[node name="Actions" type="GridContainer" parent="TranslationSettings/VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
columns = 2
|
||||
|
||||
[node name="UpdateCsvFiles" type="Button" parent="TranslationSettings/VBoxContainer2/Actions"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
disabled = true
|
||||
text = "Update CSV files"
|
||||
icon = SubResource("ImageTexture_xbph7")
|
||||
|
||||
[node name="HintTooltip5" parent="TranslationSettings/VBoxContainer2/Actions" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "This button will scan all timelines and generate or update their CSV files.
|
||||
|
||||
A Dialogic CSV file will be prefixed with \"dialogic_\".
|
||||
|
||||
This action will be disabled if the \"Translation folder\" is missing or has an invalid path."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "This button will scan all timelines and generate or update their CSV files.
|
||||
|
||||
A Dialogic CSV file will be prefixed with \"dialogic_\".
|
||||
|
||||
This action will be disabled if the \"Translation folder\" is missing or has an invalid path."
|
||||
|
||||
[node name="CollectTranslations" type="Button" parent="TranslationSettings/VBoxContainer2/Actions"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Collect translations"
|
||||
icon = SubResource("ImageTexture_xbph7")
|
||||
|
||||
[node name="HintTooltip6" parent="TranslationSettings/VBoxContainer2/Actions" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Godot imports CSV files as \".translation\" files.
|
||||
This buttons adds them to \"Project Settings -> Localization\".
|
||||
"
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Godot imports CSV files as \".translation\" files.
|
||||
This buttons adds them to \"Project Settings -> Localization\".
|
||||
"
|
||||
|
||||
[node name="AspectRatioContainer2" type="AspectRatioContainer" parent="TranslationSettings/VBoxContainer2/Actions"]
|
||||
custom_minimum_size = Vector2(0, 31)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="TranslationSettings/VBoxContainer2/Actions"]
|
||||
custom_minimum_size = Vector2(0, 31)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TransRemove" type="Button" parent="TranslationSettings/VBoxContainer2/Actions"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Remove translations"
|
||||
icon = SubResource("ImageTexture_xbph7")
|
||||
|
||||
[node name="HintTooltip7" parent="TranslationSettings/VBoxContainer2/Actions" instance=ExtResource("2_k2lou")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Be very careful with this button!
|
||||
|
||||
It will try to delete any \".csv\" and \".translation\" files that are related to Dialogic.
|
||||
CSV and translation files prefixed with \"dialogic_\" are treated as Dialogic-related.
|
||||
|
||||
Removes translation IDs (eg. #id:33) from timelines and characters."
|
||||
texture = SubResource("ImageTexture_xbph7")
|
||||
hint_text = "Be very careful with this button!
|
||||
|
||||
It will try to delete any \".csv\" and \".translation\" files that are related to Dialogic.
|
||||
CSV and translation files prefixed with \"dialogic_\" are treated as Dialogic-related.
|
||||
|
||||
Removes translation IDs (eg. #id:33) from timelines and characters."
|
||||
|
||||
[node name="StatusMessage" type="Label" parent="TranslationSettings/VBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "⛔ Requires valid translation folder to translate character names and the project CSV file."
|
||||
autowrap_mode = 3
|
||||
|
||||
[node name="UpdateConfirmationDialog" type="ConfirmationDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
title = "Please Decide..."
|
||||
size = Vector2i(490, 200)
|
||||
ok_button_text = "Delete old & Generate new"
|
||||
dialog_text = "You have previously generated CSVs and translation files with different Translation Settings!
|
||||
|
||||
Please consider to delete the old CSVs and then generate new changes."
|
||||
dialog_autowrap = true
|
||||
|
||||
[node name="EraseConfirmationDialog" type="ConfirmationDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
position = Vector2i(0, 36)
|
||||
size = Vector2i(500, 280)
|
||||
min_size = Vector2i(300, 70)
|
||||
ok_button_text = "DELETE ALL"
|
||||
dialog_text = "You are about to:
|
||||
- Delete all CSVs prefixed with \"dialogic_\".
|
||||
- Delete the related CSV import files.
|
||||
- Delete the related translation files.
|
||||
- Remove translation IDs from timelines and characters.
|
||||
- Remove all \"dialogic\" prefixed translations from \"Project Settings -> Localization\".
|
||||
- Remove the \"_translation_keys\" and \"entries\" starting with \"Glossary/\"."
|
||||
dialog_autowrap = true
|
||||
|
||||
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="."]
|
||||
custom_minimum_size = Vector2(0, 31)
|
||||
layout_mode = 2
|
||||
|
||||
[connection signal="confirmed" from="UpdateConfirmationDialog" to="." method="_delete_and_update"]
|
||||
[connection signal="confirmed" from="EraseConfirmationDialog" to="." method="erase_translations"]
|
||||
Reference in New Issue
Block a user