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"]