Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Character Editor Update #1380

Merged
merged 7 commits into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 225 additions & 89 deletions addons/dialogic/Editor/CharacterEditor/character_editor.gd

Large diffs are not rendered by default.

286 changes: 130 additions & 156 deletions addons/dialogic/Editor/CharacterEditor/character_editor.tscn

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ var character_editor:Control

var selected_item :TreeItem = null

func _load_portrait(data:Dictionary) -> void:
func _load_portrait_data(data:Dictionary) -> void:
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
@tool
extends Tree

## Tree that displays the portrait list as a hirarchy

var editor := find_parent('Character Editor')
var current_group_nodes := {}


func clear_tree() -> void:
clear()
current_group_nodes = {}


func add_portrait_item(portrait_name:String, portrait_data:Dictionary, parent_item:TreeItem) -> TreeItem:
var item :TreeItem = %PortraitTree.create_item(parent_item)
item.set_text(0, portrait_name)
item.set_metadata(0, portrait_data)
if portrait_name == editor.current_resource.default_portrait:
item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default')
item.add_button(0, get_theme_icon('Duplicate', 'EditorIcons'), 3, false, 'Duplicate')
item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove')
return item


func add_portrait_group(goup_name:String = "Group", parent_item:TreeItem = get_root()):
var item :TreeItem = %PortraitTree.create_item(parent_item)
item.set_icon(0, get_theme_icon("Groups", "EditorIcons"))
item.set_text(0, goup_name)
item.set_metadata(0, {'group':true})
item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove')
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) -> void:
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 := add_portrait_group(i, last_item)
current_group_nodes[item_path+"/"+i] = new_item
last_item = new_item
return last_item


################################################################################
## DRAG AND DROP
################################################################################

func _get_drag_data(position:Vector2) -> Variant:
set_drop_mode_flags(DROP_MODE_ON_ITEM)

var preview := Label.new()
preview.text = " "+get_selected().get_text(0)
preview.add_theme_stylebox_override('normal', get_theme_stylebox("Background", "EditorStyles"))
set_drag_preview(preview)

return get_selected()


func _can_drop_data(position:Vector2, data:Variant) -> bool:
return data is TreeItem


