First work on dialogic, resized guild, and started implementing portraits.

This commit is contained in:
2025-08-14 10:26:24 -04:00
parent 95a7db036b
commit 3aeb3d44e6
959 changed files with 47688 additions and 46 deletions

View File

@@ -0,0 +1,91 @@
@tool
extends DialogicCharacterEditorPortraitSection
## Section that allows setting values of exported scene variables
## for custom portrait scenes
var current_portrait_data := {}
var last_scene := ""
func _get_title() -> String:
return "Settings"
func _load_portrait_data(data:Dictionary) -> void:
_recheck(data, true)
## Recheck section visibility and reload export fields.
## This allows reacting to changes of the portrait_scene setting.
func _recheck(data: Dictionary, force:=false):
if last_scene == data.get("scene", "") and not force:
current_portrait_data = data
last_scene = data.get("scene", "")
return
last_scene = data.get("scene", "")
current_portrait_data = data
for child in $Grid.get_children():
child.get_parent().remove_child(child)
child.queue_free()
var scene: Variant = null
if current_portrait_data.get('scene', '').is_empty():
if ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
scene = load(character_editor.def_portrait_path)
else:
scene = load(ProjectSettings.get_setting('dialogic/portraits/default_portrait', ''))
else:
scene = load(current_portrait_data.get('scene'))
if not scene:
return
scene = scene.instantiate()
var skip := false
for i in scene.script.get_script_property_list():
if i['usage'] & PROPERTY_USAGE_EDITOR and !skip:
var label := Label.new()
label.text = i['name'].capitalize()
$Grid.add_child(label)
var current_value: Variant = scene.get(i['name'])
if current_portrait_data.has('export_overrides') and current_portrait_data['export_overrides'].has(i['name']):
current_value = str_to_var(current_portrait_data.export_overrides[i['name']])
if current_value == null and typeof(scene.get(i['name'])) == TYPE_STRING:
current_value = current_portrait_data['export_overrides'][i['name']]
var input: Node = DialogicUtil.setup_script_property_edit_node(i, current_value, set_export_override)
input.size_flags_horizontal = SIZE_EXPAND_FILL
$Grid.add_child(input)
if i['usage'] & PROPERTY_USAGE_GROUP:
if i['name'] == 'Main' or i["name"] == "Private":
skip = true
continue
else:
skip = false
if $Grid.get_child_count():
get_parent().get_child(get_index()-1).show()
show()
else:
hide()
get_parent().get_child(get_index()-1).hide()
get_parent().get_child(get_index()+1).hide()
## On any change, save the export override to the portrait items metadata.
func set_export_override(property_name:String, value:String = "") -> void:
var data: Dictionary = selected_item.get_metadata(0)
if !data.has('export_overrides'):
data['export_overrides'] = {}
if !value.is_empty():
data.export_overrides[property_name] = value
else:
data.export_overrides.erase(property_name)
changed.emit()
update_preview.emit()

View File

@@ -0,0 +1 @@
uid://b8tapr3u1xqcs

View File

@@ -0,0 +1,16 @@
[gd_scene load_steps=2 format=3 uid="uid://cfcs7lb6gqnmd"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd" id="1_isys8"]
[node name="Settings" type="VBoxContainer"]
custom_minimum_size = Vector2(0, 35)
offset_right = 367.0
offset_bottom = 82.0
script = ExtResource("1_isys8")
[node name="Grid" type="GridContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/h_separation = 10
columns = 2

View File

@@ -0,0 +1,44 @@
@tool
extends DialogicCharacterEditorPortraitSection
## Tab that allows setting size, offset and mirror of a portrait.
func _get_title() -> String:
return "Scale, Offset & Mirror"
func _load_portrait_data(data:Dictionary) -> void:
%IgnoreScale.set_pressed_no_signal(data.get('ignore_char_scale', false))
%PortraitScale.value = data.get('scale', 1.0)*100
%PortraitOffset.set_value(data.get('offset', Vector2()))
%PortraitOffset._load_display_info({'step':1})
%PortraitMirror.set_pressed_no_signal(data.get('mirror', false))
func _on_portrait_scale_value_changed(value:float) -> void:
var data: Dictionary = selected_item.get_metadata(0)
data['scale'] = value/100.0
update_preview.emit()
changed.emit()
func _on_portrait_mirror_toggled(button_pressed:bool)-> void:
var data: Dictionary = selected_item.get_metadata(0)
data['mirror'] = button_pressed
update_preview.emit()
changed.emit()
func _on_ignore_scale_toggled(button_pressed:bool) -> void:
var data: Dictionary = selected_item.get_metadata(0)
data['ignore_char_scale'] = button_pressed
update_preview.emit()
changed.emit()
func _on_portrait_offset_value_changed(property:String, value:Vector2) -> void:
var data: Dictionary = selected_item.get_metadata(0)
data['offset'] = value
update_preview.emit()
changed.emit()

View File

@@ -0,0 +1 @@
uid://bx5eoolcasq2a

View File

@@ -0,0 +1,64 @@
[gd_scene load_steps=3 format=3 uid="uid://crke8suvv52c6"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd" id="1_76vf2"]
[ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="2_c8kyi"]
[node name="Layout" type="HFlowContainer"]
offset_right = 428.0
offset_bottom = 128.0
size_flags_horizontal = 3
script = ExtResource("1_76vf2")
[node name="Label3" type="Label" parent="."]
layout_mode = 2
text = "Ignore Main Scale: "
[node name="IgnoreScale" type="CheckBox" parent="."]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "This portrait will ignore the main scale."
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="Label" type="Label" parent="HBoxContainer"]
layout_mode = 2
text = "Scale:"
[node name="PortraitScale" type="SpinBox" parent="HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "A scale to be applied on top of the main scale
(unless ignore main scale is pressed)."
value = 100.0
allow_greater = true
suffix = "%"
[node name="HBoxContainer2" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="Label2" type="Label" parent="HBoxContainer2"]
layout_mode = 2
text = "Offset:"
[node name="PortraitOffset" parent="HBoxContainer2" instance=ExtResource("2_c8kyi")]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Offset that is applied on top of the main portrait offset."
[node name="MirrorOption" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="Label" type="Label" parent="MirrorOption"]
layout_mode = 2
text = "Mirror:"
[node name="PortraitMirror" type="CheckBox" parent="MirrorOption"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Mirroring that is applied on top of the main portrait mirror."
[connection signal="toggled" from="IgnoreScale" to="." method="_on_ignore_scale_toggled"]
[connection signal="value_changed" from="HBoxContainer/PortraitScale" to="." method="_on_portrait_scale_value_changed"]
[connection signal="value_changed" from="HBoxContainer2/PortraitOffset" to="." method="_on_portrait_offset_value_changed"]
[connection signal="toggled" from="MirrorOption/PortraitMirror" to="." method="_on_portrait_mirror_toggled"]

View File

@@ -0,0 +1,101 @@
@tool
extends DialogicCharacterEditorPortraitSection
## Tab that allows setting a custom scene for a portrait.
func _get_title() -> String:
return "Scene"
func _init() -> void:
hint_text = "You can use a custom scene for this portrait."
func _start_opened() -> bool:
return true
func _ready() -> void:
%ChangeSceneButton.icon = get_theme_icon("Loop", "EditorIcons")
%ScenePicker.file_filter = "*.tscn, *.scn; Scenes"
%ScenePicker.resource_icon = get_theme_icon('PackedScene', 'EditorIcons')
%ScenePicker.placeholder = 'Default scene'
%OpenSceneButton.icon = get_theme_icon("ExternalLink", "EditorIcons")
func _load_portrait_data(data:Dictionary) -> void:
reload_ui(data)
func _on_open_scene_button_pressed() -> void:
var data: Dictionary = selected_item.get_metadata(0)
if ResourceLoader.exists(data.get("scene", "")):
DialogicUtil.get_dialogic_plugin().get_editor_interface().open_scene_from_path(data.get("scene", ""))
await get_tree().process_frame
EditorInterface.set_main_screen_editor("2D")
func _on_change_scene_button_pressed() -> void:
%PortraitSceneBrowserWindow.popup_centered_ratio(0.6)
func _on_portrait_scene_browser_activate_part(part_info: Dictionary) -> void:
%PortraitSceneBrowserWindow.hide()
match part_info.type:
"General":
set_scene_path(part_info.path)
"Preset":
find_parent("EditorView").godot_file_dialog(
create_new_portrait_scene.bind(part_info),
'*.tscn,*.scn',
EditorFileDialog.FILE_MODE_SAVE_FILE,
"Select where to save the new scene",
part_info.path.get_file().trim_suffix("."+part_info.path.get_extension())+"_"+character_editor.current_resource.get_character_name().to_lower())
"Custom":
find_parent("EditorView").godot_file_dialog(
set_scene_path,
'*.tscn, *.scn',
EditorFileDialog.FILE_MODE_OPEN_FILE,
"Select custom portrait scene",)
"Default":
set_scene_path("")
func create_new_portrait_scene(target_file: String, info: Dictionary) -> void:
var path := make_portrait_preset_custom(target_file, info)
set_scene_path(path)
func make_portrait_preset_custom(target_file:String, info: Dictionary) -> String:
var previous_file: String = info.path
var result_path := DialogicUtil.make_file_custom(previous_file, target_file.get_base_dir(), target_file.get_file())
return result_path
func set_scene_path(path:String) -> void:
var data: Dictionary = selected_item.get_metadata(0)
data['scene'] = path
update_preview.emit()
changed.emit()
reload_ui(data)
func reload_ui(data: Dictionary) -> void:
var path: String = data.get('scene', '')
%OpenSceneButton.hide()
if path.is_empty():
%SceneLabel.text = "Default Portrait Scene"
%SceneLabel.tooltip_text = "Can be changed in the settings."
%SceneLabel.add_theme_color_override("font_color", get_theme_color("readonly_color", "Editor"))
elif %PortraitSceneBrowser.is_premade_portrait_scene(path):
%SceneLabel.text = %PortraitSceneBrowser.portrait_scenes_info[path].name
%SceneLabel.tooltip_text = path
%SceneLabel.add_theme_color_override("font_color", get_theme_color("accent_color", "Editor"))
else:
%SceneLabel.text = path.get_file()
%SceneLabel.tooltip_text = path
%SceneLabel.add_theme_color_override("font_color", get_theme_color("property_color_x", "Editor"))
%OpenSceneButton.show()

View File

@@ -0,0 +1 @@
uid://cgxkh7p7noqj3

View File

@@ -0,0 +1,72 @@
[gd_scene load_steps=6 format=3 uid="uid://djq4aasoihexj"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd" id="1_ht8lu"]
[ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="2_k8xs0"]
[ext_resource type="PackedScene" uid="uid://b1wn8r84uh11b" path="res://addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn" id="3_ngvgq"]
[sub_resource type="Image" id="Image_tg5pd"]
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_f5xt2"]
image = SubResource("Image_tg5pd")
[node name="Scene" type="GridContainer"]
offset_right = 298.0
offset_bottom = 86.0
size_flags_horizontal = 3
script = ExtResource("1_ht8lu")
[node name="HBox" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="ChangeSceneButton" type="Button" parent="HBox"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Change Scene"
icon = SubResource("ImageTexture_f5xt2")
[node name="SceneLabel" type="Label" parent="HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 0
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "asdsdasdasd"
clip_text = true
[node name="ScenePicker" parent="HBox" instance=ExtResource("2_k8xs0")]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_horizontal = 3
file_filter = "*.tscn, *.scn; Scenes"
placeholder = "Default scene"
[node name="OpenSceneButton" type="Button" parent="HBox"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Open/Edit Scene"
icon = SubResource("ImageTexture_f5xt2")
[node name="PortraitSceneBrowserWindow" type="Window" parent="."]
unique_name_in_owner = true
title = "Portrait Scene Browser"
position = Vector2i(0, 36)
visible = false
wrap_controls = true
transient = true
popup_window = true
[node name="PortraitSceneBrowser" parent="PortraitSceneBrowserWindow" instance=ExtResource("3_ngvgq")]
unique_name_in_owner = true
[connection signal="pressed" from="HBox/ChangeSceneButton" to="." method="_on_change_scene_button_pressed"]
[connection signal="pressed" from="HBox/OpenSceneButton" to="." method="_on_open_scene_button_pressed"]
[connection signal="activate_part" from="PortraitSceneBrowserWindow/PortraitSceneBrowser" to="." method="_on_portrait_scene_browser_activate_part"]

View File

@@ -0,0 +1,80 @@
@tool
extends DialogicCharacterEditorPortraitSection
## Portrait Settings Section that only shows the MAIN settings of a portrait scene.
var current_portrait_data := {}
var last_scene := ""
func _show_title() -> bool:
return false
func _load_portrait_data(data:Dictionary) -> void:
_recheck(data, true)
func _recheck(data:Dictionary, force := false) -> void:
get_parent().get_child(get_index()+1).hide()
if last_scene == data.get("scene", "") and not force:
current_portrait_data = data
last_scene = data.get("scene", "")
return
last_scene = data.get("scene", "")
current_portrait_data = data
load_portrait_scene_export_variables()
func load_portrait_scene_export_variables() -> void:
for child in $Grid.get_children():
child.queue_free()
var scene: Variant = null
if current_portrait_data.get('scene', '').is_empty():
if ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
scene = load(character_editor.def_portrait_path)
else:
scene = load(ProjectSettings.get_setting('dialogic/portraits/default_portrait', ''))
else:
scene = load(current_portrait_data.get('scene'))
if not scene:
return
scene = scene.instantiate()
var skip := true
for i in scene.script.get_script_property_list():
if i['usage'] & PROPERTY_USAGE_EDITOR and !skip:
var label := Label.new()
label.text = i['name'].capitalize()
$Grid.add_child(label)
var current_value: Variant = scene.get(i['name'])
if current_portrait_data.has('export_overrides') and current_portrait_data['export_overrides'].has(i['name']):
current_value = str_to_var(current_portrait_data['export_overrides'][i['name']])
if current_value == null and typeof(scene.get(i['name'])) == TYPE_STRING:
current_value = current_portrait_data['export_overrides'][i['name']]
var input: Node = DialogicUtil.setup_script_property_edit_node(i, current_value, set_export_override)
input.size_flags_horizontal = SIZE_EXPAND_FILL
$Grid.add_child(input)
if i['usage'] & PROPERTY_USAGE_GROUP:
if i['name'] == 'Main':
skip = false
else:
skip = true
continue
func set_export_override(property_name:String, value:String = "") -> void:
var data: Dictionary = selected_item.get_metadata(0)
if !data.has('export_overrides'):
data['export_overrides'] = {}
if !value.is_empty():
data['export_overrides'][property_name] = value
else:
data['export_overrides'].erase(property_name)
changed.emit()
update_preview.emit()

View File

@@ -0,0 +1 @@
uid://4if0rb0jqyyy

View File

@@ -0,0 +1,15 @@
[gd_scene load_steps=2 format=3 uid="uid://ba5w02lm3ewkj"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd" id="1_mttrr"]
[node name="MainExports" type="VBoxContainer"]
offset_right = 374.0
offset_bottom = 82.0
script = ExtResource("1_mttrr")
[node name="Grid" type="GridContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/h_separation = 10
columns = 2

View File

@@ -0,0 +1,53 @@
@tool
extends DialogicCharacterEditorMainSection
var min_width := 200
## The general character settings tab
func _get_title() -> String:
return "General"
func _start_opened() -> bool:
return true
func _ready() -> void:
# Connecting all necessary signals
%ColorPickerButton.custom_minimum_size.x = DialogicUtil.get_editor_scale() * 30
%ColorPickerButton.color_changed.connect(character_editor.something_changed)
%DisplayNameLineEdit.text_changed.connect(character_editor.something_changed)
%NicknameLineEdit.text_changed.connect(character_editor.something_changed)
%DescriptionTextEdit.text_changed.connect(character_editor.something_changed)
min_width = get_minimum_size().x
resized.connect(_on_resized)
func _load_character(resource:DialogicCharacter) -> void:
%DisplayNameLineEdit.text = resource.display_name
%ColorPickerButton.color = resource.color
%NicknameLineEdit.text = ""
for nickname in resource.nicknames:
%NicknameLineEdit.text += nickname +", "
%NicknameLineEdit.text = %NicknameLineEdit.text.trim_suffix(', ')
%DescriptionTextEdit.text = resource.description
func _save_changes(resource:DialogicCharacter) -> DialogicCharacter:
resource.display_name = %DisplayNameLineEdit.text
resource.color = %ColorPickerButton.color
var nicknames := []
for n_name in %NicknameLineEdit.text.split(','):
nicknames.append(n_name.strip_edges())
resource.nicknames = nicknames
resource.description = %DescriptionTextEdit.text
return resource
func _on_resized() -> void:
if size.x > min_width+20:
self.columns = 2
else:
self.columns = 1

View File

@@ -0,0 +1 @@
uid://dsg3an4r8rwqc

View File

@@ -0,0 +1,114 @@
[gd_scene load_steps=5 format=3 uid="uid://bnkck3hocbkk5"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd" id="1_3e1i1"]
[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_cxfqm"]
[sub_resource type="Image" id="Image_yiygw"]
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_hx3oq"]
image = SubResource("Image_yiygw")
[node name="General" type="GridContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 7.5
offset_top = 38.5
offset_right = -7.5
offset_bottom = -7.5
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/h_separation = 6
theme_override_constants/v_separation = 6
columns = 2
script = ExtResource("1_3e1i1")
[node name="HBox" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="Label2" type="Label" parent="HBox"]
layout_mode = 2
size_flags_vertical = 0
text = "Display Name"
[node name="HintTooltip" parent="HBox" instance=ExtResource("2_cxfqm")]
layout_mode = 2
tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable. E.g. :{Player.name}"
texture = SubResource("ImageTexture_hx3oq")
hint_text = "This name will be displayed on the name label. You can use a dialogic variable. E.g. :{Player.name}"
[node name="DisplayName" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="DisplayNameLineEdit" type="LineEdit" parent="DisplayName"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
caret_blink = true
caret_blink_interval = 0.5
[node name="HintTooltip4" parent="DisplayName" instance=ExtResource("2_cxfqm")]
layout_mode = 2
tooltip_text = "This color can be used on the name label and for occurences of the characters name in text (autocolor names)."
texture = SubResource("ImageTexture_hx3oq")
hint_text = "This color can be used on the name label and for occurences of the characters name in text (autocolor names)."
[node name="ColorPickerButton" type="ColorPickerButton" parent="DisplayName"]
unique_name_in_owner = true
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
color = Color(1, 1, 1, 1)
edit_alpha = false
[node name="HBox2" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="Label3" type="Label" parent="HBox2"]
layout_mode = 2
size_flags_vertical = 0
text = "Nicknames"
[node name="HintTooltip2" parent="HBox2" instance=ExtResource("2_cxfqm")]
layout_mode = 2
tooltip_text = "If autocolor names is enabled, these will be colored in the characters color as well."
texture = SubResource("ImageTexture_hx3oq")
hint_text = "If autocolor names is enabled, these will be colored in the characters color as well."
[node name="NicknameLineEdit" type="LineEdit" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
caret_blink = true
caret_blink_interval = 0.5
[node name="HBox3" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="Label4" type="Label" parent="HBox3"]
layout_mode = 2
size_flags_vertical = 0
text = "Description"
[node name="HintTooltip3" parent="HBox3" instance=ExtResource("2_cxfqm")]
layout_mode = 2
tooltip_text = "No effect, just for you."
texture = SubResource("ImageTexture_hx3oq")
hint_text = "No effect, just for you."
[node name="DescriptionTextEdit" type="TextEdit" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 65)
layout_mode = 2
size_flags_horizontal = 3
wrap_mode = 1

View File

@@ -0,0 +1,77 @@
@tool
extends DialogicCharacterEditorMainSection
## The general portrait settings section
var loading := false
func _get_title() -> String:
return "Portraits"
func _ready() -> void:
# Connecting all necessary signals
%DefaultPortraitPicker.value_changed.connect(default_portrait_changed)
%MainScale.value_changed.connect(main_portrait_settings_update)
%MainOffset._load_display_info({'step':1})
%MainOffset.value_changed.connect(main_portrait_settings_update)
%MainMirror.toggled.connect(main_portrait_settings_update)
# Setting up Default Portrait Picker
%DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg")
%DefaultPortraitPicker.get_suggestions_func = suggest_portraits
## Make sure preview get's updated when portrait settings change
func main_portrait_settings_update(_something=null, _value=null) -> void:
if loading:
return
character_editor.current_resource.scale = %MainScale.value/100.0
character_editor.current_resource.offset = %MainOffset.current_value
character_editor.current_resource.mirror = %MainMirror.button_pressed
character_editor.update_preview()
character_editor.something_changed()
func default_portrait_changed(property:String, value:String) -> void:
character_editor.current_resource.default_portrait = value
character_editor.update_default_portrait_star(value)
func set_default_portrait(portrait_name:String) -> void:
%DefaultPortraitPicker.set_value(portrait_name)
default_portrait_changed("", portrait_name)
func _load_character(resource:DialogicCharacter) -> void:
loading = true
%DefaultPortraitPicker.set_value(resource.default_portrait)
%MainScale.value = 100*resource.scale
%MainOffset.set_value(resource.offset)
%MainMirror.button_pressed = resource.mirror
loading = false
func _save_changes(resource:DialogicCharacter) -> DialogicCharacter:
# Portrait settings
if %DefaultPortraitPicker.current_value in resource.portraits.keys():
resource.default_portrait = %DefaultPortraitPicker.current_value
elif !resource.portraits.is_empty():
resource.default_portrait = resource.portraits.keys()[0]
else:
resource.default_portrait = ""
resource.scale = %MainScale.value/100.0
resource.offset = %MainOffset.current_value
resource.mirror = %MainMirror.button_pressed
return resource
## Get suggestions for DefaultPortraitPicker
func suggest_portraits(search:String) -> Dictionary:
var suggestions := {}
for portrait in character_editor.get_updated_portrait_dict().keys():
suggestions[portrait] = {'value':portrait}
return suggestions

View File

@@ -0,0 +1 @@
uid://j2j3xrrypli8

View File

@@ -0,0 +1,59 @@
[gd_scene load_steps=4 format=3 uid="uid://cmrgbo8qi145o"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd" id="1_6sxsl"]
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="2_birla"]
[ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="3_vcvin"]
[node name="Portraits" type="GridContainer"]
offset_right = 453.0
offset_bottom = 141.0
theme_override_constants/h_separation = 1
theme_override_constants/v_separation = 6
columns = 2
script = ExtResource("1_6sxsl")
[node name="Label5" type="Label" parent="."]
layout_mode = 2
size_flags_vertical = 0
text = "Default"
[node name="DefaultPortraitPicker" parent="." instance=ExtResource("2_birla")]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Select Default Portrait"
fit_text_length = false
[node name="Label" type="Label" parent="."]
layout_mode = 2
size_flags_vertical = 0
text = "Main Scale"
[node name="MainScale" type="SpinBox" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
value = 100.0
allow_greater = true
alignment = 1
suffix = "%"
[node name="Label2" type="Label" parent="."]
layout_mode = 2
size_flags_vertical = 0
text = "Main Offset"
[node name="MainOffset" parent="." instance=ExtResource("3_vcvin")]
unique_name_in_owner = true
layout_mode = 2
alignment = 2
[node name="Label3" type="Label" parent="."]
layout_mode = 2
size_flags_vertical = 0
text = "Main Mirror"
[node name="MainMirror" type="CheckBox" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8

View File

@@ -0,0 +1,688 @@
@tool
extends DialogicEditor
## Editor for editing character resources.
signal character_loaded(resource_path:String)
signal portrait_selected()
# Current state
var loading := false
var current_previewed_scene: Variant = null
var current_scene_path: String = ""
# References
var selected_item: TreeItem
var def_portrait_path: String = DialogicUtil.get_module_path('Character').path_join('default_portrait.tscn')
######### EDITOR STUFF and LOADING/SAVING ######################################
#region Resource Logic
## Method is called once editors manager is ready to accept registers.
func _register() -> void:
## Makes the editor open this when a .dch file is selected.
## Then _open_resource() is called.
editors_manager.register_resource_editor("dch", self)
## Add an "add character" button
var add_character_button: Button = editors_manager.add_icon_button(
load("res://addons/dialogic/Editor/Images/Toolbar/add-character.svg"),
'Add Character',
self)
add_character_button.pressed.connect(_on_create_character_button_pressed)
add_character_button.shortcut = Shortcut.new()
add_character_button.shortcut.events.append(InputEventKey.new())
add_character_button.shortcut.events[0].keycode = KEY_2
add_character_button.shortcut.events[0].ctrl_pressed = true
## By default show the no character screen
$NoCharacterScreen.show()
func _get_title() -> String:
return "Character"
func _get_icon() -> Texture:
return load("res://addons/dialogic/Editor/Images/Resources/character.svg")
## Called when a character is opened somehow
func _open_resource(resource:Resource) -> void:
if resource == null:
$NoCharacterScreen.show()
return
## Update resource
current_resource = (resource as DialogicCharacter)
## Make sure changes in the ui won't trigger saving
loading = true
## Load other main tabs
for child in %MainSettingsSections.get_children():
if child is DialogicCharacterEditorMainSection:
child._load_character(current_resource)
## Clear and then load Portrait section
%PortraitSearch.text = ""
load_portrait_tree()
loading = false
character_loaded.emit(resource.resource_path)
%CharacterName.text = DialogicResourceUtil.get_unique_identifier(resource.resource_path)
$NoCharacterScreen.hide()
%PortraitChangeInfo.hide()
## Called when the character is opened.
func _open(extra_info:Variant="") -> void:
if !ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
def_portrait_path = ProjectSettings.get_setting('dialogic/portraits/default_portrait', '')
else:
def_portrait_path = DialogicUtil.get_module_path('Character').path_join('default_portrait.tscn')
if current_resource == null:
$NoCharacterScreen.show()
return
update_preview(true)
%PortraitChangeInfo.hide()
func _clear() -> void:
current_resource = null
current_resource_state = ResourceStates.SAVED
$NoCharacterScreen.show()
func _save() -> void:
if ! visible or not current_resource:
return
## Portrait list
current_resource.portraits = get_updated_portrait_dict()
## Main tabs
for child in %MainSettingsSections.get_children():
if child is DialogicCharacterEditorMainSection:
current_resource = child._save_changes(current_resource)
ResourceSaver.save(current_resource, current_resource.resource_path)
current_resource_state = ResourceStates.SAVED
DialogicResourceUtil.update_directory('dch')
## Saves a new empty character to the given path
func new_character(path: String) -> void:
var resource := DialogicCharacter.new()
resource.resource_path = path
resource.display_name = path.get_file().trim_suffix("."+path.get_extension())
resource.color = Color(1,1,1,1)
resource.default_portrait = ""
resource.custom_info = {}
ResourceSaver.save(resource, path)
EditorInterface.get_resource_filesystem().update_file(path)
DialogicResourceUtil.update_directory('dch')
editors_manager.edit_resource(resource)
#endregion
######### INTERFACE ############################################################
#region Interface
func _ready() -> void:
if get_parent() is SubViewport:
return
DialogicUtil.get_dialogic_plugin().resource_saved.connect(_on_some_resource_saved)
# NOTE: This check is required because up to 4.2 this signal is not exposed.
if DialogicUtil.get_dialogic_plugin().has_signal("scene_saved"):
DialogicUtil.get_dialogic_plugin().scene_saved.connect(_on_some_resource_saved)
$NoCharacterScreen.color = get_theme_color("dark_color_2", "Editor")
$NoCharacterScreen.show()
setup_portrait_list_tab()
_on_fit_preview_toggle_toggled(DialogicUtil.get_editor_setting('character_preview_fit', true))
%PreviewLabel.add_theme_color_override("font_color", get_theme_color("readonly_color", "Editor"))
%PortraitChangeWarning.add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"))
%RealPreviewPivot.texture = get_theme_icon("EditorPivot", "EditorIcons")
%MainSettingsCollapse.icon = get_theme_icon("GuiVisibilityVisible", "EditorIcons")
set_portrait_settings_position(DialogicUtil.get_editor_setting('portrait_settings_position', true))
await find_parent('EditorView').ready
## Add general tabs
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn").instantiate(), %MainSettingsSections)
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn").instantiate(), %MainSettingsSections)
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn").instantiate(), %PortraitSettingsSection)
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.tscn").instantiate(), %PortraitSettingsSection)
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.tscn").instantiate(), %PortraitSettingsSection)
add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.tscn").instantiate(), %PortraitSettingsSection)
## Load custom sections from modules
for indexer in DialogicUtil.get_indexers():
for path in indexer._get_character_editor_sections():
var scene: Control = load(path).instantiate()
if scene is DialogicCharacterEditorMainSection:
add_settings_section(scene, %MainSettingsSections)
elif scene is DialogicCharacterEditorPortraitSection:
add_settings_section(scene, %PortraitSettingsSection)
## Add a section (a control) either to the given settings section (Main or Portraits)
## - sets up the title of the section
## - connects to various signals
func add_settings_section(edit:Control, parent:Node) -> void:
edit.changed.connect(something_changed)
edit.character_editor = self
if edit.has_signal('update_preview'):
edit.update_preview.connect(update_preview)
var button: Button
if edit._show_title():
var hbox := HBoxContainer.new()
hbox.name = edit._get_title()+"BOX"
button = Button.new()
button.flat = true
button.theme_type_variation = "DialogicSection"
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
button.text = edit._get_title()
button.icon_alignment = HORIZONTAL_ALIGNMENT_RIGHT
button.pressed.connect(_on_section_button_pressed.bind(button))
button.focus_mode = Control.FOCUS_NONE
button.icon = get_theme_icon("CodeFoldDownArrow", "EditorIcons")
button.add_theme_color_override('icon_normal_color', get_theme_color("font_color", "DialogicSection"))
hbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
hbox.add_child(button)
if !edit.hint_text.is_empty():
var hint: Node = load("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn").instantiate()
hint.hint_text = edit.hint_text
hbox.add_child(hint)
parent.add_child(hbox)
parent.add_child(edit)
parent.add_child(HSeparator.new())
if button and !edit._start_opened():
_on_section_button_pressed(button)
func get_settings_section_by_name(name:String, main:=true) -> Node:
var parent := %MainSettingsSections
if not main:
parent = %PortraitSettingsSection
if parent.has_node(name):
return parent.get_node(name)
elif parent.has_node(name+"BOX/"+name):
return parent.get_node(name+"BOX/"+name)
else:
return null
func _on_section_button_pressed(button:Button) -> void:
var section_header := button.get_parent()
var section := section_header.get_parent().get_child(section_header.get_index()+1)
if section.visible:
button.icon = get_theme_icon("CodeFoldedRightArrow", "EditorIcons")
section.visible = false
else:
button.icon = get_theme_icon("CodeFoldDownArrow", "EditorIcons")
section.visible = true
if section_header.get_parent().get_child_count() > section_header.get_index()+2 and section_header.get_parent().get_child(section_header.get_index()+2) is Separator:
section_header.get_parent().get_child(section_header.get_index()+2).visible = section_header.get_parent().get_child(section_header.get_index()+1).visible
func something_changed(fake_argument = "", fake_arg2 = null) -> void:
if not loading:
current_resource_state = ResourceStates.UNSAVED
func _on_main_settings_collapse_toggled(button_pressed:bool) -> void:
%MainSettingsTitle.visible = !button_pressed
%MainSettingsScroll.visible = !button_pressed
if button_pressed:
%MainSettings.hide()
%MainSettingsCollapse.icon = get_theme_icon("GuiVisibilityHidden", "EditorIcons")
else:
%MainSettings.show()
%MainSettingsCollapse.icon = get_theme_icon("GuiVisibilityVisible", "EditorIcons")
func _on_switch_portrait_settings_position_pressed() -> void:
set_portrait_settings_position(!%RightSection.vertical)
func set_portrait_settings_position(is_below:bool) -> void:
%RightSection.vertical = is_below
DialogicUtil.set_editor_setting('portrait_settings_position', is_below)
if is_below:
%SwitchPortraitSettingsPosition.icon = get_theme_icon("ControlAlignRightWide", "EditorIcons")
else:
%SwitchPortraitSettingsPosition.icon = get_theme_icon("ControlAlignBottomWide", "EditorIcons")
#endregion
########## PORTRAIT SECTION ####################################################
#region Portrait Section
func setup_portrait_list_tab() -> void:
%PortraitTree.editor = self
## Portrait section styling/connections
%AddPortraitButton.icon = get_theme_icon("Add", "EditorIcons")
%AddPortraitButton.pressed.connect(add_portrait)
%AddPortraitGroupButton.icon = load("res://addons/dialogic/Editor/Images/Pieces/add-folder.svg")
%AddPortraitGroupButton.pressed.connect(add_portrait_group)
%ImportPortraitsButton.icon = get_theme_icon("Load", "EditorIcons")
%ImportPortraitsButton.pressed.connect(open_portrait_folder_select)
%PortraitSearch.right_icon = get_theme_icon("Search", "EditorIcons")
%PortraitSearch.text_changed.connect(filter_portrait_list)
%PortraitTree.item_selected.connect(load_selected_portrait)
%PortraitTree.item_edited.connect(_on_item_edited)
%PortraitTree.item_activated.connect(_on_item_activated)
func open_portrait_folder_select() -> void:
find_parent("EditorView").godot_file_dialog(
import_portraits_from_folder, "*.svg, *.png",
EditorFileDialog.FILE_MODE_OPEN_DIR)
func import_portraits_from_folder(path:String) -> void:
var parent: TreeItem = %PortraitTree.get_root()
if %PortraitTree.get_selected() and %PortraitTree.get_selected() != parent and %PortraitTree.get_selected().get_metadata(0).has('group'):
parent = %PortraitTree.get_selected()
var dir := DirAccess.open(path)
dir.list_dir_begin()
var file_name: String = dir.get_next()
var files := []
while file_name != "":
if not dir.current_is_dir():
var file_lower := file_name.to_lower()
if '.svg' in file_lower or '.png' in file_lower:
if not '.import' in file_lower:
files.append(file_name)
file_name = dir.get_next()
var prefix: String = files[0]
for file in files:
while true:
if file.begins_with(prefix):
break
if prefix.is_empty():
break
prefix = prefix.substr(0, len(prefix)-1)
for file in files:
%PortraitTree.add_portrait_item(file.trim_prefix(prefix).trim_suffix('.'+file.get_extension()),
{'scene':"",'export_overrides':{'image':var_to_str(path.path_join(file))}, 'scale':1, 'offset':Vector2(), 'mirror':false}, parent)
## Handle selection
if parent.get_child_count():
parent.get_first_child().select(0)
else:
# Call anyways to clear preview and hide portrait settings section
load_selected_portrait()
something_changed()
func add_portrait(portrait_name:String='New portrait', portrait_data:Dictionary={'scene':"", 'export_overrides':{'image':''}, 'scale':1, 'offset':Vector2(), 'mirror':false}) -> void:
var parent: TreeItem = %PortraitTree.get_root()
if %PortraitTree.get_selected():
if %PortraitTree.get_selected().get_metadata(0) and %PortraitTree.get_selected().get_metadata(0).has('group'):
parent = %PortraitTree.get_selected()
else:
parent = %PortraitTree.get_selected().get_parent()
var item: TreeItem = %PortraitTree.add_portrait_item(portrait_name, portrait_data, parent)
item.set_meta('new', true)
item.set_editable(0, true)
item.select(0)
%PortraitTree.call_deferred('edit_selected')
something_changed()
func add_portrait_group() -> void:
var parent_item: TreeItem = %PortraitTree.get_root()
if %PortraitTree.get_selected() and %PortraitTree.get_selected().get_metadata(0).has('group'):
parent_item = %PortraitTree.get_selected()
var item: TreeItem = %PortraitTree.add_portrait_group("Group", parent_item)
item.set_meta('new', true)
item.set_editable(0, true)
item.select(0)
%PortraitTree.call_deferred('edit_selected')
func load_portrait_tree() -> void:
%PortraitTree.clear_tree()
var root: TreeItem = %PortraitTree.create_item()
for portrait in current_resource.portraits.keys():
var portrait_label: String = portrait
var parent: TreeItem = %PortraitTree.get_root()
if '/' in portrait:
parent = %PortraitTree.create_necessary_group_items(portrait)
portrait_label = portrait.split('/')[-1]
%PortraitTree.add_portrait_item(portrait_label, current_resource.portraits[portrait], parent)
update_default_portrait_star(current_resource.default_portrait)
if root.get_child_count():
root.get_first_child().select(0)
while %PortraitTree.get_selected().get_child_count():
%PortraitTree.get_selected().get_child(0).select(0)
else:
# Call anyways to clear preview and hide portrait settings section
load_selected_portrait()
func filter_portrait_list(filter_term := "") -> void:
filter_branch(%PortraitTree.get_root(), filter_term)
func filter_branch(parent: TreeItem, filter_term: String) -> bool:
var anything_visible := false
for item in parent.get_children():
if item.get_metadata(0).has('group'):
item.visible = filter_branch(item, filter_term)
anything_visible = item.visible
elif filter_term.is_empty() or filter_term.to_lower() in item.get_text(0).to_lower():
item.visible = true
anything_visible = true
else:
item.visible = false
return anything_visible
## This is used to save the portrait data
func get_updated_portrait_dict() -> Dictionary:
return list_portraits(%PortraitTree.get_root().get_children())
func list_portraits(tree_items: Array[TreeItem], dict := {}, path_prefix := "") -> Dictionary:
for item in tree_items:
if item.get_metadata(0).has('group'):
dict = list_portraits(item.get_children(), dict, path_prefix+item.get_text(0)+"/")
else:
dict[path_prefix +item.get_text(0)] = item.get_metadata(0)
return dict
func load_selected_portrait() -> void:
if selected_item and is_instance_valid(selected_item):
selected_item.set_editable(0, false)
selected_item = %PortraitTree.get_selected()
if selected_item and selected_item.get_metadata(0) != null and !selected_item.get_metadata(0).has('group'):
%PortraitSettingsSection.show()
var current_portrait_data: Dictionary = selected_item.get_metadata(0)
portrait_selected.emit(%PortraitTree.get_full_item_name(selected_item), current_portrait_data)
update_preview()
for child in %PortraitSettingsSection.get_children():
if child is DialogicCharacterEditorPortraitSection:
child.selected_item = selected_item
child._load_portrait_data(current_portrait_data)
else:
%PortraitSettingsSection.hide()
update_preview()
func delete_portrait_item(item: TreeItem) -> void:
if item.get_next_visible(true) and item.get_next_visible(true) != item:
item.get_next_visible(true).select(0)
else:
selected_item = null
load_selected_portrait()
item.free()
something_changed()
func duplicate_item(item: TreeItem) -> void:
var new_item: TreeItem = %PortraitTree.add_portrait_item(item.get_text(0)+'_duplicated', item.get_metadata(0).duplicate(true), item.get_parent())
new_item.set_meta('new', true)
new_item.select(0)
func _input(event: InputEvent) -> void:
if !is_visible_in_tree() or (get_viewport().gui_get_focus_owner()!= null and !name+'/' in str(get_viewport().gui_get_focus_owner().get_path())):
return
if event is InputEventKey and event.pressed:
if event.keycode == KEY_F2 and %PortraitTree.get_selected():
%PortraitTree.get_selected().set_editable(0, true)
%PortraitTree.edit_selected()
get_viewport().set_input_as_handled()
elif event.keycode == KEY_DELETE and get_viewport().gui_get_focus_owner() is Tree and %PortraitTree.get_selected():
delete_portrait_item(%PortraitTree.get_selected())
get_viewport().set_input_as_handled()
func _on_portrait_right_click_menu_index_pressed(id: int) -> void:
# RENAME BUTTON
if id == 0:
_on_item_activated()
# DELETE BUTTON
if id == 2:
delete_portrait_item(%PortraitTree.get_selected())
# DUPLICATE ITEM
elif id == 1:
duplicate_item(%PortraitTree.get_selected())
elif id == 4:
get_settings_section_by_name("Portraits").set_default_portrait(%PortraitTree.get_full_item_name(%PortraitTree.get_selected()))
## This removes/and adds the DEFAULT star on the portrait list
func update_default_portrait_star(default_portrait_name: String) -> void:
var item_list: Array = %PortraitTree.get_root().get_children()
if item_list.is_empty() == false:
while true:
var item: TreeItem = item_list.pop_back()
if item.get_button_by_id(0, 2) != -1:
item.erase_button(0, item.get_button_by_id(0, 2))
if %PortraitTree.get_full_item_name(item) == default_portrait_name:
item.add_button(0, get_theme_icon("Favorites", "EditorIcons"), 2, true, "Default")
item_list.append_array(item.get_children())
if item_list.is_empty():
break
func _on_item_edited() -> void:
selected_item = %PortraitTree.get_selected()
something_changed()
if selected_item:
if %PreviewLabel.text.trim_prefix('Preview of "').trim_suffix('"') == current_resource.default_portrait:
current_resource.default_portrait = %PortraitTree.get_full_item_name(selected_item)
selected_item.set_editable(0, false)
if !selected_item.has_meta('new') and %PortraitTree.get_full_item_name(selected_item) != selected_item.get_meta('previous_name'):
report_name_change(selected_item)
%PortraitChangeInfo.show()
update_preview()
func _on_item_activated() -> void:
if %PortraitTree.get_selected() == null:
return
%PortraitTree.get_selected().set_editable(0, true)
%PortraitTree.edit_selected()
func report_name_change(item: TreeItem) -> void:
if item.get_metadata(0).has('group'):
for s_item in item.get_children():
if s_item.get_metadata(0).has('group') or !s_item.has_meta('new'):
report_name_change(s_item)
else:
if item.get_meta('previous_name') == %PortraitTree.get_full_item_name(item):
return
editors_manager.reference_manager.add_portrait_ref_change(
item.get_meta('previous_name'),
%PortraitTree.get_full_item_name(item),
[DialogicResourceUtil.get_unique_identifier(current_resource.resource_path)])
item.set_meta('previous_name', %PortraitTree.get_full_item_name(item))
%PortraitChangeInfo.show()
#endregion
########### PREVIEW ############################################################
#region Preview
func update_preview(force := false, ignore_settings_reload := false) -> void:
%ScenePreviewWarning.hide()
if selected_item and is_instance_valid(selected_item) and selected_item.get_metadata(0) != null and !selected_item.get_metadata(0).has('group'):
%PreviewLabel.text = 'Preview of "'+%PortraitTree.get_full_item_name(selected_item)+'"'
var current_portrait_data: Dictionary = selected_item.get_metadata(0)
if not force and current_previewed_scene != null \
and scene_file_path == current_portrait_data.get('scene') \
and current_previewed_scene.has_method('_should_do_portrait_update') \
and is_instance_valid(current_previewed_scene.get_script()) \
and current_previewed_scene._should_do_portrait_update(current_resource, selected_item.get_text(0)):
# We keep the same scene.
pass
else:
for node in %RealPreviewPivot.get_children():
node.queue_free()
current_previewed_scene = null
current_scene_path = ""
var scene_path := def_portrait_path
if not current_portrait_data.get('scene', '').is_empty():
scene_path = current_portrait_data.get('scene')
if ResourceLoader.exists(scene_path):
current_previewed_scene = load(scene_path).instantiate()
current_scene_path = scene_path
if not current_previewed_scene == null:
%RealPreviewPivot.add_child(current_previewed_scene)
if not current_previewed_scene == null:
var scene: Node = current_previewed_scene
scene.show_behind_parent = true
DialogicUtil.apply_scene_export_overrides(scene, current_portrait_data.get('export_overrides', {}))
var mirror: bool = current_portrait_data.get('mirror', false) != current_resource.mirror
var scale: float = current_portrait_data.get('scale', 1) * current_resource.scale
if current_portrait_data.get('ignore_char_scale', false):
scale = current_portrait_data.get('scale', 1)
var offset: Vector2 = current_portrait_data.get('offset', Vector2()) + current_resource.offset
if is_instance_valid(scene.get_script()) and scene.script.is_tool():
if scene.has_method('_update_portrait'):
## Create a fake duplicate resource that has all the portrait changes applied already
var preview_character := current_resource.duplicate()
preview_character.portraits = get_updated_portrait_dict()
scene._update_portrait(preview_character, %PortraitTree.get_full_item_name(selected_item))
if scene.has_method('_set_mirror'):
scene._set_mirror(mirror)
if !%FitPreview_Toggle.button_pressed:
scene.position = Vector2() + offset
scene.scale = Vector2(1,1)*scale
else:
if not scene.get_script() == null and scene.script.is_tool() and scene.has_method('_get_covered_rect'):
var rect: Rect2 = scene._get_covered_rect()
var available_rect: Rect2 = %FullPreviewAvailableRect.get_rect()
scene.scale = Vector2(1,1) * min(available_rect.size.x/rect.size.x, available_rect.size.y/rect.size.y)
%RealPreviewPivot.position = (rect.position)*-1*scene.scale
%RealPreviewPivot.position.x = %FullPreviewAvailableRect.size.x/2
scene.position = Vector2()
else:
%ScenePreviewWarning.show()
else:
%PreviewLabel.text = 'Nothing to preview'
if not ignore_settings_reload:
for child in %PortraitSettingsSection.get_children():
if child is DialogicCharacterEditorPortraitSection:
child._recheck(current_portrait_data)
else:
%PreviewLabel.text = 'No portrait to preview.'
for node in %RealPreviewPivot.get_children():
node.queue_free()
current_previewed_scene = null
current_scene_path = ""
func _on_some_resource_saved(file:Variant) -> void:
if current_previewed_scene == null:
return
if file is Resource and file == current_previewed_scene.script:
update_preview(true)
if typeof(file) == TYPE_STRING and file == current_previewed_scene.get_meta("path", ""):
update_preview(true)
func _on_full_preview_available_rect_resized() -> void:
if %FitPreview_Toggle.button_pressed:
update_preview(false, true)
func _on_create_character_button_pressed() -> void:
editors_manager.show_add_resource_dialog(
new_character,
'*.dch; DialogicCharacter',
'Create new character',
'character',
)
func _on_fit_preview_toggle_toggled(button_pressed):
%FitPreview_Toggle.set_pressed_no_signal(button_pressed)
if button_pressed:
%FitPreview_Toggle.icon = get_theme_icon("ScrollContainer", "EditorIcons")
%FitPreview_Toggle.tooltip_text = "Real scale"
else:
%FitPreview_Toggle.tooltip_text = "Fit into preview"
%FitPreview_Toggle.icon = get_theme_icon("CenterContainer", "EditorIcons")
DialogicUtil.set_editor_setting('character_preview_fit', button_pressed)
update_preview(false, true)
#endregion
## Open the reference manager
func _on_reference_manger_button_pressed() -> void:
editors_manager.reference_manager.open()
%PortraitChangeInfo.hide()

View File

@@ -0,0 +1 @@
uid://dgy7q0odhk3ow

View File

@@ -0,0 +1,456 @@
[gd_scene load_steps=11 format=3 uid="uid://dlskc36c5hrwv"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"]
[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_uhhqs"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd" id="2_vad0i"]
[ext_resource type="Texture2D" uid="uid://babwe22dqjta" path="res://addons/dialogic/Editor/Images/Pieces/add-folder.svg" id="3_v1qnr"]
[sub_resource type="Image" id="Image_s4mcg"]
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_oab13"]
image = SubResource("Image_s4mcg")
[sub_resource type="Image" id="Image_fnxud"]
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_u1a6g"]
image = SubResource("Image_fnxud")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_es2rd"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4xgdx"]
[node name="CharacterEditor" type="Control"]
self_modulate = Color(0, 0, 0, 1)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2")
[node name="Scroll" type="ScrollContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBox" type="VBoxContainer" parent="Scroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.3
theme_override_constants/separation = 0
[node name="TopSection" type="HBoxContainer" parent="Scroll/VBox"]
layout_mode = 2
[node name="NameContainer" type="HBoxContainer" parent="Scroll/VBox/TopSection"]
layout_mode = 2
[node name="CharacterName" type="Label" parent="Scroll/VBox/TopSection/NameContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicTitle"
text = "My Character"
[node name="NameTooltip" parent="Scroll/VBox/TopSection/NameContainer" instance=ExtResource("2_uhhqs")]
layout_mode = 2
tooltip_text = "This unique identifier is based on the file name. You can change it in the Reference Manager.
Use this name in timelines to reference this character."
texture = SubResource("ImageTexture_oab13")
hint_text = "This unique identifier is based on the file name. You can change it in the Reference Manager.
Use this name in timelines to reference this character."
[node name="MainSettingsCollapse" type="Button" parent="Scroll/VBox/TopSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
toggle_mode = true
text = "Main Settings"
icon = SubResource("ImageTexture_u1a6g")
[node name="MainHSplit" type="HSplitContainer" parent="Scroll/VBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="MainSettings" type="VBoxContainer" parent="Scroll/VBox/MainHSplit"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.2
[node name="MainSettingsTitle" type="Label" parent="Scroll/VBox/MainHSplit/MainSettings"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_type_variation = &"DialogicSubTitle"
text = "Main Settings"
[node name="MainSettingsScroll" type="ScrollContainer" parent="Scroll/VBox/MainHSplit/MainSettings"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_es2rd")
horizontal_scroll_mode = 0
[node name="MainSettingsSections" type="VBoxContainer" parent="Scroll/VBox/MainHSplit/MainSettings/MainSettingsScroll"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Split" type="HSplitContainer" parent="Scroll/VBox/MainHSplit"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="HBoxContainer" type="HBoxContainer" parent="Scroll/VBox/MainHSplit/Split"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.2
theme_override_constants/separation = 0
[node name="MarginContainer" type="MarginContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.2
theme_override_constants/margin_bottom = 10
[node name="PortraitListSection" type="PanelContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_type_variation = &"DialogicPanelA"
[node name="Portraits" type="VBoxContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection"]
layout_mode = 2
[node name="PortraitsTitle" type="Label" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
layout_mode = 2
theme_type_variation = &"DialogicSubTitle"
text = "Portraits"
[node name="PortraitListTools" type="HBoxContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
layout_mode = 2
[node name="AddPortraitButton" type="Button" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitListTools"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Add portrait"
icon = SubResource("ImageTexture_u1a6g")
[node name="AddPortraitGroupButton" type="Button" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitListTools"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Add Group"
icon = ExtResource("3_v1qnr")
[node name="ImportPortraitsButton" type="Button" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitListTools"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Import images from folder"
icon = SubResource("ImageTexture_u1a6g")
[node name="PortraitSearch" type="LineEdit" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitListTools"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 4
placeholder_text = "Search"
expand_to_text_length = true
clear_button_enabled = true
right_icon = SubResource("ImageTexture_u1a6g")
caret_blink = true
caret_blink_interval = 0.5
[node name="PortraitTreePanel" type="PanelContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_4xgdx")
[node name="PortraitTree" type="Tree" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel"]
unique_name_in_owner = true
layout_mode = 2
allow_rmb_select = true
hide_root = true
drop_mode_flags = 3
script = ExtResource("2_vad0i")
[node name="PortraitRightClickMenu" type="PopupMenu" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree"]
size = Vector2i(118, 100)
item_count = 5
item_0/text = "Rename"
item_0/icon = SubResource("ImageTexture_oab13")
item_0/id = 2
item_1/text = "Duplicate"
item_1/icon = SubResource("ImageTexture_oab13")
item_1/id = 0
item_2/text = "Delete"
item_2/icon = SubResource("ImageTexture_oab13")
item_2/id = 1
item_3/text = ""
item_3/id = 3
item_3/separator = true
item_4/text = "Make Default"
item_4/icon = SubResource("ImageTexture_oab13")
item_4/id = 4
[node name="PortraitChangeInfo" type="HBoxContainer" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
unique_name_in_owner = true
layout_mode = 2
[node name="PortraitChangeWarning" type="Label" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitChangeInfo"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "Some portraits were renamed. Make sure no references broke!"
autowrap_mode = 3
[node name="ReferenceMangerButton" type="Button" parent="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitChangeInfo"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 4
text = "Reference
Manager"
[node name="RightSection2" type="VBoxContainer" parent="Scroll/VBox/MainHSplit/Split"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.5
[node name="Spacer" type="Control" parent="Scroll/VBox/MainHSplit/Split/RightSection2"]
custom_minimum_size = Vector2(0, 10)
layout_mode = 2
[node name="RightSection" type="SplitContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.5
vertical = true
[node name="PortraitPreviewSection" type="Panel" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection"]
unique_name_in_owner = true
show_behind_parent = true
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_type_variation = &"DialogicPanelB"
[node name="ClipRect" type="Control" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection"]
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Node2D" type="Node2D" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/ClipRect"]
position = Vector2(13, 17)
[node name="RealPreviewPivot" type="Sprite2D" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/ClipRect/Node2D"]
unique_name_in_owner = true
position = Vector2(326.5, 267)
texture = SubResource("ImageTexture_u1a6g")
[node name="ScenePreviewWarning" type="Label" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection"]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -143.0
offset_top = -44.5
offset_right = 143.0
offset_bottom = 85.5
grow_horizontal = 2
grow_vertical = 2
text = "Custom scenes can only be viewed in \"Full mode\" if they are in @tool mode and override _get_covered_rect"
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 3
metadata/_edit_layout_mode = 1
[node name="PreviewReal" type="CenterContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -302.0
offset_top = -80.0
offset_right = 302.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 2
metadata/_edit_layout_mode = 1
[node name="Control" type="Control" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/PreviewReal"]
layout_mode = 2
[node name="RealSizeRemotePivotTransform" type="RemoteTransform2D" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/PreviewReal/Control"]
unique_name_in_owner = true
remote_path = NodePath("../../../ClipRect/Node2D/RealPreviewPivot")
update_rotation = false
update_scale = false
[node name="FullPreviewAvailableRect" type="Control" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = 28.0
offset_right = -10.0
offset_bottom = -16.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
metadata/_edit_layout_mode = 1
[node name="HBoxContainer" type="HBoxContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection"]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_left = 6.0
offset_top = 7.0
offset_right = -6.0
offset_bottom = 43.0
grow_horizontal = 2
mouse_filter = 2
[node name="PreviewLabel" type="Label" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/HBoxContainer"]
unique_name_in_owner = true
show_behind_parent = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "No portrait to preview."
text_overrun_behavior = 1
[node name="FitPreview_Toggle" type="Button" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
tooltip_text = "Real scale"
focus_mode = 0
toggle_mode = true
button_pressed = true
icon = SubResource("ImageTexture_u1a6g")
flat = true
metadata/_edit_layout_mode = 1
[node name="VBox" type="VBoxContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.75
[node name="Hbox" type="HBoxContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox"]
layout_mode = 2
[node name="PortraitSettingsTitle" type="Label" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox/Hbox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicSubTitle"
text = "Portrait Settings"
[node name="SwitchPortraitSettingsPosition" type="Button" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox/Hbox"]
unique_name_in_owner = true
modulate = Color(1, 1, 1, 0.647059)
layout_mode = 2
tooltip_text = "Switch position"
focus_mode = 0
icon = SubResource("ImageTexture_u1a6g")
flat = true
[node name="Scroll" type="ScrollContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox"]
layout_mode = 2
size_flags_vertical = 3
size_flags_stretch_ratio = 0.4
[node name="PortraitSettingsSection" type="VBoxContainer" parent="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox/Scroll"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.3
[node name="Spacer2" type="Control" parent="Scroll/VBox/MainHSplit/Split/RightSection2"]
custom_minimum_size = Vector2(0, 20)
layout_mode = 2
[node name="NoCharacterScreen" type="ColorRect" parent="."]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
color = Color(0, 0, 0, 1)
[node name="CenterContainer" type="CenterContainer" parent="NoCharacterScreen"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="NoCharacterScreen/CenterContainer"]
custom_minimum_size = Vector2(250, 0)
layout_mode = 2
[node name="Label" type="Label" parent="NoCharacterScreen/CenterContainer/VBoxContainer"]
layout_mode = 2
text = "No character opened.
Create a character or double-click one in the file system dock."
horizontal_alignment = 1
autowrap_mode = 3
[node name="CreateCharacterButton" type="Button" parent="NoCharacterScreen/CenterContainer/VBoxContainer"]
layout_mode = 2
text = "Create New Character"
[connection signal="toggled" from="Scroll/VBox/TopSection/MainSettingsCollapse" to="." method="_on_main_settings_collapse_toggled"]
[connection signal="item_mouse_selected" from="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree" to="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree" method="_on_item_mouse_selected"]
[connection signal="index_pressed" from="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree/PortraitRightClickMenu" to="." method="_on_portrait_right_click_menu_index_pressed"]
[connection signal="pressed" from="Scroll/VBox/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitChangeInfo/ReferenceMangerButton" to="." method="_on_reference_manger_button_pressed"]
[connection signal="resized" from="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/FullPreviewAvailableRect" to="." method="_on_full_preview_available_rect_resized"]
[connection signal="toggled" from="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/HBoxContainer/FitPreview_Toggle" to="." method="_on_fit_preview_toggle_toggled"]
[connection signal="pressed" from="Scroll/VBox/MainHSplit/Split/RightSection2/RightSection/VBox/Hbox/SwitchPortraitSettingsPosition" to="." method="_on_switch_portrait_settings_position_pressed"]
[connection signal="pressed" from="NoCharacterScreen/CenterContainer/VBoxContainer/CreateCharacterButton" to="." method="_on_create_character_button_pressed"]

View File

@@ -0,0 +1,41 @@
@tool
class_name DialogicCharacterEditorMainSection
extends Control
## Base class for all character editor main sections. Methods should be overriden.
## Emit this, if something changed
signal changed
## Reference to the character editor, set when instantiated
var character_editor: Control
## If not empty, a hint icon is added to the section title.
var hint_text := ""
## Overwrite to set the title of this section
func _get_title() -> String:
return "MainSection"
## Overwrite to set the visibility of the section title
func _show_title() -> bool:
return true
## Overwrite to set whether this should initially be opened.
func _start_opened() -> bool:
return false
## Overwrite to load all the information from the character into this section.
func _load_character(resource:DialogicCharacter) -> void:
pass
## Overwrite to save all changes made in this section to the resource.
## In custom sections you will mostly likely save to the [resource.custom_info]
## dictionary.
func _save_changes(resource:DialogicCharacter) -> DialogicCharacter:
return resource

View File

@@ -0,0 +1 @@
uid://bffbbrvyqx8wi

View File

@@ -0,0 +1,48 @@
@tool
class_name DialogicCharacterEditorPortraitSection
extends Control
## Base class for all portrait settings sections. Methods should be overriden.
## Changes made through fields in such a section should instantly be "saved"
## to the portrait_items metadata from where they will be saved to the resource.
## Emit this, if something changed
signal changed
## Emit this if the preview should reload
signal update_preview
## Reference to the character editor, set when instantiated
var character_editor: Control
## Reference to the selected portrait item.
## `selected_item.get_metadata(0)` can access the portraits data
var selected_item: TreeItem = null
## If not empty a hint icon is added to the section title
var hint_text := ""
## Overwrite to set the title of this section
func _get_title() -> String:
return "CustomSection"
## Overwrite to set the visibility of the section title
func _show_title() -> bool:
return true
## Overwrite to set whether this should initially be opened.
func _start_opened() -> bool:
return false
## Overwrite to load all the information from the character into this section.
func _load_portrait_data(data:Dictionary) -> void:
pass
## Overwrite to recheck visibility of your section and the content of your fields.
## This is called whenever the preview is updated so it allows reacting to major
## changes in other portrait sections.
func _recheck(data:Dictionary) -> void:
pass

View File

@@ -0,0 +1 @@
uid://bn545tqj6cx3y

View File

@@ -0,0 +1,142 @@
@tool
extends Tree
## Tree that displays the portrait list as a hirarchy
var editor := find_parent('Character Editor')
var current_group_nodes := {}
func _ready() -> void:
$PortraitRightClickMenu.set_item_icon(0, get_theme_icon('Rename', 'EditorIcons'))
$PortraitRightClickMenu.set_item_icon(1, get_theme_icon('Duplicate', 'EditorIcons'))
$PortraitRightClickMenu.set_item_icon(2, get_theme_icon('Remove', 'EditorIcons'))
$PortraitRightClickMenu.set_item_icon(4, get_theme_icon("Favorites", "EditorIcons"))
func clear_tree() -> void:
clear()
current_group_nodes = {}
func add_portrait_item(portrait_name: String, portrait_data: Dictionary, parent_item: TreeItem, previous_name := "") -> TreeItem:
var item: TreeItem = %PortraitTree.create_item(parent_item)
item.set_text(0, portrait_name)
item.set_metadata(0, portrait_data)
if previous_name.is_empty():
item.set_meta('previous_name', get_full_item_name(item))
else:
item.set_meta('previous_name', previous_name)
if portrait_name == editor.current_resource.default_portrait:
item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default')
return item
func add_portrait_group(goup_name := "Group", parent_item: TreeItem = get_root(), previous_name := "") -> TreeItem:
var item: TreeItem = %PortraitTree.create_item(parent_item)
item.set_icon(0, get_theme_icon("Folder", "EditorIcons"))
item.set_text(0, goup_name)
item.set_metadata(0, {'group':true})
if previous_name.is_empty():
item.set_meta('previous_name', get_full_item_name(item))
else:
item.set_meta('previous_name', previous_name)
return item
func get_full_item_name(item: TreeItem) -> String:
var item_name := item.get_text(0)
while item.get_parent() != get_root() and item != get_root():
item_name = item.get_parent().get_text(0)+"/"+item_name
item = item.get_parent()
return item_name
## Will create all not yet existing folders in the given path.
## Returns the last folder (the parent of the portrait item of this path).
func create_necessary_group_items(path: String) -> TreeItem:
var last_item := get_root()
var item_path := ""
for i in Array(path.split('/')).slice(0, -1):
item_path += "/"+i
item_path = item_path.trim_prefix('/')
if current_group_nodes.has(item_path+"/"+i):
last_item = current_group_nodes[item_path+"/"+i]
else:
var new_item: TreeItem = add_portrait_group(i, last_item)
current_group_nodes[item_path+"/"+i] = new_item
last_item = new_item
return last_item
func _on_item_mouse_selected(pos: Vector2, mouse_button_index: int) -> void:
if mouse_button_index == MOUSE_BUTTON_RIGHT:
$PortraitRightClickMenu.set_item_disabled(1, get_selected().get_metadata(0).has('group'))
$PortraitRightClickMenu.popup_on_parent(Rect2(get_global_mouse_position(),Vector2()))
################################################################################
## DRAG AND DROP
################################################################################
func _get_drag_data(at_position: Vector2) -> Variant:
var drag_item := get_item_at_position(at_position)
if not drag_item:
return null
drop_mode_flags = DROP_MODE_INBETWEEN
var preview := Label.new()
preview.text = " "+drag_item.get_text(0)
preview.add_theme_stylebox_override('normal', get_theme_stylebox("Background", "EditorStyles"))
set_drag_preview(preview)
return drag_item
func _can_drop_data(_at_position: Vector2, data: Variant) -> bool:
return data is TreeItem
func _drop_data(at_position: Vector2, item: Variant) -> void:
var to_item := get_item_at_position(at_position)
if to_item:
var test_item := to_item
while true:
if test_item == item:
return
test_item = test_item.get_parent()
if test_item == get_root():
break
var drop_section := get_drop_section_at_position(at_position)
var parent := get_root()
if to_item:
parent = to_item.get_parent()
if to_item and to_item.get_metadata(0).has('group') and drop_section == 1:
parent = to_item
var new_item := copy_branch_or_item(item, parent)
if to_item and !to_item.get_metadata(0).has('group') and drop_section == 1:
new_item.move_after(to_item)
if drop_section == -1:
new_item.move_before(to_item)
editor.report_name_change(new_item)
item.free()
func copy_branch_or_item(item: TreeItem, new_parent: TreeItem) -> TreeItem:
var new_item: TreeItem = null
if item.get_metadata(0).has('group'):
new_item = add_portrait_group(item.get_text(0), new_parent, item.get_meta('previous_name'))
else:
new_item = add_portrait_item(item.get_text(0), item.get_metadata(0), new_parent, item.get_meta('previous_name'))
for child in item.get_children():
copy_branch_or_item(child, new_item)
return new_item

View File

@@ -0,0 +1 @@
uid://drmovq04bj584

View File

@@ -0,0 +1,126 @@
@tool
extends Control
var ListItem := load("res://addons/dialogic/Editor/Common/BrowserItem.tscn")
enum Types {ALL, GENERAL, PRESET}
var current_type := Types.ALL
var current_info := {}
var portrait_scenes_info := {}
signal activate_part(part_info:Dictionary)
func _ready() -> void:
collect_portrait_scenes()
%Search.right_icon = get_theme_icon("Search", "EditorIcons")
%CloseButton.icon = get_theme_icon("Close", "EditorIcons")
get_parent().close_requested.connect(_on_close_button_pressed)
get_parent().visibility_changed.connect(func():if get_parent().visible: open())
func collect_portrait_scenes() -> void:
for indexer in DialogicUtil.get_indexers():
for element in indexer._get_portrait_scene_presets():
portrait_scenes_info[element.get('path', '')] = element
func open() -> void:
collect_portrait_scenes()
load_parts()
func is_premade_portrait_scene(scene_path:String) -> bool:
return scene_path in portrait_scenes_info
func load_parts() -> void:
for i in %PartGrid.get_children():
i.queue_free()
%Search.placeholder_text = "Search for "
%Search.text = ""
match current_type:
Types.GENERAL: %Search.placeholder_text += "general portrait scenes"
Types.PRESET: %Search.placeholder_text += "portrait scene presets"
Types.ALL: %Search.placeholder_text += "general portrait scenes and presets"
for info in portrait_scenes_info.values():
var type: String = info.get('type', '_')
if (current_type == Types.GENERAL and type != "General") or (current_type == Types.PRESET and type != "Preset"):
continue
var item: Node = ListItem.instantiate()
item.load_info(info)
%PartGrid.add_child(item)
item.set_meta('info', info)
item.clicked.connect(_on_item_clicked.bind(item, info))
item.focused.connect(_on_item_clicked.bind(item, info))
item.double_clicked.connect(emit_signal.bind('activate_part', info))
await get_tree().process_frame
if %PartGrid.get_child_count() > 0:
%PartGrid.get_child(0).clicked.emit()
%PartGrid.get_child(0).grab_focus()
func _on_item_clicked(item: Node, info:Dictionary) -> void:
load_part_info(info)
func load_part_info(info:Dictionary) -> void:
current_info = info
%PartTitle.text = info.get('name', 'Unknown Part')
%PartAuthor.text = "by "+info.get('author', 'Anonymus')
%PartDescription.text = info.get('description', '')
if info.get('preview_image', null) and ResourceLoader.exists(info.preview_image[0]):
%PreviewImage.texture = load(info.preview_image[0])
%PreviewImage.show()
else:
%PreviewImage.hide()
match info.type:
"General":
%ActivateButton.text = "Use this scene"
%TypeDescription.text = "This is a general use scene, it can be used directly."
"Preset":
%ActivateButton.text = "Customize this scene"
%TypeDescription.text = "This is a preset you can use for a custom portrait scene. Dialogic will promt you to save a copy of this scene that you can then use and customize."
"Default":
%ActivateButton.text = "Use default scene"
%TypeDescription.text = ""
"Custom":
%ActivateButton.text = "Select a custom scene"
%TypeDescription.text = ""
if info.get("documentation", ""):
%DocumentationButton.show()
%DocumentationButton.uri = info.documentation
else:
%DocumentationButton.hide()
func _on_activate_button_pressed() -> void:
activate_part.emit(current_info)
func _on_close_button_pressed() -> void:
get_parent().hide()
func _on_search_text_changed(new_text: String) -> void:
for item in %PartGrid.get_children():
if new_text.is_empty():
item.show()
continue
if new_text.to_lower() in item.get_meta('info').name.to_lower():
item.show()
continue
item.hide()

View File

@@ -0,0 +1 @@
uid://dce2b82qam7w1

View File

@@ -0,0 +1,260 @@
[gd_scene load_steps=11 format=3 uid="uid://b1wn8r84uh11b"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd" id="1_an6nc"]
[sub_resource type="Gradient" id="Gradient_0o1u0"]
colors = PackedColorArray(0.100572, 0.303996, 0.476999, 1, 0.296448, 0.231485, 0.52887, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_gxpvv"]
gradient = SubResource("Gradient_0o1u0")
fill = 2
fill_from = Vector2(0.478632, 1)
fill_to = Vector2(0, 0)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_we8bq"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(1, 1, 1, 0.615686)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3x0xw"]
content_margin_left = 6.0
content_margin_top = 3.0
content_margin_right = 6.0
content_margin_bottom = 3.0
draw_center = false
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color(1, 1, 1, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
expand_margin_left = 2.0
expand_margin_top = 2.0
expand_margin_right = 2.0
expand_margin_bottom = 2.0
[sub_resource type="Image" id="Image_lwe0k"]
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_d2gam"]
image = SubResource("Image_lwe0k")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lf1ht"]
bg_color = Color(0.0588235, 0.0313726, 0.0980392, 1)
border_width_left = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_a5iyu"]
bg_color = Color(1, 1, 1, 1)
draw_center = false
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
shadow_color = Color(0.992157, 0.992157, 0.992157, 0.101961)
shadow_size = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_htwsp"]
bg_color = Color(1, 1, 1, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[node name="PortraitSceneBrowser" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_an6nc")
[node name="BGColor" type="TextureRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture2D_gxpvv")
[node name="HSplitContainer" type="HSplitContainer" parent="."]
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 3
[node name="Margin" type="MarginContainer" parent="HSplitContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 1.5
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBox" type="VBoxContainer" parent="HSplitContainer/Margin"]
layout_mode = 2
size_flags_horizontal = 3
[node name="BrowserTitle" type="Label" parent="HSplitContainer/Margin/VBox"]
layout_mode = 2
theme_type_variation = &"DialogicSubTitle"
theme_override_font_sizes/font_size = 25
text = "Dialogic Portrait Scene Browser"
[node name="HBox" type="HBoxContainer" parent="HSplitContainer/Margin/VBox"]
layout_mode = 2
[node name="Search" type="LineEdit" parent="HSplitContainer/Margin/VBox/HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/normal = SubResource("StyleBoxFlat_we8bq")
theme_override_styles/focus = SubResource("StyleBoxFlat_3x0xw")
placeholder_text = "Search"
right_icon = SubResource("ImageTexture_d2gam")
[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer/Margin/VBox"]
layout_mode = 2
size_flags_vertical = 3
[node name="PartGrid" type="HFlowContainer" parent="HSplitContainer/Margin/VBox/ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Buttons" type="HBoxContainer" parent="HSplitContainer/Margin/VBox"]
layout_mode = 2
alignment = 1
[node name="CloseButton" type="Button" parent="HSplitContainer/Margin/VBox/Buttons"]
unique_name_in_owner = true
layout_mode = 2
text = "Close"
icon = SubResource("ImageTexture_d2gam")
[node name="PanelContainer" type="PanelContainer" parent="HSplitContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_lf1ht")
[node name="Control" type="Control" parent="HSplitContainer/PanelContainer"]
layout_mode = 2
[node name="Panel" type="Panel" parent="HSplitContainer/PanelContainer/Control"]
layout_mode = 1
anchors_preset = 9
anchor_bottom = 1.0
offset_left = -4.0
offset_right = 40.0
offset_bottom = 71.0
grow_vertical = 2
rotation = 0.0349066
theme_override_styles/panel = SubResource("StyleBoxFlat_lf1ht")
[node name="MarginContainer" type="MarginContainer" parent="HSplitContainer/PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBox" type="VBoxContainer" parent="HSplitContainer/PanelContainer/MarginContainer"]
layout_mode = 2
alignment = 1
[node name="Panel" type="PanelContainer" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_a5iyu")
[node name="Panel" type="PanelContainer" parent="HSplitContainer/PanelContainer/MarginContainer/VBox/Panel"]
clip_children = 1
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_htwsp")
[node name="PreviewImage" type="TextureRect" parent="HSplitContainer/PanelContainer/MarginContainer/VBox/Panel/Panel"]
unique_name_in_owner = true
layout_mode = 2
expand_mode = 5
stretch_mode = 6
[node name="HFlowContainer" type="HFlowContainer" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
layout_mode = 2
[node name="PartTitle" type="Label" parent="HSplitContainer/PanelContainer/MarginContainer/VBox/HFlowContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 8
theme_type_variation = &"DialogicTitle"
text = "Cool Style Part"
[node name="PartAuthor" type="Label" parent="HSplitContainer/PanelContainer/MarginContainer/VBox/HFlowContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 8
theme_type_variation = &"DialogicHintText"
text = "by Jowan"
[node name="PartType" type="Label" parent="HSplitContainer/PanelContainer/MarginContainer/VBox/HFlowContainer"]
visible = false
layout_mode = 2
size_flags_vertical = 8
theme_type_variation = &"DialogicHintText"
text = "a style"
[node name="PartDescription" type="Label" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicHintText2"
text = "A cool textbox layer"
autowrap_mode = 3
[node name="DocumentationButton" type="LinkButton" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Learn more"
[node name="HSeparator" type="HSeparator" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
layout_mode = 2
[node name="ActivateButton" type="Button" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Use"
[node name="TypeDescription" type="Label" parent="HSplitContainer/PanelContainer/MarginContainer/VBox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicHintText"
text = "A cool textbox layer"
autowrap_mode = 3
[connection signal="text_changed" from="HSplitContainer/Margin/VBox/HBox/Search" to="." method="_on_search_text_changed"]
[connection signal="pressed" from="HSplitContainer/Margin/VBox/Buttons/CloseButton" to="." method="_on_close_button_pressed"]
[connection signal="pressed" from="HSplitContainer/PanelContainer/MarginContainer/VBox/ActivateButton" to="." method="_on_activate_button_pressed"]

View File

@@ -0,0 +1,86 @@
@tool
extends Container
signal clicked
signal middle_clicked
signal double_clicked
signal focused
var base_size := 1
func _ready() -> void:
if get_parent() is SubViewport:
return
%Name.add_theme_font_override("font", get_theme_font("bold", "EditorFonts"))
custom_minimum_size = base_size * Vector2(200, 150) * DialogicUtil.get_editor_scale()
%CurrentIcon.texture = get_theme_icon("Favorites", "EditorIcons")
if %Image.texture == null:
%Image.texture = get_theme_icon("ImportFail", "EditorIcons")
%Image.stretch_mode = TextureRect.STRETCH_KEEP_CENTERED
func load_info(info:Dictionary) -> void:
%Name.text = info.name
if not info.has("preview_image"):
pass
elif info.preview_image[0] == 'custom':
await ready
%Image.texture = get_theme_icon("CreateNewSceneFrom", "EditorIcons")
%Image.stretch_mode = TextureRect.STRETCH_KEEP_CENTERED
%Panel.self_modulate = get_theme_color("property_color_z", "Editor")
elif info.preview_image[0].ends_with('scn'):
DialogicUtil.get_dialogic_plugin().get_editor_interface().get_resource_previewer().queue_resource_preview(info.preview_image[0], self, 'set_scene_preview', null)
elif ResourceLoader.exists(info.preview_image[0]):
%Image.texture = load(info.preview_image[0])
elif info.preview_image[0].is_valid_html_color():
%Image.texture = null
%Panel.self_modulate = Color(info.preview_image[0])
if ResourceLoader.exists(info.get('icon', '')):
%Icon.get_parent().show()
%Icon.texture = load(info.get('icon'))
else:
%Icon.get_parent().hide()
tooltip_text = info.description
func set_scene_preview(path:String, preview:Texture2D, thumbnail:Texture2D, userdata:Variant) -> void:
if preview:
%Image.texture = preview
else:
%Image.texture = get_theme_icon("PackedScene", "EditorIcons")
func set_current(current:bool):
%CurrentIcon.visible = current
func _on_mouse_entered() -> void:
%HoverBG.show()
func _on_mouse_exited() -> void:
%HoverBG.hide()
func _on_gui_input(event):
if event.is_action_pressed('ui_accept') or event.is_action_pressed("ui_select") or (
event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT):
clicked.emit()
if not event is InputEventMouseButton or event.double_click:
double_clicked.emit()
elif event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_MIDDLE:
middle_clicked.emit()
func _on_focus_entered() -> void:
$FocusFG.show()
focused.emit()
func _on_focus_exited() -> void:
$FocusFG.hide()

View File

@@ -0,0 +1 @@
uid://cxfu3mv2lrriv

View File

@@ -0,0 +1,154 @@
[gd_scene load_steps=6 format=3 uid="uid://ddlxjde1cx035"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/BrowserItem.gd" id="1_s3kf0"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pfw08"]
bg_color = Color(1, 1, 1, 0.32549)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
expand_margin_left = 4.0
expand_margin_top = 4.0
expand_margin_right = 4.0
expand_margin_bottom = 4.0
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ab24c"]
bg_color = Color(1, 1, 1, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qnehp"]
bg_color = Color(0, 0, 0, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
shadow_color = Color(0.847059, 0.847059, 0.847059, 0.384314)
shadow_size = 5
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nxx8t"]
bg_color = Color(0.435294, 0.435294, 0.435294, 0.211765)
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
expand_margin_left = 4.0
expand_margin_top = 4.0
expand_margin_right = 4.0
expand_margin_bottom = 4.0
[node name="BrowserItem" type="MarginContainer"]
custom_minimum_size = Vector2(200, 150)
offset_left = 1.0
offset_top = 1.0
offset_right = 128.0
offset_bottom = 102.0
size_flags_horizontal = 0
focus_mode = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
script = ExtResource("1_s3kf0")
[node name="HoverBG" type="Panel" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_pfw08")
[node name="VBox" type="VBoxContainer" parent="."]
layout_mode = 2
mouse_filter = 2
theme_override_constants/separation = 0
alignment = 1
[node name="Panel" type="PanelContainer" parent="VBox"]
unique_name_in_owner = true
self_modulate = Color(0.0705882, 0.0705882, 0.0705882, 1)
clip_children = 2
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ab24c")
[node name="Image" type="TextureRect" parent="VBox/Panel"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
expand_mode = 1
stretch_mode = 6
[node name="CurrentIcon" type="TextureRect" parent="VBox/Panel/Image"]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -22.0
offset_top = 5.0
offset_right = -6.0
offset_bottom = 21.0
grow_horizontal = 0
tooltip_text = "Currently in use"
stretch_mode = 2
[node name="Panel" type="Panel" parent="VBox/Panel/Image"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -37.0
offset_top = -36.0
offset_right = -7.0
offset_bottom = -6.0
grow_horizontal = 0
grow_vertical = 0
theme_override_styles/panel = SubResource("StyleBoxFlat_qnehp")
[node name="Icon" type="TextureRect" parent="VBox/Panel/Image/Panel"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 4.0
offset_top = 4.0
offset_right = -4.0
offset_bottom = -4.0
grow_horizontal = 2
grow_vertical = 2
expand_mode = 1
stretch_mode = 5
[node name="Name" type="Label" parent="VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Dialogic Theme"
horizontal_alignment = 1
[node name="FocusFG" type="Panel" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_nxx8t")
[connection signal="focus_entered" from="." to="." method="_on_focus_entered"]
[connection signal="focus_exited" from="." to="." method="_on_focus_exited"]
[connection signal="gui_input" from="." to="." method="_on_gui_input"]
[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"]
[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"]

View File

@@ -0,0 +1,47 @@
@tool
class_name DCSS
static func inline(style: Dictionary) -> StyleBoxFlat:
var scale: float = DialogicUtil.get_editor_scale()
var s := StyleBoxFlat.new()
for property in style.keys():
match property:
'border-left':
s.set('border_width_left', style[property] * scale)
'border-radius':
var radius: float = style[property] * scale
s.set('corner_radius_top_left', radius)
s.set('corner_radius_top_right', radius)
s.set('corner_radius_bottom_left', radius)
s.set('corner_radius_bottom_right', radius)
'background':
if typeof(style[property]) == TYPE_STRING and style[property] == "none":
s.set('draw_center', false)
else:
s.set('bg_color', style[property])
'border':
var width: float = style[property] * scale
s.set('border_width_left', width)
s.set('border_width_right', width)
s.set('border_width_top', width)
s.set('border_width_bottom', width)
'border-color':
s.set('border_color', style[property])
'padding':
var value_v: float = 0.0
var value_h: float = 0.0
if style[property] is int:
value_v = style[property] * scale
value_h = value_v
else:
value_v = style[property][0] * scale
value_h = style[property][1] * scale
s.set('content_margin_top', value_v)
s.set('content_margin_bottom', value_v)
s.set('content_margin_left', value_h)
s.set('content_margin_right', value_h)
'padding-right':
s.set('content_margin_right', style[property] * scale)
'padding-left':
s.set('content_margin_left', style[property] * scale)
return s

View File

@@ -0,0 +1 @@
uid://b5ngxiswvr5pm

View File

@@ -0,0 +1,119 @@
@tool
extends PanelContainer
enum Modes {EDIT, ADD}
var mode := Modes.EDIT
var item: TreeItem = null
func _ready() -> void:
hide()
%Character.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/character.svg")
%Character.get_suggestions_func = get_character_suggestions
%WholeWords.icon = get_theme_icon("FontItem", "EditorIcons")
%MatchCase.icon = get_theme_icon("MatchCase", "EditorIcons")
func _on_add_pressed() -> void:
if visible:
if mode == Modes.ADD:
hide()
return
elif mode == Modes.EDIT:
save()
%AddButton.text = "Add"
mode = Modes.ADD
show()
%Type.selected = 0
_on_type_item_selected(0)
%Where.selected = 2
_on_where_item_selected(2)
%Old.text = ""
%New.text = ""
func open_existing(_item:TreeItem, info:Dictionary):
mode = Modes.EDIT
item = _item
show()
%AddButton.text = "Update"
%Type.selected = info.type
_on_type_item_selected(info.type)
if !info.character_names.is_empty():
%Where.selected = 1
%Character.set_value(info.character_names[0])
else:
%Where.selected = 0
_on_where_item_selected(%Where.selected)
%Old.text = info.what
%New.text = info.forwhat
func _on_type_item_selected(index:int) -> void:
match index:
0:
%Where.select(0)
%Where.set_item_disabled(0, false)
%Where.set_item_disabled(1, false)
%Where.set_item_disabled(2, true)
1:
%Where.select(0)
%Where.set_item_disabled(0, false)
%Where.set_item_disabled(1, false)
%Where.set_item_disabled(2, true)
2:
%Where.select(1)
%Where.set_item_disabled(0, true)
%Where.set_item_disabled(1, false)
%Where.set_item_disabled(2, true)
3,4:
%Where.select(0)
%Where.set_item_disabled(0, false)
%Where.set_item_disabled(1, true)
%Where.set_item_disabled(2, true)
%PureTextFlags.visible = index == 0
_on_where_item_selected(%Where.selected)
func _on_where_item_selected(index:int) -> void:
%Character.visible = index == 1
func get_character_suggestions(search_text:String) -> Dictionary:
var suggestions := {}
#override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work
var _character_directory := DialogicResourceUtil.get_character_directory()
var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg")
suggestions['(No one)'] = {'value':null, 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]}
for resource in _character_directory.keys():
suggestions[resource] = {
'value' : resource,
'tooltip' : _character_directory[resource],
'icon' : icon.duplicate()}
return suggestions
func save() -> void:
if %Old.text.is_empty() or %New.text.is_empty():
return
if %Where.selected == 1 and %Character.current_value == null:
return
var previous := {}
if mode == Modes.EDIT:
previous = item.get_metadata(0)
item.get_parent()
item.free()
var ref_manager := find_parent('ReferenceManager')
var character_names := []
if %Character.current_value != null:
character_names = [%Character.current_value]
ref_manager.add_ref_change(%Old.text, %New.text, %Type.selected, %Where.selected, character_names, %WholeWords.button_pressed, %MatchCase.button_pressed, previous)
hide()

View File

@@ -0,0 +1 @@
uid://yv2r6lvx1ccn

View File

@@ -0,0 +1,8 @@
[gd_resource type="StyleBoxFlat" format=3 uid="uid://dmsjhgv22dns8"]
[resource]
content_margin_left = 5.0
content_margin_top = 5.0
content_margin_right = 5.0
content_margin_bottom = 5.0
bg_color = Color(0.545098, 0.545098, 0.545098, 0.211765)

View File

@@ -0,0 +1,363 @@
@tool
extends VSplitContainer
## This manager shows a list of changed references and allows searching for them and replacing them.
var reference_changes: Array[Dictionary] = []:
set(changes):
reference_changes = changes
update_indicator()
var search_regexes: Array[Array]
var finder_thread: Thread
var progress_mutex: Mutex
var progress_percent: float = 0.0
var progress_message: String = ""
func _ready() -> void:
if owner.get_parent() is SubViewport:
return
%TabA.text = "Broken References"
%TabA.icon = get_theme_icon("Unlinked", "EditorIcons")
owner.get_parent().visibility_changed.connect(func(): if is_visible_in_tree(): open())
%ReplacementSection.hide()
%CheckButton.icon = get_theme_icon("Search", "EditorIcons")
%Replace.icon = get_theme_icon("ArrowRight", "EditorIcons")
%State.add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"))
visibility_changed.connect(func(): if !visible: close())
await get_parent().ready
var tab_button: Control = %TabA
var dot := Sprite2D.new()
dot.texture = get_theme_icon("GuiGraphNodePort", "EditorIcons")
dot.scale = Vector2(0.8, 0.8)
dot.z_index = 10
dot.position = Vector2(tab_button.size.x, tab_button.size.y*0.25)
dot.modulate = get_theme_color("warning_color", "Editor").lightened(0.5)
tab_button.add_child(dot)
update_indicator()
func open() -> void:
%ReplacementEditPanel.hide()
%ReplacementSection.hide()
%ChangeTree.clear()
%ChangeTree.create_item()
%ChangeTree.set_column_expand(0, false)
%ChangeTree.set_column_expand(2, false)
%ChangeTree.set_column_custom_minimum_width(2, 50)
var categories := {null:%ChangeTree.get_root()}
for i in reference_changes:
var parent: TreeItem = null
if !i.get('category', null) in categories:
parent = %ChangeTree.create_item()
parent.set_text(1, i.category)
parent.set_custom_color(1, get_theme_color("disabled_font_color", "Editor"))
categories[i.category] = parent
else:
parent = categories[i.get('category')]
var item: TreeItem = %ChangeTree.create_item(parent)
item.set_text(1, i.what+" -> "+i.forwhat)
item.add_button(1, get_theme_icon("Edit", "EditorIcons"), 1, false, 'Edit')
item.add_button(1, get_theme_icon("Remove", "EditorIcons"), 0, false, 'Remove Change from List')
item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK)
item.set_checked(0, true)
item.set_editable(0, true)
item.set_metadata(0, i)
%CheckButton.disabled = reference_changes.is_empty()
func _on_change_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int) -> void:
if id == 0:
reference_changes.erase(item.get_metadata(0))
if item.get_parent().get_child_count() == 1:
item.get_parent().free()
else:
item.free()
update_indicator()
%CheckButton.disabled = reference_changes.is_empty()
if id == 1:
%ReplacementEditPanel.open_existing(item, item.get_metadata(0))
%ReplacementSection.hide()
func _on_change_tree_item_edited() -> void:
if !%ChangeTree.get_selected():
return
%CheckButton.disabled = false
func _on_check_button_pressed() -> void:
var to_be_checked: Array[Dictionary]= []
var item: TreeItem = %ChangeTree.get_root()
while item.get_next_visible():
item = item.get_next_visible()
if item.get_child_count():
continue
if item.is_checked(0):
to_be_checked.append(item.get_metadata(0))
to_be_checked[-1]['item'] = item
to_be_checked[-1]['count'] = 0
open_finder(to_be_checked)
%CheckButton.disabled = true
func open_finder(replacements:Array[Dictionary]) -> void:
%ReplacementSection.show()
%Progress.show()
%ReferenceTree.hide()
search_regexes = []
for i in replacements:
if i.has('character_names') and !i.character_names.is_empty():
i['character_regex'] = RegEx.create_from_string("(?m)^(join|update|leave)?\\s*("+str(i.character_names).replace('"', '').replace(', ', '|').trim_suffix(']').trim_prefix('[').replace('/', '\\/')+")(?(1).*|.*:)")
for regex_string in i.regex:
var regex := RegEx.create_from_string(regex_string)
search_regexes.append([regex, i])
finder_thread = Thread.new()
progress_mutex = Mutex.new()
finder_thread.start(search_timelines.bind(search_regexes))
func _process(delta: float) -> void:
if finder_thread and finder_thread.is_started():
if finder_thread.is_alive():
progress_mutex.lock()
%State.text = progress_message
%Progress.value = progress_percent
progress_mutex.unlock()
else:
var finds: Variant = finder_thread.wait_to_finish()
display_search_results(finds)
func display_search_results(finds:Array[Dictionary]) -> void:
%Progress.hide()
%ReferenceTree.show()
for regex_info in search_regexes:
regex_info[1]['item'].set_text(2, str(regex_info[1]['count']))
update_count_coloring()
%State.text = str(len(finds))+ " occurrences found"
%ReferenceTree.clear()
%ReferenceTree.set_column_expand(0, false)
%ReferenceTree.create_item()
var timelines := {}
var height := 0
for i in finds:
var parent: TreeItem = null
if !i.timeline in timelines:
parent = %ReferenceTree.create_item()
parent.set_text(1, i.timeline)
parent.set_custom_color(1, get_theme_color("disabled_font_color", "Editor"))
timelines[i.timeline] = parent
height += %ReferenceTree.get_item_area_rect(parent).size.y+10
else:
parent = timelines[i.timeline]
var item: TreeItem = %ReferenceTree.create_item(parent)
item.set_text(1, 'Line '+str(i.line_number)+': '+i.line)
item.set_tooltip_text(1, i.info.what+' -> '+i.info.forwhat)
item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK)
item.set_checked(0, true)
item.set_editable(0, true)
item.set_metadata(0, i)
height += %ReferenceTree.get_item_area_rect(item).size.y+10
var change_item: TreeItem = i.info.item
change_item.set_meta('found_items', change_item.get_meta('found_items', [])+[item])
%ReferenceTree.custom_minimum_size.y = min(height, 200)
%ReferenceTree.visible = !finds.is_empty()
%Replace.disabled = finds.is_empty()
if finds.is_empty():
%State.text = "Nothing found"
else:
%Replace.grab_focus()
func search_timelines(regexes:Array[Array]) -> Array[Dictionary]:
var finds: Array[Dictionary] = []
var timeline_paths := DialogicResourceUtil.list_resources_of_type('.dtl')
var progress := 0
var progress_max: float = len(timeline_paths)*len(regexes)
for timeline_path:String in timeline_paths:
var timeline_file := FileAccess.open(timeline_path, FileAccess.READ)
var timeline_text: String = timeline_file.get_as_text()
var timeline_event: PackedStringArray = timeline_text.split('\n')
timeline_file.close()
for regex_info in regexes:
progress += 1
progress_mutex.lock()
progress_percent = 1/progress_max*progress
progress_message = "Searching '"+timeline_path+"' for "+regex_info[1].what+' -> '+regex_info[1].forwhat
progress_mutex.unlock()
for i in regex_info[0].search_all(timeline_text):
if regex_info[1].has('character_regex'):
if regex_info[1].character_regex.search(get_line(timeline_text, i.get_start()+1)) == null:
continue
var line_number := timeline_text.count('\n', 0, i.get_start()+1)+1
var line := timeline_text.get_slice('\n', line_number-1)
finds.append({
'match':i,
'timeline':timeline_path,
'info': regex_info[1],
'line_number': line_number,
'line': line,
'line_start': timeline_text.rfind('\n', i.get_start())
})
regex_info[1]['count'] += 1
return finds
func _exit_tree() -> void:
# Shutting of
if finder_thread and finder_thread.is_alive():
finder_thread.wait_to_finish()
func get_line(string:String, at_index:int) -> String:
return string.substr(max(string.rfind('\n', at_index), 0), string.find('\n', at_index)-string.rfind('\n', at_index))
func update_count_coloring() -> void:
var item: TreeItem = %ChangeTree.get_root()
while item.get_next_visible():
item = item.get_next_visible()
if item.get_child_count():
continue
if int(item.get_text(2)) > 0:
item.set_custom_bg_color(1, get_theme_color("warning_color", "Editor").darkened(0.8))
item.set_custom_color(1, get_theme_color("warning_color", "Editor"))
item.set_custom_color(2, get_theme_color("warning_color", "Editor"))
else:
item.set_custom_color(2, get_theme_color("success_color", "Editor"))
item.set_custom_color(1, get_theme_color("readonly_font_color", "Editor"))
if item.get_button_count(1):
item.erase_button(1, 1)
item.add_button(1, get_theme_icon("Eraser", "EditorIcons"), -1, true, "This reference was not found anywhere and will be removed from this list.")
func _on_replace_pressed() -> void:
var to_be_replaced: Array[Dictionary]= []
var item: TreeItem = %ReferenceTree.get_root()
var affected_timelines: Array[String]= []
while item.get_next_visible():
item = item.get_next_visible()
if item.get_child_count():
continue
if item.is_checked(0):
to_be_replaced.append(item.get_metadata(0))
to_be_replaced[-1]['f_item'] = item
if !item.get_metadata(0).timeline in affected_timelines:
affected_timelines.append(item.get_metadata(0).timeline)
replace(affected_timelines, to_be_replaced)
func replace(timelines:Array[String], replacement_info:Array[Dictionary]) -> void:
var reopen_timeline := ""
var timeline_editor: DialogicEditor = find_parent('EditorView').editors_manager.editors['Timeline'].node
if timeline_editor.current_resource != null and timeline_editor.current_resource.resource_path in timelines:
reopen_timeline = timeline_editor.current_resource.resource_path
find_parent('EditorView').editors_manager.clear_editor(timeline_editor)
replacement_info.sort_custom(func(a,b): return a.match.get_start() < b.match.get_start())
for timeline_path in timelines:
%State.text = "Loading '"+timeline_path+"'"
var timeline_file := FileAccess.open(timeline_path, FileAccess.READ_WRITE)
var timeline_text: String = timeline_file.get_as_text()
var timeline_events := timeline_text.split('\n')
timeline_file.close()
var idx := 1
var offset_correction := 0
for replacement in replacement_info:
if replacement.timeline != timeline_path:
continue
%State.text = "Replacing in '"+timeline_path + "' ("+str(idx)+"/"+str(len(replacement_info))+")"
var group := 'replace'
if not 'replace' in replacement.match.names:
group = ''
timeline_text = timeline_text.substr(0, replacement.match.get_start(group) + offset_correction) + \
replacement.info.regex_replacement + \
timeline_text.substr(replacement.match.get_end(group) + offset_correction)
offset_correction += len(replacement.info.regex_replacement)-len(replacement.match.get_string(group))
replacement.info.count -= 1
replacement.info.item.set_text(2, str(replacement.info.count))
replacement.f_item.set_custom_bg_color(1, get_theme_color("success_color", "Editor").darkened(0.8))
timeline_file = FileAccess.open(timeline_path, FileAccess.WRITE)
timeline_file.store_string(timeline_text.strip_edges(false, true))
timeline_file.close()
if ResourceLoader.has_cached(timeline_path):
var tml := load(timeline_path)
tml.from_text(timeline_text)
if !reopen_timeline.is_empty():
find_parent('EditorView').editors_manager.edit_resource(load(reopen_timeline), false, true)
update_count_coloring()
%Replace.disabled = true
%CheckButton.disabled = false
%State.text = "Done Replacing"
func update_indicator() -> void:
%TabA.get_child(0).visible = !reference_changes.is_empty()
func close() -> void:
var item: TreeItem = %ChangeTree.get_root()
if item:
while item.get_next_visible():
item = item.get_next_visible()
if item.get_child_count():
continue
if item.get_text(2) != "" and int(item.get_text(2)) == 0:
reference_changes.erase(item.get_metadata(0))
for i in reference_changes:
i.item = null
DialogicUtil.set_editor_setting('reference_changes', reference_changes)
update_indicator()
find_parent("ReferenceManager").update_indicator()
func _on_add_button_pressed() -> void:
%ReplacementEditPanel._on_add_pressed()

View File

@@ -0,0 +1 @@
uid://bhml2gwyjbpj7

View File

@@ -0,0 +1,12 @@
@tool
extends TextureRect
@export_multiline var hint_text := ""
func _ready() -> void:
if owner and owner.get_parent() is SubViewport:
texture = null
return
texture = get_theme_icon("NodeInfo", "EditorIcons")
modulate = get_theme_color("contrast_color_1", "Editor")
tooltip_text = hint_text

View File

@@ -0,0 +1 @@
uid://pv58uk852jre

View File

@@ -0,0 +1,21 @@
[gd_scene load_steps=4 format=3 uid="uid://dbpkta2tjsqim"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.gd" id="1_x8t45"]
[sub_resource type="Image" id="Image_eiyxd"]
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_lseut"]
image = SubResource("Image_eiyxd")
[node name="HintTooltip" type="TextureRect"]
modulate = Color(0, 0, 0, 1)
texture = SubResource("ImageTexture_lseut")
stretch_mode = 3
script = ExtResource("1_x8t45")

View File

@@ -0,0 +1,38 @@
@tool
extends PanelContainer
func _ready() -> void:
if get_parent() is SubViewport:
return
add_theme_stylebox_override("panel", get_theme_stylebox("Background", "EditorStyles"))
$Tabs/Close.icon = get_theme_icon("Close", "EditorIcons")
for tab in $Tabs/Tabs.get_children():
tab.add_theme_color_override("font_selected_color", get_theme_color("accent_color", "Editor"))
tab.add_theme_font_override("font", get_theme_font("main", "EditorFonts"))
tab.toggled.connect(tab_changed.bind(tab.get_index()+1))
func tab_changed(enabled:bool, index:int) -> void:
for child in $Tabs.get_children():
if child.get_index() == 0 or child.get_index() == index or child is Button:
child.show()
if child.get_index() == index:
child.open()
else:
if child.visible:
child.close()
child.hide()
for child in $Tabs/Tabs.get_children():
child.set_pressed_no_signal(index-1 == child.get_index())
func open() -> void:
show()
$Tabs/BrokenReferences.update_indicator()
func _on_close_pressed() -> void:
get_parent()._on_close_requested()

View File

@@ -0,0 +1 @@
uid://clihsosyt8utt

View File

@@ -0,0 +1,324 @@
[gd_scene load_steps=13 format=3 uid="uid://c7lmt5cp7bxcm"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/reference_manager.gd" id="1_3t531"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/broken_reference_manager.gd" id="1_agmg4"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd" id="2_tt4jd"]
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_yomsc"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/unique_identifiers_manager.gd" id="5_wnvbq"]
[sub_resource type="ButtonGroup" id="ButtonGroup_l6uiy"]
[sub_resource type="Image" id="Image_36731"]
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, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 224, 224, 224, 255, 224, 224, 224, 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, 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_a0gfq"]
image = SubResource("Image_36731")
[sub_resource type="Image" id="Image_0rvkq"]
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_mr0fw"]
image = SubResource("Image_0rvkq")
[sub_resource type="Image" id="Image_5fmdt"]
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_5fmdt")
[node name="Manager" type="PanelContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_3t531")
[node name="Tabs" type="VBoxContainer" parent="."]
layout_mode = 2
[node name="Tabs" type="HBoxContainer" parent="Tabs"]
layout_mode = 2
alignment = 1
[node name="TabA" type="Button" parent="Tabs/Tabs"]
unique_name_in_owner = true
layout_mode = 2
toggle_mode = true
button_pressed = true
text = "Broken References"
flat = true
[node name="TabB" type="Button" parent="Tabs/Tabs"]
unique_name_in_owner = true
layout_mode = 2
toggle_mode = true
button_group = SubResource("ButtonGroup_l6uiy")
text = "Unique Identifiers"
flat = true
[node name="BrokenReferences" type="VSplitContainer" parent="Tabs"]
layout_mode = 2
size_flags_vertical = 3
script = ExtResource("1_agmg4")
[node name="ChangesList" type="PanelContainer" parent="Tabs/BrokenReferences"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme_type_variation = &"DialogicPanelA"
[node name="VBox" type="VBoxContainer" parent="Tabs/BrokenReferences/ChangesList"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox"]
layout_mode = 2
[node name="SectionTitle" type="Label" parent="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_font_sizes/font_size = 16
text = "Recent renames"
[node name="AddButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 2
tooltip_text = "Add custom rename"
icon = SubResource("ImageTexture_a0gfq")
[node name="ReplacementEditPanel" type="PanelContainer" parent="Tabs/BrokenReferences/ChangesList/VBox"]
unique_name_in_owner = true
visible = false
layout_mode = 2
script = ExtResource("2_tt4jd")
[node name="VBox" type="HFlowContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel"]
layout_mode = 2
[node name="HBoxContainer3" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
layout_mode = 2
[node name="Type" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer3"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "This decides the regexes for searching. Pure text allows you to enter your own regex into into \"Old\". "
item_count = 5
selected = 0
popup/item_0/text = "Pure Text"
popup/item_0/id = 0
popup/item_1/text = "Variable"
popup/item_1/id = 1
popup/item_2/text = "Portrait"
popup/item_2/id = 2
popup/item_3/text = "Character (Ref)"
popup/item_3/id = 3
popup/item_4/text = "Timeline (Ref)"
popup/item_4/id = 4
[node name="HBoxContainer" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Old" type="LineEdit" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Old"
[node name="Label2" type="Label" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
layout_mode = 2
text = "->"
[node name="New" type="LineEdit" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "New"
[node name="PureTextFlags" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
unique_name_in_owner = true
layout_mode = 2
alignment = 2
[node name="MatchCase" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/PureTextFlags"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Match Case"
toggle_mode = true
icon = SubResource("ImageTexture_mr0fw")
[node name="WholeWords" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/PureTextFlags"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Whole World"
toggle_mode = true
icon = SubResource("ImageTexture_mr0fw")
[node name="HBoxContainer4" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
layout_mode = 2
[node name="Where" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4"]
unique_name_in_owner = true
layout_mode = 2
item_count = 3
selected = 0
fit_to_longest_item = false
popup/item_0/text = "Everywhere"
popup/item_0/id = 0
popup/item_1/text = "Only for Character"
popup/item_1/id = 1
popup/item_2/text = "Texts only"
popup/item_2/id = 2
[node name="Character" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4" instance=ExtResource("3_yomsc")]
unique_name_in_owner = true
layout_mode = 2
[node name="AddButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Add/Save"
[node name="ChangeTree" type="Tree" parent="Tabs/BrokenReferences/ChangesList/VBox"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 50)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/draw_relationship_lines = 1
columns = 3
hide_root = true
[node name="CheckButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
tooltip_text = "Search timelines for occurences of these renames"
text = "Check Selected"
icon = SubResource("ImageTexture_lce2m")
[node name="ReplacementSection" type="PanelContainer" parent="Tabs/BrokenReferences"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicPanelA"
[node name="FindList" type="VBoxContainer" parent="Tabs/BrokenReferences/ReplacementSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
[node name="HBox" type="HBoxContainer" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
layout_mode = 2
[node name="SectionTitle2" type="Label" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBox"]
unique_name_in_owner = true
layout_mode = 2
theme_override_font_sizes/font_size = 16
text = "Found references"
[node name="State" type="Label" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 8
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "State"
[node name="ReferenceTree" type="Tree" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/draw_relationship_lines = 1
columns = 2
hide_root = true
[node name="Progress" type="ProgressBar" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
unique_name_in_owner = true
layout_mode = 2
max_value = 1.0
[node name="Replace" type="Button" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
tooltip_text = "Replace all selected findings (Careful, no undo!)"
text = "Replace Selected"
icon = SubResource("ImageTexture_lce2m")
[node name="UniqueIdentifiers" type="PanelContainer" parent="Tabs"]
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_type_variation = &"DialogicPanelA"
script = ExtResource("5_wnvbq")
[node name="VBox" type="VBoxContainer" parent="Tabs/UniqueIdentifiers"]
layout_mode = 2
[node name="Tools" type="HBoxContainer" parent="Tabs/UniqueIdentifiers/VBox"]
layout_mode = 2
alignment = 1
[node name="Search" type="LineEdit" parent="Tabs/UniqueIdentifiers/VBox/Tools"]
unique_name_in_owner = true
custom_minimum_size = Vector2(400, 0)
layout_mode = 2
placeholder_text = "Search"
[node name="IdentifierTable" type="Tree" parent="Tabs/UniqueIdentifiers/VBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
columns = 2
column_titles_visible = true
hide_root = true
[node name="RenameNotification" type="Label" parent="Tabs/UniqueIdentifiers/VBox"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
text = "You've renamed some identifier(s)! Use the \"Broken References\" tab to check if you have used this identifier (and fix it if so)."
autowrap_mode = 3
[node name="Close" type="Button" parent="Tabs"]
layout_mode = 2
size_flags_horizontal = 4
text = "Close"
[node name="HelpButton" type="LinkButton" parent="."]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 0
text = "Documentation"
uri = "https://docs.dialogic.pro/reference-manager.html"
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer/AddButton" to="Tabs/BrokenReferences" method="_on_add_button_pressed"]
[connection signal="item_selected" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer3/Type" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="_on_type_item_selected"]
[connection signal="item_selected" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4/Where" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="_on_where_item_selected"]
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/AddButton" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="save"]
[connection signal="button_clicked" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_button_clicked"]
[connection signal="item_edited" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_item_edited"]
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/CheckButton" to="Tabs/BrokenReferences" method="_on_check_button_pressed"]
[connection signal="pressed" from="Tabs/BrokenReferences/ReplacementSection/FindList/Replace" to="Tabs/BrokenReferences" method="_on_replace_pressed"]
[connection signal="text_changed" from="Tabs/UniqueIdentifiers/VBox/Tools/Search" to="Tabs/UniqueIdentifiers" method="_on_search_text_changed"]
[connection signal="button_clicked" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_button_clicked"]
[connection signal="item_edited" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_item_edited"]
[connection signal="pressed" from="Tabs/Close" to="." method="_on_close_pressed"]

View File

@@ -0,0 +1,191 @@
@tool
extends Window
## This window manages communication with the replacement manager it contains.
## Other scripts can call the add_ref_change() method to register changes directly
## or use the helpers add_variable_ref_change() and add_portrait_ref_change()
@onready var editors_manager := get_node("../EditorsManager")
@onready var broken_manager := get_node("Manager/Tabs/BrokenReferences")
enum Where {EVERYWHERE, BY_CHARACTER, TEXTS_ONLY}
enum Types {TEXT, VARIABLE, PORTRAIT, CHARACTER_NAME, TIMELINE_NAME}
var icon_button: Button = null
func _ready() -> void:
if owner.get_parent() is SubViewport:
return
$Manager.theme = owner.get_theme()
icon_button = editors_manager.add_icon_button(get_theme_icon("Unlinked", "EditorIcons"), 'Reference Manager')
icon_button.pressed.connect(open)
var dot := Sprite2D.new()
dot.texture = get_theme_icon("GuiGraphNodePort", "EditorIcons")
dot.scale = Vector2(0.8, 0.8)
dot.z_index = 10
dot.position = Vector2(icon_button.size.x*0.8, icon_button.size.x*0.2)
dot.modulate = get_theme_color("warning_color", "Editor").lightened(0.5)
icon_button.add_child(dot)
var old_changes: Array = DialogicUtil.get_editor_setting('reference_changes', [])
if !old_changes.is_empty():
broken_manager.reference_changes = old_changes
update_indicator()
hide()
get_parent().plugin_reference.get_editor_interface().get_file_system_dock().files_moved.connect(_on_file_moved)
get_parent().plugin_reference.get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed)
get_parent().get_node('ResourceRenameWarning').confirmed.connect(open)
func add_ref_change(old_name:String, new_name:String, type:Types, where:=Where.TEXTS_ONLY, character_names:=[],
whole_words:=false, case_sensitive:=false, previous:Dictionary = {}) -> void:
var regexes := []
var category_name := ""
match type:
Types.TEXT:
category_name = "Texts"
if '<replace>' in old_name:
regexes = [old_name]
else:
regexes = [
r'(?<replace>%s)' % old_name.replace('/', '\\/')
]
if !case_sensitive:
regexes[0] = '(?i)'+regexes[0]
if whole_words:
regexes = ['\\b'+regexes[0]+'\\b']
Types.VARIABLE:
regexes = [
r'{(?<replace>\s*%s\s*)}' % old_name.replace("/", "\\/"),
r'var\s*=\s*"(?<replace>\s*%s\s*)"' % old_name.replace("/", "\\/")
]
category_name = "Variables"
Types.PORTRAIT:
regexes = [
r'(?m)^[^:(\n]*\((?<replace>%s)\)' % old_name.replace('/', '\\/'),
r'\[\s*portrait\s*=(?<replace>\s*%s\s*)\]' % old_name.replace('/', '\\/')
]
category_name = "Portraits by "+character_names[0]
Types.CHARACTER_NAME:
# for reference: ((join|leave|update) )?(?<replace>NAME)(?!\B)(?(1)|(?!([^:\n]|\\:)*(\n|$)))
regexes = [
r'((join|leave|update) )?(?<replace>%s)(?!\B)(?(1)|(?!([^:\n]|\\:)*(\n|$)))' % old_name
]
category_name = "Renamed Character Files"
Types.TIMELINE_NAME:
regexes = [
r'timeline ?= ?" ?(?<replace>%s) ?"' % old_name
]
category_name = "Renamed Timeline Files"
if where != Where.BY_CHARACTER:
character_names = []
# previous is only given when an existing item is edited
# in that case the old one is removed first
var idx := len(broken_manager.reference_changes)
if previous in broken_manager.reference_changes:
idx = broken_manager.reference_changes.find(previous)
broken_manager.reference_changes.erase(previous)
if _check_for_ref_change_cycle(old_name, new_name, category_name):
update_indicator()
return
broken_manager.reference_changes.insert(idx,
{'what':old_name,
'forwhat':new_name,
'regex': regexes,
'regex_replacement':new_name,
'category':category_name,
'character_names':character_names,
'texts_only':where == Where.TEXTS_ONLY,
'type':type
})
update_indicator()
if visible:
$Manager.open()
broken_manager.open()
## Checks for reference cycles or chains.
## E.g. if you first rename a portrait from "happy" to "happy1" and then to "Happy/happy1"
## This will make sure only a change "happy" -> "Happy/happy1" is remembered
## This is very important for correct replacement
func _check_for_ref_change_cycle(old_name:String, new_name:String, category:String) -> bool:
for ref in broken_manager.reference_changes:
if ref['forwhat'] == old_name and ref['category'] == category:
if new_name == ref['what']:
broken_manager.reference_changes.erase(ref)
else:
broken_manager.reference_changes[broken_manager.reference_changes.find(ref)]['forwhat'] = new_name
broken_manager.reference_changes[broken_manager.reference_changes.find(ref)]['regex_replacement'] = new_name
return true
return false
## Helper for adding variable ref changes
func add_variable_ref_change(old_name:String, new_name:String) -> void:
add_ref_change(old_name, new_name, Types.VARIABLE, Where.EVERYWHERE)
## Helper for adding portrait ref changes
func add_portrait_ref_change(old_name:String, new_name:String, character_names:PackedStringArray) -> void:
add_ref_change(old_name, new_name, Types.PORTRAIT, Where.BY_CHARACTER, character_names)
## Helper for adding character name ref changes
func add_character_name_ref_change(old_name:String, new_name:String) -> void:
add_ref_change(old_name, new_name, Types.CHARACTER_NAME, Where.EVERYWHERE)
## Helper for adding timeline name ref changes
func add_timeline_name_ref_change(old_name:String, new_name:String) -> void:
add_ref_change(old_name, new_name, Types.TIMELINE_NAME, Where.EVERYWHERE)
func open() -> void:
DialogicResourceUtil.update_directory('dch')
DialogicResourceUtil.update_directory('dtl')
popup_centered_ratio(0.5)
move_to_foreground()
grab_focus()
func _on_close_requested() -> void:
hide()
broken_manager.close()
func update_indicator() -> void:
icon_button.get_child(0).visible = !broken_manager.reference_changes.is_empty()
## FILE MANAGEMENT:
func _on_file_moved(old_file:String, new_file:String) -> void:
if old_file.ends_with('.dch') and new_file.ends_with('.dch'):
DialogicResourceUtil.change_resource_path(old_file, new_file)
if old_file.get_file() != new_file.get_file():
get_parent().get_node('ResourceRenameWarning').popup_centered()
elif old_file.ends_with('.dtl') and new_file.ends_with('.dtl'):
DialogicResourceUtil.change_resource_path(old_file, new_file)
if old_file.get_file() != new_file.get_file():
get_parent().get_node('ResourceRenameWarning').popup_centered()
func _on_file_removed(file:String) -> void:
if file.get_extension() in ['dch', 'dtl']:
DialogicResourceUtil.remove_resource(file)

View File

@@ -0,0 +1 @@
uid://bqab632sxner5

View File

@@ -0,0 +1,211 @@
[gd_scene load_steps=7 format=3 uid="uid://cwe3r2tbh2og1"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/sidebar.gd" id="1_jnq65"]
[ext_resource type="Texture2D" uid="uid://bff65e82555qr" path="res://addons/dialogic/Editor/Images/Pieces/close-icon.svg" id="2_54pks"]
[ext_resource type="Texture2D" uid="uid://dx3o2ild56i76" path="res://addons/dialogic/Editor/Images/Pieces/closed-icon.svg" id="2_ilyps"]
[sub_resource type="Theme" id="Theme_pn0f4"]
VBoxContainer/constants/separation = 4
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_gxwm6"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_n8rql"]
[node name="SideBar" type="VSplitContainer"]
custom_minimum_size = Vector2(100, 130)
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("Theme_pn0f4")
split_offset = 100
script = ExtResource("1_jnq65")
[node name="VBoxHidden" type="VBoxContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
[node name="OpenButton" type="Button" parent="VBoxHidden"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 3
tooltip_text = "Show Sidebar"
theme_override_constants/icon_max_width = 20
icon = ExtResource("2_ilyps")
flat = true
icon_alignment = 1
[node name="VBoxPrimary" type="VBoxContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
[node name="Margin" type="MarginContainer" parent="VBoxPrimary"]
layout_mode = 2
size_flags_vertical = 3
[node name="MainVSplit" type="VSplitContainer" parent="VBoxPrimary/Margin"]
unique_name_in_owner = true
layout_mode = 2
[node name="VBox" type="VBoxContainer" parent="VBoxPrimary/Margin/MainVSplit"]
layout_mode = 2
size_flags_vertical = 3
[node name="Logo" type="TextureRect" parent="VBoxPrimary/Margin/MainVSplit/VBox"]
unique_name_in_owner = true
modulate = Color(1, 1, 1, 0.623529)
texture_filter = 6
custom_minimum_size = Vector2(0, 25)
layout_mode = 2
expand_mode = 3
stretch_mode = 4
[node name="HBox" type="HBoxContainer" parent="VBoxPrimary/Margin/MainVSplit/VBox"]
layout_mode = 2
[node name="CurrentResource" type="LineEdit" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "No resource"
alignment = 1
editable = false
[node name="CloseButton" type="Button" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBox"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Hide Sidebar"
text = " "
icon = ExtResource("2_54pks")
flat = true
icon_alignment = 1
expand_icon = true
[node name="HBoxSearchSort" type="HBoxContainer" parent="VBoxPrimary/Margin/MainVSplit/VBox"]
layout_mode = 2
[node name="Search" type="LineEdit" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
tooltip_text = "Filter Resources"
placeholder_text = "Filter Resources"
caret_blink = true
caret_blink_interval = 0.5
[node name="Options" type="Button" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort"]
unique_name_in_owner = true
layout_mode = 2
[node name="OptionsPopup" type="Popup" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options"]
unique_name_in_owner = true
transparent_bg = true
position = Vector2i(890, 65)
size = Vector2i(165, 101)
visible = true
transparent = true
[node name="OptionsPanel" type="PanelContainer" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup"]
unique_name_in_owner = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBox" type="VBoxContainer" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel"]
layout_mode = 2
[node name="GroupingOptions" type="OptionButton" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel/VBox"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Grouping
- None: No Grouping, sorted alphabetically
- Type: Group by type (Characters/Timeilnes)
- Folder: Group based on the parent folder name.
- Path: Group based on folders."
text_overrun_behavior = 1
clip_text = true
selected = 0
item_count = 4
popup/item_0/text = "No Grouping"
popup/item_1/text = "Type Grouping"
popup/item_1/id = 1
popup/item_2/text = "Folder Grouping"
popup/item_2/id = 2
popup/item_3/text = "Path Grouping"
popup/item_3/id = 3
[node name="FolderColors" type="CheckBox" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel/VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Use Folder Colors"
[node name="TrimFolderPaths" type="CheckBox" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel/VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Trim Folder Paths"
[node name="ResourceTree" type="Tree" parent="VBoxPrimary/Margin/MainVSplit/VBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
allow_rmb_select = true
hide_root = true
scroll_horizontal_enabled = false
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxPrimary/Margin/MainVSplit/VBox"]
visible = false
layout_mode = 2
[node name="Label" type="Label" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxContainer"]
layout_mode = 2
size_flags_vertical = 1
text = "Sort Order"
vertical_alignment = 1
[node name="SortOption" type="OptionButton" parent="VBoxPrimary/Margin/MainVSplit/VBox/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
item_count = 1
popup/item_0/text = "Alphabetical (All)"
[node name="ContentListSection" type="VBoxContainer" parent="VBoxPrimary/Margin/MainVSplit"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 15)
layout_mode = 2
size_flags_vertical = 3
[node name="ContentList" type="ItemList" parent="VBoxPrimary/Margin/MainVSplit/ContentListSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
tooltip_text = "Label events in your timeline will appear here, allowing you to jump to them."
theme_override_styles/selected = SubResource("StyleBoxEmpty_gxwm6")
theme_override_styles/selected_focus = SubResource("StyleBoxEmpty_n8rql")
allow_reselect = true
same_column_width = true
[node name="CurrentVersion" type="Button" parent="VBoxPrimary"]
unique_name_in_owner = true
layout_mode = 2
text = "Some Version"
flat = true
clip_text = true
[node name="RightClickMenu" type="PopupMenu" parent="."]
unique_name_in_owner = true
size = Vector2i(164, 100)
[connection signal="dragged" from="VBoxPrimary/Margin/MainVSplit" to="." method="_on_main_v_split_dragged"]
[connection signal="gui_input" from="VBoxPrimary/Margin/MainVSplit/VBox/Logo" to="." method="_on_logo_gui_input"]
[connection signal="text_changed" from="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Search" to="." method="_on_search_text_changed"]
[connection signal="text_submitted" from="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Search" to="." method="_on_search_text_submitted"]
[connection signal="pressed" from="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options" to="." method="_on_options_pressed"]
[connection signal="toggled" from="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel/VBox/FolderColors" to="." method="_on_folder_colors_toggled"]
[connection signal="toggled" from="VBoxPrimary/Margin/MainVSplit/VBox/HBoxSearchSort/Options/OptionsPopup/OptionsPanel/VBox/TrimFolderPaths" to="." method="_on_trim_folder_paths_toggled"]
[connection signal="id_pressed" from="RightClickMenu" to="." method="_on_right_click_menu_id_pressed"]

View File

@@ -0,0 +1,529 @@
@tool
class_name DialogicSidebar extends Control
## Script that handles the editor sidebar.
signal content_item_activated(item_name)
signal show_sidebar(show: bool)
# References
@onready var editors_manager = get_parent().get_parent()
@onready var resource_tree: Tree = %ResourceTree
var current_resource_list: Array = []
enum GroupMode {
NONE,
TYPE,
FOLDER,
PATH,
}
var group_mode: GroupMode = GroupMode.TYPE
func _ready() -> void:
if owner != null and owner.get_parent() is SubViewport:
return
if editors_manager is SubViewportContainer:
return
## CONNECTIONS
editors_manager.resource_opened.connect(_on_editors_resource_opened)
editors_manager.editor_changed.connect(_on_editors_editor_changed)
resource_tree.item_activated.connect(_on_resources_tree_item_activated)
resource_tree.item_mouse_selected.connect(_on_resources_tree_item_clicked)
resource_tree.item_collapsed.connect(_on_resources_tree_item_collapsed)
%ContentList.item_selected.connect(
func(idx: int): content_item_activated.emit(%ContentList.get_item_text(idx))
)
%OpenButton.pressed.connect(_show_sidebar)
%CloseButton.pressed.connect(_hide_sidebar)
var editor_scale := DialogicUtil.get_editor_scale()
## ICONS
%Logo.texture = load("res://addons/dialogic/Editor/Images/dialogic-logo.svg")
%Logo.custom_minimum_size.y = 30 * editor_scale
%Search.right_icon = get_theme_icon("Search", "EditorIcons")
%Options.icon = get_theme_icon("GuiTabMenuHl", "EditorIcons")
%OptionsPanel.add_theme_stylebox_override("panel", get_theme_stylebox("PanelForeground", "EditorStyles"))
%OptionsPopup.hide()
%ContentList.add_theme_color_override(
"font_hovered_color", get_theme_color("warning_color", "Editor")
)
%ContentList.add_theme_color_override(
"font_selected_color", get_theme_color("property_color_z", "Editor")
)
## RIGHT CLICK MENU
%RightClickMenu.clear()
%RightClickMenu.add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Remove From List", 1)
%RightClickMenu.add_separator()
%RightClickMenu.add_icon_item(get_theme_icon("ActionCopy", "EditorIcons"), "Copy Identifier", 4)
%RightClickMenu.add_separator()
%RightClickMenu.add_icon_item(
get_theme_icon("Filesystem", "EditorIcons"), "Show in FileSystem", 2
)
%RightClickMenu.add_icon_item(
get_theme_icon("ExternalLink", "EditorIcons"), "Open in External Program", 3
)
## SORT MENU
%GroupingOptions.set_item_icon(0, get_theme_icon("AnimationTrackGroup", "EditorIcons"))
%GroupingOptions.set_item_icon(1, get_theme_icon("Folder", "EditorIcons"))
%GroupingOptions.set_item_icon(2, get_theme_icon("FolderBrowse", "EditorIcons"))
%GroupingOptions.set_item_icon(3, get_theme_icon("AnimationTrackList", "EditorIcons"))
%GroupingOptions.item_selected.connect(_on_grouping_changed)
await get_tree().process_frame
if DialogicUtil.get_editor_setting("sidebar_collapsed", false):
_hide_sidebar()
%MainVSplit.split_offset = DialogicUtil.get_editor_setting("sidebar_v_split", 0)
group_mode = DialogicUtil.get_editor_setting("sidebar_group_mode", 0)
%GroupingOptions.select(%GroupingOptions.get_item_index(group_mode))
%FolderColors.button_pressed = DialogicUtil.get_editor_setting("sidebar_use_folder_colors", true)
%TrimFolderPaths.button_pressed = DialogicUtil.get_editor_setting("sidebar_trim_folder_paths", true)
update_resource_list()
func set_unsaved_indicator(saved: bool = true) -> void:
if saved and %CurrentResource.text.ends_with("(*)"):
%CurrentResource.text = %CurrentResource.text.trim_suffix("(*)")
if not saved and not %CurrentResource.text.ends_with("(*)"):
%CurrentResource.text = %CurrentResource.text + "(*)"
func _on_logo_gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
editors_manager.open_editor(editors_manager.editors["HomePage"].node)
#region SHOW/HIDE SIDEBAR
################################################################################
func _show_sidebar() -> void:
%VBoxPrimary.show()
%VBoxHidden.hide()
DialogicUtil.set_editor_setting("sidebar_collapsed", false)
show_sidebar.emit(true)
func _hide_sidebar() -> void:
%VBoxPrimary.hide()
%VBoxHidden.show()
DialogicUtil.set_editor_setting("sidebar_collapsed", true)
show_sidebar.emit(false)
#endregion
################################################################################
## RESOURCE LIST
################################################################################
func _on_editors_resource_opened(_resource: Resource) -> void:
update_resource_list()
func _on_editors_editor_changed(_previous: DialogicEditor, current: DialogicEditor) -> void:
%ContentListSection.visible = current.current_resource is DialogicTimeline
update_resource_list()
## Cleans resources that have been deleted from the resource list
func clean_resource_list(resources_list: Array = []) -> PackedStringArray:
return PackedStringArray(resources_list.filter(func(x): return ResourceLoader.exists(x)))
#region BULDING/FILTERING THE RESOURCE LIST
func update_resource_list(resources_list: PackedStringArray = []) -> void:
var filter: String = %Search.text
var current_file := ""
if editors_manager.current_editor and editors_manager.current_editor.current_resource:
current_file = editors_manager.current_editor.current_resource.resource_path
var character_directory: Dictionary = DialogicResourceUtil.get_character_directory()
var timeline_directory: Dictionary = DialogicResourceUtil.get_timeline_directory()
if resources_list.is_empty():
resources_list = DialogicUtil.get_editor_setting("last_resources", [])
if not current_file in resources_list:
resources_list.append(current_file)
resources_list = clean_resource_list(resources_list)
%CurrentResource.text = "No Resource"
%CurrentResource.add_theme_color_override(
"font_uneditable_color", get_theme_color("disabled_font_color", "Editor")
)
resource_tree.clear()
var character_items: Array = get_directory_items.call(character_directory, filter, load("res://addons/dialogic/Editor/Images/Resources/character.svg"), resources_list)
var timeline_items: Array = get_directory_items.call(timeline_directory, filter, get_theme_icon("TripleBar", "EditorIcons"), resources_list)
var all_items := character_items + timeline_items
# BUILD TREE
var root: TreeItem = resource_tree.create_item()
match group_mode:
GroupMode.NONE:
all_items.sort_custom(_sort_by_item_text)
for item in all_items:
add_item(item, root, current_file)
GroupMode.TYPE:
character_items.sort_custom(_sort_by_item_text)
timeline_items.sort_custom(_sort_by_item_text)
if character_items.size() > 0:
var character_tree := add_folder_item("Characters", root)
for item in character_items:
add_item(item, character_tree, current_file)
if timeline_items.size() > 0:
var timeline_tree := add_folder_item("Timelines", root)
for item in timeline_items:
add_item(item, timeline_tree, current_file)
GroupMode.FOLDER:
var dirs := {}
for item in all_items:
var dir := item.get_parent_directory() as String
if not dirs.has(dir):
dirs[dir] = []
dirs[dir].append(item)
for dir in dirs:
var dir_item := add_folder_item(dir, root)
for item in dirs[dir]:
add_item(item, dir_item, current_file)
GroupMode.PATH:
# Collect all different directories that contain resources
var dirs := {}
for item in all_items:
var path := (item.metadata.get_base_dir() as String).trim_prefix("res://")
if not dirs.has(path):
dirs[path] = []
dirs[path].append(item)
# Sort them into ones with the same folder name
var dir_names := {}
for dir in dirs:
var sliced: String = dir.get_slice("/", dir.get_slice_count("/")-1)
if not sliced in dir_names:
dir_names[sliced] = {"folders":[dir]}
else:
dir_names[sliced].folders.append(dir)
# Create a dictionary mapping a unique name to each directory
# If two have been found to have the same folder name, the parent directory is added
var unique_folder_names := {}
for dir_name in dir_names:
if dir_names[dir_name].folders.size() > 1:
for i in dir_names[dir_name].folders:
if "/" in i:
unique_folder_names[i.get_slice("/", i.get_slice_count("/")-2)+"/"+i.get_slice("/", i.get_slice_count("/")-1)] = i
else:
unique_folder_names[i] = i
else:
unique_folder_names[dir_name] = dir_names[dir_name].folders[0]
# Sort the folder names by their folder name (not by the full path)
var sorted_dir_keys := unique_folder_names.keys()
sorted_dir_keys.sort_custom(
func(x, y):
return x.get_slice("/", x.get_slice_count("/")-1) < y.get_slice("/", y.get_slice_count("/")-1)
)
var folder_colors: Dictionary = ProjectSettings.get_setting("file_customization/folder_colors", {})
for dir in sorted_dir_keys:
var display_name: String = dir
if not %TrimFolderPaths.button_pressed:
display_name = unique_folder_names[dir]
var dir_path: String = unique_folder_names[dir]
var dir_color_path := ""
var dir_color := Color.BLACK
if %FolderColors.button_pressed:
for path in folder_colors:
if String("res://"+dir_path+"/").begins_with(path) and len(path) > len(dir_color_path):
dir_color_path = path
dir_color = folder_colors[path]
var dir_item := add_folder_item(display_name, root, dir_color, dir_path)
for item in dirs[dir_path]:
add_item(item, dir_item, current_file)
if %CurrentResource.text != "No Resource":
%CurrentResource.add_theme_color_override(
"font_uneditable_color", get_theme_color("font_color", "Editor")
)
DialogicUtil.set_editor_setting("last_resources", resources_list)
func add_item(item:ResourceListItem, parent:TreeItem, current_file := "") -> TreeItem:
var tree_item := resource_tree.create_item(parent)
tree_item.set_text(0, item.text)
tree_item.set_icon(0, item.icon)
tree_item.set_metadata(0, item.metadata)
tree_item.set_tooltip_text(0, item.tooltip)
if item.metadata == current_file:
%CurrentResource.text = item.metadata.get_file()
resource_tree.set_selected(tree_item, 0)
var bg_color := parent.get_custom_bg_color(0)
if bg_color != get_theme_color("base_color", "Editor"):
bg_color.a = 0.1
tree_item.set_custom_bg_color(0, bg_color)
return tree_item
func add_folder_item(label: String, parent:TreeItem, color:= Color.BLACK, tooltip:="") -> TreeItem:
var folder_item := resource_tree.create_item(parent)
folder_item.set_text(0, label)
folder_item.set_icon(0, get_theme_icon("Folder", "EditorIcons"))
folder_item.set_tooltip_text(0, tooltip)
if color == Color.BLACK:
folder_item.set_custom_bg_color(0, get_theme_color("base_color", "Editor"))
else:
color.a = 0.2
folder_item.set_custom_bg_color(0, color)
if label in DialogicUtil.get_editor_setting("resource_list_collapsed_info", []):
folder_item.collapsed = true
return folder_item
func get_directory_items(directory:Dictionary, filter:String, icon:Texture2D, resources_list:Array) -> Array:
var items := []
for item_name in directory:
if (directory[item_name] in resources_list) and (filter.is_empty() or filter.to_lower() in item_name.to_lower()):
var item := ResourceListItem.new()
item.text = item_name
item.icon = icon
item.metadata = directory[item_name]
item.tooltip = directory[item_name]
items.append(item)
return items
class ResourceListItem:
extends Object
var text: String
var index: int = -1
var icon: Texture
var metadata: String
var tooltip: String
func _to_string() -> String:
return JSON.stringify(
{
"text": text,
"index": index,
"icon": icon.resource_path,
"metadata": metadata,
"tooltip": tooltip,
"parent_dir": get_parent_directory()
},
"\t",
false
)
func get_parent_directory() -> String:
return (metadata.get_base_dir() as String).split("/")[-1]
func _sort_by_item_text(a: ResourceListItem, b: ResourceListItem) -> bool:
return a.text < b.text
#endregion
#region INTERACTING WITH RESOURCES
func _on_resources_tree_item_activated() -> void:
if resource_tree.get_selected() == null:
return
var item := resource_tree.get_selected()
if item.get_metadata(0) == null:
return
edit_resource(item.get_metadata(0))
func _on_resources_tree_item_clicked(_pos: Vector2, mouse_button_index: int) -> void:
match mouse_button_index:
MOUSE_BUTTON_LEFT:
var selected_item := resource_tree.get_selected()
if selected_item == null:
return
if selected_item.get_metadata(0) == null:
return
var resource_item := load(selected_item.get_metadata(0))
call_deferred("edit_resource", resource_item)
MOUSE_BUTTON_MIDDLE:
remove_item_from_list(resource_tree.get_selected())
MOUSE_BUTTON_RIGHT:
if resource_tree.get_selected().get_metadata(0):
%RightClickMenu.popup_on_parent(Rect2(get_global_mouse_position(), Vector2()))
%RightClickMenu.set_meta("item_clicked", resource_tree.get_selected())
func _on_resources_tree_item_collapsed(item:TreeItem) -> void:
var collapsed_info := DialogicUtil.get_editor_setting("resource_list_collapsed_info", [])
if item.get_text(0) in collapsed_info:
if not item.collapsed:
collapsed_info.erase(item.get_text(0))
else:
if item.collapsed:
collapsed_info.append(item.get_text(0))
DialogicUtil.set_editor_setting("resource_list_collapsed_info", collapsed_info)
func edit_resource(resource_item: Variant) -> void:
if resource_item is Resource:
editors_manager.edit_resource(resource_item)
else:
editors_manager.edit_resource(load(resource_item))
func remove_item_from_list(item: TreeItem) -> void:
var new_list := []
for entry in DialogicUtil.get_editor_setting("last_resources", []):
if entry != item.get_metadata(0):
new_list.append(entry)
DialogicUtil.set_editor_setting("last_resources", new_list)
update_resource_list(new_list)
func _on_right_click_menu_id_pressed(id: int) -> void:
match id:
1: # REMOVE ITEM FROM LIST
remove_item_from_list(%RightClickMenu.get_meta("item_clicked"))
2: # OPEN IN FILESYSTEM
EditorInterface.get_file_system_dock().navigate_to_path(
%RightClickMenu.get_meta("item_clicked").get_metadata(0)
)
3: # OPEN IN EXTERNAL EDITOR
OS.shell_open(
ProjectSettings.globalize_path(
%RightClickMenu.get_meta("item_clicked").get_metadata(0)
)
)
4: # COPY IDENTIFIER
DisplayServer.clipboard_set(
DialogicResourceUtil.get_unique_identifier(
%RightClickMenu.get_meta("item_clicked").get_metadata(0)
)
)
#endregion
#region FILTERING
func _on_search_text_changed(_new_text: String) -> void:
update_resource_list()
for item in resource_tree.get_root().get_children():
if item.get_children().size() > 0:
resource_tree.set_selected(item.get_child(0), 0)
break
func _on_search_text_submitted(_new_text: String) -> void:
if resource_tree.get_selected() == null:
return
var item := resource_tree.get_selected()
if item.get_metadata(0) == null:
return
edit_resource(item.get_metadata(0))
%Search.clear()
#endregion
#region CONTENT LIST
func update_content_list(list: PackedStringArray) -> void:
var prev_selected := ""
if %ContentList.is_anything_selected():
prev_selected = %ContentList.get_item_text(%ContentList.get_selected_items()[0])
%ContentList.clear()
%ContentList.add_item("~ Top")
for i in list:
if i.is_empty():
continue
%ContentList.add_item(i)
if i == prev_selected:
%ContentList.select(%ContentList.item_count - 1)
if list.is_empty():
return
var current_resource: Resource = editors_manager.get_current_editor().current_resource
var timeline_directory := DialogicResourceUtil.get_timeline_directory()
var label_directory := DialogicResourceUtil.get_label_cache()
if current_resource != null:
for i in timeline_directory:
if timeline_directory[i] == current_resource.resource_path:
label_directory[i] = list
# also always store the current timelines labels for easy access
label_directory[""] = list
DialogicResourceUtil.set_label_cache(label_directory)
#endregion
#region RESOURCE LIST OPTIONS
func _on_options_pressed() -> void:
%OptionsPopup.popup_on_parent(Rect2(%Options.global_position+%Options.size*Vector2(0,1), Vector2()))
func _on_grouping_changed(idx: int) -> void:
var id: int = %GroupingOptions.get_item_id(idx)
if (GroupMode as Dictionary).values().has(id):
group_mode = (id as GroupMode)
DialogicUtil.set_editor_setting("sidebar_group_mode", id)
update_resource_list()
%FolderColors.disabled = group_mode != GroupMode.PATH
%TrimFolderPaths.disabled = group_mode != GroupMode.PATH
func _on_folder_colors_toggled(toggled_on: bool) -> void:
DialogicUtil.set_editor_setting("sidebar_use_folder_colors", toggled_on)
update_resource_list()
func _on_trim_folder_paths_toggled(toggled_on: bool) -> void:
DialogicUtil.set_editor_setting("sidebar_trim_folder_paths", toggled_on)
update_resource_list()
#endregion
func _on_main_v_split_dragged(offset: int) -> void:
DialogicUtil.set_editor_setting("sidebar_v_split", offset)

View File

@@ -0,0 +1 @@
uid://bbsxh24r01ali

View File

@@ -0,0 +1,49 @@
@tool
extends HBoxContainer
# Dialogic Editor toolbar. Works together with editors_mangager.
################################################################################
## EDITOR BUTTONS/LABELS
################################################################################
func _ready() -> void:
if owner.get_parent() is SubViewport:
return
%CustomButtons.custom_minimum_size.y = 33 * DialogicUtil.get_editor_scale()
for child in get_children():
if child is Button:
child.queue_free()
func add_icon_button(icon: Texture, tooltip: String) -> Button:
var button := Button.new()
button.icon = icon
button.tooltip_text = tooltip
button.flat = true
button.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
button.add_theme_color_override('icon_hover_color', get_theme_color('warning_color', 'Editor'))
button.add_theme_stylebox_override('focus', StyleBoxEmpty.new())
add_child(button)
move_child(button, -2)
return button
func add_custom_button(label:String, icon:Texture) -> Button:
var button := Button.new()
button.text = label
button.icon = icon
# button.flat = true
button.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
%CustomButtons.add_child(button)
# custom_minimum_size.y = button.size.y
return button
func hide_all_custom_buttons() -> void:
for button in %CustomButtons.get_children():
button.hide()

View File

@@ -0,0 +1 @@
uid://btsx2sqodaqns

View File

@@ -0,0 +1,95 @@
@tool
extends PanelContainer
func _ready() -> void:
if owner.get_parent() is SubViewport:
return
%TabB.text = "Unique Identifiers"
%TabB.icon = get_theme_icon("CryptoKey", "EditorIcons")
owner.get_parent().visibility_changed.connect(func(): if is_visible_in_tree(): open())
%RenameNotification.add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"))
func open() -> void:
fill_table()
%RenameNotification.hide()
func close() -> void:
pass
func fill_table() -> void:
var t: Tree = %IdentifierTable
t.set_column_expand(1, true)
t.clear()
t.set_column_title(1, "Identifier")
t.set_column_title(0, "Resource Path")
t.set_column_title_alignment(0, 0)
t.set_column_title_alignment(1, 0)
t.create_item()
for d in [["Characters", 'dch'], ["Timelines", "dtl"]]:
var directory := DialogicResourceUtil.get_directory(d[1])
var directory_item := t.create_item()
directory_item.set_text(0, d[0])
directory_item.set_metadata(0, d[1])
for key in directory:
var item: TreeItem = t.create_item(directory_item)
item.set_text(0, directory[key])
item.set_text(1, key)
item.set_editable(1, true)
item.set_metadata(1, key)
item.add_button(1, get_theme_icon("Edit", "EditorIcons"), 0, false, "Edit")
func _on_identifier_table_item_edited() -> void:
var item: TreeItem = %IdentifierTable.get_edited()
var new_identifier: String = item.get_text(1)
if new_identifier == item.get_metadata(1):
return
if new_identifier.is_empty() or not DialogicResourceUtil.is_identifier_unused(item.get_parent().get_metadata(0), new_identifier):
item.set_text(1, item.get_metadata(1))
return
DialogicResourceUtil.change_unique_identifier(item.get_text(0), new_identifier)
match item.get_parent().get_metadata(0):
'dch':
owner.get_parent().add_character_name_ref_change(item.get_metadata(1), new_identifier)
'dtl':
owner.get_parent().add_timeline_name_ref_change(item.get_metadata(1), new_identifier)
%RenameNotification.show()
item.set_metadata(1, new_identifier)
func _on_identifier_table_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void:
item.select(column)
%IdentifierTable.edit_selected(true)
func filter_tree(filter:String= "", item:TreeItem = null) -> bool:
if item == null:
item = %IdentifierTable.get_root()
var any := false
for child in item.get_children():
if child.get_child_count() > 0:
child.visible = filter_tree(filter, child)
if child.visible: any = true
else:
child.visible = filter.is_empty() or filter.to_lower() in child.get_text(0).to_lower() or filter.to_lower() in child.get_text(1).to_lower()
if child.visible: any = true
return any
func _on_search_text_changed(new_text: String) -> void:
filter_tree(new_text)

View File

@@ -0,0 +1 @@
uid://cua4voas2kcfm

View File

@@ -0,0 +1,180 @@
@tool
extends Control
var current_info := {}
@onready var editor_view := find_parent('EditorView')
func _ready() -> void:
await editor_view.ready
theme = editor_view.theme
%Install.icon = editor_view.get_theme_icon("AssetLib", "EditorIcons")
%LoadingIcon.texture = editor_view.get_theme_icon("KeyTrackScale", "EditorIcons")
%InstallWarning.modulate = editor_view.get_theme_color("warning_color", "Editor")
%CloseButton.icon = editor_view.get_theme_icon("Close", "EditorIcons")
DialogicUtil.get_dialogic_plugin().get_editor_interface().get_resource_filesystem().resources_reimported.connect(_on_resources_reimported)
func open() -> void:
get_parent().popup_centered_ratio(0.5)
get_parent().mode = Window.MODE_WINDOWED
get_parent().move_to_foreground()
get_parent().grab_focus()
func load_info(info:Dictionary, update_type:int) -> void:
current_info = info
if update_type == 2:
%State.text = "No Information Available"
%UpdateName.text = "Unable to access versions."
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("readonly_color", "Editor"))
%Content.text = "You are probably not connected to the internet. Fair enough."
%ShortInfo.text = "Huh, what happened here?"
%ReadFull.hide()
%Install.disabled = true
return
# If we are up to date (or beyond):
if info.is_empty():
info['name'] = "You are in the future, Marty!"
info["body"] = "# 😎 You are using the WIP branch!\nSeems like you are using a version that isn't even released yet. Be careful and give us your feedback ;)"
info["published_at"] = "????T"
info["author"] = {'login':"???"}
%State.text = "Where are we Doc?"
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("property_color_z", "Editor"))
%Install.disabled = true
elif update_type == 0:
%State.text = "Update Available!"
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("warning_color", "Editor"))
%Install.disabled = false
else:
%State.text = "You are up to date:"
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("success_color", "Editor"))
%Install.disabled = true
%UpdateName.text = info.name
%Content.text = markdown_to_bbcode(info.body).get_slice("\n[font_size", 0).strip_edges()
%ShortInfo.text = "Published on "+info.published_at.substr(0, info.published_at.find('T'))+" by "+info.author.login
if info.has("html_url"):
%ReadFull.uri = info.html_url
%ReadFull.show()
else:
%ReadFull.hide()
if info.has('reactions'):
%Reactions.show()
var reactions := {"laugh":"😂", "hooray":"🎉", "confused":"😕", "heart":"❤️", "rocket":"🚀", "eyes":"👀"}
for i in reactions:
%Reactions.get_node(i.capitalize()).visible = info.reactions[i] > 0
%Reactions.get_node(i.capitalize()).text = reactions[i]+" "+str(info.reactions[i]) if info.reactions[i] > 0 else reactions[i]
if info.reactions['+1']+info.reactions['-1'] > 0:
%Reactions.get_node("Likes").visible = true
%Reactions.get_node("Likes").text = "👍 "+str(info.reactions['+1']+info.reactions['-1'])
else:
%Reactions.get_node("Likes").visible = false
else:
%Reactions.hide()
func _on_window_close_requested() -> void:
get_parent().visible = false
func _on_install_pressed() -> void:
find_parent('UpdateManager').request_update_download()
%InfoLabel.text = "Downloading. This can take a moment."
%Loading.show()
%LoadingIcon.create_tween().set_loops().tween_property(%LoadingIcon, 'rotation', 2*PI, 1).from(0)
func _on_refresh_pressed() -> void:
find_parent('UpdateManager').request_update_check()
func _on_update_manager_downdload_completed(result:int):
%Loading.hide()
match result:
0: # success
%InfoLabel.text = "Installed successfully. Restart needed!"
%InfoLabel.modulate = editor_view.get_theme_color("success_color", "Editor")
%Restart.show()
%Restart.grab_focus()
1: # failure
%InfoLabel.text = "Download failed."
%InfoLabel.modulate = editor_view.get_theme_color("readonly_color", "Editor")
func _on_resources_reimported(resources:Array) -> void:
if is_inside_tree():
await get_tree().process_frame
get_parent().move_to_foreground()
func markdown_to_bbcode(text:String) -> String:
var font_sizes := {1:20, 2:16, 3:16,4:14, 5:14}
var title_regex := RegEx.create_from_string('(^|\n)((?<level>#+)(?<title>.*))\\n')
var res := title_regex.search(text)
while res:
text = text.replace(res.get_string(2), '[font_size='+str(font_sizes[len(res.get_string('level'))])+']'+res.get_string('title').strip_edges()+'[/font_size]')
res = title_regex.search(text)
var link_regex := RegEx.create_from_string('(?<!\\!)\\[(?<text>[^\\]]*)]\\((?<link>[^)]*)\\)')
res = link_regex.search(text)
while res:
text = text.replace(res.get_string(), '[url='+res.get_string('link')+']'+res.get_string('text').strip_edges()+'[/url]')
res = link_regex.search(text)
var image_regex := RegEx.create_from_string('\\!\\[(?<text>[^\\]]*)]\\((?<link>[^)]*)\\)\n*')
res = image_regex.search(text)
while res:
text = text.replace(res.get_string(), '[url='+res.get_string('link')+']'+res.get_string('text').strip_edges()+'[/url]')
res = image_regex.search(text)
var italics_regex := RegEx.create_from_string('\\*(?<text>[^\\*\\n]*)\\*')
res = italics_regex.search(text)
while res:
text = text.replace(res.get_string(), '[i]'+res.get_string('text').strip_edges()+'[/i]')
res = italics_regex.search(text)
var bullets_regex := RegEx.create_from_string('(?<=\\n)(\\*|-)(?<text>[^\\*\\n]*)\\n')
res = bullets_regex.search(text)
while res:
text = text.replace(res.get_string(), '[ul]'+res.get_string('text').strip_edges()+'[/ul]\n')
res = bullets_regex.search(text)
var small_code_regex := RegEx.create_from_string('(?<!`)`(?<text>[^`]+)`')
res = small_code_regex.search(text)
while res:
text = text.replace(res.get_string(), '[code][color='+get_theme_color("accent_color", "Editor").to_html()+']'+res.get_string('text').strip_edges()+'[/color][/code]')
res = small_code_regex.search(text)
var big_code_regex := RegEx.create_from_string('(?<!`)```(?<text>[^`]+)```')
res = big_code_regex.search(text)
while res:
text = text.replace(res.get_string(), '[code][bgcolor='+get_theme_color("box_selection_fill_color", "Editor").to_html()+']'+res.get_string('text').strip_edges()+'[/bgcolor][/code]')
res = big_code_regex.search(text)
return text
func _on_content_meta_clicked(meta:Variant) -> void:
OS.shell_open(str(meta))
func _on_install_mouse_entered() -> void:
if not %Install.disabled:
%InstallWarning.show()
func _on_install_mouse_exited() -> void:
%InstallWarning.hide()
func _on_restart_pressed() -> void:
DialogicUtil.get_dialogic_plugin().get_editor_interface().restart_editor(true)
func _on_close_button_pressed() -> void:
get_parent().hide()

View File

@@ -0,0 +1 @@
uid://bdjggd3qpyo6l

View File

@@ -0,0 +1,308 @@
[gd_scene load_steps=9 format=3 uid="uid://vv3m5m68fwg7"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/update_install_window.gd" id="1_p1pbx"]
[ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="2_20ke0"]
[sub_resource type="Gradient" id="Gradient_lt7uf"]
colors = PackedColorArray(0.296484, 0.648457, 1, 1, 0.732014, 0.389374, 1, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_nl8ke"]
gradient = SubResource("Gradient_lt7uf")
fill_from = Vector2(0.151515, 0.272727)
fill_to = Vector2(1, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1g1am"]
content_margin_left = 0.0
content_margin_top = 15.0
content_margin_right = 15.0
content_margin_bottom = 15.0
bg_color = Color(0.0627451, 0.0627451, 0.0627451, 0.407843)
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
expand_margin_left = 20.0
expand_margin_right = 20.0
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_j1mw2"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h4v2s"]
content_margin_left = 5.0
content_margin_top = 3.0
content_margin_right = 5.0
content_margin_bottom = 3.0
bg_color = Color(0, 0, 0, 0.631373)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_utju1"]
content_margin_left = 5.0
content_margin_top = 3.0
content_margin_right = 5.0
content_margin_bottom = 3.0
bg_color = Color(0.0470588, 0.0470588, 0.0470588, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[node name="UpdateInstallWindow" type="ColorRect"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.207843, 0.129412, 0.372549, 1)
script = ExtResource("1_p1pbx")
[node name="TextureRect" type="TextureRect" parent="."]
modulate = Color(0.447059, 0.447059, 0.447059, 1)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture2D_nl8ke")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 14.0
offset_top = 13.0
offset_right = -14.0
offset_bottom = -13.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 7
[node name="VBox" type="VBoxContainer" parent="VBoxContainer/HBoxContainer2"]
custom_minimum_size = Vector2(450, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 3.74
alignment = 1
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/HBoxContainer2/VBox"]
clip_contents = false
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 1
[node name="Panel" type="PanelContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_1g1am")
[node name="VBox" type="VBoxContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel"]
layout_mode = 2
theme_override_constants/separation = -8
[node name="State" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel/VBox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicSubTitle"
text = "Update Available!"
[node name="UpdateName" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel/VBox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicTitle"
theme_override_font_sizes/font_size = 25
text = "Dialogic 2.0 - alpha 9"
uppercase = true
[node name="ShortInfo" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel/VBox"]
unique_name_in_owner = true
layout_mode = 2
theme_type_variation = &"DialogicHintText2"
theme_override_font_sizes/font_size = 10
text = "12/31/23"
[node name="Refresh" type="Button" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 0
text = "Refresh
"
flat = true
[node name="Content" type="RichTextLabel" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/normal_font_size = 14
theme_override_styles/normal = SubResource("StyleBoxEmpty_j1mw2")
bbcode_enabled = true
text = "[font_size=25]🎉 New alpha, new stuff![/font_size]
If you are using dialogic 2 alphas then we've got an exciting update. It's not the beta yet, but we are getting closer! As always if you have questions or feedback it's best to reach out on [url=https://discord.gg/2hHQzkf2pX]emilios discord[/url].
This alpha brings a couple of very useful new features to dialogic as well as some syntax changes and a design overhaul (and many, many bug fixes).
"
fit_content = true
[node name="Reactions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
[node name="Likes" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "👍12"
[node name="Hooray" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "🎉12"
[node name="Laugh" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "👀12"
[node name="Heart" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "❤12"
[node name="Rocket" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "😕12"
[node name="Eyes" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "🚀12"
[node name="Confused" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_h4v2s")
text = "😂12"
[node name="ReadFull" type="LinkButton" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Reactions"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
text = "Read Full Announcement"
[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 20)
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer"]
layout_mode = 2
alignment = 2
[node name="InfoLabel" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
horizontal_alignment = 2
autowrap_mode = 3
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer"]
self_modulate = Color(0, 0, 0, 1)
layout_mode = 2
size_flags_horizontal = 4
theme_override_styles/panel = SubResource("StyleBoxFlat_h4v2s")
[node name="HBox" type="HBoxContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer"]
layout_mode = 2
alignment = 2
[node name="Loading" type="CenterContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(30, 0)
layout_mode = 2
[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Loading"]
layout_mode = 2
[node name="LoadingIcon" type="Sprite2D" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Loading/Control"]
unique_name_in_owner = true
texture = ExtResource("2_20ke0")
[node name="Restart" type="Button" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_vertical = 4
text = "Restart Now"
flat = true
[node name="Install" type="Button" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 4
text = "Install"
flat = true
[node name="InstallWarning" type="PanelContainer" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Install"]
unique_name_in_owner = true
visible = false
self_modulate = Color(0, 0, 0, 1)
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -493.0
offset_top = -92.0
offset_right = 5.0
offset_bottom = -8.0
grow_horizontal = 0
theme_override_styles/panel = SubResource("StyleBoxFlat_utju1")
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Install/InstallWarning"]
layout_mode = 2
theme_override_font_sizes/font_size = 14
text = "Be careful. This will delete the addons/dialogic folder and install the new version. Any custom changes in that folder will be lost.
To be on the save side, use version control!"
autowrap_mode = 3
[node name="Control2" type="Control" parent="VBoxContainer/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 7
[node name="Close" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
alignment = 1
[node name="CloseButton" type="Button" parent="VBoxContainer/Close"]
unique_name_in_owner = true
layout_mode = 2
text = "Close"
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Panel/Refresh" to="." method="_on_refresh_pressed"]
[connection signal="meta_clicked" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/Content" to="." method="_on_content_meta_clicked"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Restart" to="." method="_on_restart_pressed"]
[connection signal="mouse_entered" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Install" to="." method="_on_install_mouse_entered"]
[connection signal="mouse_exited" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Install" to="." method="_on_install_mouse_exited"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/VBox/ScrollContainer/VBoxContainer/HBoxContainer/PanelContainer/HBox/Install" to="." method="_on_install_pressed"]
[connection signal="pressed" from="VBoxContainer/Close/CloseButton" to="." method="_on_close_button_pressed"]

View File

@@ -0,0 +1,190 @@
@tool
extends Node
## Script that checks for new versions and can install them.
signal update_check_completed(result:UpdateCheckResult)
signal downdload_completed(result:DownloadResult)
enum UpdateCheckResult {UPDATE_AVAILABLE, UP_TO_DATE, NO_ACCESS}
enum DownloadResult {SUCCESS, FAILURE}
enum ReleaseState {ALPHA, BETA, STABLE}
const REMOTE_RELEASES_URL := "https://api.github.com/repos/dialogic-godot/dialogic/releases"
const TEMP_FILE_NAME := "user://temp.zip"
var current_version := ""
var update_info: Dictionary
var current_info: Dictionary
var version_indicator: Button
func _ready() -> void:
request_update_check()
setup_version_indicator()
func get_current_version() -> String:
var plugin_cfg := ConfigFile.new()
plugin_cfg.load("res://addons/dialogic/plugin.cfg")
return plugin_cfg.get_value('plugin', 'version', 'unknown version')
func request_update_check() -> void:
if $UpdateCheckRequest.get_http_client_status() == HTTPClient.STATUS_DISCONNECTED:
$UpdateCheckRequest.request(REMOTE_RELEASES_URL)
func _on_UpdateCheck_request_completed(result:int, response_code:int, headers:PackedStringArray, body:PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
update_check_completed.emit(UpdateCheckResult.NO_ACCESS)
return
# Work out the next version from the releases information on GitHub
var response: Variant = JSON.parse_string(body.get_string_from_utf8())
if typeof(response) != TYPE_ARRAY: return
var current_release_info := get_release_tag_info(get_current_version())
# GitHub releases are in order of creation, not order of version
var versions: Array = (response as Array).filter(compare_versions.bind(current_release_info))
if versions.size() > 0:
update_info = versions[0]
update_check_completed.emit(UpdateCheckResult.UPDATE_AVAILABLE)
else:
update_info = current_info
update_check_completed.emit(UpdateCheckResult.UP_TO_DATE)
func compare_versions(release, current_release_info:Dictionary) -> bool:
var checked_release_info := get_release_tag_info(release.tag_name)
if checked_release_info.major < current_release_info.major:
return false
if checked_release_info.minor < current_release_info.minor:
return false
if checked_release_info.state < current_release_info.state:
return false
elif checked_release_info.state == current_release_info.state:
if checked_release_info.state_version < current_release_info.state_version:
return false
if checked_release_info.state_version == current_release_info.state_version:
current_info = release
return false
if checked_release_info.state == ReleaseState.STABLE:
if checked_release_info.minor == current_release_info.minor:
current_info = release
return false
return true
func get_release_tag_info(release_tag:String) -> Dictionary:
release_tag = release_tag.strip_edges().trim_prefix('v')
release_tag = release_tag.substr(0, release_tag.find('('))
release_tag = release_tag.to_lower()
var regex := RegEx.create_from_string(r"(?<major>\d+\.\d+)(-(?<state>alpha|beta)-)?(?(2)(?<stateversion>\d*)|\.(?<minor>\d*))?")
var result: RegExMatch = regex.search(release_tag)
if !result:
return {}
var info: Dictionary = {'tag':release_tag}
info['major'] = float(result.get_string('major'))
info['minor'] = int(result.get_string('minor'))
match result.get_string('state'):
'alpha':
info['state'] = ReleaseState.ALPHA
'beta':
info['state'] = ReleaseState.BETA
_:
info['state'] = ReleaseState.STABLE
info['state_version'] = int(result.get_string('stateversion'))
return info
func request_update_download() -> void:
# Safeguard the actual dialogue manager repo from accidentally updating itself
if DirAccess.dir_exists_absolute("res://test-project/"):
prints("[Dialogic] Looks like you are working on the addon. You can't update the addon from within itself.")
downdload_completed.emit(DownloadResult.FAILURE)
return
$DownloadRequest.request(update_info.zipball_url)
func _on_DownloadRequest_completed(result:int, response_code:int, headers:PackedStringArray, body:PackedByteArray):
if result != HTTPRequest.RESULT_SUCCESS:
downdload_completed.emit(DownloadResult.FAILURE)
return
# Save the downloaded zip
var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
zip_file.store_buffer(body)
zip_file.close()
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogic"))
var zip_reader: ZIPReader = ZIPReader.new()
zip_reader.open(TEMP_FILE_NAME)
var files: PackedStringArray = zip_reader.get_files()
var base_path: String = files[0].path_join('addons/')
for path in files:
if not "dialogic/" in path:
continue
var new_file_path: String = path.replace(base_path, "")
if path.ends_with("/"):
DirAccess.make_dir_recursive_absolute("res://addons/".path_join(new_file_path))
else:
var file: FileAccess = FileAccess.open("res://addons/".path_join(new_file_path), FileAccess.WRITE)
file.store_buffer(zip_reader.read_file(path))
zip_reader.close()
DirAccess.remove_absolute(TEMP_FILE_NAME)
downdload_completed.emit(DownloadResult.SUCCESS)
###################### SOME UI MANAGEMENT #####################################
################################################################################
func setup_version_indicator() -> void:
version_indicator = %Sidebar.get_node('%CurrentVersion')
version_indicator.pressed.connect($Window/UpdateInstallWindow.open)
version_indicator.text = get_current_version()
func _on_update_check_completed(result:int):
var result_color: Color
match result:
UpdateCheckResult.UPDATE_AVAILABLE:
result_color = version_indicator.get_theme_color("warning_color", "Editor")
version_indicator.icon = version_indicator.get_theme_icon("StatusWarning", "EditorIcons")
$Window/UpdateInstallWindow.load_info(update_info, result)
UpdateCheckResult.UP_TO_DATE:
result_color = version_indicator.get_theme_color("success_color", "Editor")
version_indicator.icon = version_indicator.get_theme_icon("StatusSuccess", "EditorIcons")
$Window/UpdateInstallWindow.load_info(current_info, result)
UpdateCheckResult.NO_ACCESS:
result_color = version_indicator.get_theme_color("success_color", "Editor")
version_indicator.icon = version_indicator.get_theme_icon("GuiRadioCheckedDisabled", "EditorIcons")
$Window/UpdateInstallWindow.load_info(update_info, result)
version_indicator.add_theme_color_override('font_color', result_color)
version_indicator.add_theme_color_override('font_hover_color', result_color.lightened(0.5))
version_indicator.add_theme_color_override('font_pressed_color', result_color)
version_indicator.add_theme_color_override('font_focus_color', result_color)

View File

@@ -0,0 +1 @@
uid://d0tnm3fgvf0kb

View File

@@ -0,0 +1,85 @@
@tool
extends Control
## A scene shown at the end of events that contain other events
var resource: DialogicEndBranchEvent
# References
var parent_node: Control = null
var end_control: Control = null
# Indent
var indent_size := 22
var current_indent_level := 1
var selected := false
func _ready() -> void:
$Icon.icon = get_theme_icon("GuiSpinboxUpdown", "EditorIcons")
$Spacer.custom_minimum_size.x = 90 * DialogicUtil.get_editor_scale()
visual_deselect()
parent_node_changed()
## Called by the visual timeline editor
func visual_select() -> void:
modulate = get_theme_color("highlighted_font_color", "Editor")
selected = true
## Called by the visual timeline editor
func visual_deselect() -> void:
if !parent_node:return
selected = false
modulate = parent_node.resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.3)
func is_selected() -> bool:
return selected
## Called by the visual timeline editor
func highlight() -> void:
if !parent_node:return
modulate = parent_node.resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.6)
## Called by the visual timeline editor
func unhighlight() -> void:
modulate = parent_node.resource.event_color
func update_hidden_events_indicator(hidden_events_count:int = 0) -> void:
$HiddenEventsLabel.visible = hidden_events_count > 0
if hidden_events_count == 1:
$HiddenEventsLabel.text = "[1 event hidden]"
else:
$HiddenEventsLabel.text = "["+str(hidden_events_count)+ " events hidden]"
## Called by the visual timeline editor
func set_indent(indent: int) -> void:
$Indent.custom_minimum_size = Vector2(indent_size * indent * DialogicUtil.get_editor_scale(), 0)
$Indent.visible = indent != 0
current_indent_level = indent
queue_redraw()
## Called by the visual timeline editor if something was edited on the parent event block
func parent_node_changed() -> void:
if parent_node and end_control and end_control.has_method('refresh'):
end_control.refresh()
## Called on creation if the parent event provides an end control
func add_end_control(control:Control) -> void:
if !control:
return
add_child(control)
control.size_flags_vertical = SIZE_SHRINK_CENTER
if "parent_resource" in control:
control.parent_resource = parent_node.resource
if control.has_method('refresh'):
control.refresh()
end_control = control

View File

@@ -0,0 +1 @@
uid://bxbe8v0ogiovk

View File

@@ -0,0 +1,48 @@
[gd_scene load_steps=4 format=3 uid="uid://de13fdeebrkcb"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/BranchEnd.gd" id="1"]
[sub_resource type="Image" id="Image_8jrl8"]
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_44ap0"]
image = SubResource("Image_8jrl8")
[node name="EndBranch" type="HBoxContainer"]
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 24.0
grow_horizontal = 2
mouse_filter = 0
script = ExtResource("1")
[node name="Indent" type="Control" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="Spacer" type="Control" parent="."]
custom_minimum_size = Vector2(90, 0)
layout_mode = 2
size_flags_vertical = 0
[node name="Icon" type="Button" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
size_flags_vertical = 4
tooltip_text = "Click and drag"
focus_mode = 0
mouse_filter = 1
icon = SubResource("ImageTexture_44ap0")
flat = true
[node name="HiddenEventsLabel" type="Label" parent="."]
visible = false
layout_mode = 2
text = "XX Events hidden"

View File

@@ -0,0 +1,420 @@
@tool
extends MarginContainer
## Scene that represents an event in the visual timeline editor.
signal content_changed()
## REFERENCES
var resource: DialogicEvent
var editor_reference
# for choice and condition
var end_node: Node = null:
get:
return end_node
set(node):
end_node = node
%ToggleChildrenVisibilityButton.visible = true if end_node else false
## FLAGS
var selected := false
# Whether the body is visible
var expanded := true
var body_was_build := false
var has_any_enabled_body_content := false
# Whether contained events (e.g. in choices) are visible
var collapsed := false
## CONSTANTS
const icon_size := 28
const indent_size := 22
## STATE
# List that stores visibility conditions
var field_list := []
var current_indent_level := 1
#region UI AND LOGIC INITIALIZATION
################################################################################
func _ready() -> void:
if get_parent() is SubViewport:
return
if not resource:
printerr("[Dialogic] Event block was added without a resource specified.")
return
initialize_ui()
initialize_logic()
func initialize_ui() -> void:
var _scale := DialogicUtil.get_editor_scale()
$PanelContainer.self_modulate = get_theme_color("accent_color", "Editor")
# Warning Icon
%Warning.texture = get_theme_icon("NodeWarning", "EditorIcons")
%Warning.size = Vector2(16 * _scale, 16 * _scale)
%Warning.position = Vector2(-5 * _scale, -10 * _scale)
# Expand Button
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldedRightArrow", "EditorIcons")
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_normal_color", get_theme_color("contrast_color_2", "Editor"))
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_hover_color", get_theme_color("accent_color", "Editor"))
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_pressed_color", get_theme_color("contrast_color_2", "Editor"))
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_hover_pressed_color", get_theme_color("accent_color", "Editor"))
%ToggleBodyVisibilityButton.add_theme_stylebox_override('hover_pressed', StyleBoxEmpty.new())
# Icon Panel
%IconPanel.tooltip_text = resource.event_name
%IconPanel.self_modulate = resource.event_color
# Event Icon
%IconTexture.texture = resource._get_icon()
%IconPanel.custom_minimum_size = Vector2(icon_size, icon_size) * _scale
%IconTexture.custom_minimum_size = %IconPanel.custom_minimum_size
var custom_style: StyleBoxFlat = %IconPanel.get_theme_stylebox('panel')
custom_style.set_corner_radius_all(5 * _scale)
# Focus Mode
set_focus_mode(1) # Allowing this node to grab focus
# Separation on the header
%Header.add_theme_constant_override("custom_constants/separation", 5 * _scale)
# Collapse Button
%ToggleChildrenVisibilityButton.toggled.connect(_on_collapse_toggled)
%ToggleChildrenVisibilityButton.icon = get_theme_icon("Collapse", "EditorIcons")
%ToggleChildrenVisibilityButton.hide()
%Body.add_theme_constant_override("margin_left", icon_size * _scale)
visual_deselect()
func initialize_logic() -> void:
resized.connect(get_parent().get_parent().queue_redraw)
resource.ui_update_needed.connect(_on_resource_ui_update_needed)
resource.ui_update_warning.connect(set_warning)
content_changed.connect(recalculate_field_visibility)
_on_ToggleBodyVisibility_toggled(resource.expand_by_default or resource.created_by_button)
#endregion
#region VISUAL METHODS
################################################################################
func visual_select() -> void:
$PanelContainer.add_theme_stylebox_override('panel', load("res://addons/dialogic/Editor/Events/styles/selected_styleboxflat.tres"))
selected = true
%IconPanel.self_modulate = resource.event_color
%IconTexture.modulate = get_theme_color("icon_saturation", "Editor")
func visual_deselect() -> void:
$PanelContainer.add_theme_stylebox_override('panel', load("res://addons/dialogic/Editor/Events/styles/unselected_stylebox.tres"))
selected = false
%IconPanel.self_modulate = resource.event_color.lerp(Color.DARK_SLATE_GRAY, 0.1)
%IconTexture.modulate = get_theme_color('font_color', 'Label')
func is_selected() -> bool:
return selected
func set_warning(text:String= "") -> void:
if !text.is_empty():
%Warning.show()
%Warning.tooltip_text = text
else:
%Warning.hide()
func set_indent(indent: int) -> void:
add_theme_constant_override("margin_left", indent_size * indent * DialogicUtil.get_editor_scale())
current_indent_level = indent
#endregion
#region EVENT FIELDS
################################################################################
var FIELD_SCENES := {
DialogicEvent.ValueType.MULTILINE_TEXT: "res://addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn",
DialogicEvent.ValueType.SINGLELINE_TEXT: "res://addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn",
DialogicEvent.ValueType.FILE: "res://addons/dialogic/Editor/Events/Fields/field_file.tscn",
DialogicEvent.ValueType.BOOL: "res://addons/dialogic/Editor/Events/Fields/field_bool_check.tscn",
DialogicEvent.ValueType.BOOL_BUTTON: "res://addons/dialogic/Editor/Events/Fields/field_bool_button.tscn",
DialogicEvent.ValueType.CONDITION: "res://addons/dialogic/Editor/Events/Fields/field_condition.tscn",
DialogicEvent.ValueType.ARRAY: "res://addons/dialogic/Editor/Events/Fields/field_array.tscn",
DialogicEvent.ValueType.DICTIONARY: "res://addons/dialogic/Editor/Events/Fields/field_dictionary.tscn",
DialogicEvent.ValueType.DYNAMIC_OPTIONS: "res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn",
DialogicEvent.ValueType.FIXED_OPTIONS : "res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn",
DialogicEvent.ValueType.NUMBER: "res://addons/dialogic/Editor/Events/Fields/field_number.tscn",
DialogicEvent.ValueType.VECTOR2: "res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn",
DialogicEvent.ValueType.VECTOR3: "res://addons/dialogic/Editor/Events/Fields/field_vector3.tscn",
DialogicEvent.ValueType.VECTOR4: "res://addons/dialogic/Editor/Events/Fields/field_vector4.tscn",
DialogicEvent.ValueType.COLOR: "res://addons/dialogic/Editor/Events/Fields/field_color.tscn",
DialogicEvent.ValueType.AUDIO_PREVIEW: "res://addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn",
}
func build_editor(build_header:bool = true, build_body:bool = false) -> void:
var current_body_container: HFlowContainer = null
if build_body and body_was_build:
build_body = false
if build_body:
if body_was_build:
return
current_body_container = HFlowContainer.new()
%BodyContent.add_child(current_body_container)
body_was_build = true
for p in resource.get_event_editor_info():
field_list.append({'node':null, 'location':p.location})
if p.has('condition'):
field_list[-1]['condition'] = p.condition
if !build_body and p.location == 1:
continue
elif !build_header and p.location == 0:
continue
### --------------------------------------------------------------------
### 1. CREATE A NODE OF THE CORRECT TYPE FOR THE PROPERTY
var editor_node: Control
### LINEBREAK
if p.name == "linebreak":
field_list.remove_at(field_list.size()-1)
if !current_body_container.get_child_count():
current_body_container.queue_free()
current_body_container = HFlowContainer.new()
%BodyContent.add_child(current_body_container)
continue
elif p.field_type in FIELD_SCENES:
editor_node = load(FIELD_SCENES[p.field_type]).instantiate()
elif p.field_type == resource.ValueType.LABEL:
editor_node = Label.new()
editor_node.text = p.display_info.text
editor_node.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
editor_node.set('custom_colors/font_color', Color("#7b7b7b"))
editor_node.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
elif p.field_type == resource.ValueType.BUTTON:
editor_node = Button.new()
editor_node.text = p.display_info.text
editor_node.tooltip_text = p.display_info.get('tooltip', '')
if typeof(p.display_info.icon) == TYPE_ARRAY:
editor_node.icon = callv('get_theme_icon', p.display_info.icon)
else:
editor_node.icon = p.display_info.icon
editor_node.flat = true
editor_node.custom_minimum_size.x = 30 * DialogicUtil.get_editor_scale()
editor_node.pressed.connect(p.display_info.callable)
## CUSTOM
elif p.field_type == resource.ValueType.CUSTOM:
if p.display_info.has('path'):
editor_node = load(p.display_info.path).instantiate()
## ELSE
else:
editor_node = Label.new()
editor_node.text = p.name
editor_node.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
field_list[-1]['node'] = editor_node
### --------------------------------------------------------------------
# Some things need to be called BEFORE the field is added to the tree
if editor_node is DialogicVisualEditorField:
editor_node.event_resource = resource
editor_node.property_name = p.name
field_list[-1]['property'] = p.name
editor_node._load_display_info(p.display_info)
var location: Control = %HeaderContent
if p.location == 1:
location = current_body_container
location.add_child(editor_node)
# Some things need to be called AFTER the field is added to the tree
if editor_node is DialogicVisualEditorField:
# Only set the value if the field is visible
#
# This prevents events with varied value types (event_setting, event_variable)
# from injecting incorrect types into hidden fields, which then throw errors
# in the console.
if p.has('condition') and not p.condition.is_empty():
if _evaluate_visibility_condition(p):
editor_node._set_value(resource.get(p.name))
else:
editor_node._set_value(resource.get(p.name))
editor_node.value_changed.connect(set_property)
editor_node.tooltip_text = p.display_info.get('tooltip', '')
# Apply autofocus
if resource.created_by_button and p.display_info.get('autofocus', false):
editor_node.call_deferred('take_autofocus')
### --------------------------------------------------------------------
### 4. ADD LEFT AND RIGHT TEXT
var left_label: Label = null
var right_label: Label = null
if !p.get('left_text', '').is_empty():
left_label = Label.new()
left_label.text = p.get('left_text')
left_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
left_label.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
location.add_child(left_label)
location.move_child(left_label, editor_node.get_index())
if !p.get('right_text', '').is_empty():
right_label = Label.new()
right_label.text = p.get('right_text')
right_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
right_label.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
location.add_child(right_label)
location.move_child(right_label, editor_node.get_index()+1)
### --------------------------------------------------------------------
### 5. REGISTER CONDITION
if p.has('condition'):
field_list[-1]['condition'] = p.condition
if left_label:
field_list.append({'node': left_label, 'condition':p.condition, 'location':p.location})
if right_label:
field_list.append({'node': right_label, 'condition':p.condition, 'location':p.location})
if build_body:
if current_body_container.get_child_count() == 0:
expanded = false
%Body.visible = false
recalculate_field_visibility()
func recalculate_field_visibility() -> void:
has_any_enabled_body_content = false
for p in field_list:
if !p.has('condition') or p.condition.is_empty():
if p.node != null:
p.node.show()
if p.location == 1:
has_any_enabled_body_content = true
else:
if _evaluate_visibility_condition(p):
if p.node != null:
if p.node.visible == false and p.has("property"):
p.node._set_value(resource.get(p.property))
p.node.show()
if p.location == 1:
has_any_enabled_body_content = true
else:
if p.node != null:
p.node.hide()
%ToggleBodyVisibilityButton.visible = has_any_enabled_body_content
func set_property(property_name:String, value:Variant) -> void:
resource.set(property_name, value)
content_changed.emit()
if end_node:
end_node.parent_node_changed()
func _evaluate_visibility_condition(p: Dictionary) -> bool:
var expr := Expression.new()
expr.parse(p.condition)
var result: bool
if expr.execute([], resource):
result = true
else:
result = false
if expr.has_execute_failed():
printerr("[Dialogic] Failed executing visibility condition for '",p.get('property', 'unnamed'),"': " + expr.get_error_text())
return result
func _on_resource_ui_update_needed() -> void:
for node_info in field_list:
if node_info.node and node_info.node.has_method('set_value'):
# Only set the value if the field is visible
#
# This prevents events with varied value types (event_setting, event_variable)
# from injecting incorrect types into hidden fields, which then throw errors
# in the console.
if node_info.has('condition') and not node_info.condition.is_empty():
if _evaluate_visibility_condition(node_info):
node_info.node.set_value(resource.get(node_info.property))
else:
node_info.node.set_value(resource.get(node_info.property))
recalculate_field_visibility()
#region SIGNALS
################################################################################
func _on_collapse_toggled(toggled:bool) -> void:
collapsed = toggled
var timeline_editor: Node = find_parent('VisualEditor')
if (timeline_editor != null):
# @todo select item and clear selection is marked as "private" in TimelineEditor.gd
# consider to make it "public" or add a public helper function
timeline_editor.indent_events()
func _on_ToggleBodyVisibility_toggled(button_pressed:bool) -> void:
if button_pressed and !body_was_build:
build_editor(false, true)
%ToggleBodyVisibilityButton.set_pressed_no_signal(button_pressed)
if button_pressed:
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldDownArrow", "EditorIcons")
else:
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldedRightArrow", "EditorIcons")
expanded = button_pressed
%Body.visible = button_pressed
if find_parent('VisualEditor') != null:
find_parent('VisualEditor').indent_events()
func _on_EventNode_gui_input(event:InputEvent) -> void:
if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1:
grab_focus() # Grab focus to avoid copy pasting text or events
if event.double_click:
if has_any_enabled_body_content:
_on_ToggleBodyVisibility_toggled(!expanded)
# For opening the context menu
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
var popup: PopupMenu = get_parent().get_parent().get_node('EventPopupMenu')
popup.current_event = self
popup.popup_on_parent(Rect2(get_global_mouse_position(),Vector2()))
if resource.help_page_path == "":
popup.set_item_disabled(2, true)
else:
popup.set_item_disabled(2, false)

View File

@@ -0,0 +1 @@
uid://dvxg2wplhkxct

View File

@@ -0,0 +1,133 @@
[gd_scene load_steps=8 format=3 uid="uid://bwaxj1n401fp4"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/EventBlock/event_block.gd" id="1"]
[ext_resource type="StyleBox" uid="uid://cl75ikyq2is7c" path="res://addons/dialogic/Editor/Events/styles/unselected_stylebox.tres" id="2_axj84"]
[ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="6"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_otutu"]
bg_color = Color(1, 1, 1, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[sub_resource type="Image" id="Image_mem38"]
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_rc1wh"]
image = SubResource("Image_mem38")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ee4ub"]
[node name="EventNode" type="MarginContainer"]
anchors_preset = 10
anchor_right = 1.0
grow_horizontal = 2
size_flags_horizontal = 3
size_flags_vertical = 9
focus_mode = 1
script = ExtResource("1")
[node name="PanelContainer" type="PanelContainer" parent="."]
self_modulate = Color(0, 0, 0, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_axj84")
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Header" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="IconPanel" type="Panel" parent="PanelContainer/VBoxContainer/Header"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
mouse_filter = 1
mouse_default_cursor_shape = 6
theme_override_styles/panel = SubResource("StyleBoxFlat_otutu")
[node name="IconTexture" type="TextureRect" parent="PanelContainer/VBoxContainer/Header/IconPanel"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("6")
expand_mode = 1
stretch_mode = 5
[node name="Warning" type="TextureRect" parent="PanelContainer/VBoxContainer/Header/IconPanel"]
unique_name_in_owner = true
visible = false
layout_mode = 0
offset_left = -5.5
offset_top = -11.0
offset_right = 12.1
offset_bottom = 6.6
texture = SubResource("ImageTexture_rc1wh")
stretch_mode = 5
[node name="HeaderContent" type="HBoxContainer" parent="PanelContainer/VBoxContainer/Header"]
unique_name_in_owner = true
layout_mode = 2
[node name="ToggleBodyVisibilityButton" type="Button" parent="PanelContainer/VBoxContainer/Header"]
unique_name_in_owner = true
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Fold/Unfold Settings"
theme_override_styles/normal = SubResource("StyleBoxEmpty_ee4ub")
theme_override_styles/hover = SubResource("StyleBoxEmpty_ee4ub")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_ee4ub")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_ee4ub")
theme_override_styles/focus = SubResource("StyleBoxEmpty_ee4ub")
toggle_mode = true
icon = SubResource("ImageTexture_rc1wh")
flat = true
[node name="ToggleChildrenVisibilityButton" type="Button" parent="PanelContainer/VBoxContainer/Header"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_horizontal = 10
tooltip_text = "Collapse Contained Events"
toggle_mode = true
icon = SubResource("ImageTexture_rc1wh")
flat = true
[node name="Body" type="MarginContainer" parent="PanelContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/margin_left = 4
[node name="BodyContent" type="VBoxContainer" parent="PanelContainer/VBoxContainer/Body"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
mouse_filter = 2
[connection signal="gui_input" from="." to="." method="_on_EventNode_gui_input"]
[connection signal="toggled" from="PanelContainer/VBoxContainer/Header/ToggleBodyVisibilityButton" to="." method="_on_ToggleBodyVisibility_toggled"]

View File

@@ -0,0 +1,22 @@
@tool
extends PopupMenu
var current_event: Node = null
func _ready() -> void:
clear()
add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), "Duplicate")
add_separator()
add_icon_item(get_theme_icon("Help", "EditorIcons"), "Documentation")
add_icon_item(get_theme_icon("CodeHighlighter", "EditorIcons"), "Open Code")
add_separator()
add_icon_item(get_theme_icon("ArrowUp", "EditorIcons"), "Move up")
add_icon_item(get_theme_icon("ArrowDown", "EditorIcons"), "Move down")
add_separator()
add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Delete")
var menu_background := StyleBoxFlat.new()
menu_background.bg_color = get_parent().get_theme_color("base_color", "Editor")
add_theme_stylebox_override('panel', menu_background)
add_theme_stylebox_override('hover', get_theme_stylebox("FocusViewport", "EditorStyles"))
add_theme_color_override('font_color_hover', get_parent().get_theme_color("accent_color", "Editor"))

View File

@@ -0,0 +1 @@
uid://dpacrygrhmjt3

View File

@@ -0,0 +1,28 @@
@tool
extends PanelContainer
## Event block field part for the Array field.
signal value_changed()
var value_field: Node
var value_type: int = -1
var current_value: Variant
func _ready() -> void:
%FlexValue.value_changed.connect(emit_signal.bind("value_changed"))
%Delete.icon = get_theme_icon("Remove", "EditorIcons")
func set_value(value:Variant):
%FlexValue.set_value(value)
func get_value() -> Variant:
return %FlexValue.current_value
func _on_delete_pressed() -> void:
queue_free()
value_changed.emit()

View File

@@ -0,0 +1 @@
uid://l73oqhxu5y82

View File

@@ -0,0 +1,39 @@
[gd_scene load_steps=5 format=3 uid="uid://ch4j2lesn1sis"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/array_part.gd" id="1"]
[ext_resource type="PackedScene" uid="uid://dl08ubinx6ugu" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.tscn" id="3_s4j7i"]
[sub_resource type="Image" id="Image_dcsrk"]
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_cpbga"]
image = SubResource("Image_dcsrk")
[node name="ArrayValue" type="PanelContainer"]
offset_left = 2.0
offset_right = 76.0
offset_bottom = 24.0
theme_type_variation = &"DialogicEventEditGroup"
script = ExtResource("1")
[node name="Value" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="FlexValue" parent="Value" instance=ExtResource("3_s4j7i")]
unique_name_in_owner = true
layout_mode = 2
[node name="Delete" type="Button" parent="Value"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Remove"
icon = SubResource("ImageTexture_cpbga")
flat = true
[connection signal="pressed" from="Value/Delete" to="." method="_on_delete_pressed"]

View File

@@ -0,0 +1,44 @@
@tool
extends PanelContainer
## Event block field part for the Dictionary field.
signal value_changed()
func set_key(value:String) -> void:
%Key.text = str(value)
func get_key() -> String:
return %Key.text
func set_value(value:Variant) -> void:
%FlexValue.set_value(value)
func get_value() -> Variant:
return %FlexValue.current_value
func _ready() -> void:
%Delete.icon = get_theme_icon("Remove", "EditorIcons")
func focus_key() -> void:
%Key.grab_focus()
func _on_key_text_changed(new_text: String) -> void:
value_changed.emit()
func _on_flex_value_value_changed() -> void:
value_changed.emit()
func _on_delete_pressed() -> void:
queue_free()
value_changed.emit()

View File

@@ -0,0 +1 @@
uid://k46spe7qsnrs

View File

@@ -0,0 +1,54 @@
[gd_scene load_steps=5 format=3 uid="uid://b27yweami3mxi"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/dictionary_part.gd" id="2_q88pg"]
[ext_resource type="PackedScene" uid="uid://dl08ubinx6ugu" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.tscn" id="3_p082d"]
[sub_resource type="Image" id="Image_dcsrk"]
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_cpbga"]
image = SubResource("Image_dcsrk")
[node name="DictionaryPart" type="PanelContainer"]
offset_left = 1.0
offset_top = -1.0
offset_right = 131.0
offset_bottom = 32.0
theme_type_variation = &"DialogicEventEditGroup"
script = ExtResource("2_q88pg")
[node name="HBox" type="HBoxContainer" parent="."]
layout_mode = 2
[node name="Key" type="LineEdit" parent="HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_type_variation = &"DialogicEventEdit"
expand_to_text_length = true
select_all_on_focus = true
[node name="Label" type="Label" parent="HBox"]
layout_mode = 2
text = ":"
[node name="FlexValue" parent="HBox" instance=ExtResource("3_p082d")]
unique_name_in_owner = true
layout_mode = 2
[node name="Delete" type="Button" parent="HBox"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Remove"
icon = SubResource("ImageTexture_cpbga")
flat = true
[connection signal="text_changed" from="HBox/Key" to="." method="_on_key_text_changed"]
[connection signal="value_changed" from="HBox/FlexValue" to="." method="_on_flex_value_value_changed"]
[connection signal="pressed" from="HBox/Delete" to="." method="_on_delete_pressed"]

View File

@@ -0,0 +1,48 @@
@tool
extends DialogicVisualEditorField
## Event block field for editing arrays.
const ArrayValue := "res://addons/dialogic/Editor/Events/Fields/array_part.tscn"
func _ready() -> void:
%Add.icon = get_theme_icon("Add", "EditorIcons")
%Add.pressed.connect(_on_AddButton_pressed)
func _set_value(value:Variant) -> void:
value = value as Array
for child in get_children():
if child != %Add:
child.queue_free()
for item in value:
var x: Node = load(ArrayValue).instantiate()
add_child(x)
x.set_value(item)
x.value_changed.connect(recalculate_values)
move_child(%Add, -1)
func _on_value_changed(value:Variant) -> void:
value_changed.emit(property_name, value)
func recalculate_values() -> void:
var arr := []
for child in get_children():
if child != %Add and !child.is_queued_for_deletion():
arr.append(child.get_value())
_on_value_changed(arr)
func _on_AddButton_pressed() -> void:
var x: Control = load(ArrayValue).instantiate()
add_child(x)
x.set_value("")
x.value_changed.connect(recalculate_values)
recalculate_values()
move_child(%Add, -1)

View File

@@ -0,0 +1 @@
uid://dktoxkoi5v3lm

View File

@@ -0,0 +1,28 @@
[gd_scene load_steps=4 format=3 uid="uid://btmy7ageqpyq1"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_array.gd" id="2"]
[sub_resource type="Image" id="Image_dcsrk"]
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_cpbga"]
image = SubResource("Image_dcsrk")
[node name="Field_Array" type="HFlowContainer"]
offset_right = 329.0
offset_bottom = 256.0
size_flags_horizontal = 3
script = ExtResource("2")
[node name="Add" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Add value"
icon = SubResource("ImageTexture_cpbga")
flat = true

View File

@@ -0,0 +1,52 @@
@tool
extends DialogicVisualEditorField
var file_path: String
func _ready() -> void:
self.pressed.connect(_on_pressed)
%AudioStreamPlayer.finished.connect(_on_finished)
#region OVERWRITES
################################################################################
## To be overwritten
func _set_value(value:Variant) -> void:
file_path = value
self.disabled = file_path.is_empty()
_stop()
#endregion
#region SIGNAL METHODS
################################################################################
func _on_pressed() -> void:
if %AudioStreamPlayer.playing:
_stop()
elif not file_path.is_empty():
_play()
func _on_finished() -> void:
_stop()
#endregion
func _stop() -> void:
%AudioStreamPlayer.stop()
%AudioStreamPlayer.stream = null
self.icon = get_theme_icon("Play", "EditorIcons")
func _play() -> void:
if ResourceLoader.exists(file_path):
%AudioStreamPlayer.stream = load(file_path)
%AudioStreamPlayer.play()
self.icon = get_theme_icon("Stop", "EditorIcons")

View File

@@ -0,0 +1 @@
uid://cj4e7ls38qk1x

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=2 format=3 uid="uid://dotvrsumm5y5c"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_audio_preview.gd" id="1_7wm54"]
[node name="Field_Audio_Preview" type="Button"]
offset_right = 8.0
offset_bottom = 8.0
flat = true
script = ExtResource("1_7wm54")
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
unique_name_in_owner = true

View File

@@ -0,0 +1,38 @@
@tool
extends DialogicVisualEditorField
## Event block field for boolean values.
#region MAIN METHODS
################################################################################
func _ready() -> void:
add_theme_color_override("icon_normal_color", get_theme_color("disabled_font_color", "Editor"))
add_theme_color_override("icon_hover_color", get_theme_color("warning_color", "Editor"))
add_theme_color_override("icon_pressed_color", get_theme_color("icon_saturation", "Editor"))
add_theme_color_override("icon_hover_pressed_color", get_theme_color("warning_color", "Editor"))
add_theme_color_override("icon_focus_color", get_theme_color("disabled_font_color", "Editor"))
self.toggled.connect(_on_value_changed)
func _load_display_info(info:Dictionary) -> void:
if info.has('editor_icon'):
if not is_inside_tree():
await ready
self.icon = callv('get_theme_icon', info.editor_icon)
else:
self.icon = info.get('icon', null)
func _set_value(value:Variant) -> void:
self.button_pressed = true if value else false
#endregion
#region SIGNAL METHODS
################################################################################
func _on_value_changed(value:bool) -> void:
value_changed.emit(property_name, value)
#endregion

View File

@@ -0,0 +1 @@
uid://dm8od5udqkx0b

View File

@@ -0,0 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://iypxcctv080u"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_bool_button.gd" id="1_t1n1f"]
[node name="Field_BoolButton" type="Button"]
theme_override_colors/icon_normal_color = Color(0, 0, 0, 1)
theme_override_colors/icon_pressed_color = Color(0, 0, 0, 1)
theme_override_colors/icon_hover_color = Color(0, 0, 0, 1)
theme_override_colors/icon_hover_pressed_color = Color(0, 0, 0, 1)
theme_override_colors/icon_focus_color = Color(0, 0, 0, 1)
toggle_mode = true
flat = true
script = ExtResource("1_t1n1f")

View File

@@ -0,0 +1,30 @@
@tool
extends DialogicVisualEditorField
## Event block field for boolean values.
#region MAIN METHODS
################################################################################
func _ready() -> void:
self.toggled.connect(_on_value_changed)
func _load_display_info(info:Dictionary) -> void:
pass
func _set_value(value:Variant) -> void:
match DialogicUtil.get_variable_value_type(value):
DialogicUtil.VarTypes.STRING:
self.button_pressed = value and not value.strip_edges() == "false"
_:
self.button_pressed = value and true
#endregion
#region SIGNAL METHODS
################################################################################
func _on_value_changed(value:bool) -> void:
value_changed.emit(property_name, value)
#endregion

View File

@@ -0,0 +1 @@
uid://dnpuarsjejd37

View File

@@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dm5hxmhyyxgq"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.gd" id="1_ckmtx"]
[node name="Field_BoolCheck" type="CheckButton"]
offset_right = 44.0
offset_bottom = 24.0
script = ExtResource("1_ckmtx")

View File

@@ -0,0 +1,30 @@
@tool
extends DialogicVisualEditorField
## Event block field for color values.
#region MAIN METHODS
################################################################################
func _ready() -> void:
self.color_changed.connect(_on_value_changed)
func _load_display_info(info:Dictionary) -> void:
self.edit_alpha = info.get("edit_alpha", true)
func _set_value(value:Variant) -> void:
if value is Color:
self.color = Color(value)
#endregion
#region SIGNAL METHODS
################################################################################
func _on_value_changed(value: Color) -> void:
value_changed.emit(property_name, value)
#endregion

View File

@@ -0,0 +1 @@
uid://cy43rgu20isih

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=2 format=3 uid="uid://4e0kjekan5e7"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_color.gd" id="1_l666a"]
[node name="Field_Color" type="ColorPickerButton"]
custom_minimum_size = Vector2(48, 0)
offset_right = 64.0
offset_bottom = 31.0
theme_type_variation = &"DialogicEventEdit"
text = " "
color = Color(1, 1, 1, 1)
script = ExtResource("1_l666a")

View File

@@ -0,0 +1,267 @@
@tool
extends DialogicVisualEditorField
## Event block field for displaying conditions in either a simple or complex way.
var _current_value1: Variant = ""
var _current_value2: Variant = ""
#region MAIN METHODS
################################################################################
func _set_value(value:Variant) -> void:
var too_complex := is_too_complex(value)
%ToggleComplex.disabled = too_complex
%ToggleComplex.button_pressed = too_complex
%ComplexEditor.visible = too_complex
%SimpleEditor.visible = !too_complex
%ComplexEditor.text = value
if not too_complex:
load_simple_editor(value)
func _autofocus() -> void:
%Value1Variable.grab_focus()
#endregion
func _ready() -> void:
for i in [%Value1Type, %Value2Type]:
i.options = [{
'label': 'String',
'icon': ["String", "EditorIcons"],
'value': 0
},{
'label': 'Number',
'icon': ["float", "EditorIcons"],
'value': 1
},{
'label': 'Variable',
'icon': load("res://addons/dialogic/Editor/Images/Pieces/variable.svg"),
'value': 2
},{
'label': 'Bool',
'icon': ["bool", "EditorIcons"],
'value': 3
},{
'label': 'Expression',
'icon': ["Variant", "EditorIcons"],
'value': 4
}]
i.symbol_only = true
i.value_changed.connect(value_type_changed.bind(i.name))
i.value_changed.connect(something_changed)
i.tooltip_text = "Change type"
for i in [%Value1Variable, %Value2Variable]:
i.get_suggestions_func = get_variable_suggestions
i.value_changed.connect(something_changed)
%Value1Number.value_changed.connect(something_changed)
%Value2Number.value_changed.connect(something_changed)
%Value1Text.value_changed.connect(something_changed)
%Value2Text.value_changed.connect(something_changed)
%Value1Bool.value_changed.connect(something_changed)
%Value2Bool.value_changed.connect(something_changed)
%ToggleComplex.icon = get_theme_icon("Enum", "EditorIcons")
%Operator.value_changed.connect(something_changed)
%Operator.options = [
{'label': '==', 'value': '=='},
{'label': '>', 'value': '>'},
{'label': '<', 'value': '<'},
{'label': '<=', 'value': '<='},
{'label': '>=', 'value': '>='},
{'label': '!=', 'value': '!='}
]
func load_simple_editor(condition_string:String) -> void:
var data := complex2simple(condition_string)
%Value1Type.set_value(get_value_type(data[0], 2))
_current_value1 = data[0]
value_type_changed('', get_value_type(data[0], 2), 'Value1')
%Operator.set_value(data[1].strip_edges())
%Value2Type.set_value(get_value_type(data[2], 0))
_current_value2 = data[2]
value_type_changed('', get_value_type(data[2], 0), 'Value2')
func value_type_changed(property:String, value_type:int, value_name:String) -> void:
value_name = value_name.trim_suffix('Type')
get_node('%'+value_name+'Variable').hide()
get_node('%'+value_name+'Text').hide()
get_node('%'+value_name+'Number').hide()
get_node('%'+value_name+'Bool').hide()
var current_val: Variant = ""
if '1' in value_name:
current_val = _current_value1
else:
current_val = _current_value2
match value_type:
0:
get_node('%'+value_name+'Text').show()
get_node('%'+value_name+'Text').set_value(trim_value(current_val, value_type))
1:
get_node('%'+value_name+'Number').show()
get_node('%'+value_name+'Number').set_value(float(current_val.strip_edges()))
2:
get_node('%'+value_name+'Variable').show()
get_node('%'+value_name+'Variable').set_value(trim_value(current_val, value_type))
3:
get_node('%'+value_name+'Bool').show()
get_node('%'+value_name+'Bool').set_value(trim_value(current_val, value_type))
4:
get_node('%'+value_name+'Text').show()
get_node('%'+value_name+'Text').set_value(str(current_val))
func get_value_type(value:String, default:int) -> int:
value = value.strip_edges()
if value.begins_with('"') and value.ends_with('"') and value.count('"')-value.count('\\"') == 2:
return 0
elif value.begins_with('{') and value.ends_with('}') and value.count('{') == 1:
return 2
elif value == "true" or value == "false":
return 3
else:
if value.is_empty():
return default
if value.is_valid_float():
return 1
else:
return 4
func prep_value(value:Variant, value_type:int) -> String:
if value != null: value = str(value)
else: value = ""
value = value.strip_edges()
match value_type:
0: return '"'+value.replace('"', '\\"')+'"'
2: return '{'+value+'}'
_: return value
func trim_value(value:Variant, value_type:int) -> String:
value = value.strip_edges()
match value_type:
0: return value.trim_prefix('"').trim_suffix('"').replace('\\"', '"')
2: return value.trim_prefix('{').trim_suffix('}')
3:
if value == "true" or (value and (typeof(value) != TYPE_STRING or value != "false")):
return "true"
else:
return "false"
_: return value
func something_changed(fake_arg1=null, fake_arg2 = null):
if %ComplexEditor.visible:
value_changed.emit(property_name, %ComplexEditor.text)
return
match %Value1Type.current_value:
0: _current_value1 = prep_value(%Value1Text.text, %Value1Type.current_value)
1: _current_value1 = str(%Value1Number.get_value())
2: _current_value1 = prep_value(%Value1Variable.current_value, %Value1Type.current_value)
3: _current_value1 = prep_value(%Value1Bool.button_pressed, %Value1Type.current_value)
_: _current_value1 = prep_value(%Value1Text.text, %Value1Type.current_value)
match %Value2Type.current_value:
0: _current_value2 = prep_value(%Value2Text.text, %Value2Type.current_value)
1: _current_value2 = str(%Value2Number.get_value())
2: _current_value2 = prep_value(%Value2Variable.current_value, %Value2Type.current_value)
3: _current_value2 = prep_value(%Value2Bool.button_pressed, %Value2Type.current_value)
_: _current_value2 = prep_value(%Value2Text.text, %Value2Type.current_value)
if event_resource:
if not %Operator.text in ['==', '!='] and get_value_type(_current_value2, 0) in [0, 3]:
event_resource.ui_update_warning.emit("This operator doesn't work with strings and booleans.")
else:
event_resource.ui_update_warning.emit("")
value_changed.emit(property_name, get_simple_condition())
func is_too_complex(condition:String) -> bool:
if condition.strip_edges().is_empty():
return false
var comparison_count: int = 0
for i in ['==', '!=', '<=', '<', '>', '>=']:
comparison_count += condition.count(i)
if comparison_count == 1:
return false
return true
## Combines the info from the simple editor fields into a string condition
func get_simple_condition() -> String:
return _current_value1 +" "+ %Operator.text +" "+ _current_value2
func complex2simple(condition:String) -> Array:
if is_too_complex(condition) or condition.strip_edges().is_empty():
return ['', '==','']
for i in ['==', '!=', '<=', '<', '>', '>=']:
if i in condition:
var cond_split := Array(condition.split(i, false))
return [cond_split[0], i, cond_split[1]]
return ['', '==','']
func _on_toggle_complex_toggled(button_pressed:bool) -> void:
if button_pressed:
%ComplexEditor.show()
%SimpleEditor.hide()
%ComplexEditor.text = get_simple_condition()
else:
if !is_too_complex(%ComplexEditor.text):
%ComplexEditor.hide()
%SimpleEditor.show()
load_simple_editor(%ComplexEditor.text)
func _on_complex_editor_text_changed(new_text:String) -> void:
%ToggleComplex.disabled = is_too_complex(%ComplexEditor.text)
something_changed()
func get_variable_suggestions(filter:String) -> Dictionary:
var suggestions := {}
var vars: Dictionary = ProjectSettings.get_setting('dialogic/variables', {})
for var_path in DialogicUtil.list_variables(vars):
suggestions[var_path] = {'value':var_path, 'editor_icon':["ClassList", "EditorIcons"]}
return suggestions
func _on_value_1_variable_value_changed(property_name: Variant, value: Variant) -> void:
var type := DialogicUtil.get_variable_type(value)
match type:
DialogicUtil.VarTypes.BOOL:
if not %Operator.text in ["==", "!="]:
%Operator.text = "=="
if get_value_type(_current_value2, 3) in [0, 1]:
%Value2Type.insert_options()
%Value2Type.index_pressed(3)
DialogicUtil.VarTypes.STRING:
if not %Operator.text in ["==", "!="]:
%Operator.text = "=="
if get_value_type(_current_value2, 0) in [1, 3]:
%Value2Type.insert_options()
%Value2Type.index_pressed(0)
DialogicUtil.VarTypes.FLOAT, DialogicUtil.VarTypes.INT:
if get_value_type(_current_value2, 1) in [0,3]:
%Value2Type.insert_options()
%Value2Type.index_pressed(1)
something_changed()

View File

@@ -0,0 +1 @@
uid://cbu4n0aj1g5tv

View File

@@ -0,0 +1,101 @@
[gd_scene load_steps=9 format=3 uid="uid://ir6334lqtuwt"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_condition.gd" id="1_owjj0"]
[ext_resource type="PackedScene" uid="uid://d3bhehatwoio" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn" id="2_f6v80"]
[ext_resource type="PackedScene" uid="uid://c0vkcehgjsjy" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn" id="3_3kfwc"]
[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="4_6q3a6"]
[ext_resource type="PackedScene" uid="uid://dm5hxmhyyxgq" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.tscn" id="5_1x02a"]
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="6_5a2xd"]
[sub_resource type="Image" id="Image_je1w7"]
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_81s3d"]
image = SubResource("Image_je1w7")
[node name="Field_Condition" type="HBoxContainer"]
offset_right = 77.0
offset_bottom = 31.0
script = ExtResource("1_owjj0")
[node name="SimpleEditor" type="HBoxContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
[node name="Value1Type" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Change type"
text = ""
[node name="Value1Text" parent="SimpleEditor" instance=ExtResource("3_3kfwc")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value1Number" parent="SimpleEditor" instance=ExtResource("4_6q3a6")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value1Bool" parent="SimpleEditor" instance=ExtResource("5_1x02a")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value1Variable" parent="SimpleEditor" instance=ExtResource("6_5a2xd")]
unique_name_in_owner = true
layout_mode = 2
placeholder_text = "Variable"
[node name="Operator" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value2Type" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Change type"
text = ""
[node name="Value2Text" parent="SimpleEditor" instance=ExtResource("3_3kfwc")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value2Number" parent="SimpleEditor" instance=ExtResource("4_6q3a6")]
unique_name_in_owner = true
layout_mode = 2
[node name="Value2Variable" parent="SimpleEditor" instance=ExtResource("6_5a2xd")]
unique_name_in_owner = true
layout_mode = 2
placeholder_text = "Variable"
[node name="Value2Bool" parent="SimpleEditor" instance=ExtResource("5_1x02a")]
unique_name_in_owner = true
layout_mode = 2
[node name="ComplexEditor" type="LineEdit" parent="."]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(150, 0)
layout_mode = 2
mouse_filter = 1
theme_type_variation = &"DialogicEventEdit"
text = "VAR.Player.Health > 20 and VAR.Counter < 3 and randi()%3 == 2"
placeholder_text = "Enter condition"
expand_to_text_length = true
[node name="ToggleComplex" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Use complex expression"
toggle_mode = true
icon = SubResource("ImageTexture_81s3d")
[connection signal="value_changed" from="SimpleEditor/Value1Variable" to="." method="_on_value_1_variable_value_changed"]
[connection signal="text_changed" from="ComplexEditor" to="." method="_on_complex_editor_text_changed"]
[connection signal="toggled" from="ToggleComplex" to="." method="_on_toggle_complex_toggled"]

View File

@@ -0,0 +1,60 @@
@tool
extends DialogicVisualEditorField
## Event block field for editing dictionaries.
const DictionaryValue = "res://addons/dialogic/Editor/Events/Fields/dictionary_part.tscn"
func _ready() -> void:
%Add.icon = get_theme_icon("Add", "EditorIcons")
func _set_value(value:Variant) -> void:
for child in get_children():
if child != %Add:
child.queue_free()
var dict: Dictionary
# attempt to take dictionary values, create a fresh one if not possible
if typeof(value) == TYPE_DICTIONARY:
dict = value
elif typeof(value) == TYPE_STRING:
if value.begins_with('{'):
var result: Variant = JSON.parse_string(value)
if result != null:
dict = result as Dictionary
var keys := dict.keys()
var values := dict.values()
for index in dict.size():
var x: Node = load(DictionaryValue).instantiate()
add_child(x)
x.set_value(values[index])
x.set_key(keys[index])
x.value_changed.connect(recalculate_values)
move_child(%Add, -1)
func _on_value_changed(value:Variant) -> void:
value_changed.emit(property_name, value)
func recalculate_values() -> void:
var dict := {}
for child in get_children():
if child != %Add and !child.is_queued_for_deletion():
dict[child.get_key()] = child.get_value()
_on_value_changed(dict)
func _on_AddButton_pressed() -> void:
var x: Control = load(DictionaryValue).instantiate()
add_child(x)
x.set_key("")
x.set_value("")
x.value_changed.connect(recalculate_values)
x.focus_key()
recalculate_values()
move_child(%Add, -1)

View File

@@ -0,0 +1 @@
uid://ce5jr72owg24n

View File

@@ -0,0 +1,28 @@
[gd_scene load_steps=4 format=3 uid="uid://c74bnmhefu72w"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_dictionary.gd" id="1_p4kmu"]
[sub_resource type="Image" id="Image_dcsrk"]
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_cpbga"]
image = SubResource("Image_dcsrk")
[node name="Field_Dictionary" type="HFlowContainer"]
size_flags_horizontal = 3
script = ExtResource("1_p4kmu")
[node name="Add" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Add key-value pair"
icon = SubResource("ImageTexture_cpbga")
flat = true
[connection signal="pressed" from="Add" to="." method="_on_AddButton_pressed"]

View File

@@ -0,0 +1,139 @@
@tool
extends DialogicVisualEditorField
## Event block field for selecting a file or directory.
#region VARIABLES
################################################################################
@export var file_filter := ""
@export var placeholder := ""
@export var file_mode: EditorFileDialog.FileMode = EditorFileDialog.FILE_MODE_OPEN_FILE
var resource_icon: Texture:
get:
return resource_icon
set(new_icon):
resource_icon = new_icon
%Icon.texture = new_icon
if new_icon == null:
%Field.theme_type_variation = ""
else:
%Field.theme_type_variation = "LineEditWithIcon"
var max_width := 200
var current_value: String
var hide_reset := false
#endregion
#region MAIN METHODS
################################################################################
func _ready() -> void:
$FocusStyle.add_theme_stylebox_override('panel', get_theme_stylebox('focus', 'DialogicEventEdit'))
%OpenButton.icon = get_theme_icon("Folder", "EditorIcons")
%OpenButton.button_down.connect(_on_OpenButton_pressed)
%ClearButton.icon = get_theme_icon("Reload", "EditorIcons")
%ClearButton.button_up.connect(clear_path)
%ClearButton.visible = !hide_reset
%Field.set_drag_forwarding(Callable(), self._can_drop_data_fw, self._drop_data_fw)
%Field.placeholder_text = placeholder
func _load_display_info(info:Dictionary) -> void:
file_filter = info.get('file_filter', '')
placeholder = info.get('placeholder', '')
resource_icon = info.get('icon', null)
await ready
if resource_icon == null and info.has('editor_icon'):
resource_icon = callv('get_theme_icon', info.editor_icon)
func _set_value(value: Variant) -> void:
current_value = value
var text: String = value
if file_mode != EditorFileDialog.FILE_MODE_OPEN_DIR:
text = value.get_file()
%Field.tooltip_text = value
if %Field.get_theme_font('font').get_string_size(
text, 0, -1,
%Field.get_theme_font_size('font_size')).x > max_width:
%Field.expand_to_text_length = false
%Field.custom_minimum_size.x = max_width
%Field.size.x = 0
else:
%Field.custom_minimum_size.x = 0
%Field.expand_to_text_length = true
if not %Field.text == text:
value_changed.emit(property_name, current_value)
%Field.text = text
%ClearButton.visible = not value.is_empty() and not hide_reset
#endregion
#region BUTTONS
################################################################################
func _on_OpenButton_pressed() -> void:
find_parent('EditorView').godot_file_dialog(_on_file_dialog_selected, file_filter, file_mode, "Open "+ property_name)
func _on_file_dialog_selected(path:String) -> void:
_set_value(path)
value_changed.emit(property_name, path)
func clear_path() -> void:
_set_value("")
value_changed.emit(property_name, "")
#endregion
#region DRAG AND DROP
################################################################################
func _can_drop_data_fw(_at_position: Vector2, data: Variant) -> bool:
if typeof(data) == TYPE_DICTIONARY and data.has('files') and len(data.files) == 1:
if file_filter:
if '*.'+data.files[0].get_extension() in file_filter:
return true
else: return true
return false
func _drop_data_fw(_at_position: Vector2, data: Variant) -> void:
var file: String = data.files[0]
_on_file_dialog_selected(file)
#endregion
#region VISUALS FOR FOCUS
################################################################################
func _on_field_focus_entered() -> void:
$FocusStyle.show()
func _on_field_focus_exited() -> void:
$FocusStyle.hide()
var field_text: String = %Field.text
_on_file_dialog_selected(field_text)
#endregion

View File

@@ -0,0 +1 @@
uid://smurqrx4p1t4

View File

@@ -0,0 +1,87 @@
[gd_scene load_steps=8 format=3 uid="uid://7mvxuaulctcq"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_file.gd" id="1_0grcf"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tr837"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wq6bt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6b7on"]
[sub_resource type="Image" id="Image_bpoe1"]
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_dkuon"]
image = SubResource("Image_bpoe1")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yv1pn"]
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="Field_File" type="MarginContainer"]
offset_right = 314.0
offset_bottom = 40.0
theme_type_variation = &"DialogicEventEdit"
script = ExtResource("1_0grcf")
[node name="BG" type="PanelContainer" parent="."]
layout_mode = 2
theme_type_variation = &"DialogicEventEdit"
[node name="HBox" type="HBoxContainer" parent="BG"]
layout_mode = 2
alignment = 2
[node name="Icon" type="TextureRect" parent="BG/HBox"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 4
mouse_filter = 2
[node name="Field" type="LineEdit" parent="BG/HBox"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 1
theme_override_styles/normal = SubResource("StyleBoxEmpty_tr837")
theme_override_styles/focus = SubResource("StyleBoxEmpty_wq6bt")
theme_override_styles/read_only = SubResource("StyleBoxEmpty_6b7on")
expand_to_text_length = true
[node name="OpenButton" type="Button" parent="BG/HBox"]
unique_name_in_owner = true
layout_mode = 2
icon = SubResource("ImageTexture_dkuon")
flat = true
[node name="ClearButton" type="Button" parent="BG/HBox"]
unique_name_in_owner = true
layout_mode = 2
icon = SubResource("ImageTexture_dkuon")
flat = true
[node name="FocusStyle" type="Panel" parent="."]
visible = false
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_yv1pn")
[connection signal="focus_entered" from="BG/HBox/Field" to="." method="_on_field_focus_entered"]
[connection signal="focus_exited" from="BG/HBox/Field" to="." method="_on_field_focus_exited"]
[connection signal="text_submitted" from="BG/HBox/Field" to="." method="_on_file_dialog_selected"]

View File

@@ -0,0 +1,154 @@
@tool
extends HBoxContainer
## Event block field part for a value that can change type.
signal value_changed
var value_field: Node
var value_type: int = -1
var current_value: Variant
func _ready() -> void:
%ValueType.options = [{
'label': 'String',
'icon': ["String", "EditorIcons"],
'value': TYPE_STRING
},{
'label': 'Number (int)',
'icon': ["int", "EditorIcons"],
'value': TYPE_INT
},{
'label': 'Number (float)',
'icon': ["float", "EditorIcons"],
'value': TYPE_FLOAT
},{
'label': 'Boolean',
'icon': ["bool", "EditorIcons"],
'value': TYPE_BOOL
},{
'label': 'Expression',
'icon': ["Variant", "EditorIcons"],
'value': TYPE_MAX
}
]
%ValueType.symbol_only = true
%ValueType.value_changed.connect(_on_type_changed.bind())
%ValueType.tooltip_text = "Change type"
func set_value(value:Variant):
change_field_type(deduce_type(value))
%ValueType.set_value(deduce_type(value))
current_value = value
match value_type:
TYPE_BOOL:
value_field.button_pressed = value
TYPE_STRING:
value_field.text = value
TYPE_FLOAT, TYPE_INT:
value_field.set_value(value)
TYPE_MAX, _:
value_field.text = value.trim_prefix('@')
func deduce_type(value:Variant) -> int:
if value is String and value.begins_with('@'):
return TYPE_MAX
else:
return typeof(value)
func _on_type_changed(prop:String, type:Variant) -> void:
if type == value_type:
return
match type:
TYPE_BOOL:
if typeof(current_value) == TYPE_STRING:
current_value = DialogicUtil.str_to_bool(current_value)
elif value_type == TYPE_FLOAT or value_type == TYPE_INT:
current_value = bool(current_value)
else:
current_value = true if current_value else false
set_value(current_value)
TYPE_STRING:
current_value = str(current_value).trim_prefix('@')
set_value(current_value)
TYPE_FLOAT:
current_value = float(current_value)
set_value(current_value)
TYPE_INT:
current_value = int(current_value)
set_value(current_value)
TYPE_MAX,_:
current_value = var_to_str(current_value)
set_value('@'+current_value)
emit_signal.call_deferred('value_changed')
func get_value() -> Variant:
return current_value
func _on_delete_pressed() -> void:
queue_free()
value_changed.emit()
func change_field_type(type:int) -> void:
if type == value_type:
return
value_type = type
if value_field:
value_field.queue_free()
match type:
TYPE_BOOL:
value_field = CheckBox.new()
value_field.toggled.connect(_on_bool_toggled)
TYPE_STRING:
value_field = LineEdit.new()
value_field.theme_type_variation = "DialogicEventEdit"
value_field.text_changed.connect(_on_str_text_changed)
value_field.expand_to_text_length = true
TYPE_FLOAT, TYPE_INT:
value_field = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate()
if type == TYPE_FLOAT:
value_field.use_float_mode()
else:
value_field.use_int_mode()
value_field.value_changed.connect(_on_number_value_changed.bind(type == TYPE_INT))
TYPE_MAX, _:
value_field = LineEdit.new()
value_field.expand_to_text_length = true
value_field.text_changed.connect(_on_expression_changed)
add_child(value_field)
move_child(value_field, 1)
func _on_bool_toggled(value:bool) -> void:
current_value = value
value_changed.emit()
func _on_str_text_changed(value:String) -> void:
current_value = value
value_changed.emit()
func _on_expression_changed(value:String) -> void:
current_value = '@'+value
value_changed.emit()
func _on_number_value_changed(prop:String, value:float, int := false) -> void:
if int:
current_value = int(value)
else:
current_value = value
value_changed.emit()

View File

@@ -0,0 +1 @@
uid://bo3recbebij1p

Some files were not shown because too many files have changed in this diff Show More