func _drop_data(position:Vector2, item:Variant) -> void:
var to_item := get_item_at_position(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 parent := get_root()
if to_item:
parent = to_item.get_parent()

if to_item and to_item.get_metadata(0).has('group'):
parent = to_item

var new_item := copy_branch_or_item(item, parent)

if to_item and !to_item.get_metadata(0).has('group'):
new_item.move_after(to_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)
else:
new_item = add_portrait_item(item.get_text(0), item.get_metadata(0), new_parent)

for child in item.get_children():
copy_branch_or_item(child, new_item)
return new_item
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
@tool
extends DialogicCharacterEditorPortraitSettingsTab

## Tab that allows setting values of exported scene variables
## for custom portrait scenes

var current_portrait_data := {}

func _ready() -> void:
get_parent().set_tab_icon(get_index(), get_theme_icon("EditInternal", "EditorIcons"))
add_theme_stylebox_override('panel', get_theme_stylebox("Background", "EditorStyles"))

func _load_portrait_data(data:Dictionary) -> void:
if data.get('scene', '').is_empty():
get_parent().set_tab_hidden(get_index(), true)
else:
get_parent().set_tab_hidden(get_index(), false)

current_portrait_data = data
load_portrait_scene_export_variables()

func load_portrait_scene_export_variables():
var scene = null
if !current_portrait_data.get('scene', '').is_empty():
scene = load(current_portrait_data.get('scene'))

if !scene:
return

for child in $Grid.get_children():
child.queue_free()

scene = scene.instantiate()
for i in scene.script.get_script_property_list():
if i['usage'] & PROPERTY_USAGE_EDITOR:
var label = Label.new()
label.text = i['name']
label.add_theme_stylebox_override('normal', get_theme_stylebox("CanvasItemInfoOverlay", "EditorStyles"))
label.size_flags_horizontal = SIZE_EXPAND_FILL
$Grid.add_child(label)


var input = null
var current_value :String = ""
if current_portrait_data.has('export_overrides') and current_portrait_data['export_overrides'].has(i['name']):
current_value = current_portrait_data['export_overrides'][i['name']]
match typeof(scene.get(i['name'])):
TYPE_BOOL:
input = CheckBox.new()
if current_value:
input.button_pressed = current_value == "true"
input.toggled.connect(_on_export_bool_submitted.bind(i['name']))
TYPE_COLOR:
input = ColorPickerButton.new()
if current_value:
input.color = str_to_var(current_value)
input.color_changed.connect(_on_export_color_submitted.bind(i['name']))
input.custom_minimum_size.x = DialogicUtil.get_editor_scale()*50
TYPE_INT:
if i['hint'] & PROPERTY_HINT_ENUM:
input = OptionButton.new()
for x in i['hint_string'].split(','):
input.add_item(x)
input.item_selected.connect(_on_export_int_enum_submitted.bind(i['name']))
_:
input = LineEdit.new()
if current_value:
input.text = current_value
input.text_submitted.connect(_on_export_input_text_submitted.bind(i['name']))
input.size_flags_horizontal = SIZE_EXPAND_FILL
$Grid.add_child(input)
if i['usage'] & PROPERTY_USAGE_GROUP:
var title := Label.new()
title.text = i['name']
title.add_theme_stylebox_override('normal', get_theme_stylebox("ContextualToolbar", "EditorStyles"))
$Grid.add_child(title)
$Grid.add_child(Control.new())

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()

func _on_export_input_text_submitted(text:String, property_name:String) -> void:
set_export_override(property_name, var_to_str(text))

func _on_export_bool_submitted(value:bool, property_name:String) -> void:
set_export_override(property_name, var_to_str(value))

func _on_export_color_submitted(color:Color, property_name:String) -> void:
set_export_override(property_name, var_to_str(color))

func _on_export_int_enum_submitted(item:int, property_name:String) -> void:
set_export_override(property_name, var_to_str(item))
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ func _ready() -> void:
func _load_portrait_data(data:Dictionary) -> void:
# hides/shows this tab based on the scene value of this portrait
# (only shown if the default scene is used)
if !data.get('scene', '').is_empty():
get_parent().set_tab_hidden(get_index(), true)
while get_parent().is_tab_hidden(get_parent().current_tab):
get_parent().current_tab = (get_parent().current_tab+1)%get_parent().get_tab_count()
else:
get_parent().set_tab_hidden(get_index(), false)
get_parent().set_tab_hidden(get_index(), !data.get('scene', '').is_empty())

%ImagePicker.set_value(data.get('image', ''))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@ func _ready() -> void:
%DisplayNameLineEdit.text_changed.connect(character_editor.something_changed)
%NicknameLineEdit.text_changed.connect(character_editor.something_changed)
%DescriptionTextEdit.text_changed.connect(character_editor.something_changed)
%DefaultPortraitPicker.value_changed.connect(default_portrait_changed)
%MainScale.value_changed.connect(main_portrait_settings_update)
%MainOffsetX.value_changed.connect(main_portrait_settings_update)
%MainOffsetY.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
%DefaultPortraitPicker.set_left_text("")


func _load_character(resource:DialogicCharacter) -> void:
Expand All @@ -32,12 +22,6 @@ func _load_character(resource:DialogicCharacter) -> void:
%NicknameLineEdit.text = %NicknameLineEdit.text.trim_suffix(', ')

%DescriptionTextEdit.text = resource.description
%DefaultPortraitPicker.set_value(resource.default_portrait)

%MainScale.value = 100*resource.scale
%MainOffsetX.value = resource.offset.x
%MainOffsetY.value = resource.offset.y
%MainMirror.button_pressed = resource.mirror


func _save_changes(resource:DialogicCharacter) -> DialogicCharacter:
Expand All @@ -49,37 +33,4 @@ func _save_changes(resource:DialogicCharacter) -> DialogicCharacter:
resource.nicknames = nicknames
resource.description = %DescriptionTextEdit.text

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 = Vector2(%MainOffsetX.value, %MainOffsetY.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


# Make sure preview get's updated when portrait settings change
func main_portrait_settings_update(value = null) -> void:
character_editor.current_resource.scale = %MainScale.value/100.0
character_editor.current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.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)

Loading