commit
699905b2ef
@ -0,0 +1,2 @@
|
|||||||
|
# Normalize EOL for all files that Git considers text files.
|
||||||
|
* text=auto eol=lf
|
@ -0,0 +1,2 @@
|
|||||||
|
# Godot 4+ specific ignores
|
||||||
|
.godot/
|
@ -0,0 +1,417 @@
|
|||||||
|
class_name DialogicGameHandler
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
## Class that is used as the Dialogic autoload.
|
||||||
|
|
||||||
|
## Autoload script that allows you to interact with all of Dialogic's systems:[br]
|
||||||
|
## - Holds all important information about the current state of Dialogic.[br]
|
||||||
|
## - Provides access to all the subsystems.[br]
|
||||||
|
## - Has methods to start/end timelines.[br]
|
||||||
|
|
||||||
|
|
||||||
|
## States indicating different phases of dialog.
|
||||||
|
enum States {
|
||||||
|
IDLE, ## Dialogic is awaiting input to advance.
|
||||||
|
REVEALING_TEXT, ## Dialogic is currently revealing text.
|
||||||
|
ANIMATING, ## Some animation is happening.
|
||||||
|
AWAITING_CHOICE, ## Dialogic awaits the selection of a choice
|
||||||
|
WAITING ## Dialogic is currently awaiting something.
|
||||||
|
}
|
||||||
|
|
||||||
|
## Flags indicating what to clear when calling [method clear].
|
||||||
|
enum ClearFlags {
|
||||||
|
FULL_CLEAR = 0, ## Clears all subsystems
|
||||||
|
KEEP_VARIABLES = 1, ## Clears all subsystems and info except for variables
|
||||||
|
TIMELINE_INFO_ONLY = 2 ## Doesn't clear subsystems but current timeline and index
|
||||||
|
}
|
||||||
|
|
||||||
|
## Reference to the currently executed timeline.
|
||||||
|
var current_timeline: DialogicTimeline = null
|
||||||
|
## Copy of the [member current_timeline]'s events.
|
||||||
|
var current_timeline_events: Array = []
|
||||||
|
|
||||||
|
## Index of the event the timeline handling is currently at.
|
||||||
|
var current_event_idx: int = 0
|
||||||
|
## Contains all information that subsystems consider relevant for
|
||||||
|
## the current situation
|
||||||
|
var current_state_info: Dictionary = {}
|
||||||
|
|
||||||
|
## Current state (see [member States] enum).
|
||||||
|
var current_state := States.IDLE:
|
||||||
|
get:
|
||||||
|
return current_state
|
||||||
|
|
||||||
|
set(new_state):
|
||||||
|
current_state = new_state
|
||||||
|
state_changed.emit(new_state)
|
||||||
|
|
||||||
|
## Emitted when [member current_state] change.
|
||||||
|
signal state_changed(new_state:States)
|
||||||
|
|
||||||
|
## When `true`, many dialogic processes won't continue until it's `false` again.
|
||||||
|
var paused := false:
|
||||||
|
set(value):
|
||||||
|
paused = value
|
||||||
|
|
||||||
|
if paused:
|
||||||
|
|
||||||
|
for subsystem in get_children():
|
||||||
|
|
||||||
|
if subsystem is DialogicSubsystem:
|
||||||
|
(subsystem as DialogicSubsystem).pause()
|
||||||
|
|
||||||
|
dialogic_paused.emit()
|
||||||
|
|
||||||
|
else:
|
||||||
|
for subsystem in get_children():
|
||||||
|
|
||||||
|
if subsystem is DialogicSubsystem:
|
||||||
|
(subsystem as DialogicSubsystem).resume()
|
||||||
|
|
||||||
|
dialogic_resumed.emit()
|
||||||
|
|
||||||
|
## Emitted when [member paused] changes to `true`.
|
||||||
|
signal dialogic_paused
|
||||||
|
## Emitted when [member paused] changes to `false`.
|
||||||
|
signal dialogic_resumed
|
||||||
|
|
||||||
|
|
||||||
|
## Emitted when the timeline ends.
|
||||||
|
## This can be a timeline ending or [method end_timeline] being called.
|
||||||
|
signal timeline_ended
|
||||||
|
## Emitted when a timeline starts by calling either [method start]
|
||||||
|
## or [method start_timeline].
|
||||||
|
signal timeline_started
|
||||||
|
## Emitted when an event starts being executed.
|
||||||
|
## The event may not have finished executing yet.
|
||||||
|
signal event_handled(resource: DialogicEvent)
|
||||||
|
|
||||||
|
## Emitted when a [class SignalEvent] event was reached.
|
||||||
|
signal signal_event(argument: Variant)
|
||||||
|
## Emitted when a signal event gets fired from a [class TextEvent] event.
|
||||||
|
signal text_signal(argument: String)
|
||||||
|
|
||||||
|
|
||||||
|
# Careful, this section is repopulated automatically at certain moments.
|
||||||
|
#region SUBSYSTEMS
|
||||||
|
|
||||||
|
var Audio := preload("res://addons/dialogic/Modules/Audio/subsystem_audio.gd").new():
|
||||||
|
get: return get_subsystem("Audio")
|
||||||
|
|
||||||
|
var Backgrounds := preload("res://addons/dialogic/Modules/Background/subsystem_backgrounds.gd").new():
|
||||||
|
get: return get_subsystem("Backgrounds")
|
||||||
|
|
||||||
|
var Portraits := preload("res://addons/dialogic/Modules/Character/subsystem_portraits.gd").new():
|
||||||
|
get: return get_subsystem("Portraits")
|
||||||
|
|
||||||
|
var Choices := preload("res://addons/dialogic/Modules/Choice/subsystem_choices.gd").new():
|
||||||
|
get: return get_subsystem("Choices")
|
||||||
|
|
||||||
|
var Expressions := preload("res://addons/dialogic/Modules/Core/subsystem_expression.gd").new():
|
||||||
|
get: return get_subsystem("Expressions")
|
||||||
|
|
||||||
|
var Animations := preload("res://addons/dialogic/Modules/Core/subsystem_animation.gd").new():
|
||||||
|
get: return get_subsystem("Animations")
|
||||||
|
|
||||||
|
var Inputs := preload("res://addons/dialogic/Modules/Core/subsystem_input.gd").new():
|
||||||
|
get: return get_subsystem("Inputs")
|
||||||
|
|
||||||
|
var Glossary := preload("res://addons/dialogic/Modules/Glossary/subsystem_glossary.gd").new():
|
||||||
|
get: return get_subsystem("Glossary")
|
||||||
|
|
||||||
|
var History := preload("res://addons/dialogic/Modules/History/subsystem_history.gd").new():
|
||||||
|
get: return get_subsystem("History")
|
||||||
|
|
||||||
|
var Jump := preload("res://addons/dialogic/Modules/Jump/subsystem_jump.gd").new():
|
||||||
|
get: return get_subsystem("Jump")
|
||||||
|
|
||||||
|
var Save := preload("res://addons/dialogic/Modules/Save/subsystem_save.gd").new():
|
||||||
|
get: return get_subsystem("Save")
|
||||||
|
|
||||||
|
var Settings := preload("res://addons/dialogic/Modules/Settings/subsystem_settings.gd").new():
|
||||||
|
get: return get_subsystem("Settings")
|
||||||
|
|
||||||
|
var Styles := preload("res://addons/dialogic/Modules/Style/subsystem_styles.gd").new():
|
||||||
|
get: return get_subsystem("Styles")
|
||||||
|
|
||||||
|
var Text := preload("res://addons/dialogic/Modules/Text/subsystem_text.gd").new():
|
||||||
|
get: return get_subsystem("Text")
|
||||||
|
|
||||||
|
var TextInput := preload("res://addons/dialogic/Modules/TextInput/subsystem_text_input.gd").new():
|
||||||
|
get: return get_subsystem("TextInput")
|
||||||
|
|
||||||
|
var VAR := preload("res://addons/dialogic/Modules/Variable/subsystem_variables.gd").new():
|
||||||
|
get: return get_subsystem("VAR")
|
||||||
|
|
||||||
|
var Voice := preload("res://addons/dialogic/Modules/Voice/subsystem_voice.gd").new():
|
||||||
|
get: return get_subsystem("Voice")
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
## Autoloads are added first, so this happens REALLY early on game startup.
|
||||||
|
func _ready() -> void:
|
||||||
|
DialogicResourceUtil.update()
|
||||||
|
|
||||||
|
_collect_subsystems()
|
||||||
|
|
||||||
|
clear()
|
||||||
|
|
||||||
|
|
||||||
|
#region TIMELINE & EVENT HANDLING
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## Method to start a timeline AND ensure that a layout scene is present.
|
||||||
|
## For argument info, checkout [method start_timeline].
|
||||||
|
## -> returns the layout node
|
||||||
|
func start(timeline:Variant, label:Variant="") -> Node:
|
||||||
|
# If we don't have a style subsystem, default to just start_timeline()
|
||||||
|
if !has_subsystem('Styles'):
|
||||||
|
printerr("[Dialogic] You called Dialogic.start() but the Styles subsystem is missing!")
|
||||||
|
clear(ClearFlags.KEEP_VARIABLES)
|
||||||
|
start_timeline(timeline, label)
|
||||||
|
return null
|
||||||
|
|
||||||
|
# Otherwise make sure there is a style active.
|
||||||
|
var scene: Node = null
|
||||||
|
if !self.Styles.has_active_layout_node():
|
||||||
|
scene = self.Styles.load_style()
|
||||||
|
else:
|
||||||
|
scene = self.Styles.get_layout_node()
|
||||||
|
scene.show()
|
||||||
|
|
||||||
|
if not scene.is_node_ready():
|
||||||
|
scene.ready.connect(clear.bind(ClearFlags.KEEP_VARIABLES))
|
||||||
|
scene.ready.connect(start_timeline.bind(timeline, label))
|
||||||
|
else:
|
||||||
|
clear(ClearFlags.KEEP_VARIABLES)
|
||||||
|
start_timeline(timeline, label)
|
||||||
|
|
||||||
|
return scene
|
||||||
|
|
||||||
|
|
||||||
|
## Method to start a timeline without adding a layout scene.
|
||||||
|
## @timeline can be either a loaded timeline resource or a path to a timeline file.
|
||||||
|
## @label_or_idx can be a label (string) or index (int) to skip to immediatly.
|
||||||
|
func start_timeline(timeline:Variant, label_or_idx:Variant = "") -> void:
|
||||||
|
# load the resource if only the path is given
|
||||||
|
if typeof(timeline) == TYPE_STRING:
|
||||||
|
#check the lookup table if it's not a full file name
|
||||||
|
if (timeline as String).contains("res://"):
|
||||||
|
timeline = load((timeline as String))
|
||||||
|
else:
|
||||||
|
timeline = DialogicResourceUtil.get_timeline_resource((timeline as String))
|
||||||
|
|
||||||
|
if timeline == null:
|
||||||
|
printerr("[Dialogic] There was an error loading this timeline. Check the filename, and the timeline for errors")
|
||||||
|
return
|
||||||
|
|
||||||
|
await (timeline as DialogicTimeline).process()
|
||||||
|
|
||||||
|
current_timeline = timeline
|
||||||
|
current_timeline_events = current_timeline.events
|
||||||
|
current_event_idx = -1
|
||||||
|
|
||||||
|
if typeof(label_or_idx) == TYPE_STRING:
|
||||||
|
if label_or_idx:
|
||||||
|
if has_subsystem('Jump'):
|
||||||
|
Jump.jump_to_label((label_or_idx as String))
|
||||||
|
elif typeof(label_or_idx) == TYPE_INT:
|
||||||
|
if label_or_idx >-1:
|
||||||
|
current_event_idx = label_or_idx -1
|
||||||
|
|
||||||
|
timeline_started.emit()
|
||||||
|
handle_next_event()
|
||||||
|
|
||||||
|
|
||||||
|
## Preloader function, prepares a timeline and returns an object to hold for later
|
||||||
|
## [param timeline_resource] can be either a path (string) or a loaded timeline (resource)
|
||||||
|
func preload_timeline(timeline_resource:Variant) -> Variant:
|
||||||
|
# I think ideally this should be on a new thread, will test
|
||||||
|
if typeof(timeline_resource) == TYPE_STRING:
|
||||||
|
timeline_resource = load((timeline_resource as String))
|
||||||
|
if timeline_resource == null:
|
||||||
|
printerr("[Dialogic] There was an error preloading this timeline. Check the filename, and the timeline for errors")
|
||||||
|
return null
|
||||||
|
|
||||||
|
await (timeline_resource as DialogicTimeline).process()
|
||||||
|
|
||||||
|
return timeline_resource
|
||||||
|
|
||||||
|
|
||||||
|
## Clears and stops the current timeline.
|
||||||
|
func end_timeline() -> void:
|
||||||
|
await clear(ClearFlags.TIMELINE_INFO_ONLY)
|
||||||
|
_on_timeline_ended()
|
||||||
|
timeline_ended.emit()
|
||||||
|
|
||||||
|
|
||||||
|
## Handles the next event.
|
||||||
|
func handle_next_event(_ignore_argument: Variant = "") -> void:
|
||||||
|
handle_event(current_event_idx+1)
|
||||||
|
|
||||||
|
|
||||||
|
## Handles the event at the given index [param event_index].
|
||||||
|
## You can call this manually, but if another event is still executing, it might have unexpected results.
|
||||||
|
func handle_event(event_index:int) -> void:
|
||||||
|
if not current_timeline:
|
||||||
|
return
|
||||||
|
|
||||||
|
if has_meta('previous_event') and get_meta('previous_event') is DialogicEvent and (get_meta('previous_event') as DialogicEvent).event_finished.is_connected(handle_next_event):
|
||||||
|
(get_meta('previous_event') as DialogicEvent).event_finished.disconnect(handle_next_event)
|
||||||
|
|
||||||
|
if paused:
|
||||||
|
await dialogic_resumed
|
||||||
|
|
||||||
|
if event_index >= len(current_timeline_events):
|
||||||
|
end_timeline()
|
||||||
|
return
|
||||||
|
|
||||||
|
#actually process the event now, since we didnt earlier at runtime
|
||||||
|
#this needs to happen before we create the copy DialogicEvent variable, so it doesn't throw an error if not ready
|
||||||
|
if current_timeline_events[event_index].event_node_ready == false:
|
||||||
|
current_timeline_events[event_index]._load_from_string(current_timeline_events[event_index].event_node_as_text)
|
||||||
|
|
||||||
|
current_event_idx = event_index
|
||||||
|
|
||||||
|
if not current_timeline_events[event_index].event_finished.is_connected(handle_next_event):
|
||||||
|
current_timeline_events[event_index].event_finished.connect(handle_next_event)
|
||||||
|
|
||||||
|
set_meta('previous_event', current_timeline_events[event_index])
|
||||||
|
|
||||||
|
current_timeline_events[event_index].execute(self)
|
||||||
|
event_handled.emit(current_timeline_events[event_index])
|
||||||
|
|
||||||
|
|
||||||
|
## Resets Dialogic's state fully or partially.
|
||||||
|
## By using the clear flags from the [member ClearFlags] enum you can specify
|
||||||
|
## what info should be kept.
|
||||||
|
## For example, at timeline end usually it doesn't clear node or subsystem info.
|
||||||
|
func clear(clear_flags := ClearFlags.FULL_CLEAR) -> void:
|
||||||
|
if !clear_flags & ClearFlags.TIMELINE_INFO_ONLY:
|
||||||
|
for subsystem in get_children():
|
||||||
|
if subsystem is DialogicSubsystem:
|
||||||
|
(subsystem as DialogicSubsystem).clear_game_state(clear_flags)
|
||||||
|
|
||||||
|
var timeline := current_timeline
|
||||||
|
|
||||||
|
current_timeline = null
|
||||||
|
current_event_idx = -1
|
||||||
|
current_timeline_events = []
|
||||||
|
current_state = States.IDLE
|
||||||
|
|
||||||
|
# Resetting variables
|
||||||
|
if timeline:
|
||||||
|
await timeline.clean()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SAVING & LOADING
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## Returns a dictionary containing all necessary information to later recreate the same state with load_full_state.
|
||||||
|
## The [subsystem Save] subsystem might be more useful for you.
|
||||||
|
## However, this can be used to integrate the info into your own save system.
|
||||||
|
func get_full_state() -> Dictionary:
|
||||||
|
if current_timeline:
|
||||||
|
current_state_info['current_event_idx'] = current_event_idx
|
||||||
|
current_state_info['current_timeline'] = current_timeline.resource_path
|
||||||
|
else:
|
||||||
|
current_state_info['current_event_idx'] = -1
|
||||||
|
current_state_info['current_timeline'] = null
|
||||||
|
|
||||||
|
return current_state_info.duplicate(true)
|
||||||
|
|
||||||
|
|
||||||
|
## This method tries to load the state from the given [param state_info].
|
||||||
|
## Will automatically start a timeline and add a layout if a timeline was running when
|
||||||
|
## the dictionary was retrieved with [method get_full_state].
|
||||||
|
func load_full_state(state_info:Dictionary) -> void:
|
||||||
|
clear()
|
||||||
|
current_state_info = state_info
|
||||||
|
## The Style subsystem needs to run first for others to load correctly.
|
||||||
|
var scene: Node = null
|
||||||
|
if has_subsystem('Styles'):
|
||||||
|
get_subsystem('Styles').load_game_state()
|
||||||
|
scene = self.Styles.get_layout_node()
|
||||||
|
|
||||||
|
var load_subsystems := func() -> void:
|
||||||
|
for subsystem in get_children():
|
||||||
|
if subsystem.name == 'Styles':
|
||||||
|
continue
|
||||||
|
(subsystem as DialogicSubsystem).load_game_state()
|
||||||
|
|
||||||
|
if null != scene and not scene.is_node_ready():
|
||||||
|
scene.ready.connect(load_subsystems)
|
||||||
|
else:
|
||||||
|
await get_tree().process_frame
|
||||||
|
load_subsystems.call()
|
||||||
|
|
||||||
|
if current_state_info.get('current_timeline', null):
|
||||||
|
start_timeline(current_state_info.current_timeline, current_state_info.get('current_event_idx', 0))
|
||||||
|
else:
|
||||||
|
end_timeline.call_deferred()
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SUB-SYTSEMS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _collect_subsystems() -> void:
|
||||||
|
var subsystem_nodes := [] as Array[DialogicSubsystem]
|
||||||
|
for indexer in DialogicUtil.get_indexers():
|
||||||
|
for subsystem in indexer._get_subsystems():
|
||||||
|
var subsystem_node := add_subsystem(str(subsystem.name), str(subsystem.script))
|
||||||
|
subsystem_nodes.push_back(subsystem_node)
|
||||||
|
|
||||||
|
for subsystem in subsystem_nodes:
|
||||||
|
subsystem.post_install()
|
||||||
|
|
||||||
|
|
||||||
|
## Returns `true` if a subystem with the given [param subsystem_name] exists.
|
||||||
|
func has_subsystem(subsystem_name:String) -> bool:
|
||||||
|
return has_node(subsystem_name)
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the subsystem node of the given [param subsystem_name] or null if it doesn't exist.
|
||||||
|
func get_subsystem(subsystem_name:String) -> DialogicSubsystem:
|
||||||
|
return get_node(subsystem_name)
|
||||||
|
|
||||||
|
|
||||||
|
## Adds a subsystem node with the given [param subsystem_name] and [param script_path].
|
||||||
|
func add_subsystem(subsystem_name:String, script_path:String) -> DialogicSubsystem:
|
||||||
|
var node: Node = Node.new()
|
||||||
|
node.name = subsystem_name
|
||||||
|
node.set_script(load(script_path))
|
||||||
|
node = node as DialogicSubsystem
|
||||||
|
node.dialogic = self
|
||||||
|
add_child(node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region HELPERS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## This handles the `Layout End Behaviour` setting that can be changed in the Dialogic settings.
|
||||||
|
func _on_timeline_ended() -> void:
|
||||||
|
if self.Styles.has_active_layout_node() and self.Styles.get_layout_node().is_inside_tree():
|
||||||
|
match ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0):
|
||||||
|
0:
|
||||||
|
self.Styles.get_layout_node().get_parent().remove_child(self.Styles.get_layout_node())
|
||||||
|
self.Styles.get_layout_node().queue_free()
|
||||||
|
1:
|
||||||
|
@warning_ignore("unsafe_method_access")
|
||||||
|
self.Styles.get_layout_node().hide()
|
||||||
|
|
||||||
|
|
||||||
|
func print_debug_moment() -> void:
|
||||||
|
if not current_timeline:
|
||||||
|
return
|
||||||
|
|
||||||
|
printerr("\tAt event ", current_event_idx+1, " (",current_timeline_events[current_event_idx].event_name, ' Event) in timeline "', DialogicResourceUtil.get_unique_identifier(current_timeline.resource_path), '" (',current_timeline.resource_path,').')
|
||||||
|
print("\n")
|
||||||
|
#endregion
|
@ -0,0 +1,238 @@
|
|||||||
|
@tool
|
||||||
|
class_name DialogicResourceUtil
|
||||||
|
|
||||||
|
static var label_cache := {}
|
||||||
|
static var event_cache: Array[DialogicEvent] = []
|
||||||
|
|
||||||
|
static var special_resources : Array[Dictionary] = []
|
||||||
|
|
||||||
|
|
||||||
|
static func update() -> void:
|
||||||
|
update_directory('.dch')
|
||||||
|
update_directory('.dtl')
|
||||||
|
update_label_cache()
|
||||||
|
|
||||||
|
|
||||||
|
#region RESOURCE DIRECTORIES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func get_directory(extension:String) -> Dictionary:
|
||||||
|
extension = extension.trim_prefix('.')
|
||||||
|
if Engine.has_meta(extension+'_directory'):
|
||||||
|
return Engine.get_meta(extension+'_directory', {})
|
||||||
|
|
||||||
|
var directory: Dictionary = ProjectSettings.get_setting("dialogic/directories/"+extension+'_directory', {})
|
||||||
|
Engine.set_meta(extension+'_directory', directory)
|
||||||
|
return directory
|
||||||
|
|
||||||
|
|
||||||
|
static func set_directory(extension:String, directory:Dictionary) -> void:
|
||||||
|
extension = extension.trim_prefix('.')
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
ProjectSettings.set_setting("dialogic/directories/"+extension+'_directory', directory)
|
||||||
|
ProjectSettings.save()
|
||||||
|
Engine.set_meta(extension+'_directory', directory)
|
||||||
|
|
||||||
|
|
||||||
|
static func update_directory(extension:String) -> void:
|
||||||
|
var directory := get_directory(extension)
|
||||||
|
|
||||||
|
for resource in list_resources_of_type(extension):
|
||||||
|
if not resource in directory.values():
|
||||||
|
directory = add_resource_to_directory(resource, directory)
|
||||||
|
|
||||||
|
var keys_to_remove := []
|
||||||
|
for key in directory:
|
||||||
|
if not ResourceLoader.exists(directory[key]):
|
||||||
|
keys_to_remove.append(key)
|
||||||
|
for key in keys_to_remove:
|
||||||
|
directory.erase(key)
|
||||||
|
|
||||||
|
set_directory(extension, directory)
|
||||||
|
|
||||||
|
|
||||||
|
static func add_resource_to_directory(file_path:String, directory:Dictionary) -> Dictionary:
|
||||||
|
var suggested_name := file_path.get_file().trim_suffix("."+file_path.get_extension())
|
||||||
|
while suggested_name in directory:
|
||||||
|
suggested_name = file_path.trim_suffix("/"+suggested_name+"."+file_path.get_extension()).get_file().path_join(suggested_name)
|
||||||
|
directory[suggested_name] = file_path
|
||||||
|
return directory
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the unique identifier for the given resource path.
|
||||||
|
## Returns an empty string if no identifier was found.
|
||||||
|
static func get_unique_identifier(file_path:String) -> String:
|
||||||
|
var identifier: String = get_directory(file_path.get_extension()).find_key(file_path)
|
||||||
|
if typeof(identifier) == TYPE_STRING:
|
||||||
|
return identifier
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the resource associated with the given unique identifier.
|
||||||
|
## The expected extension is needed to use the right directory.
|
||||||
|
static func get_resource_from_identifier(identifier:String, extension:String) -> Resource:
|
||||||
|
var path: String = get_directory(extension).get(identifier, '')
|
||||||
|
if ResourceLoader.exists(path):
|
||||||
|
return load(path)
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
static func change_unique_identifier(file_path:String, new_identifier:String) -> void:
|
||||||
|
var directory := get_directory(file_path.get_extension())
|
||||||
|
var key: String = directory.find_key(file_path)
|
||||||
|
while key != null:
|
||||||
|
if key == new_identifier:
|
||||||
|
break
|
||||||
|
directory.erase(key)
|
||||||
|
directory[new_identifier] = file_path
|
||||||
|
key = directory.find_key(file_path)
|
||||||
|
set_directory(file_path.get_extension(), directory)
|
||||||
|
|
||||||
|
|
||||||
|
static func change_resource_path(old_path:String, new_path:String) -> void:
|
||||||
|
var directory := get_directory(new_path.get_extension())
|
||||||
|
var key: String = directory.find_key(old_path)
|
||||||
|
while key != null:
|
||||||
|
directory[key] = new_path
|
||||||
|
key = directory.find_key(old_path)
|
||||||
|
set_directory(new_path.get_extension(), directory)
|
||||||
|
|
||||||
|
|
||||||
|
static func remove_resource(file_path:String) -> void:
|
||||||
|
var directory := get_directory(file_path.get_extension())
|
||||||
|
var key: String = directory.find_key(file_path)
|
||||||
|
while key != null:
|
||||||
|
directory.erase(key)
|
||||||
|
key = directory.find_key(file_path)
|
||||||
|
set_directory(file_path.get_extension(), directory)
|
||||||
|
|
||||||
|
|
||||||
|
static func is_identifier_unused(extension:String, identifier:String) -> bool:
|
||||||
|
return not identifier in get_directory(extension)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region LABEL CACHE
|
||||||
|
################################################################################
|
||||||
|
# The label cache is only for the editor so we don't have to scan all timelines
|
||||||
|
# whenever we want to suggest labels. This has no use in game and is not always perfect.
|
||||||
|
|
||||||
|
static func get_label_cache() -> Dictionary:
|
||||||
|
if not label_cache.is_empty():
|
||||||
|
return label_cache
|
||||||
|
|
||||||
|
label_cache = DialogicUtil.get_editor_setting('label_ref', {})
|
||||||
|
return label_cache
|
||||||
|
|
||||||
|
|
||||||
|
static func set_label_cache(cache:Dictionary) -> void:
|
||||||
|
label_cache = cache
|
||||||
|
|
||||||
|
|
||||||
|
static func update_label_cache() -> void:
|
||||||
|
var cache := get_label_cache()
|
||||||
|
var timelines := get_timeline_directory().values()
|
||||||
|
for timeline in cache:
|
||||||
|
if !timeline in timelines:
|
||||||
|
cache.erase(timeline)
|
||||||
|
set_label_cache(cache)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region EVENT CACHE
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## Dialogic keeps a list that has each event once. This allows retrieval of that list.
|
||||||
|
static func get_event_cache() -> Array:
|
||||||
|
if not event_cache.is_empty():
|
||||||
|
return event_cache
|
||||||
|
|
||||||
|
event_cache = update_event_cache()
|
||||||
|
return event_cache
|
||||||
|
|
||||||
|
|
||||||
|
static func update_event_cache() -> Array:
|
||||||
|
event_cache = []
|
||||||
|
for indexer in DialogicUtil.get_indexers():
|
||||||
|
# build event cache
|
||||||
|
for event in indexer._get_events():
|
||||||
|
if not ResourceLoader.exists(event):
|
||||||
|
continue
|
||||||
|
if not 'event_end_branch.gd' in event and not 'event_text.gd' in event:
|
||||||
|
event_cache.append(load(event).new())
|
||||||
|
|
||||||
|
# Events are checked in order while testing them. EndBranch needs to be first, Text needs to be last
|
||||||
|
event_cache.push_front(DialogicEndBranchEvent.new())
|
||||||
|
event_cache.push_back(DialogicTextEvent.new())
|
||||||
|
|
||||||
|
return event_cache
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region SPECIAL RESOURCES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func update_special_resources() -> void:
|
||||||
|
special_resources = []
|
||||||
|
for indexer in DialogicUtil.get_indexers():
|
||||||
|
special_resources.append_array(indexer._get_special_resources())
|
||||||
|
|
||||||
|
|
||||||
|
static func list_special_resources_of_type(type:String) -> Array:
|
||||||
|
if special_resources.is_empty():
|
||||||
|
update_special_resources()
|
||||||
|
return special_resources.filter(func(x:Dictionary): return type == x.get('type','')).map(func(x:Dictionary): return x.get('path', ''))
|
||||||
|
|
||||||
|
|
||||||
|
static func guess_special_resource(type:String, name:String, default:="") -> String:
|
||||||
|
if special_resources.is_empty():
|
||||||
|
update_special_resources()
|
||||||
|
if name.begins_with('res://'):
|
||||||
|
return name
|
||||||
|
for path in list_special_resources_of_type(type):
|
||||||
|
if DialogicUtil.pretty_name(path).to_lower() == name.to_lower():
|
||||||
|
return path
|
||||||
|
return default
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region HELPERS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func get_character_directory() -> Dictionary:
|
||||||
|
return get_directory('dch')
|
||||||
|
|
||||||
|
|
||||||
|
static func get_timeline_directory() -> Dictionary:
|
||||||
|
return get_directory('dtl')
|
||||||
|
|
||||||
|
|
||||||
|
static func get_timeline_resource(timeline_identifier:String) -> DialogicTimeline:
|
||||||
|
return get_resource_from_identifier(timeline_identifier, 'dtl')
|
||||||
|
|
||||||
|
|
||||||
|
static func get_character_resource(character_identifier:String) -> DialogicCharacter:
|
||||||
|
return get_resource_from_identifier(character_identifier, 'dch')
|
||||||
|
|
||||||
|
|
||||||
|
static func list_resources_of_type(extension:String) -> Array:
|
||||||
|
var all_resources := scan_folder('res://', extension)
|
||||||
|
return all_resources
|
||||||
|
|
||||||
|
|
||||||
|
static func scan_folder(path:String, extension:String) -> Array:
|
||||||
|
var list: Array = []
|
||||||
|
if DirAccess.dir_exists_absolute(path):
|
||||||
|
var dir := DirAccess.open(path)
|
||||||
|
dir.list_dir_begin()
|
||||||
|
var file_name := dir.get_next()
|
||||||
|
while file_name != "":
|
||||||
|
if dir.current_is_dir() and not file_name.begins_with("."):
|
||||||
|
list += scan_folder(path.path_join(file_name), extension)
|
||||||
|
else:
|
||||||
|
if file_name.ends_with(extension):
|
||||||
|
list.append(path.path_join(file_name))
|
||||||
|
file_name = dir.get_next()
|
||||||
|
return list
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,519 @@
|
|||||||
|
@tool
|
||||||
|
class_name DialogicUtil
|
||||||
|
|
||||||
|
## Script that container helper methods for both editor and game execution.
|
||||||
|
## Used whenever the same thing is needed in different parts of the plugin.
|
||||||
|
|
||||||
|
#region EDITOR
|
||||||
|
|
||||||
|
# This method should be used instead of EditorInterface.get_editor_scale(), because if you use that
|
||||||
|
# it will run perfectly fine from the editor, but crash when the game is exported.
|
||||||
|
static func get_editor_scale() -> float:
|
||||||
|
return get_dialogic_plugin().get_editor_interface().get_editor_scale()
|
||||||
|
|
||||||
|
|
||||||
|
## Although this does in fact always return a EditorPlugin node,
|
||||||
|
## that class is apparently not present in export and referencing it here creates a crash.
|
||||||
|
static func get_dialogic_plugin() -> Node:
|
||||||
|
for child in Engine.get_main_loop().get_root().get_children():
|
||||||
|
if child.get_class() == "EditorNode":
|
||||||
|
return child.get_node('DialogicPlugin')
|
||||||
|
return null
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the autoload when in-game.
|
||||||
|
static func autoload() -> DialogicGameHandler:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return null
|
||||||
|
if not Engine.get_main_loop().root.has_node("Dialogic"):
|
||||||
|
return null
|
||||||
|
return Engine.get_main_loop().root.get_node("Dialogic")
|
||||||
|
|
||||||
|
|
||||||
|
#region FILE SYSTEM
|
||||||
|
################################################################################
|
||||||
|
static func listdir(path: String, files_only:= true, throw_error:= true, full_file_path:= false, include_imports := false) -> Array:
|
||||||
|
var files: Array = []
|
||||||
|
if path.is_empty(): path = "res://"
|
||||||
|
if DirAccess.dir_exists_absolute(path):
|
||||||
|
var dir := DirAccess.open(path)
|
||||||
|
dir.list_dir_begin()
|
||||||
|
var file_name := dir.get_next()
|
||||||
|
while file_name != "":
|
||||||
|
if not file_name.begins_with("."):
|
||||||
|
if files_only:
|
||||||
|
if not dir.current_is_dir() and (not file_name.ends_with('.import') or include_imports):
|
||||||
|
if full_file_path:
|
||||||
|
files.append(path.path_join(file_name))
|
||||||
|
else:
|
||||||
|
files.append(file_name)
|
||||||
|
else:
|
||||||
|
if full_file_path:
|
||||||
|
files.append(path.path_join(file_name))
|
||||||
|
else:
|
||||||
|
files.append(file_name)
|
||||||
|
file_name = dir.get_next()
|
||||||
|
dir.list_dir_end()
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
static func get_module_path(name:String, builtin:=true) -> String:
|
||||||
|
if builtin:
|
||||||
|
return "res://addons/dialogic/Modules".path_join(name)
|
||||||
|
else:
|
||||||
|
return ProjectSettings.get_setting('dialogic/extensions_folder', 'res://addons/dialogic_additions').path_join(name)
|
||||||
|
|
||||||
|
|
||||||
|
## This is a private and editor-only function.
|
||||||
|
##
|
||||||
|
## Populates the [class DialogicGameHandler] with new custom subsystems by
|
||||||
|
## directly manipulating the file's content and then importing the file.
|
||||||
|
static func _update_autoload_subsystem_access() -> void:
|
||||||
|
if not Engine.is_editor_hint():
|
||||||
|
printerr("[Dialogic] This function is only available in the editor.")
|
||||||
|
return
|
||||||
|
|
||||||
|
var script: Script = load("res://addons/dialogic/Core/DialogicGameHandler.gd")
|
||||||
|
var new_subsystem_access_list := "#region SUBSYSTEMS\n"
|
||||||
|
|
||||||
|
for indexer: DialogicIndexer in get_indexers(true, true):
|
||||||
|
|
||||||
|
for subsystem: Dictionary in indexer._get_subsystems().duplicate(true):
|
||||||
|
new_subsystem_access_list += '\nvar {name} := preload("{script}").new():\n\tget: return get_subsystem("{name}")\n'.format(subsystem)
|
||||||
|
|
||||||
|
new_subsystem_access_list += "\n#endregion"
|
||||||
|
script.source_code = RegEx.create_from_string("#region SUBSYSTEMS\\n#*\\n((?!#endregion)(.*\\n))*#endregion").sub(script.source_code, new_subsystem_access_list)
|
||||||
|
ResourceSaver.save(script)
|
||||||
|
Engine.get_singleton("EditorInterface").get_resource_filesystem().reimport_files(["res://addons/dialogic/Core/DialogicGameHandler.gd"])
|
||||||
|
|
||||||
|
|
||||||
|
static func get_indexers(include_custom := true, force_reload := false) -> Array[DialogicIndexer]:
|
||||||
|
if Engine.get_main_loop().has_meta('dialogic_indexers') and !force_reload:
|
||||||
|
return Engine.get_main_loop().get_meta('dialogic_indexers')
|
||||||
|
|
||||||
|
var indexers: Array[DialogicIndexer] = []
|
||||||
|
|
||||||
|
for file in listdir(DialogicUtil.get_module_path(''), false):
|
||||||
|
var possible_script: String = DialogicUtil.get_module_path(file).path_join("index.gd")
|
||||||
|
if ResourceLoader.exists(possible_script):
|
||||||
|
indexers.append(load(possible_script).new())
|
||||||
|
|
||||||
|
if include_custom:
|
||||||
|
var extensions_folder: String = ProjectSettings.get_setting('dialogic/extensions_folder', "res://addons/dialogic_additions/")
|
||||||
|
for file in listdir(extensions_folder, false, false):
|
||||||
|
var possible_script: String = extensions_folder.path_join(file + "/index.gd")
|
||||||
|
if ResourceLoader.exists(possible_script):
|
||||||
|
indexers.append(load(possible_script).new())
|
||||||
|
|
||||||
|
Engine.get_main_loop().set_meta('dialogic_indexers', indexers)
|
||||||
|
return indexers
|
||||||
|
|
||||||
|
|
||||||
|
enum AnimationType {ALL, IN, OUT, ACTION}
|
||||||
|
static func get_portrait_animation_scripts(type:=AnimationType.ALL, include_custom:=true) -> Array:
|
||||||
|
var animations := DialogicResourceUtil.list_special_resources_of_type("PortraitAnimation")
|
||||||
|
|
||||||
|
return animations.filter(
|
||||||
|
func(script):
|
||||||
|
if type == AnimationType.ALL: return true;
|
||||||
|
if type == AnimationType.IN: return '_in' in script;
|
||||||
|
if type == AnimationType.OUT: return '_out' in script;
|
||||||
|
if type == AnimationType.ACTION: return not ('_in' in script or '_out' in script))
|
||||||
|
|
||||||
|
|
||||||
|
static func pretty_name(script:String) -> String:
|
||||||
|
var _name := script.get_file().trim_suffix("."+script.get_extension())
|
||||||
|
_name = _name.replace('_', ' ')
|
||||||
|
_name = _name.capitalize()
|
||||||
|
return _name
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region EDITOR SETTINGS & COLORS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func set_editor_setting(setting:String, value:Variant) -> void:
|
||||||
|
var cfg := ConfigFile.new()
|
||||||
|
if FileAccess.file_exists('user://dialogic/editor_settings.cfg'):
|
||||||
|
cfg.load('user://dialogic/editor_settings.cfg')
|
||||||
|
|
||||||
|
cfg.set_value('DES', setting, value)
|
||||||
|
|
||||||
|
if !DirAccess.dir_exists_absolute('user://dialogic'):
|
||||||
|
DirAccess.make_dir_absolute('user://dialogic')
|
||||||
|
cfg.save('user://dialogic/editor_settings.cfg')
|
||||||
|
|
||||||
|
|
||||||
|
static func get_editor_setting(setting:String, default:Variant=null) -> Variant:
|
||||||
|
var cfg := ConfigFile.new()
|
||||||
|
if !FileAccess.file_exists('user://dialogic/editor_settings.cfg'):
|
||||||
|
return default
|
||||||
|
|
||||||
|
if !cfg.load('user://dialogic/editor_settings.cfg') == OK:
|
||||||
|
return default
|
||||||
|
|
||||||
|
return cfg.get_value('DES', setting, default)
|
||||||
|
|
||||||
|
|
||||||
|
static func get_color_palette(default:bool = false) -> Dictionary:
|
||||||
|
var defaults := {
|
||||||
|
'Color1': Color('#3b8bf2'), # Blue
|
||||||
|
'Color2': Color('#00b15f'), # Green
|
||||||
|
'Color3': Color('#e868e2'), # Pink
|
||||||
|
'Color4': Color('#9468e8'), # Purple
|
||||||
|
'Color5': Color('#574fb0'), # DarkPurple
|
||||||
|
'Color6': Color('#1fa3a3'), # Aquamarine
|
||||||
|
'Color7': Color('#fa952a'), # Orange
|
||||||
|
'Color8': Color('#de5c5c'), # Red
|
||||||
|
'Color9': Color('#7c7c7c'), # Gray
|
||||||
|
}
|
||||||
|
if default:
|
||||||
|
return defaults
|
||||||
|
return get_editor_setting('color_palette', defaults)
|
||||||
|
|
||||||
|
|
||||||
|
static func get_color(value:String) -> Color:
|
||||||
|
var colors := get_color_palette()
|
||||||
|
return colors[value]
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region TIMER PROCESS MODE
|
||||||
|
################################################################################
|
||||||
|
static func is_physics_timer() -> bool:
|
||||||
|
return ProjectSettings.get_setting('dialogic/timer/process_in_physics', false)
|
||||||
|
|
||||||
|
|
||||||
|
static func update_timer_process_callback(timer:Timer) -> void:
|
||||||
|
timer.process_callback = Timer.TIMER_PROCESS_PHYSICS if is_physics_timer() else Timer.TIMER_PROCESS_IDLE
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region TRANSLATIONS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func get_next_translation_id() -> String:
|
||||||
|
ProjectSettings.set_setting('dialogic/translation/id_counter', ProjectSettings.get_setting('dialogic/translation/id_counter', 16)+1)
|
||||||
|
return '%x' % ProjectSettings.get_setting('dialogic/translation/id_counter', 16)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region VARIABLES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
enum VarTypes {ANY, STRING, FLOAT, INT, BOOL}
|
||||||
|
|
||||||
|
|
||||||
|
static func get_default_variables() -> Dictionary:
|
||||||
|
return ProjectSettings.get_setting('dialogic/variables', {})
|
||||||
|
|
||||||
|
|
||||||
|
# helper that converts a nested variable dictionary into an array with paths
|
||||||
|
static func list_variables(dict:Dictionary, path := "", type:=VarTypes.ANY) -> Array:
|
||||||
|
var array := []
|
||||||
|
for key in dict.keys():
|
||||||
|
if typeof(dict[key]) == TYPE_DICTIONARY:
|
||||||
|
array.append_array(list_variables(dict[key], path+key+".", type))
|
||||||
|
else:
|
||||||
|
if type == VarTypes.ANY or get_variable_value_type(dict[key]) == type:
|
||||||
|
array.append(path+key)
|
||||||
|
return array
|
||||||
|
|
||||||
|
|
||||||
|
static func get_variable_value_type(value:Variant) -> int:
|
||||||
|
match typeof(value):
|
||||||
|
TYPE_STRING:
|
||||||
|
return VarTypes.STRING
|
||||||
|
TYPE_FLOAT:
|
||||||
|
return VarTypes.FLOAT
|
||||||
|
TYPE_INT:
|
||||||
|
return VarTypes.INT
|
||||||
|
TYPE_BOOL:
|
||||||
|
return VarTypes.BOOL
|
||||||
|
return VarTypes.ANY
|
||||||
|
|
||||||
|
|
||||||
|
static func get_variable_type(path:String, dict:Dictionary={}) -> VarTypes:
|
||||||
|
if dict.is_empty():
|
||||||
|
dict = get_default_variables()
|
||||||
|
return get_variable_value_type(_get_value_in_dictionary(path, dict))
|
||||||
|
|
||||||
|
|
||||||
|
## This will set a value in a dictionary (or a sub-dictionary based on the path)
|
||||||
|
## e.g. it could set "Something.Something.Something" in {'Something':{'Something':{'Someting':"value"}}}
|
||||||
|
static func _set_value_in_dictionary(path:String, dictionary:Dictionary, value):
|
||||||
|
if '.' in path:
|
||||||
|
var from := path.split('.')[0]
|
||||||
|
if from in dictionary.keys():
|
||||||
|
dictionary[from] = _set_value_in_dictionary(path.trim_prefix(from+"."), dictionary[from], value)
|
||||||
|
else:
|
||||||
|
if path in dictionary.keys():
|
||||||
|
dictionary[path] = value
|
||||||
|
return dictionary
|
||||||
|
|
||||||
|
|
||||||
|
## This will get a value in a dictionary (or a sub-dictionary based on the path)
|
||||||
|
## e.g. it could get "Something.Something.Something" in {'Something':{'Something':{'Someting':"value"}}}
|
||||||
|
static func _get_value_in_dictionary(path:String, dictionary:Dictionary, default= null) -> Variant:
|
||||||
|
if '.' in path:
|
||||||
|
var from := path.split('.')[0]
|
||||||
|
if from in dictionary.keys():
|
||||||
|
return _get_value_in_dictionary(path.trim_prefix(from+"."), dictionary[from], default)
|
||||||
|
else:
|
||||||
|
if path in dictionary.keys():
|
||||||
|
return dictionary[path]
|
||||||
|
return default
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region STYLES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func get_default_layout_base() -> PackedScene:
|
||||||
|
return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Base_Default/default_layout_base.tscn"))
|
||||||
|
|
||||||
|
|
||||||
|
static func get_fallback_style() -> DialogicStyle:
|
||||||
|
return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Style_VN_Default/default_vn_style.tres"))
|
||||||
|
|
||||||
|
|
||||||
|
static func get_default_style() -> DialogicStyle:
|
||||||
|
var default: String = ProjectSettings.get_setting('dialogic/layout/default_style', '')
|
||||||
|
if !ResourceLoader.exists(default):
|
||||||
|
return get_fallback_style()
|
||||||
|
return load(default)
|
||||||
|
|
||||||
|
|
||||||
|
static func get_style_by_name(name:String) -> DialogicStyle:
|
||||||
|
if name.is_empty():
|
||||||
|
return get_default_style()
|
||||||
|
|
||||||
|
var styles: Array = ProjectSettings.get_setting('dialogic/layout/style_list', [])
|
||||||
|
for style in styles:
|
||||||
|
if not ResourceLoader.exists(style):
|
||||||
|
continue
|
||||||
|
if load(style).name == name:
|
||||||
|
return load(style)
|
||||||
|
|
||||||
|
return get_default_style()
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SCENE EXPORT OVERRIDES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func apply_scene_export_overrides(node:Node, export_overrides:Dictionary, apply := true) -> void:
|
||||||
|
var default_info := get_scene_export_defaults(node)
|
||||||
|
if !node.script:
|
||||||
|
return
|
||||||
|
var property_info: Array[Dictionary] = node.script.get_script_property_list()
|
||||||
|
for i in property_info:
|
||||||
|
if i['usage'] & PROPERTY_USAGE_EDITOR:
|
||||||
|
if i['name'] in export_overrides:
|
||||||
|
if str_to_var(export_overrides[i['name']]) == null and typeof(node.get(i['name'])) == TYPE_STRING:
|
||||||
|
node.set(i['name'], export_overrides[i['name']])
|
||||||
|
else:
|
||||||
|
node.set(i['name'], str_to_var(export_overrides[i['name']]))
|
||||||
|
elif i['name'] in default_info:
|
||||||
|
node.set(i['name'], default_info.get(i['name']))
|
||||||
|
if apply:
|
||||||
|
if node.has_method('apply_export_overrides'):
|
||||||
|
node.apply_export_overrides()
|
||||||
|
|
||||||
|
|
||||||
|
static func get_scene_export_defaults(node:Node) -> Dictionary:
|
||||||
|
if !node.script:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if Engine.get_main_loop().has_meta('dialogic_scene_export_defaults') and \
|
||||||
|
node.script.resource_path in Engine.get_main_loop().get_meta('dialogic_scene_export_defaults'):
|
||||||
|
return Engine.get_main_loop().get_meta('dialogic_scene_export_defaults')[node.script.resource_path]
|
||||||
|
|
||||||
|
if !Engine.get_main_loop().has_meta('dialogic_scene_export_defaults'):
|
||||||
|
Engine.get_main_loop().set_meta('dialogic_scene_export_defaults', {})
|
||||||
|
var defaults := {}
|
||||||
|
var property_info :Array[Dictionary] = node.script.get_script_property_list()
|
||||||
|
for i in property_info:
|
||||||
|
if i['usage'] & PROPERTY_USAGE_EDITOR:
|
||||||
|
defaults[i['name']] = node.get(i['name'])
|
||||||
|
Engine.get_main_loop().get_meta('dialogic_scene_export_defaults')[node.script.resource_path] = defaults
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region INSPECTOR FIELDS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func setup_script_property_edit_node(property_info: Dictionary, value:Variant, property_changed:Callable) -> Control:
|
||||||
|
var input: Control = null
|
||||||
|
match property_info['type']:
|
||||||
|
TYPE_BOOL:
|
||||||
|
input = CheckBox.new()
|
||||||
|
if value != null:
|
||||||
|
input.button_pressed = value
|
||||||
|
input.toggled.connect(DialogicUtil._on_export_bool_submitted.bind(property_info.name, property_changed))
|
||||||
|
TYPE_COLOR:
|
||||||
|
input = ColorPickerButton.new()
|
||||||
|
if value != null:
|
||||||
|
input.color = value
|
||||||
|
input.color_changed.connect(DialogicUtil._on_export_color_submitted.bind(property_info.name, property_changed))
|
||||||
|
input.custom_minimum_size.x = get_editor_scale() * 50
|
||||||
|
TYPE_INT:
|
||||||
|
if property_info['hint'] & PROPERTY_HINT_ENUM:
|
||||||
|
input = OptionButton.new()
|
||||||
|
for x in property_info['hint_string'].split(','):
|
||||||
|
input.add_item(x.split(':')[0])
|
||||||
|
if value != null:
|
||||||
|
input.select(value)
|
||||||
|
input.item_selected.connect(DialogicUtil._on_export_int_enum_submitted.bind(property_info.name, property_changed))
|
||||||
|
else:
|
||||||
|
input = SpinBox.new()
|
||||||
|
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed))
|
||||||
|
if property_info.hint_string == 'int':
|
||||||
|
input.step = 1
|
||||||
|
input.allow_greater = true
|
||||||
|
input.allow_lesser = true
|
||||||
|
elif ',' in property_info.hint_string:
|
||||||
|
input.min_value = int(property_info.hint_string.get_slice(',', 0))
|
||||||
|
input.max_value = int(property_info.hint_string.get_slice(',', 1))
|
||||||
|
if property_info.hint_string.count(',') > 1:
|
||||||
|
input.step = int(property_info.hint_string.get_slice(',', 2))
|
||||||
|
if value != null:
|
||||||
|
input.value = value
|
||||||
|
TYPE_FLOAT:
|
||||||
|
input = SpinBox.new()
|
||||||
|
input.step = 0.01
|
||||||
|
if ',' in property_info.hint_string:
|
||||||
|
input.min_value = float(property_info.hint_string.get_slice(',', 0))
|
||||||
|
input.max_value = float(property_info.hint_string.get_slice(',', 1))
|
||||||
|
if property_info.hint_string.count(',') > 1:
|
||||||
|
input.step = float(property_info.hint_string.get_slice(',', 2))
|
||||||
|
input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed))
|
||||||
|
if value != null:
|
||||||
|
input.value = value
|
||||||
|
TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4:
|
||||||
|
var vectorSize: String = type_string(typeof(value))[-1]
|
||||||
|
input = load("res://addons/dialogic/Editor/Events/Fields/field_vector" + vectorSize + ".tscn").instantiate()
|
||||||
|
input.property_name = property_info['name']
|
||||||
|
input.set_value(value)
|
||||||
|
input.value_changed.connect(DialogicUtil._on_export_vector_submitted.bind(property_changed))
|
||||||
|
TYPE_STRING:
|
||||||
|
if property_info['hint'] & PROPERTY_HINT_FILE or property_info['hint'] & PROPERTY_HINT_DIR:
|
||||||
|
input = load("res://addons/dialogic/Editor/Events/Fields/field_file.tscn").instantiate()
|
||||||
|
input.file_filter = property_info['hint_string']
|
||||||
|
input.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||||
|
if property_info['hint'] == PROPERTY_HINT_DIR:
|
||||||
|
input.file_mode = FileDialog.FILE_MODE_OPEN_DIR
|
||||||
|
input.property_name = property_info['name']
|
||||||
|
input.placeholder = "Default"
|
||||||
|
input.hide_reset = true
|
||||||
|
if value != null:
|
||||||
|
input.set_value(value)
|
||||||
|
input.value_changed.connect(DialogicUtil._on_export_file_submitted.bind(property_changed))
|
||||||
|
elif property_info['hint'] & PROPERTY_HINT_ENUM:
|
||||||
|
input = OptionButton.new()
|
||||||
|
var options: PackedStringArray = []
|
||||||
|
for x in property_info['hint_string'].split(','):
|
||||||
|
options.append(x.split(':')[0].strip_edges())
|
||||||
|
input.add_item(options[-1])
|
||||||
|
if value != null:
|
||||||
|
input.select(options.find(value))
|
||||||
|
input.item_selected.connect(DialogicUtil._on_export_string_enum_submitted.bind(property_info.name, options, property_changed))
|
||||||
|
else:
|
||||||
|
input = LineEdit.new()
|
||||||
|
if value != null:
|
||||||
|
input.text = value
|
||||||
|
input.text_submitted.connect(DialogicUtil._on_export_input_text_submitted.bind(property_info.name, property_changed))
|
||||||
|
TYPE_OBJECT:
|
||||||
|
input = load("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn").instantiate()
|
||||||
|
input.hint_text = "Objects/Resources as settings are currently not supported. \nUse @export_file('*.extension') instead and load the resource once needed."
|
||||||
|
_:
|
||||||
|
input = LineEdit.new()
|
||||||
|
if value != null:
|
||||||
|
input.text = value
|
||||||
|
input.text_submitted.connect(_on_export_input_text_submitted.bind(property_info.name, property_changed))
|
||||||
|
return input
|
||||||
|
|
||||||
|
|
||||||
|
static func _on_export_input_text_submitted(text:String, property_name:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(text))
|
||||||
|
|
||||||
|
static func _on_export_bool_submitted(value:bool, property_name:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(value))
|
||||||
|
|
||||||
|
static func _on_export_color_submitted(color:Color, property_name:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(color))
|
||||||
|
|
||||||
|
static func _on_export_int_enum_submitted(item:int, property_name:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(item))
|
||||||
|
|
||||||
|
static func _on_export_number_submitted(value:float, property_name:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(value))
|
||||||
|
|
||||||
|
static func _on_export_file_submitted(property_name:String, value:String, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(value))
|
||||||
|
|
||||||
|
static func _on_export_string_enum_submitted(value:int, property_name:String, list:PackedStringArray, callable: Callable):
|
||||||
|
callable.call(property_name, var_to_str(list[value]))
|
||||||
|
|
||||||
|
static func _on_export_vector_submitted(property_name:String, value:Variant, callable: Callable) -> void:
|
||||||
|
callable.call(property_name, var_to_str(value))
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENT DEFAULTS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func get_custom_event_defaults(event_name:String) -> Dictionary:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return ProjectSettings.get_setting('dialogic/event_default_overrides', {}).get(event_name, {})
|
||||||
|
else:
|
||||||
|
if !Engine.get_main_loop().has_meta('dialogic_event_defaults'):
|
||||||
|
Engine.get_main_loop().set_meta('dialogic_event_defaults', ProjectSettings.get_setting('dialogic/event_default_overrides', {}))
|
||||||
|
return Engine.get_main_loop().get_meta('dialogic_event_defaults').get(event_name, {})
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region CONVERSION
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
static func str_to_bool(boolstring:String) -> bool:
|
||||||
|
return true if boolstring == "true" else false
|
||||||
|
|
||||||
|
|
||||||
|
static func logical_convert(value:Variant) -> Variant:
|
||||||
|
if typeof(value) == TYPE_STRING:
|
||||||
|
if value.is_valid_int():
|
||||||
|
return value.to_int()
|
||||||
|
if value.is_valid_float():
|
||||||
|
return value.to_float()
|
||||||
|
if value == 'true':
|
||||||
|
return true
|
||||||
|
if value == 'false':
|
||||||
|
return false
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
## Takes [param source] and builds a dictionary of keys only.
|
||||||
|
## The values are `null`.
|
||||||
|
static func str_to_hash_set(source: String) -> Dictionary:
|
||||||
|
var dictionary := Dictionary()
|
||||||
|
|
||||||
|
for character in source:
|
||||||
|
dictionary[character] = null
|
||||||
|
|
||||||
|
return dictionary
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,34 @@
|
|||||||
|
class_name DialogicSubsystem
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
var dialogic: DialogicGameHandler = null
|
||||||
|
|
||||||
|
enum LoadFlags {FULL_LOAD, ONLY_DNODES}
|
||||||
|
|
||||||
|
# To be overriden by sub-classes
|
||||||
|
# Called once after every subsystem has been added to the tree
|
||||||
|
func post_install() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# To be overriden by sub-classes
|
||||||
|
# Fill in everything that should be cleared (for example before loading a different state)
|
||||||
|
func clear_game_state(clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# To be overriden by sub-classes
|
||||||
|
# Fill in everything that should be loaded using the dialogic_game_handler.current_state_info
|
||||||
|
# This is called when a save is loaded
|
||||||
|
func load_game_state(load_flag:=LoadFlags.FULL_LOAD) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# To be overriden by sub-classes
|
||||||
|
func pause() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# To be overriden by sub-classes
|
||||||
|
func resume() -> void:
|
||||||
|
pass
|
@ -0,0 +1,133 @@
|
|||||||
|
@tool
|
||||||
|
class_name DialogicIndexer
|
||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
## Script that indexes events, subsystems, settings pages and more. [br]
|
||||||
|
## Place a script of this type in every folder in "addons/Events". [br]
|
||||||
|
## Overwrite the methods to return the contents of that folder.
|
||||||
|
|
||||||
|
|
||||||
|
var this_folder : String = get_script().resource_path.get_base_dir()
|
||||||
|
|
||||||
|
## Overwrite if this module contains any events. [br]
|
||||||
|
## Return an array with all the paths to the event scripts.[br]
|
||||||
|
## You can use the [property this_folder].path_join('my_event.gd')
|
||||||
|
func _get_events() -> Array:
|
||||||
|
if ResourceLoader.exists(this_folder.path_join('event.gd')):
|
||||||
|
return [this_folder.path_join('event.gd')]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
## Overwrite if this module contains any subsystems.
|
||||||
|
## Should return an array of dictionaries each with the following keys: [br]
|
||||||
|
## "name" -> name for this subsystem[br]
|
||||||
|
## "script" -> array of preview images[br]
|
||||||
|
func _get_subsystems() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
func _get_editors() -> Array[String]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
func _get_settings_pages() -> Array:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
func _get_character_editor_sections() -> Array:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
#region TEXT EFFECTS & MODIFIERS
|
||||||
|
|
||||||
|
## Should return array of dictionaries with the following keys:[br]
|
||||||
|
## "command" -> the text e.g. "speed"[br]
|
||||||
|
## "node_path" or "subsystem" -> whichever contains your effect method[br]
|
||||||
|
## "method" -> name of the effect method[br]
|
||||||
|
func _get_text_effects() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
## Should return array of dictionaries with the same arguments as _get_text_effects()
|
||||||
|
func _get_text_modifiers() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
## Return a list of resources, scripts, etc.
|
||||||
|
## These can later be retrieved with DialogicResourceUtil.
|
||||||
|
## Each dictionary should contain (at least "type" and "path").
|
||||||
|
## E.g. {"type":"Animation", "path": "res://..."}
|
||||||
|
func _get_special_resources() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
#region HELPERS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func list_dir(subdir:='') -> Array:
|
||||||
|
return Array(DirAccess.get_files_at(this_folder.path_join(subdir))).map(func(file):return this_folder.path_join(subdir).path_join(file))
|
||||||
|
|
||||||
|
|
||||||
|
func list_special_resources(subdir:='', type:='', extension:="") -> Array[Dictionary]:
|
||||||
|
var array := []
|
||||||
|
for i in list_dir(subdir):
|
||||||
|
if extension.is_empty() or i.ends_with(extension):
|
||||||
|
array.append({'type':type, 'path':i})
|
||||||
|
return Array(array, TYPE_DICTIONARY, "", null)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region STYLES & LAYOUTS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _get_style_presets() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
## Should return an array of dictionaries with the following keys:[br]
|
||||||
|
## "path" -> the path to the scene[br]
|
||||||
|
## "name" -> name for this layout[br]
|
||||||
|
## "description"-> description of this layout. list what features/events are supported[br]
|
||||||
|
## "preview_image"-> array of preview images[br]
|
||||||
|
func _get_layout_parts() -> Array[Dictionary]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
## Helper that allows scanning sub directories that might be layout parts or styles
|
||||||
|
func scan_for_layout_parts() -> Array[Dictionary]:
|
||||||
|
var dir := DirAccess.open(this_folder)
|
||||||
|
var style_list :Array[Dictionary] = []
|
||||||
|
if !dir:
|
||||||
|
return style_list
|
||||||
|
dir.list_dir_begin()
|
||||||
|
var dir_name := dir.get_next()
|
||||||
|
while dir_name != "":
|
||||||
|
if !dir.current_is_dir() or !dir.file_exists(dir_name.path_join('part_config.cfg')):
|
||||||
|
dir_name = dir.get_next()
|
||||||
|
continue
|
||||||
|
var config := ConfigFile.new()
|
||||||
|
config.load(this_folder.path_join(dir_name).path_join('part_config.cfg'))
|
||||||
|
var default_image_path: String = this_folder.path_join(dir_name).path_join('preview.png')
|
||||||
|
style_list.append(
|
||||||
|
{
|
||||||
|
'type': config.get_value('style', 'type', 'Unknown type'),
|
||||||
|
'name': config.get_value('style', 'name', 'Unnamed Layout'),
|
||||||
|
'path': this_folder.path_join(dir_name).path_join(config.get_value('style', 'scene', '')),
|
||||||
|
'author': config.get_value('style', 'author', 'Anonymous'),
|
||||||
|
'description': config.get_value('style', 'description', 'No description'),
|
||||||
|
'preview_image': [config.get_value('style', 'image', default_image_path)],
|
||||||
|
'style_path':config.get_value('style', 'style_path', ''),
|
||||||
|
'icon':this_folder.path_join(dir_name).path_join(config.get_value('style', 'icon', '')),
|
||||||
|
})
|
||||||
|
|
||||||
|
if not style_list[-1].style_path.begins_with('res://'):
|
||||||
|
style_list[-1].style_path = this_folder.path_join(dir_name).path_join(style_list[-1].style_path)
|
||||||
|
|
||||||
|
dir_name = dir.get_next()
|
||||||
|
|
||||||
|
return style_list
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,89 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicCharacterEditorPortraitSection
|
||||||
|
|
||||||
|
## Section that allows setting values of exported scene variables
|
||||||
|
## for custom portrait scenes
|
||||||
|
|
||||||
|
var current_portrait_data := {}
|
||||||
|
|
||||||
|
|
||||||
|
func _get_title() -> String:
|
||||||
|
return "Settings"
|
||||||
|
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
hint_text = "The settings here are @export variables from the used scene."
|
||||||
|
|
||||||
|
|
||||||
|
func _load_portrait_data(data:Dictionary) -> void:
|
||||||
|
_recheck(data)
|
||||||
|
|
||||||
|
|
||||||
|
## Recheck section visibility and reload export fields.
|
||||||
|
## This allows reacting to changes of the portrait_scene setting.
|
||||||
|
func _recheck(data:Dictionary):
|
||||||
|
if data.get('scene', '').is_empty() and ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
|
||||||
|
hide()
|
||||||
|
get_parent().get_child(get_index()-1).hide()
|
||||||
|
get_parent().get_child(get_index()+1).hide()
|
||||||
|
else:
|
||||||
|
get_parent().get_child(get_index()-1).show()
|
||||||
|
|
||||||
|
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'))
|
||||||
|
elif !ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
|
||||||
|
scene = load(ProjectSettings.get_setting('dialogic/portraits/default_portrait', ''))
|
||||||
|
else:
|
||||||
|
scene = load(character_editor.def_portrait_path)
|
||||||
|
|
||||||
|
if !scene:
|
||||||
|
return
|
||||||
|
|
||||||
|
for child in $Grid.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
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':
|
||||||
|
skip = true
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
skip = false
|
||||||
|
|
||||||
|
$Label.visible = $Grid.get_child_count() == 0
|
||||||
|
|
||||||
|
|
||||||
|
## 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()
|
@ -0,0 +1,23 @@
|
|||||||
|
[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="Label" type="Label" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicHintText"
|
||||||
|
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||||
|
text = "There are no exported variables to override. Add @export properties to the root script of your scene and make sure it's in @tool mode."
|
||||||
|
autowrap_mode = 3
|
||||||
|
|
||||||
|
[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
|
@ -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()
|
@ -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"]
|
@ -0,0 +1,36 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicCharacterEditorPortraitSection
|
||||||
|
|
||||||
|
## Tab that allows setting a custom scene for a portrait.
|
||||||
|
|
||||||
|
func _get_title() -> String:
|
||||||
|
return "Scene"
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
hint_text = "You can use a custom scene for this portrait."
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
%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:
|
||||||
|
%ScenePicker.set_value(data.get('scene', ''))
|
||||||
|
%OpenSceneButton.visible = !data.get('scene', '').is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_scene_picker_value_changed(prop_name:String, value:String) -> void:
|
||||||
|
var data:Dictionary = selected_item.get_metadata(0)
|
||||||
|
data['scene'] = value
|
||||||
|
update_preview.emit()
|
||||||
|
changed.emit()
|
||||||
|
%OpenSceneButton.visible = !data.get('scene', '').is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_open_scene_button_pressed():
|
||||||
|
if !%ScenePicker.current_value.is_empty() and ResourceLoader.exists(%ScenePicker.current_value):
|
||||||
|
DialogicUtil.get_dialogic_plugin().get_editor_interface().open_scene_from_path(%ScenePicker.current_value)
|
||||||
|
EditorInterface.set_main_screen_editor("2D")
|
@ -0,0 +1,42 @@
|
|||||||
|
[gd_scene load_steps=5 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"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_sbh6e"]
|
||||||
|
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_mbv6v"]
|
||||||
|
image = SubResource("Image_sbh6e")
|
||||||
|
|
||||||
|
[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="ScenePicker" parent="HBox" instance=ExtResource("2_k8xs0")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
file_filter = "*.tscn, *.scn; Scenes"
|
||||||
|
placeholder = "Default scene"
|
||||||
|
resource_icon = SubResource("ImageTexture_mbv6v")
|
||||||
|
|
||||||
|
[node name="OpenSceneButton" type="Button" parent="HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_mbv6v")
|
||||||
|
|
||||||
|
[connection signal="value_changed" from="HBox/ScenePicker" to="." method="_on_scene_picker_value_changed"]
|
||||||
|
[connection signal="pressed" from="HBox/OpenSceneButton" to="." method="_on_open_scene_button_pressed"]
|
@ -0,0 +1,65 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicCharacterEditorPortraitSection
|
||||||
|
|
||||||
|
## Portrait Settings Section that only shows the MAIN settings of a portrait scene.
|
||||||
|
|
||||||
|
func _show_title() -> bool:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var current_portrait_data := {}
|
||||||
|
|
||||||
|
func _load_portrait_data(data:Dictionary) -> void:
|
||||||
|
get_parent().get_child(get_index()+1).hide()
|
||||||
|
current_portrait_data = data
|
||||||
|
load_portrait_scene_export_variables()
|
||||||
|
|
||||||
|
func load_portrait_scene_export_variables():
|
||||||
|
for child in $Grid.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
var scene = null
|
||||||
|
if !current_portrait_data.get('scene', '').is_empty():
|
||||||
|
scene = load(current_portrait_data.get('scene'))
|
||||||
|
elif !ProjectSettings.get_setting('dialogic/portraits/default_portrait', '').is_empty():
|
||||||
|
scene = load(ProjectSettings.get_setting('dialogic/portraits/default_portrait', ''))
|
||||||
|
else:
|
||||||
|
scene = load(character_editor.def_portrait_path)
|
||||||
|
|
||||||
|
if !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()
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||||
|
|
@ -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
|
@ -0,0 +1,658 @@
|
|||||||
|
@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 = null
|
||||||
|
|
||||||
|
# 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 = 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)
|
||||||
|
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()
|
||||||
|
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:
|
||||||
|
var final_name: String = path.path_join(file_name)
|
||||||
|
%PortraitTree.add_portrait_item(file_name.trim_suffix('.'+file_name.get_extension()),
|
||||||
|
{'scene':"",'export_overrides':{'image':var_to_str(final_name)}, 'scale':1, 'offset':Vector2(), 'mirror':false}, parent)
|
||||||
|
file_name = dir.get_next()
|
||||||
|
|
||||||
|
## 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 = portrait
|
||||||
|
var parent = %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 := 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) -> 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 current_previewed_scene.get_meta('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)):
|
||||||
|
pass # we keep the same scene
|
||||||
|
else:
|
||||||
|
for node in %RealPreviewPivot.get_children():
|
||||||
|
node.queue_free()
|
||||||
|
|
||||||
|
current_previewed_scene = null
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
if current_previewed_scene:
|
||||||
|
%RealPreviewPivot.add_child(current_previewed_scene)
|
||||||
|
|
||||||
|
if 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 is_instance_valid(scene.get_script()) 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'
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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():
|
||||||
|
if %FitPreview_Toggle.button_pressed:
|
||||||
|
update_preview()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_create_character_button_pressed():
|
||||||
|
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()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
## Open the reference manager
|
||||||
|
func _on_reference_manger_button_pressed():
|
||||||
|
editors_manager.reference_manager.open()
|
||||||
|
%PortraitChangeInfo.hide()
|
||||||
|
|
@ -0,0 +1,452 @@
|
|||||||
|
[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_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")
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_1n61j"]
|
||||||
|
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_1n61j")
|
||||||
|
|
||||||
|
[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="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_stretch_ratio = 0.3
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TopSection" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="NameContainer" type="HBoxContainer" parent="VBoxContainer/TopSection"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="CharacterName" type="Label" parent="VBoxContainer/TopSection/NameContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicTitle"
|
||||||
|
text = "My Character"
|
||||||
|
|
||||||
|
[node name="NameTooltip" parent="VBoxContainer/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_hx3oq")
|
||||||
|
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="VBoxContainer/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="VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="MainSettings" type="VBoxContainer" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PortraitsTitle" type="Label" parent="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicSubTitle"
|
||||||
|
text = "Portraits"
|
||||||
|
|
||||||
|
[node name="PortraitListTools" type="HBoxContainer" parent="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="AddPortraitButton" type="Button" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree"]
|
||||||
|
size = Vector2i(118, 100)
|
||||||
|
item_count = 5
|
||||||
|
item_0/text = "Rename"
|
||||||
|
item_0/icon = SubResource("ImageTexture_hx3oq")
|
||||||
|
item_0/id = 2
|
||||||
|
item_1/text = "Duplicate"
|
||||||
|
item_1/icon = SubResource("ImageTexture_hx3oq")
|
||||||
|
item_1/id = 0
|
||||||
|
item_2/text = "Delete"
|
||||||
|
item_2/icon = SubResource("ImageTexture_hx3oq")
|
||||||
|
item_2/id = 1
|
||||||
|
item_3/text = ""
|
||||||
|
item_3/id = 3
|
||||||
|
item_3/separator = true
|
||||||
|
item_4/text = "Make Default"
|
||||||
|
item_4/id = 4
|
||||||
|
|
||||||
|
[node name="PortraitChangeInfo" type="HBoxContainer" parent="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PortraitChangeWarning" type="Label" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/RightSection2"]
|
||||||
|
custom_minimum_size = Vector2(0, 10)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="RightSection" type="SplitContainer" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/ClipRect"]
|
||||||
|
position = Vector2(13, 17)
|
||||||
|
|
||||||
|
[node name="RealPreviewPivot" type="Sprite2D" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/PreviewReal"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="RealSizeRemotePivotTransform" type="RemoteTransform2D" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PortraitSettingsTitle" type="Label" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
size_flags_stretch_ratio = 0.4
|
||||||
|
|
||||||
|
[node name="PortraitSettingsSection" type="VBoxContainer" parent="VBoxContainer/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="VBoxContainer/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="VBoxContainer/TopSection/MainSettingsCollapse" to="." method="_on_main_settings_collapse_toggled"]
|
||||||
|
[connection signal="item_mouse_selected" from="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree" to="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree" method="_on_item_mouse_selected"]
|
||||||
|
[connection signal="index_pressed" from="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitTreePanel/PortraitTree/PortraitRightClickMenu" to="." method="_on_portrait_right_click_menu_index_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/MainHSplit/Split/HBoxContainer/MarginContainer/PortraitListSection/Portraits/PortraitChangeInfo/ReferenceMangerButton" to="." method="_on_reference_manger_button_pressed"]
|
||||||
|
[connection signal="resized" from="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/FullPreviewAvailableRect" to="." method="_on_full_preview_available_rect_resized"]
|
||||||
|
[connection signal="toggled" from="VBoxContainer/MainHSplit/Split/RightSection2/RightSection/PortraitPreviewSection/HBoxContainer/FitPreview_Toggle" to="." method="_on_fit_preview_toggle_toggled"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/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"]
|
@ -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
|
@ -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
|
@ -0,0 +1,138 @@
|
|||||||
|
@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(position: Vector2) -> Variant:
|
||||||
|
drop_mode_flags = DROP_MODE_INBETWEEN
|
||||||
|
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 drop_section := get_drop_section_at_position(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
|
@ -0,0 +1,56 @@
|
|||||||
|
@tool
|
||||||
|
class_name DCSS
|
||||||
|
|
||||||
|
static func inline(style:Dictionary) -> StyleBoxFlat:
|
||||||
|
var scale:float = DialogicUtil.get_editor_scale()
|
||||||
|
var s := StyleBoxFlat.new()
|
||||||
|
for property in style.keys():
|
||||||
|
match property:
|
||||||
|
'border-left':
|
||||||
|
s.set('border_width_left', style[property] * scale)
|
||||||
|
'border-radius':
|
||||||
|
var radius:float = style[property] * scale
|
||||||
|
s.set('corner_radius_top_left', radius)
|
||||||
|
s.set('corner_radius_top_right', radius)
|
||||||
|
s.set('corner_radius_bottom_left', radius)
|
||||||
|
s.set('corner_radius_bottom_right', radius)
|
||||||
|
'background':
|
||||||
|
s.set('bg_color', style[property])
|
||||||
|
'border':
|
||||||
|
var width:float = style[property] * scale
|
||||||
|
s.set('border_width_left', width)
|
||||||
|
s.set('border_width_right', width)
|
||||||
|
s.set('border_width_top', width)
|
||||||
|
s.set('border_width_bottom', width)
|
||||||
|
'border-color':
|
||||||
|
s.set('border_color', style[property])
|
||||||
|
'padding':
|
||||||
|
var value_v: float = 0.0
|
||||||
|
var value_h: float = 0.0
|
||||||
|
if style[property] is int:
|
||||||
|
value_v = style[property] * scale
|
||||||
|
value_h = value_v
|
||||||
|
else:
|
||||||
|
value_v = style[property][0] * scale
|
||||||
|
value_h = style[property][1] * scale
|
||||||
|
s.set('content_margin_top', value_v)
|
||||||
|
s.set('content_margin_bottom', value_v)
|
||||||
|
s.set('content_margin_left', value_h)
|
||||||
|
s.set('content_margin_right', value_h)
|
||||||
|
'padding-right':
|
||||||
|
s.set('content_margin_right', style[property] * scale)
|
||||||
|
'padding-left':
|
||||||
|
s.set('content_margin_left', style[property] * scale)
|
||||||
|
return s
|
||||||
|
|
||||||
|
static func style(node, style:Dictionary) -> StyleBoxFlat:
|
||||||
|
var s:StyleBoxFlat = inline(style)
|
||||||
|
|
||||||
|
node.set('theme_override_styles/normal', s)
|
||||||
|
node.set('theme_override_styles/focus', s)
|
||||||
|
node.set('theme_override_styles/read_only', s)
|
||||||
|
node.set('theme_override_styles/hover', s)
|
||||||
|
node.set('theme_override_styles/pressed', s)
|
||||||
|
node.set('theme_override_styles/disabled', s)
|
||||||
|
node.set('theme_override_styles/panel', s)
|
||||||
|
return s
|
@ -0,0 +1,119 @@
|
|||||||
|
@tool
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
|
||||||
|
enum Modes {EDIT, ADD}
|
||||||
|
|
||||||
|
var mode := Modes.EDIT
|
||||||
|
var item :TreeItem = null
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
hide()
|
||||||
|
%Character.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/character.svg")
|
||||||
|
%Character.get_suggestions_func = get_character_suggestions
|
||||||
|
|
||||||
|
%WholeWords.icon = get_theme_icon("FontItem", "EditorIcons")
|
||||||
|
%MatchCase.icon = get_theme_icon("MatchCase", "EditorIcons")
|
||||||
|
|
||||||
|
func _on_add_pressed() -> void:
|
||||||
|
if visible:
|
||||||
|
if mode == Modes.ADD:
|
||||||
|
hide()
|
||||||
|
return
|
||||||
|
elif mode == Modes.EDIT:
|
||||||
|
save()
|
||||||
|
|
||||||
|
%AddButton.text = "Add"
|
||||||
|
mode = Modes.ADD
|
||||||
|
show()
|
||||||
|
%Type.selected = 0
|
||||||
|
_on_type_item_selected(0)
|
||||||
|
%Where.selected = 2
|
||||||
|
_on_where_item_selected(2)
|
||||||
|
%Old.text = ""
|
||||||
|
%New.text = ""
|
||||||
|
|
||||||
|
|
||||||
|
func open_existing(_item:TreeItem, info:Dictionary):
|
||||||
|
mode = Modes.EDIT
|
||||||
|
item = _item
|
||||||
|
show()
|
||||||
|
%AddButton.text = "Update"
|
||||||
|
%Type.selected = info.type
|
||||||
|
_on_type_item_selected(info.type)
|
||||||
|
if !info.character_names.is_empty():
|
||||||
|
%Where.selected = 1
|
||||||
|
%Character.set_value(info.character_names[0])
|
||||||
|
else:
|
||||||
|
%Where.selected = 0
|
||||||
|
_on_where_item_selected(%Where.selected)
|
||||||
|
|
||||||
|
%Old.text = info.what
|
||||||
|
%New.text = info.forwhat
|
||||||
|
|
||||||
|
func _on_type_item_selected(index:int) -> void:
|
||||||
|
match index:
|
||||||
|
0:
|
||||||
|
%Where.select(0)
|
||||||
|
%Where.set_item_disabled(0, false)
|
||||||
|
%Where.set_item_disabled(1, false)
|
||||||
|
%Where.set_item_disabled(2, true)
|
||||||
|
1:
|
||||||
|
%Where.select(0)
|
||||||
|
%Where.set_item_disabled(0, false)
|
||||||
|
%Where.set_item_disabled(1, false)
|
||||||
|
%Where.set_item_disabled(2, true)
|
||||||
|
2:
|
||||||
|
%Where.select(1)
|
||||||
|
%Where.set_item_disabled(0, true)
|
||||||
|
%Where.set_item_disabled(1, false)
|
||||||
|
%Where.set_item_disabled(2, true)
|
||||||
|
3,4:
|
||||||
|
%Where.select(0)
|
||||||
|
%Where.set_item_disabled(0, false)
|
||||||
|
%Where.set_item_disabled(1, true)
|
||||||
|
%Where.set_item_disabled(2, true)
|
||||||
|
%PureTextFlags.visible = index == 0
|
||||||
|
_on_where_item_selected(%Where.selected)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_where_item_selected(index:int) -> void:
|
||||||
|
%Character.visible = index == 1
|
||||||
|
|
||||||
|
|
||||||
|
func get_character_suggestions(search_text:String) -> Dictionary:
|
||||||
|
var suggestions := {}
|
||||||
|
|
||||||
|
#override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work
|
||||||
|
var _character_directory = DialogicResourceUtil.get_character_directory()
|
||||||
|
|
||||||
|
var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg")
|
||||||
|
suggestions['(No one)'] = {'value':null, 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]}
|
||||||
|
|
||||||
|
for resource in _character_directory.keys():
|
||||||
|
suggestions[resource] = {
|
||||||
|
'value' : resource,
|
||||||
|
'tooltip' : _character_directory[resource],
|
||||||
|
'icon' : icon.duplicate()}
|
||||||
|
return suggestions
|
||||||
|
|
||||||
|
|
||||||
|
func save():
|
||||||
|
if %Old.text.is_empty() or %New.text.is_empty():
|
||||||
|
return
|
||||||
|
if %Where.selected == 1 and %Character.current_value == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
var previous := {}
|
||||||
|
if mode == Modes.EDIT:
|
||||||
|
previous = item.get_metadata(0)
|
||||||
|
item.get_parent()
|
||||||
|
item.free()
|
||||||
|
|
||||||
|
var ref_manager := find_parent('ReferenceManager')
|
||||||
|
var character_names := []
|
||||||
|
if %Character.current_value != null:
|
||||||
|
character_names = [%Character.current_value]
|
||||||
|
ref_manager.add_ref_change(%Old.text, %New.text, %Type.selected, %Where.selected, character_names, %WholeWords.button_pressed, %MatchCase.button_pressed, previous)
|
||||||
|
hide()
|
@ -0,0 +1,8 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://dmsjhgv22dns8"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 5.0
|
||||||
|
content_margin_top = 5.0
|
||||||
|
content_margin_right = 5.0
|
||||||
|
content_margin_bottom = 5.0
|
||||||
|
bg_color = Color(0.545098, 0.545098, 0.545098, 0.211765)
|
@ -0,0 +1,363 @@
|
|||||||
|
@tool
|
||||||
|
extends VSplitContainer
|
||||||
|
|
||||||
|
## This manager shows a list of changed references and allows searching for them and replacing them.
|
||||||
|
|
||||||
|
var reference_changes :Array[Dictionary] = []:
|
||||||
|
set(changes):
|
||||||
|
reference_changes = changes
|
||||||
|
update_indicator()
|
||||||
|
|
||||||
|
var search_regexes: Array[Array]
|
||||||
|
var finder_thread: Thread
|
||||||
|
var progress_mutex: Mutex
|
||||||
|
var progress_percent: float = 0.0
|
||||||
|
var progress_message: String = ""
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if owner.get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
%TabA.text = "Broken References"
|
||||||
|
%TabA.icon = get_theme_icon("Unlinked", "EditorIcons")
|
||||||
|
|
||||||
|
owner.get_parent().visibility_changed.connect(func(): if is_visible_in_tree(): open())
|
||||||
|
|
||||||
|
%ReplacementSection.hide()
|
||||||
|
|
||||||
|
%CheckButton.icon = get_theme_icon("Search", "EditorIcons")
|
||||||
|
%Replace.icon = get_theme_icon("ArrowRight", "EditorIcons")
|
||||||
|
|
||||||
|
%State.add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"))
|
||||||
|
visibility_changed.connect(func(): if !visible: close())
|
||||||
|
await get_parent().ready
|
||||||
|
|
||||||
|
var tab_button: Control = %TabA
|
||||||
|
var dot := Sprite2D.new()
|
||||||
|
dot.texture = get_theme_icon("GuiGraphNodePort", "EditorIcons")
|
||||||
|
dot.scale = Vector2(0.8, 0.8)
|
||||||
|
dot.z_index = 10
|
||||||
|
dot.position = Vector2(tab_button.size.x, tab_button.size.y*0.25)
|
||||||
|
dot.modulate = get_theme_color("warning_color", "Editor").lightened(0.5)
|
||||||
|
|
||||||
|
tab_button.add_child(dot)
|
||||||
|
update_indicator()
|
||||||
|
|
||||||
|
|
||||||
|
func open() -> void:
|
||||||
|
%ReplacementEditPanel.hide()
|
||||||
|
%ReplacementSection.hide()
|
||||||
|
%ChangeTree.clear()
|
||||||
|
%ChangeTree.create_item()
|
||||||
|
%ChangeTree.set_column_expand(0, false)
|
||||||
|
%ChangeTree.set_column_expand(2, false)
|
||||||
|
%ChangeTree.set_column_custom_minimum_width(2, 50)
|
||||||
|
var categories := {null:%ChangeTree.get_root()}
|
||||||
|
for i in reference_changes:
|
||||||
|
var parent : TreeItem = null
|
||||||
|
if !i.get('category', null) in categories:
|
||||||
|
parent = %ChangeTree.create_item()
|
||||||
|
parent.set_text(1, i.category)
|
||||||
|
parent.set_custom_color(1, get_theme_color("disabled_font_color", "Editor"))
|
||||||
|
categories[i.category] = parent
|
||||||
|
else:
|
||||||
|
parent = categories[i.get('category')]
|
||||||
|
|
||||||
|
var item :TreeItem = %ChangeTree.create_item(parent)
|
||||||
|
item.set_text(1, i.what+" -> "+i.forwhat)
|
||||||
|
item.add_button(1, get_theme_icon("Edit", "EditorIcons"), 1, false, 'Edit')
|
||||||
|
item.add_button(1, get_theme_icon("Remove", "EditorIcons"), 0, false, 'Remove Change from List')
|
||||||
|
item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK)
|
||||||
|
item.set_checked(0, true)
|
||||||
|
item.set_editable(0, true)
|
||||||
|
item.set_metadata(0, i)
|
||||||
|
%CheckButton.disabled = reference_changes.is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_change_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int) -> void:
|
||||||
|
if id == 0:
|
||||||
|
reference_changes.erase(item.get_metadata(0))
|
||||||
|
if item.get_parent().get_child_count() == 1:
|
||||||
|
item.get_parent().free()
|
||||||
|
else:
|
||||||
|
item.free()
|
||||||
|
update_indicator()
|
||||||
|
%CheckButton.disabled = reference_changes.is_empty()
|
||||||
|
|
||||||
|
if id == 1:
|
||||||
|
%ReplacementEditPanel.open_existing(item, item.get_metadata(0))
|
||||||
|
|
||||||
|
%ReplacementSection.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_change_tree_item_edited() -> void:
|
||||||
|
if !%ChangeTree.get_selected():
|
||||||
|
return
|
||||||
|
%CheckButton.disabled = false
|
||||||
|
|
||||||
|
|
||||||
|
func _on_check_button_pressed() -> void:
|
||||||
|
var to_be_checked :Array[Dictionary]= []
|
||||||
|
var item :TreeItem = %ChangeTree.get_root()
|
||||||
|
while item.get_next_visible():
|
||||||
|
item = item.get_next_visible()
|
||||||
|
|
||||||
|
if item.get_child_count():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if item.is_checked(0):
|
||||||
|
to_be_checked.append(item.get_metadata(0))
|
||||||
|
to_be_checked[-1]['item'] = item
|
||||||
|
to_be_checked[-1]['count'] = 0
|
||||||
|
|
||||||
|
open_finder(to_be_checked)
|
||||||
|
%CheckButton.disabled = true
|
||||||
|
|
||||||
|
|
||||||
|
func open_finder(replacements:Array[Dictionary]) -> void:
|
||||||
|
%ReplacementSection.show()
|
||||||
|
%Progress.show()
|
||||||
|
%ReferenceTree.hide()
|
||||||
|
|
||||||
|
search_regexes = []
|
||||||
|
for i in replacements:
|
||||||
|
if i.has('character_names') and !i.character_names.is_empty():
|
||||||
|
i['character_regex'] = RegEx.create_from_string("(?m)^(join|update|leave)?\\s*("+str(i.character_names).replace('"', '').replace(', ', '|').trim_suffix(']').trim_prefix('[').replace('/', '\\/')+")(?(1).*|.*:)")
|
||||||
|
|
||||||
|
for regex_string in i.regex:
|
||||||
|
var regex := RegEx.create_from_string(regex_string)
|
||||||
|
search_regexes.append([regex, i])
|
||||||
|
|
||||||
|
finder_thread = Thread.new()
|
||||||
|
progress_mutex = Mutex.new()
|
||||||
|
finder_thread.start(search_timelines.bind(search_regexes))
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if finder_thread and finder_thread.is_started():
|
||||||
|
if finder_thread.is_alive():
|
||||||
|
progress_mutex.lock()
|
||||||
|
%State.text = progress_message
|
||||||
|
%Progress.value = progress_percent
|
||||||
|
progress_mutex.unlock()
|
||||||
|
else:
|
||||||
|
var finds := finder_thread.wait_to_finish()
|
||||||
|
display_search_results(finds)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func display_search_results(finds:Array[Dictionary]) -> void:
|
||||||
|
%Progress.hide()
|
||||||
|
%ReferenceTree.show()
|
||||||
|
for regex_info in search_regexes:
|
||||||
|
regex_info[1]['item'].set_text(2, str(regex_info[1]['count']))
|
||||||
|
|
||||||
|
update_count_coloring()
|
||||||
|
%State.text = str(len(finds))+ " occurrences found"
|
||||||
|
|
||||||
|
%ReferenceTree.clear()
|
||||||
|
%ReferenceTree.set_column_expand(0, false)
|
||||||
|
%ReferenceTree.create_item()
|
||||||
|
|
||||||
|
var timelines := {}
|
||||||
|
var height := 0
|
||||||
|
for i in finds:
|
||||||
|
var parent: TreeItem = null
|
||||||
|
if !i.timeline in timelines:
|
||||||
|
parent = %ReferenceTree.create_item()
|
||||||
|
parent.set_text(1, i.timeline)
|
||||||
|
parent.set_custom_color(1, get_theme_color("disabled_font_color", "Editor"))
|
||||||
|
timelines[i.timeline] = parent
|
||||||
|
height += %ReferenceTree.get_item_area_rect(parent).size.y+10
|
||||||
|
else:
|
||||||
|
parent = timelines[i.timeline]
|
||||||
|
|
||||||
|
var item: TreeItem = %ReferenceTree.create_item(parent)
|
||||||
|
item.set_text(1, 'Line '+str(i.line_number)+': '+i.line)
|
||||||
|
item.set_tooltip_text(1, i.info.what+' -> '+i.info.forwhat)
|
||||||
|
item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK)
|
||||||
|
item.set_checked(0, true)
|
||||||
|
item.set_editable(0, true)
|
||||||
|
item.set_metadata(0, i)
|
||||||
|
height += %ReferenceTree.get_item_area_rect(item).size.y+10
|
||||||
|
var change_item: TreeItem = i.info.item
|
||||||
|
change_item.set_meta('found_items', change_item.get_meta('found_items', [])+[item])
|
||||||
|
|
||||||
|
%ReferenceTree.custom_minimum_size.y = min(height, 200)
|
||||||
|
|
||||||
|
%ReferenceTree.visible = !finds.is_empty()
|
||||||
|
%Replace.disabled = finds.is_empty()
|
||||||
|
if finds.is_empty():
|
||||||
|
%State.text = "Nothing found"
|
||||||
|
else:
|
||||||
|
%Replace.grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func search_timelines(regexes:Array[Array]) -> Array[Dictionary]:
|
||||||
|
var finds: Array[Dictionary] = []
|
||||||
|
|
||||||
|
var timeline_paths := DialogicResourceUtil.list_resources_of_type('.dtl')
|
||||||
|
|
||||||
|
var progress := 0
|
||||||
|
var progress_max: float = len(timeline_paths)*len(regexes)
|
||||||
|
|
||||||
|
for timeline_path:String in timeline_paths:
|
||||||
|
|
||||||
|
var timeline_file := FileAccess.open(timeline_path, FileAccess.READ)
|
||||||
|
var timeline_text: String = timeline_file.get_as_text()
|
||||||
|
var timeline_event: PackedStringArray = timeline_text.split('\n')
|
||||||
|
timeline_file.close()
|
||||||
|
|
||||||
|
for regex_info in regexes:
|
||||||
|
progress += 1
|
||||||
|
progress_mutex.lock()
|
||||||
|
progress_percent = 1/progress_max*progress
|
||||||
|
progress_message = "Searching '"+timeline_path+"' for "+regex_info[1].what+' -> '+regex_info[1].forwhat
|
||||||
|
progress_mutex.unlock()
|
||||||
|
for i in regex_info[0].search_all(timeline_text):
|
||||||
|
if regex_info[1].has('character_regex'):
|
||||||
|
if regex_info[1].character_regex.search(get_line(timeline_text, i.get_start()+1)) == null:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var line_number := timeline_text.count('\n', 0, i.get_start()+1)+1
|
||||||
|
var line := timeline_text.get_slice('\n', line_number-1)
|
||||||
|
finds.append({
|
||||||
|
'match':i,
|
||||||
|
'timeline':timeline_path,
|
||||||
|
'info': regex_info[1],
|
||||||
|
'line_number': line_number,
|
||||||
|
'line': line,
|
||||||
|
'line_start': timeline_text.rfind('\n', i.get_start())
|
||||||
|
})
|
||||||
|
regex_info[1]['count'] += 1
|
||||||
|
return finds
|
||||||
|
|
||||||
|
|
||||||
|
func _exit_tree() -> void:
|
||||||
|
# Shutting of
|
||||||
|
if finder_thread and finder_thread.is_alive():
|
||||||
|
finder_thread.wait_to_finish()
|
||||||
|
|
||||||
|
|
||||||
|
func get_line(string:String, at_index:int) -> String:
|
||||||
|
return string.substr(max(string.rfind('\n', at_index), 0), string.find('\n', at_index)-string.rfind('\n', at_index))
|
||||||
|
|
||||||
|
|
||||||
|
func update_count_coloring() -> void:
|
||||||
|
var item :TreeItem = %ChangeTree.get_root()
|
||||||
|
while item.get_next_visible():
|
||||||
|
item = item.get_next_visible()
|
||||||
|
|
||||||
|
if item.get_child_count():
|
||||||
|
continue
|
||||||
|
if int(item.get_text(2)) > 0:
|
||||||
|
item.set_custom_bg_color(1, get_theme_color("warning_color", "Editor").darkened(0.8))
|
||||||
|
item.set_custom_color(1, get_theme_color("warning_color", "Editor"))
|
||||||
|
item.set_custom_color(2, get_theme_color("warning_color", "Editor"))
|
||||||
|
else:
|
||||||
|
item.set_custom_color(2, get_theme_color("success_color", "Editor"))
|
||||||
|
item.set_custom_color(1, get_theme_color("readonly_font_color", "Editor"))
|
||||||
|
if item.get_button_count(1):
|
||||||
|
item.erase_button(1, 1)
|
||||||
|
item.add_button(1, get_theme_icon("Eraser", "EditorIcons"), -1, true, "This reference was not found anywhere and will be removed from this list.")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_replace_pressed() -> void:
|
||||||
|
var to_be_replaced :Array[Dictionary]= []
|
||||||
|
var item :TreeItem = %ReferenceTree.get_root()
|
||||||
|
var affected_timelines :Array[String]= []
|
||||||
|
|
||||||
|
while item.get_next_visible():
|
||||||
|
item = item.get_next_visible()
|
||||||
|
|
||||||
|
if item.get_child_count():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if item.is_checked(0):
|
||||||
|
to_be_replaced.append(item.get_metadata(0))
|
||||||
|
to_be_replaced[-1]['f_item'] = item
|
||||||
|
if !item.get_metadata(0).timeline in affected_timelines:
|
||||||
|
affected_timelines.append(item.get_metadata(0).timeline)
|
||||||
|
replace(affected_timelines, to_be_replaced)
|
||||||
|
|
||||||
|
|
||||||
|
func replace(timelines:Array[String], replacement_info:Array[Dictionary]) -> void:
|
||||||
|
var reopen_timeline := ""
|
||||||
|
var timeline_editor :DialogicEditor = find_parent('EditorView').editors_manager.editors['Timeline'].node
|
||||||
|
if timeline_editor.current_resource != null and timeline_editor.current_resource.resource_path in timelines:
|
||||||
|
reopen_timeline = timeline_editor.current_resource.resource_path
|
||||||
|
find_parent('EditorView').editors_manager.clear_editor(timeline_editor)
|
||||||
|
|
||||||
|
replacement_info.sort_custom(func(a,b): return a.match.get_start() < b.match.get_start())
|
||||||
|
|
||||||
|
for timeline_path in timelines:
|
||||||
|
%State.text = "Loading '"+timeline_path+"'"
|
||||||
|
|
||||||
|
var timeline_file := FileAccess.open(timeline_path, FileAccess.READ_WRITE)
|
||||||
|
var timeline_text :String = timeline_file.get_as_text()
|
||||||
|
var timeline_events := timeline_text.split('\n')
|
||||||
|
timeline_file.close()
|
||||||
|
|
||||||
|
var idx := 1
|
||||||
|
var offset_correction := 0
|
||||||
|
for replacement in replacement_info:
|
||||||
|
if replacement.timeline != timeline_path:
|
||||||
|
continue
|
||||||
|
|
||||||
|
%State.text = "Replacing in '"+timeline_path + "' ("+str(idx)+"/"+str(len(replacement_info))+")"
|
||||||
|
var group := 'replace'
|
||||||
|
if not 'replace' in replacement.match.names:
|
||||||
|
group = ''
|
||||||
|
|
||||||
|
|
||||||
|
timeline_text = timeline_text.substr(0, replacement.match.get_start(group) + offset_correction) + \
|
||||||
|
replacement.info.regex_replacement + \
|
||||||
|
timeline_text.substr(replacement.match.get_end(group) + offset_correction)
|
||||||
|
offset_correction += len(replacement.info.regex_replacement)-len(replacement.match.get_string(group))
|
||||||
|
|
||||||
|
replacement.info.count -= 1
|
||||||
|
replacement.info.item.set_text(2, str(replacement.info.count))
|
||||||
|
replacement.f_item.set_custom_bg_color(1, get_theme_color("success_color", "Editor").darkened(0.8))
|
||||||
|
|
||||||
|
timeline_file = FileAccess.open(timeline_path, FileAccess.WRITE)
|
||||||
|
timeline_file.store_string(timeline_text.strip_edges(false, true))
|
||||||
|
timeline_file.close()
|
||||||
|
|
||||||
|
if ResourceLoader.has_cached(timeline_path):
|
||||||
|
var tml := load(timeline_path)
|
||||||
|
tml.from_text(timeline_text)
|
||||||
|
|
||||||
|
if !reopen_timeline.is_empty():
|
||||||
|
find_parent('EditorView').editors_manager.edit_resource(load(reopen_timeline), false, true)
|
||||||
|
|
||||||
|
update_count_coloring()
|
||||||
|
|
||||||
|
%Replace.disabled = true
|
||||||
|
%CheckButton.disabled = false
|
||||||
|
%State.text = "Done Replacing"
|
||||||
|
|
||||||
|
|
||||||
|
func update_indicator() -> void:
|
||||||
|
%TabA.get_child(0).visible = !reference_changes.is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func close() -> void:
|
||||||
|
var item :TreeItem = %ChangeTree.get_root()
|
||||||
|
if item:
|
||||||
|
while item.get_next_visible():
|
||||||
|
item = item.get_next_visible()
|
||||||
|
|
||||||
|
if item.get_child_count():
|
||||||
|
continue
|
||||||
|
if item.get_text(2) != "" and int(item.get_text(2)) == 0:
|
||||||
|
reference_changes.erase(item.get_metadata(0))
|
||||||
|
for i in reference_changes:
|
||||||
|
i.item = null
|
||||||
|
DialogicUtil.set_editor_setting('reference_changes', reference_changes)
|
||||||
|
update_indicator()
|
||||||
|
find_parent("ReferenceManager").update_indicator()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_add_button_pressed() -> void:
|
||||||
|
%ReplacementEditPanel._on_add_pressed()
|
@ -0,0 +1,9 @@
|
|||||||
|
@tool
|
||||||
|
extends TextureRect
|
||||||
|
|
||||||
|
@export_multiline var hint_text = ""
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
texture = get_theme_icon("NodeInfo", "EditorIcons")
|
||||||
|
modulate = get_theme_color("contrast_color_1", "Editor")
|
||||||
|
tooltip_text = hint_text
|
@ -0,0 +1,21 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dbpkta2tjsqim"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.gd" id="1_x8t45"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_eiyxd"]
|
||||||
|
data = {
|
||||||
|
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||||
|
"format": "RGBA8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id="ImageTexture_lseut"]
|
||||||
|
image = SubResource("Image_eiyxd")
|
||||||
|
|
||||||
|
[node name="HintTooltip" type="TextureRect"]
|
||||||
|
modulate = Color(0, 0, 0, 1)
|
||||||
|
texture = SubResource("ImageTexture_lseut")
|
||||||
|
stretch_mode = 3
|
||||||
|
script = ExtResource("1_x8t45")
|
@ -0,0 +1,33 @@
|
|||||||
|
@tool
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
add_theme_stylebox_override("panel", get_theme_stylebox("Background", "EditorStyles"))
|
||||||
|
|
||||||
|
for tab in $Tabs/Tabs.get_children():
|
||||||
|
tab.add_theme_color_override("font_selected_color", get_theme_color("accent_color", "Editor"))
|
||||||
|
tab.add_theme_font_override("font", get_theme_font("main", "EditorFonts"))
|
||||||
|
tab.toggled.connect(tab_changed.bind(tab.get_index()+1))
|
||||||
|
|
||||||
|
|
||||||
|
func tab_changed(enabled:bool, index:int) -> void:
|
||||||
|
for child in $Tabs.get_children():
|
||||||
|
if child.get_index() == 0 or child.get_index() == index:
|
||||||
|
child.show()
|
||||||
|
if child.get_index() == index:
|
||||||
|
child.open()
|
||||||
|
else:
|
||||||
|
if child.visible:
|
||||||
|
child.close()
|
||||||
|
child.hide()
|
||||||
|
for child in $Tabs/Tabs.get_children():
|
||||||
|
child.set_pressed_no_signal(index-1 == child.get_index())
|
||||||
|
|
||||||
|
|
||||||
|
func open():
|
||||||
|
show()
|
||||||
|
$Tabs/BrokenReferences.update_indicator()
|
@ -0,0 +1,319 @@
|
|||||||
|
[gd_scene load_steps=13 format=3 uid="uid://c7lmt5cp7bxcm"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/reference_manager.gd" id="1_3t531"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/broken_reference_manager.gd" id="1_agmg4"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd" id="2_tt4jd"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_yomsc"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/unique_identifiers_manager.gd" id="5_wnvbq"]
|
||||||
|
|
||||||
|
[sub_resource type="ButtonGroup" id="ButtonGroup_l6uiy"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_ii0d5"]
|
||||||
|
data = {
|
||||||
|
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||||
|
"format": "RGBA8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id="ImageTexture_a0gfq"]
|
||||||
|
image = SubResource("Image_ii0d5")
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_k5gyt"]
|
||||||
|
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_8oycd"]
|
||||||
|
image = SubResource("Image_k5gyt")
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_qpnp8"]
|
||||||
|
data = {
|
||||||
|
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||||
|
"format": "RGBA8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id="ImageTexture_lce2m"]
|
||||||
|
image = SubResource("Image_qpnp8")
|
||||||
|
|
||||||
|
[node name="Manager" type="PanelContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_3t531")
|
||||||
|
|
||||||
|
[node name="Tabs" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Tabs" type="HBoxContainer" parent="Tabs"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="TabA" type="Button" parent="Tabs/Tabs"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
toggle_mode = true
|
||||||
|
button_pressed = true
|
||||||
|
text = "Broken References"
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="TabB" type="Button" parent="Tabs/Tabs"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
toggle_mode = true
|
||||||
|
button_group = SubResource("ButtonGroup_l6uiy")
|
||||||
|
text = "Unique Identifiers"
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="BrokenReferences" type="VSplitContainer" parent="Tabs"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("1_agmg4")
|
||||||
|
|
||||||
|
[node name="ChangesList" type="PanelContainer" parent="Tabs/BrokenReferences"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_type_variation = &"DialogicPanelA"
|
||||||
|
|
||||||
|
[node name="VBox" type="VBoxContainer" parent="Tabs/BrokenReferences/ChangesList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="SectionTitle" type="Label" parent="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 16
|
||||||
|
text = "Recent renames"
|
||||||
|
|
||||||
|
[node name="AddButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 2
|
||||||
|
tooltip_text = "Add custom rename"
|
||||||
|
icon = SubResource("ImageTexture_a0gfq")
|
||||||
|
|
||||||
|
[node name="ReplacementEditPanel" type="PanelContainer" parent="Tabs/BrokenReferences/ChangesList/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_tt4jd")
|
||||||
|
|
||||||
|
[node name="VBox" type="HFlowContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer3" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Type" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer3"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "This decides the regexes for searching. Pure text allows you to enter your own regex into into \"Old\". "
|
||||||
|
item_count = 5
|
||||||
|
selected = 0
|
||||||
|
popup/item_0/text = "Pure Text"
|
||||||
|
popup/item_0/id = 0
|
||||||
|
popup/item_1/text = "Variable"
|
||||||
|
popup/item_1/id = 1
|
||||||
|
popup/item_2/text = "Portrait"
|
||||||
|
popup/item_2/id = 2
|
||||||
|
popup/item_3/text = "Character (Ref)"
|
||||||
|
popup/item_3/id = 3
|
||||||
|
popup/item_4/text = "Timeline (Ref)"
|
||||||
|
popup/item_4/id = 4
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Old" type="LineEdit" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
placeholder_text = "Old"
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "->"
|
||||||
|
|
||||||
|
[node name="New" type="LineEdit" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
placeholder_text = "New"
|
||||||
|
|
||||||
|
[node name="PureTextFlags" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 2
|
||||||
|
|
||||||
|
[node name="MatchCase" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/PureTextFlags"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Match Case"
|
||||||
|
toggle_mode = true
|
||||||
|
icon = SubResource("ImageTexture_8oycd")
|
||||||
|
|
||||||
|
[node name="WholeWords" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/PureTextFlags"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Whole World"
|
||||||
|
toggle_mode = true
|
||||||
|
icon = SubResource("ImageTexture_8oycd")
|
||||||
|
|
||||||
|
[node name="HBoxContainer4" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Where" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
item_count = 3
|
||||||
|
selected = 0
|
||||||
|
fit_to_longest_item = false
|
||||||
|
popup/item_0/text = "Everywhere"
|
||||||
|
popup/item_0/id = 0
|
||||||
|
popup/item_1/text = "Only for Character"
|
||||||
|
popup/item_1/id = 1
|
||||||
|
popup/item_2/text = "Texts only"
|
||||||
|
popup/item_2/id = 2
|
||||||
|
|
||||||
|
[node name="Character" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4" instance=ExtResource("3_yomsc")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="AddButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Add/Save"
|
||||||
|
|
||||||
|
[node name="ChangeTree" type="Tree" parent="Tabs/BrokenReferences/ChangesList/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(0, 50)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/draw_relationship_lines = 1
|
||||||
|
columns = 3
|
||||||
|
hide_root = true
|
||||||
|
|
||||||
|
[node name="CheckButton" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
tooltip_text = "Search timelines for occurences of these renames"
|
||||||
|
text = "Check Selected"
|
||||||
|
icon = SubResource("ImageTexture_lce2m")
|
||||||
|
|
||||||
|
[node name="ReplacementSection" type="PanelContainer" parent="Tabs/BrokenReferences"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicPanelA"
|
||||||
|
|
||||||
|
[node name="FindList" type="VBoxContainer" parent="Tabs/BrokenReferences/ReplacementSection"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="HBox" type="HBoxContainer" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="SectionTitle2" type="Label" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 16
|
||||||
|
text = "Found references"
|
||||||
|
|
||||||
|
[node name="State" type="Label" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 8
|
||||||
|
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||||
|
text = "State"
|
||||||
|
|
||||||
|
[node name="ReferenceTree" type="Tree" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/draw_relationship_lines = 1
|
||||||
|
columns = 2
|
||||||
|
hide_root = true
|
||||||
|
|
||||||
|
[node name="Progress" type="ProgressBar" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
max_value = 1.0
|
||||||
|
|
||||||
|
[node name="Replace" type="Button" parent="Tabs/BrokenReferences/ReplacementSection/FindList"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
tooltip_text = "Replace all selected findings (Careful, no undo!)"
|
||||||
|
text = "Replace Selected"
|
||||||
|
icon = SubResource("ImageTexture_lce2m")
|
||||||
|
|
||||||
|
[node name="UniqueIdentifiers" type="PanelContainer" parent="Tabs"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_type_variation = &"DialogicPanelA"
|
||||||
|
script = ExtResource("5_wnvbq")
|
||||||
|
|
||||||
|
[node name="VBox" type="VBoxContainer" parent="Tabs/UniqueIdentifiers"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Tools" type="HBoxContainer" parent="Tabs/UniqueIdentifiers/VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="Search" type="LineEdit" parent="Tabs/UniqueIdentifiers/VBox/Tools"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(400, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
placeholder_text = "Search"
|
||||||
|
|
||||||
|
[node name="IdentifierTable" type="Tree" parent="Tabs/UniqueIdentifiers/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
columns = 2
|
||||||
|
column_titles_visible = true
|
||||||
|
hide_root = true
|
||||||
|
|
||||||
|
[node name="RenameNotification" type="Label" parent="Tabs/UniqueIdentifiers/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(100, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "You've renamed some identifier(s)! Use the \"Broken References\" tab to check if you have used this identifier (and fix it if so)."
|
||||||
|
autowrap_mode = 3
|
||||||
|
|
||||||
|
[node name="HelpButton" type="LinkButton" parent="."]
|
||||||
|
custom_minimum_size = Vector2(0, 30)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 8
|
||||||
|
size_flags_vertical = 0
|
||||||
|
text = "What is this about?"
|
||||||
|
uri = "https://docs.dialogic.pro/reference-manager.html"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/HBoxContainer/AddButton" to="Tabs/BrokenReferences" method="_on_add_button_pressed"]
|
||||||
|
[connection signal="item_selected" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer3/Type" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="_on_type_item_selected"]
|
||||||
|
[connection signal="item_selected" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4/Where" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="_on_where_item_selected"]
|
||||||
|
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/AddButton" to="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel" method="save"]
|
||||||
|
[connection signal="button_clicked" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_button_clicked"]
|
||||||
|
[connection signal="item_edited" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_item_edited"]
|
||||||
|
[connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/CheckButton" to="Tabs/BrokenReferences" method="_on_check_button_pressed"]
|
||||||
|
[connection signal="pressed" from="Tabs/BrokenReferences/ReplacementSection/FindList/Replace" to="Tabs/BrokenReferences" method="_on_replace_pressed"]
|
||||||
|
[connection signal="text_changed" from="Tabs/UniqueIdentifiers/VBox/Tools/Search" to="Tabs/UniqueIdentifiers" method="_on_search_text_changed"]
|
||||||
|
[connection signal="button_clicked" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_button_clicked"]
|
||||||
|
[connection signal="item_edited" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_item_edited"]
|
@ -0,0 +1,191 @@
|
|||||||
|
@tool
|
||||||
|
extends Window
|
||||||
|
|
||||||
|
## This window manages communication with the replacement manager it contains.
|
||||||
|
## Other scripts can call the add_ref_change() method to register changes directly
|
||||||
|
## or use the helpers add_variable_ref_change() and add_portrait_ref_change()
|
||||||
|
|
||||||
|
@onready var editors_manager := get_node("../Margin/EditorsManager")
|
||||||
|
@onready var broken_manager := get_node("Manager/Tabs/BrokenReferences")
|
||||||
|
enum Where {EVERYWHERE, BY_CHARACTER, TEXTS_ONLY}
|
||||||
|
enum Types {TEXT, VARIABLE, PORTRAIT, CHARACTER_NAME, TIMELINE_NAME}
|
||||||
|
|
||||||
|
var icon_button :Button = null
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if owner.get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
$Manager.theme = owner.get_theme()
|
||||||
|
|
||||||
|
icon_button = editors_manager.add_icon_button(get_theme_icon("Unlinked", "EditorIcons"), 'Reference Manager')
|
||||||
|
icon_button.pressed.connect(open)
|
||||||
|
|
||||||
|
var dot := Sprite2D.new()
|
||||||
|
dot.texture = get_theme_icon("GuiGraphNodePort", "EditorIcons")
|
||||||
|
dot.scale = Vector2(0.8, 0.8)
|
||||||
|
dot.z_index = 10
|
||||||
|
dot.position = Vector2(icon_button.size.x*0.8, icon_button.size.x*0.2)
|
||||||
|
dot.modulate = get_theme_color("warning_color", "Editor").lightened(0.5)
|
||||||
|
|
||||||
|
icon_button.add_child(dot)
|
||||||
|
|
||||||
|
var old_changes :Array = DialogicUtil.get_editor_setting('reference_changes', [])
|
||||||
|
if !old_changes.is_empty():
|
||||||
|
broken_manager.reference_changes = old_changes
|
||||||
|
|
||||||
|
update_indicator()
|
||||||
|
|
||||||
|
hide()
|
||||||
|
|
||||||
|
get_parent().plugin_reference.get_editor_interface().get_file_system_dock().files_moved.connect(_on_file_moved)
|
||||||
|
get_parent().plugin_reference.get_editor_interface().get_file_system_dock().file_removed.connect(_on_file_removed)
|
||||||
|
get_parent().get_node('ResourceRenameWarning').confirmed.connect(open)
|
||||||
|
|
||||||
|
|
||||||
|
func add_ref_change(old_name:String, new_name:String, type:Types, where:=Where.TEXTS_ONLY, character_names:=[],
|
||||||
|
whole_words:=false, case_sensitive:=false, previous:Dictionary = {}) -> void:
|
||||||
|
var regexes := []
|
||||||
|
var category_name := ""
|
||||||
|
match type:
|
||||||
|
Types.TEXT:
|
||||||
|
category_name = "Texts"
|
||||||
|
if '<replace>' in old_name:
|
||||||
|
regexes = [old_name]
|
||||||
|
else:
|
||||||
|
regexes = [
|
||||||
|
r'(?<replace>%s)' % old_name.replace('/', '\\/')
|
||||||
|
]
|
||||||
|
if !case_sensitive:
|
||||||
|
regexes[0] = '(?i)'+regexes[0]
|
||||||
|
if whole_words:
|
||||||
|
regexes = ['\\b'+regexes[0]+'\\b']
|
||||||
|
|
||||||
|
Types.VARIABLE:
|
||||||
|
regexes = [
|
||||||
|
r'{(?<replace>\s*%s\s*)}' % old_name.replace("/", "\\/"),
|
||||||
|
r'var\s*=\s*"(?<replace>\s*%s\s*)"' % old_name.replace("/", "\\/")
|
||||||
|
]
|
||||||
|
category_name = "Variables"
|
||||||
|
|
||||||
|
Types.PORTRAIT:
|
||||||
|
regexes = [
|
||||||
|
r'(?m)^[^:(\n]*\((?<replace>%s)\)' % old_name.replace('/', '\\/'),
|
||||||
|
r'\[\s*portrait\s*=(?<replace>\s*%s\s*)\]' % old_name.replace('/', '\\/')
|
||||||
|
]
|
||||||
|
category_name = "Portraits by "+character_names[0]
|
||||||
|
|
||||||
|
Types.CHARACTER_NAME:
|
||||||
|
# for reference: ((join|leave|update) )?(?<replace>NAME)(?!\B)(?(1)|(?!([^:\n]|\\:)*(\n|$)))
|
||||||
|
regexes = [
|
||||||
|
r'((join|leave|update) )?(?<replace>%s)(?!\B)(?(1)|(?!([^:\n]|\\:)*(\n|$)))' % old_name
|
||||||
|
]
|
||||||
|
category_name = "Renamed Character Files"
|
||||||
|
|
||||||
|
Types.TIMELINE_NAME:
|
||||||
|
regexes = [
|
||||||
|
r'timeline ?= ?" ?(?<replace>%s) ?"' % old_name
|
||||||
|
]
|
||||||
|
category_name = "Renamed Timeline Files"
|
||||||
|
|
||||||
|
if where != Where.BY_CHARACTER:
|
||||||
|
character_names = []
|
||||||
|
|
||||||
|
# previous is only given when an existing item is edited
|
||||||
|
# in that case the old one is removed first
|
||||||
|
var idx := len(broken_manager.reference_changes)
|
||||||
|
if previous in broken_manager.reference_changes:
|
||||||
|
idx = broken_manager.reference_changes.find(previous)
|
||||||
|
broken_manager.reference_changes.erase(previous)
|
||||||
|
|
||||||
|
if _check_for_ref_change_cycle(old_name, new_name, category_name):
|
||||||
|
update_indicator()
|
||||||
|
return
|
||||||
|
|
||||||
|
broken_manager.reference_changes.insert(idx,
|
||||||
|
{'what':old_name,
|
||||||
|
'forwhat':new_name,
|
||||||
|
'regex': regexes,
|
||||||
|
'regex_replacement':new_name,
|
||||||
|
'category':category_name,
|
||||||
|
'character_names':character_names,
|
||||||
|
'texts_only':where == Where.TEXTS_ONLY,
|
||||||
|
'type':type
|
||||||
|
})
|
||||||
|
|
||||||
|
update_indicator()
|
||||||
|
|
||||||
|
if visible:
|
||||||
|
$Manager.open()
|
||||||
|
broken_manager.open()
|
||||||
|
|
||||||
|
|
||||||
|
## Checks for reference cycles or chains.
|
||||||
|
## E.g. if you first rename a portrait from "happy" to "happy1" and then to "Happy/happy1"
|
||||||
|
## This will make sure only a change "happy" -> "Happy/happy1" is remembered
|
||||||
|
## This is very important for correct replacement
|
||||||
|
func _check_for_ref_change_cycle(old_name:String, new_name:String, category:String) -> bool:
|
||||||
|
for ref in broken_manager.reference_changes:
|
||||||
|
if ref['forwhat'] == old_name and ref['category'] == category:
|
||||||
|
if new_name == ref['what']:
|
||||||
|
broken_manager.reference_changes.erase(ref)
|
||||||
|
else:
|
||||||
|
broken_manager.reference_changes[broken_manager.reference_changes.find(ref)]['forwhat'] = new_name
|
||||||
|
broken_manager.reference_changes[broken_manager.reference_changes.find(ref)]['regex_replacement'] = new_name
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
## Helper for adding variable ref changes
|
||||||
|
func add_variable_ref_change(old_name:String, new_name:String) -> void:
|
||||||
|
add_ref_change(old_name, new_name, Types.VARIABLE, Where.EVERYWHERE)
|
||||||
|
|
||||||
|
|
||||||
|
## Helper for adding portrait ref changes
|
||||||
|
func add_portrait_ref_change(old_name:String, new_name:String, character_names:PackedStringArray) -> void:
|
||||||
|
add_ref_change(old_name, new_name, Types.PORTRAIT, Where.BY_CHARACTER, character_names)
|
||||||
|
|
||||||
|
|
||||||
|
## Helper for adding character name ref changes
|
||||||
|
func add_character_name_ref_change(old_name:String, new_name:String) -> void:
|
||||||
|
add_ref_change(old_name, new_name, Types.CHARACTER_NAME, Where.EVERYWHERE)
|
||||||
|
|
||||||
|
|
||||||
|
## Helper for adding timeline name ref changes
|
||||||
|
func add_timeline_name_ref_change(old_name:String, new_name:String) -> void:
|
||||||
|
add_ref_change(old_name, new_name, Types.TIMELINE_NAME, Where.EVERYWHERE)
|
||||||
|
|
||||||
|
|
||||||
|
func open() -> void:
|
||||||
|
DialogicResourceUtil.update_directory('dch')
|
||||||
|
DialogicResourceUtil.update_directory('dtl')
|
||||||
|
popup_centered_ratio(0.5)
|
||||||
|
move_to_foreground()
|
||||||
|
grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_close_requested() -> void:
|
||||||
|
hide()
|
||||||
|
broken_manager.close()
|
||||||
|
|
||||||
|
|
||||||
|
func update_indicator() -> void:
|
||||||
|
icon_button.get_child(0).visible = !broken_manager.reference_changes.is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
## FILE MANAGEMENT:
|
||||||
|
func _on_file_moved(old_file:String, new_file:String) -> void:
|
||||||
|
if old_file.ends_with('.dch') and new_file.ends_with('.dch'):
|
||||||
|
DialogicResourceUtil.change_resource_path(old_file, new_file)
|
||||||
|
if old_file.get_file() != new_file.get_file():
|
||||||
|
get_parent().get_node('ResourceRenameWarning').popup_centered()
|
||||||
|
elif old_file.ends_with('.dtl') and new_file.ends_with('.dtl'):
|
||||||
|
DialogicResourceUtil.change_resource_path(old_file, new_file)
|
||||||
|
if old_file.get_file() != new_file.get_file():
|
||||||
|
get_parent().get_node('ResourceRenameWarning').popup_centered()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_file_removed(file:String) -> void:
|
||||||
|
if file.get_extension() in ['dch', 'dtl']:
|
||||||
|
DialogicResourceUtil.remove_resource(file)
|
@ -0,0 +1,100 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://cwe3r2tbh2og1"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/sidebar.gd" id="1_jnq65"]
|
||||||
|
|
||||||
|
[sub_resource type="Theme" id="Theme_pn0f4"]
|
||||||
|
VBoxContainer/constants/separation = 4
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_gxwm6"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_n8rql"]
|
||||||
|
|
||||||
|
[node name="SideBar" type="VSplitContainer"]
|
||||||
|
custom_minimum_size = Vector2(100, 130)
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme = SubResource("Theme_pn0f4")
|
||||||
|
split_offset = 100
|
||||||
|
script = ExtResource("1_jnq65")
|
||||||
|
|
||||||
|
[node name="VBox" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="Margin" type="MarginContainer" parent="VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/margin_left = 5
|
||||||
|
theme_override_constants/margin_bottom = 5
|
||||||
|
|
||||||
|
[node name="VSplitContainer" type="VSplitContainer" parent="VBox/Margin"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBox" type="VBoxContainer" parent="VBox/Margin/VSplitContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="Logo" type="TextureRect" parent="VBox/Margin/VSplitContainer/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
modulate = Color(1, 1, 1, 0.623529)
|
||||||
|
texture_filter = 6
|
||||||
|
custom_minimum_size = Vector2(0, 25)
|
||||||
|
layout_mode = 2
|
||||||
|
expand_mode = 3
|
||||||
|
stretch_mode = 4
|
||||||
|
|
||||||
|
[node name="CurrentResource" type="Label" parent="VBox/Margin/VSplitContainer/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "No resource"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
text_overrun_behavior = 1
|
||||||
|
|
||||||
|
[node name="Search" type="LineEdit" parent="VBox/Margin/VSplitContainer/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
placeholder_text = "Filter Resources"
|
||||||
|
caret_blink = true
|
||||||
|
caret_blink_interval = 0.5
|
||||||
|
|
||||||
|
[node name="ResourcesList" type="ItemList" parent="VBox/Margin/VSplitContainer/VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
same_column_width = true
|
||||||
|
|
||||||
|
[node name="ContentListSection" type="VBoxContainer" parent="VBox/Margin/VSplitContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="ContentList" type="ItemList" parent="VBox/Margin/VSplitContainer/ContentListSection"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
tooltip_text = "Label events in your timeline will appear here, allowing you to jump to them."
|
||||||
|
theme_override_styles/selected = SubResource("StyleBoxEmpty_gxwm6")
|
||||||
|
theme_override_styles/selected_focus = SubResource("StyleBoxEmpty_n8rql")
|
||||||
|
allow_reselect = true
|
||||||
|
same_column_width = true
|
||||||
|
|
||||||
|
[node name="CurrentVersion" type="Button" parent="VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Some Version"
|
||||||
|
flat = true
|
||||||
|
clip_text = true
|
||||||
|
|
||||||
|
[node name="RightClickMenu" type="PopupMenu" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
size = Vector2i(164, 100)
|
||||||
|
|
||||||
|
[connection signal="gui_input" from="VBox/Margin/VSplitContainer/VBox/Logo" to="." method="_on_logo_gui_input"]
|
||||||
|
[connection signal="text_changed" from="VBox/Margin/VSplitContainer/VBox/Search" to="." method="_on_search_text_changed"]
|
||||||
|
[connection signal="pressed" from="VBox/CurrentVersion" to="." method="_on_current_version_pressed"]
|
||||||
|
[connection signal="id_pressed" from="RightClickMenu" to="." method="_on_right_click_menu_id_pressed"]
|
@ -0,0 +1,188 @@
|
|||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
## Script that handles the editor sidebar.
|
||||||
|
|
||||||
|
signal file_activated(file_path)
|
||||||
|
|
||||||
|
signal content_item_activated(item_name)
|
||||||
|
|
||||||
|
@onready var editors_manager = get_parent().get_parent()
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if owner.get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
## CONNECTIONS
|
||||||
|
%ResourcesList.item_selected.connect(_on_resources_list_item_selected)
|
||||||
|
%ResourcesList.item_clicked.connect(_on_resources_list_item_clicked)
|
||||||
|
editors_manager.resource_opened.connect(_on_editors_resource_opened)
|
||||||
|
editors_manager.editor_changed.connect(_on_editors_editor_changed)
|
||||||
|
|
||||||
|
%ContentList.item_selected.connect(func (idx:int): content_item_activated.emit(%ContentList.get_item_text(idx)))
|
||||||
|
|
||||||
|
var editor_scale := DialogicUtil.get_editor_scale()
|
||||||
|
## ICONS
|
||||||
|
%Logo.texture = load("res://addons/dialogic/Editor/Images/dialogic-logo.svg")
|
||||||
|
%Logo.custom_minimum_size.y = 30 * editor_scale
|
||||||
|
%Search.right_icon = get_theme_icon("Search", "EditorIcons")
|
||||||
|
|
||||||
|
%CurrentResource.add_theme_stylebox_override('normal', get_theme_stylebox('normal', 'LineEdit'))
|
||||||
|
|
||||||
|
%ContentList.add_theme_color_override("font_hovered_color", get_theme_color("warning_color", "Editor"))
|
||||||
|
%ContentList.add_theme_color_override("font_selected_color", get_theme_color("property_color_z", "Editor"))
|
||||||
|
|
||||||
|
## MARGINS
|
||||||
|
$VBox/Margin.set("theme_override_constants/margin_left", get_theme_constant("base_margin", "Editor") * editor_scale)
|
||||||
|
$VBox/Margin.set("theme_override_constants/margin_bottom", get_theme_constant("base_margin", "Editor") * editor_scale)
|
||||||
|
|
||||||
|
## RIGHT CLICK MENU
|
||||||
|
%RightClickMenu.clear()
|
||||||
|
%RightClickMenu.add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Remove From List", 1)
|
||||||
|
%RightClickMenu.add_separator()
|
||||||
|
%RightClickMenu.add_icon_item(get_theme_icon("Filesystem", "EditorIcons"), "Show in FileSystem", 2)
|
||||||
|
%RightClickMenu.add_icon_item(get_theme_icon("ExternalLink", "EditorIcons"), "Open in External Program", 3)
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
## RESOURCE LIST
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_editors_resource_opened(resource:Resource) -> void:
|
||||||
|
update_resource_list()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_editors_editor_changed(previous:DialogicEditor, current:DialogicEditor) -> void:
|
||||||
|
%ContentListSection.visible = current.current_resource is DialogicTimeline
|
||||||
|
update_resource_list()
|
||||||
|
|
||||||
|
|
||||||
|
func clean_resource_list(resources_list:Array = []) -> PackedStringArray:
|
||||||
|
return PackedStringArray(resources_list.filter(func(x): return ResourceLoader.exists(x)))
|
||||||
|
|
||||||
|
|
||||||
|
func update_resource_list(resources_list:PackedStringArray = []) -> void:
|
||||||
|
var filter :String = %Search.text
|
||||||
|
var current_file := ""
|
||||||
|
if editors_manager.current_editor and editors_manager.current_editor.current_resource:
|
||||||
|
current_file = editors_manager.current_editor.current_resource.resource_path
|
||||||
|
|
||||||
|
var character_directory: Dictionary = DialogicResourceUtil.get_character_directory()
|
||||||
|
var timeline_directory: Dictionary = DialogicResourceUtil.get_timeline_directory()
|
||||||
|
if resources_list.is_empty():
|
||||||
|
resources_list = DialogicUtil.get_editor_setting('last_resources', [])
|
||||||
|
if !current_file in resources_list:
|
||||||
|
resources_list.append(current_file)
|
||||||
|
|
||||||
|
resources_list = clean_resource_list(resources_list)
|
||||||
|
|
||||||
|
%CurrentResource.text = "No Resource"
|
||||||
|
%CurrentResource.add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"))
|
||||||
|
|
||||||
|
%ResourcesList.clear()
|
||||||
|
var idx := 0
|
||||||
|
for character_name in character_directory:
|
||||||
|
if character_directory[character_name] in resources_list:
|
||||||
|
if filter.is_empty() or filter.to_lower() in character_name.to_lower():
|
||||||
|
%ResourcesList.add_item(
|
||||||
|
character_name,
|
||||||
|
load("res://addons/dialogic/Editor/Images/Resources/character.svg"))
|
||||||
|
%ResourcesList.set_item_metadata(idx, character_directory[character_name])
|
||||||
|
%ResourcesList.set_item_tooltip(idx, character_directory[character_name])
|
||||||
|
if character_directory[character_name] == current_file:
|
||||||
|
%ResourcesList.select(idx)
|
||||||
|
%ResourcesList.set_item_custom_fg_color(idx, get_theme_color("accent_color", "Editor"))
|
||||||
|
%CurrentResource.text = character_directory[character_name].get_file()
|
||||||
|
idx += 1
|
||||||
|
for timeline_name in timeline_directory:
|
||||||
|
if timeline_directory[timeline_name] in resources_list:
|
||||||
|
if filter.is_empty() or filter.to_lower() in timeline_name.to_lower():
|
||||||
|
%ResourcesList.add_item(timeline_name, get_theme_icon("TripleBar", "EditorIcons"))
|
||||||
|
%ResourcesList.set_item_metadata(idx, timeline_directory[timeline_name])
|
||||||
|
if timeline_directory[timeline_name] == current_file:
|
||||||
|
%ResourcesList.select(idx)
|
||||||
|
%ResourcesList.set_item_custom_fg_color(idx, get_theme_color("accent_color", "Editor"))
|
||||||
|
%CurrentResource.text = timeline_name+'.dtl'
|
||||||
|
idx += 1
|
||||||
|
if %CurrentResource.text != "No Resource":
|
||||||
|
%CurrentResource.add_theme_color_override("font_color", get_theme_color("font_color", "Editor"))
|
||||||
|
%ResourcesList.sort_items_by_text()
|
||||||
|
DialogicUtil.set_editor_setting('last_resources', resources_list)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_resources_list_item_selected(index:int) -> void:
|
||||||
|
if %ResourcesList.get_item_metadata(index) == null:
|
||||||
|
return
|
||||||
|
editors_manager.edit_resource(load(%ResourcesList.get_item_metadata(index)))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_resources_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void:
|
||||||
|
# If clicked with the middle mouse button, remove the item from the list
|
||||||
|
if mouse_button_index == MOUSE_BUTTON_MIDDLE:
|
||||||
|
remove_item_from_list(index)
|
||||||
|
if mouse_button_index == MOUSE_BUTTON_RIGHT:
|
||||||
|
%RightClickMenu.popup_on_parent(Rect2(get_global_mouse_position(), Vector2()))
|
||||||
|
%RightClickMenu.set_meta('item_index', index)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_search_text_changed(new_text:String) -> void:
|
||||||
|
update_resource_list()
|
||||||
|
|
||||||
|
|
||||||
|
func set_unsaved_indicator(saved:bool = true) -> void:
|
||||||
|
if saved and %CurrentResource.text.ends_with('(*)'):
|
||||||
|
%CurrentResource.text = %CurrentResource.text.trim_suffix('(*)')
|
||||||
|
if not saved and not %CurrentResource.text.ends_with('(*)'):
|
||||||
|
%CurrentResource.text = %CurrentResource.text+"(*)"
|
||||||
|
|
||||||
|
|
||||||
|
func _on_logo_gui_input(event:InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||||
|
editors_manager.open_editor(editors_manager.editors['HomePage'].node)
|
||||||
|
|
||||||
|
|
||||||
|
func update_content_list(list:PackedStringArray) -> void:
|
||||||
|
var prev_selected := ""
|
||||||
|
if %ContentList.is_anything_selected():
|
||||||
|
prev_selected = %ContentList.get_item_text(%ContentList.get_selected_items()[0])
|
||||||
|
%ContentList.clear()
|
||||||
|
%ContentList.add_item('~ Top')
|
||||||
|
for i in list:
|
||||||
|
if i.is_empty(): continue
|
||||||
|
%ContentList.add_item(i)
|
||||||
|
if i == prev_selected:
|
||||||
|
%ContentList.select(%ContentList.item_count-1)
|
||||||
|
if list.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var current_resource: Resource = editors_manager.get_current_editor().current_resource
|
||||||
|
|
||||||
|
var timeline_directory := DialogicResourceUtil.get_timeline_directory()
|
||||||
|
var label_directory := DialogicResourceUtil.get_label_cache()
|
||||||
|
if current_resource != null:
|
||||||
|
for i in timeline_directory:
|
||||||
|
if timeline_directory[i] == current_resource.resource_path:
|
||||||
|
label_directory[i] = list
|
||||||
|
|
||||||
|
# also always store the current timelines labels for easy access
|
||||||
|
label_directory[""] = list
|
||||||
|
|
||||||
|
DialogicResourceUtil.set_label_cache(label_directory)
|
||||||
|
|
||||||
|
func remove_item_from_list(index) -> void:
|
||||||
|
var new_list := []
|
||||||
|
for entry in DialogicUtil.get_editor_setting('last_resources', []):
|
||||||
|
if entry != %ResourcesList.get_item_metadata(index):
|
||||||
|
new_list.append(entry)
|
||||||
|
DialogicUtil.set_editor_setting('last_resources', new_list)
|
||||||
|
%ResourcesList.remove_item(index)
|
||||||
|
|
||||||
|
func _on_right_click_menu_id_pressed(id:int) -> void:
|
||||||
|
match id:
|
||||||
|
1: # REMOVE ITEM FROM LIST
|
||||||
|
remove_item_from_list(%RightClickMenu.get_meta("item_index"))
|
||||||
|
2: # OPEN IN FILESYSTEM
|
||||||
|
EditorInterface.get_file_system_dock().navigate_to_path(%ResourcesList.get_item_metadata(%RightClickMenu.get_meta("item_index")))
|
||||||
|
3: # OPEN IN EXTERNAL EDITOR
|
||||||
|
OS.shell_open(ProjectSettings.globalize_path(%ResourcesList.get_item_metadata(%RightClickMenu.get_meta("item_index"))))
|
@ -0,0 +1,49 @@
|
|||||||
|
@tool
|
||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
# Dialogic Editor toolbar. Works together with editors_mangager.
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
## EDITOR BUTTONS/LABELS
|
||||||
|
################################################################################
|
||||||
|
func _ready():
|
||||||
|
if owner.get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
%CustomButtons.custom_minimum_size.y = 33 * DialogicUtil.get_editor_scale()
|
||||||
|
|
||||||
|
for child in get_children():
|
||||||
|
if child is Button:
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func add_icon_button(icon: Texture, tooltip: String) -> Button:
|
||||||
|
var button := Button.new()
|
||||||
|
button.icon = icon
|
||||||
|
button.tooltip_text = tooltip
|
||||||
|
button.flat = true
|
||||||
|
button.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||||
|
button.add_theme_color_override('icon_hover_color', get_theme_color('warning_color', 'Editor'))
|
||||||
|
button.add_theme_stylebox_override('focus', StyleBoxEmpty.new())
|
||||||
|
add_child(button)
|
||||||
|
move_child(button, -2)
|
||||||
|
return button
|
||||||
|
|
||||||
|
|
||||||
|
func add_custom_button(label:String, icon:Texture) -> Button:
|
||||||
|
var button := Button.new()
|
||||||
|
button.text = label
|
||||||
|
button.icon = icon
|
||||||
|
# button.flat = true
|
||||||
|
|
||||||
|
button.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||||
|
%CustomButtons.add_child(button)
|
||||||
|
# custom_minimum_size.y = button.size.y
|
||||||
|
return button
|
||||||
|
|
||||||
|
|
||||||
|
func hide_all_custom_buttons() -> void:
|
||||||
|
for button in %CustomButtons.get_children():
|
||||||
|
button.hide()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
@tool
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if owner.get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
%TabB.text = "Unique Identifiers"
|
||||||
|
%TabB.icon = get_theme_icon("CryptoKey", "EditorIcons")
|
||||||
|
|
||||||
|
owner.get_parent().visibility_changed.connect(func(): if is_visible_in_tree(): open())
|
||||||
|
|
||||||
|
%RenameNotification.add_theme_color_override("font_color", get_theme_color("warning_color", "Editor"))
|
||||||
|
|
||||||
|
|
||||||
|
func open() -> void:
|
||||||
|
fill_table()
|
||||||
|
%RenameNotification.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func close() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func fill_table() -> void:
|
||||||
|
var t: Tree = %IdentifierTable
|
||||||
|
t.set_column_expand(1, true)
|
||||||
|
t.clear()
|
||||||
|
t.set_column_title(1, "Identifier")
|
||||||
|
t.set_column_title(0, "Resource Path")
|
||||||
|
t.set_column_title_alignment(0, 0)
|
||||||
|
t.set_column_title_alignment(1, 0)
|
||||||
|
t.create_item()
|
||||||
|
|
||||||
|
for d in [["Characters", 'dch'], ["Timelines", "dtl"]]:
|
||||||
|
var directory := DialogicResourceUtil.get_directory(d[1])
|
||||||
|
var directory_item := t.create_item()
|
||||||
|
directory_item.set_text(0, d[0])
|
||||||
|
directory_item.set_metadata(0, d[1])
|
||||||
|
for key in directory:
|
||||||
|
var item: TreeItem = t.create_item(directory_item)
|
||||||
|
item.set_text(0, directory[key])
|
||||||
|
item.set_text(1, key)
|
||||||
|
item.set_editable(1, true)
|
||||||
|
item.set_metadata(1, key)
|
||||||
|
item.add_button(1, get_theme_icon("Edit", "EditorIcons"), 0, false, "Edit")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_identifier_table_item_edited() -> void:
|
||||||
|
var item: TreeItem = %IdentifierTable.get_edited()
|
||||||
|
var new_identifier : String = item.get_text(1)
|
||||||
|
|
||||||
|
|
||||||
|
if new_identifier == item.get_metadata(1):
|
||||||
|
return
|
||||||
|
|
||||||
|
if new_identifier.is_empty() or not DialogicResourceUtil.is_identifier_unused(item.get_parent().get_metadata(0), new_identifier):
|
||||||
|
item.set_text(1, item.get_metadata(1))
|
||||||
|
return
|
||||||
|
|
||||||
|
DialogicResourceUtil.change_unique_identifier(item.get_text(0), new_identifier)
|
||||||
|
|
||||||
|
match item.get_parent().get_metadata(0):
|
||||||
|
'dch':
|
||||||
|
owner.get_parent().add_character_name_ref_change(item.get_metadata(1), new_identifier)
|
||||||
|
'dtl':
|
||||||
|
owner.get_parent().add_timeline_name_ref_change(item.get_metadata(1), new_identifier)
|
||||||
|
|
||||||
|
%RenameNotification.show()
|
||||||
|
item.set_metadata(1, new_identifier)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_identifier_table_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void:
|
||||||
|
item.select(column)
|
||||||
|
%IdentifierTable.edit_selected(true)
|
||||||
|
|
||||||
|
|
||||||
|
func filter_tree(filter:String= "", item:TreeItem = null) -> bool:
|
||||||
|
if item == null:
|
||||||
|
item = %IdentifierTable.get_root()
|
||||||
|
|
||||||
|
var any := false
|
||||||
|
for child in item.get_children():
|
||||||
|
if child.get_child_count() > 0:
|
||||||
|
child.visible = filter_tree(filter, child)
|
||||||
|
if child.visible: any = true
|
||||||
|
else:
|
||||||
|
child.visible = filter.is_empty() or filter.to_lower() in child.get_text(0).to_lower() or filter.to_lower() in child.get_text(1).to_lower()
|
||||||
|
if child.visible: any = true
|
||||||
|
|
||||||
|
return any
|
||||||
|
|
||||||
|
|
||||||
|
func _on_search_text_changed(new_text: String) -> void:
|
||||||
|
filter_tree(new_text)
|
@ -0,0 +1,176 @@
|
|||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
var current_info : Dictionary = {}
|
||||||
|
@onready var editor_view := find_parent('EditorView')
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
await editor_view.ready
|
||||||
|
theme = editor_view.theme
|
||||||
|
|
||||||
|
%Install.icon = editor_view.get_theme_icon("AssetLib", "EditorIcons")
|
||||||
|
%LoadingIcon.texture = editor_view.get_theme_icon("KeyTrackScale", "EditorIcons")
|
||||||
|
%InstallWarning.modulate = editor_view.get_theme_color("warning_color", "Editor")
|
||||||
|
|
||||||
|
DialogicUtil.get_dialogic_plugin().get_editor_interface().get_resource_filesystem().resources_reimported.connect(_on_resources_reimported)
|
||||||
|
|
||||||
|
|
||||||
|
func open():
|
||||||
|
get_parent().popup_centered_ratio(0.5)
|
||||||
|
get_parent().mode = Window.MODE_WINDOWED
|
||||||
|
get_parent().move_to_foreground()
|
||||||
|
get_parent().grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func load_info(info:Dictionary, update_type:int) -> void:
|
||||||
|
current_info = info
|
||||||
|
if update_type == 2:
|
||||||
|
%State.text = "No Information Available"
|
||||||
|
%UpdateName.text = "Unable to access versions."
|
||||||
|
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("readonly_color", "Editor"))
|
||||||
|
%Content.text = "You are probably not connected to the internet. Fair enough."
|
||||||
|
%ShortInfo.text = "Huh, what happened here?"
|
||||||
|
%ReadFull.hide()
|
||||||
|
%Install.disabled = true
|
||||||
|
return
|
||||||
|
|
||||||
|
# If we are up to date (or beyond):
|
||||||
|
if info.is_empty():
|
||||||
|
info['name'] = "You are in the future, Marty!"
|
||||||
|
info["body"] = "# 😎 You are using the WIP branch!\nSeems like you are using a version that isn't even released yet. Be careful and give us your feedback ;)"
|
||||||
|
info["published_at"] = "????T"
|
||||||
|
info["author"] = {'login':"???"}
|
||||||
|
%State.text = "Where are we Doc?"
|
||||||
|
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("property_color_z", "Editor"))
|
||||||
|
%Install.disabled = true
|
||||||
|
|
||||||
|
elif update_type == 0:
|
||||||
|
%State.text = "Update Available!"
|
||||||
|
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("warning_color", "Editor"))
|
||||||
|
%Install.disabled = false
|
||||||
|
else:
|
||||||
|
%State.text = "You are up to date:"
|
||||||
|
%UpdateName.add_theme_color_override("font_color", editor_view.get_theme_color("success_color", "Editor"))
|
||||||
|
%Install.disabled = true
|
||||||
|
|
||||||
|
%UpdateName.text = info.name
|
||||||
|
%Content.text = markdown_to_bbcode('#'+info.body.get_slice('#', 1)).strip_edges()
|
||||||
|
%ShortInfo.text = "Published on "+info.published_at.substr(0, info.published_at.find('T'))+" by "+info.author.login
|
||||||
|
if info.has("html_url"):
|
||||||
|
%ReadFull.uri = info.html_url
|
||||||
|
%ReadFull.show()
|
||||||
|
else:
|
||||||
|
%ReadFull.hide()
|
||||||
|
if info.has('reactions'):
|
||||||
|
%Reactions.show()
|
||||||
|
var reactions := {"laugh":"😂", "hooray":"🎉", "confused":"😕", "heart":"❤️", "rocket":"🚀", "eyes":"👀"}
|
||||||
|
for i in reactions:
|
||||||
|
%Reactions.get_node(i.capitalize()).visible = info.reactions[i] > 0
|
||||||
|
%Reactions.get_node(i.capitalize()).text = reactions[i]+" "+str(info.reactions[i]) if info.reactions[i] > 0 else reactions[i]
|
||||||
|
if info.reactions['+1']+info.reactions['-1'] > 0:
|
||||||
|
%Reactions.get_node("Likes").visible = true
|
||||||
|
%Reactions.get_node("Likes").text = "👍 "+str(info.reactions['+1']+info.reactions['-1'])
|
||||||
|
else:
|
||||||
|
%Reactions.get_node("Likes").visible = false
|
||||||
|
else:
|
||||||
|
%Reactions.hide()
|
||||||
|
|
||||||
|
func _on_window_close_requested():
|
||||||
|
get_parent().visible = false
|
||||||
|
|
||||||
|
|
||||||
|
func _on_install_pressed():
|
||||||
|
find_parent('UpdateManager').request_update_download()
|
||||||
|
|
||||||
|
%InfoLabel.text = "Downloading. This can take a moment."
|
||||||
|
%Loading.show()
|
||||||
|
%LoadingIcon.create_tween().set_loops().tween_property(%LoadingIcon, 'rotation', 2*PI, 1).from(0)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_refresh_pressed():
|
||||||
|
find_parent('UpdateManager').request_update_check()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_update_manager_downdload_completed(result:int):
|
||||||
|
%Loading.hide()
|
||||||
|
match result:
|
||||||
|
0: # success
|
||||||
|
%InfoLabel.text = "Installed successfully. Restart needed!"
|
||||||
|
%InfoLabel.modulate = editor_view.get_theme_color("success_color", "Editor")
|
||||||
|
%Restart.show()
|
||||||
|
%Restart.grab_focus()
|
||||||
|
1: # failure
|
||||||
|
%InfoLabel.text = "Download failed."
|
||||||
|
%InfoLabel.modulate = editor_view.get_theme_color("readonly_color", "Editor")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_resources_reimported(resources:Array) -> void:
|
||||||
|
if is_inside_tree():
|
||||||
|
await get_tree().process_frame
|
||||||
|
get_parent().move_to_foreground()
|
||||||
|
|
||||||
|
|
||||||
|
func markdown_to_bbcode(text:String) -> String:
|
||||||
|
var font_sizes := {1:20, 2:16, 3:16,4:14, 5:14}
|
||||||
|
var title_regex := RegEx.create_from_string('(^|\n)((?<level>#+)(?<title>.*))\\n')
|
||||||
|
var res := title_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(2), '[font_size='+str(font_sizes[len(res.get_string('level'))])+']'+res.get_string('title').strip_edges()+'[/font_size]')
|
||||||
|
res = title_regex.search(text)
|
||||||
|
|
||||||
|
var link_regex := RegEx.create_from_string('(?<!\\!)\\[(?<text>[^\\]]*)]\\((?<link>[^)]*)\\)')
|
||||||
|
res = link_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[url='+res.get_string('link')+']'+res.get_string('text').strip_edges()+'[/url]')
|
||||||
|
res = link_regex.search(text)
|
||||||
|
|
||||||
|
var image_regex := RegEx.create_from_string('\\!\\[(?<text>[^\\]]*)]\\((?<link>[^)]*)\\)\n*')
|
||||||
|
res = image_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[url='+res.get_string('link')+']'+res.get_string('text').strip_edges()+'[/url]')
|
||||||
|
res = image_regex.search(text)
|
||||||
|
|
||||||
|
var italics_regex := RegEx.create_from_string('\\*(?<text>[^\\*\\n]*)\\*')
|
||||||
|
res = italics_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[i]'+res.get_string('text').strip_edges()+'[/i]')
|
||||||
|
res = italics_regex.search(text)
|
||||||
|
|
||||||
|
var bullets_regex := RegEx.create_from_string('(?<=\\n)(\\*|-)(?<text>[^\\*\\n]*)\\n')
|
||||||
|
res = bullets_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[ul]'+res.get_string('text').strip_edges()+'[/ul]\n')
|
||||||
|
res = bullets_regex.search(text)
|
||||||
|
|
||||||
|
var small_code_regex := RegEx.create_from_string('(?<!`)`(?<text>[^`]+)`')
|
||||||
|
res = small_code_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[code][color='+get_theme_color("accent_color", "Editor").to_html()+']'+res.get_string('text').strip_edges()+'[/color][/code]')
|
||||||
|
res = small_code_regex.search(text)
|
||||||
|
|
||||||
|
var big_code_regex := RegEx.create_from_string('(?<!`)```(?<text>[^`]+)```')
|
||||||
|
res = big_code_regex.search(text)
|
||||||
|
while res:
|
||||||
|
text = text.replace(res.get_string(), '[code][bgcolor='+get_theme_color("box_selection_fill_color", "Editor").to_html()+']'+res.get_string('text').strip_edges()+'[/bgcolor][/code]')
|
||||||
|
res = big_code_regex.search(text)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _on_content_meta_clicked(meta:Variant) -> void:
|
||||||
|
OS.shell_open(str(meta))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_install_mouse_entered():
|
||||||
|
if not %Install.disabled:
|
||||||
|
%InstallWarning.show()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_install_mouse_exited():
|
||||||
|
%InstallWarning.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_restart_pressed():
|
||||||
|
DialogicUtil.get_dialogic_plugin().get_editor_interface().restart_editor(true)
|
@ -0,0 +1,192 @@
|
|||||||
|
@tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
## Script that checks for new versions and can install them.
|
||||||
|
|
||||||
|
signal update_check_completed(result:UpdateCheckResult)
|
||||||
|
signal downdload_completed(result:DownloadResult)
|
||||||
|
|
||||||
|
enum UpdateCheckResult {UPDATE_AVAILABLE, UP_TO_DATE, NO_ACCESS}
|
||||||
|
enum DownloadResult {SUCCESS, FAILURE}
|
||||||
|
enum ReleaseState {ALPHA, BETA, STABLE}
|
||||||
|
|
||||||
|
const REMOTE_RELEASES_URL := "https://api.github.com/repos/dialogic-godot/dialogic/releases"
|
||||||
|
const TEMP_FILE_NAME = "user://temp.zip"
|
||||||
|
|
||||||
|
var current_version : String = ""
|
||||||
|
var update_info: Dictionary
|
||||||
|
var current_info: Dictionary
|
||||||
|
|
||||||
|
var version_indicator :Button
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
request_update_check()
|
||||||
|
|
||||||
|
setup_version_indicator()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func get_current_version() -> String:
|
||||||
|
var plugin_cfg := ConfigFile.new()
|
||||||
|
plugin_cfg.load("res://addons/dialogic/plugin.cfg")
|
||||||
|
return plugin_cfg.get_value('plugin', 'version', 'unknown version')
|
||||||
|
|
||||||
|
|
||||||
|
func request_update_check() -> void:
|
||||||
|
if $UpdateCheckRequest.get_http_client_status() == HTTPClient.STATUS_DISCONNECTED:
|
||||||
|
$UpdateCheckRequest.request(REMOTE_RELEASES_URL)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_UpdateCheck_request_completed(result:int, response_code:int, headers:PackedStringArray, body:PackedByteArray) -> void:
|
||||||
|
if result != HTTPRequest.RESULT_SUCCESS:
|
||||||
|
update_check_completed.emit(UpdateCheckResult.NO_ACCESS)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Work out the next version from the releases information on GitHub
|
||||||
|
var response :Variant= JSON.parse_string(body.get_string_from_utf8())
|
||||||
|
if typeof(response) != TYPE_ARRAY: return
|
||||||
|
|
||||||
|
|
||||||
|
var current_release_info := get_release_tag_info(get_current_version())
|
||||||
|
|
||||||
|
# GitHub releases are in order of creation, not order of version
|
||||||
|
var versions :Array = (response as Array).filter(compare_versions.bind(current_release_info))
|
||||||
|
if versions.size() > 0:
|
||||||
|
update_info = versions[0]
|
||||||
|
update_check_completed.emit(UpdateCheckResult.UPDATE_AVAILABLE)
|
||||||
|
else:
|
||||||
|
update_info = current_info
|
||||||
|
update_check_completed.emit(UpdateCheckResult.UP_TO_DATE)
|
||||||
|
|
||||||
|
|
||||||
|
func compare_versions(release, current_release_info:Dictionary) -> bool:
|
||||||
|
var checked_release_info := get_release_tag_info(release.tag_name)
|
||||||
|
|
||||||
|
if checked_release_info.major < current_release_info.major:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if checked_release_info.minor < current_release_info.minor:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if checked_release_info.state < current_release_info.state:
|
||||||
|
return false
|
||||||
|
|
||||||
|
elif checked_release_info.state == current_release_info.state:
|
||||||
|
if checked_release_info.state_version < current_release_info.state_version:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if checked_release_info.state_version == current_release_info.state_version:
|
||||||
|
current_info = release
|
||||||
|
return false
|
||||||
|
|
||||||
|
if checked_release_info.state == ReleaseState.STABLE:
|
||||||
|
if checked_release_info.minor == current_release_info.minor:
|
||||||
|
current_info = release
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
func get_release_tag_info(release_tag:String) -> Dictionary:
|
||||||
|
release_tag = release_tag.strip_edges().trim_prefix('v')
|
||||||
|
release_tag = release_tag.substr(0, release_tag.find('('))
|
||||||
|
release_tag = release_tag.to_lower()
|
||||||
|
|
||||||
|
var regex := RegEx.create_from_string('(?<major>\\d+\\.\\d+)(-(?<state>alpha|beta)-)?(?(2)(?<stateversion>\\d*)|\\.(?<minor>\\d*))?')
|
||||||
|
|
||||||
|
var result: RegExMatch = regex.search(release_tag)
|
||||||
|
if !result:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
var info:Dictionary = {'tag':release_tag}
|
||||||
|
info['major'] = float(result.get_string('major'))
|
||||||
|
info['minor'] = int(result.get_string('minor'))
|
||||||
|
|
||||||
|
match result.get_string('state'):
|
||||||
|
'alpha':
|
||||||
|
info['state'] = ReleaseState.ALPHA
|
||||||
|
'beta':
|
||||||
|
info['state'] = ReleaseState.BETA
|
||||||
|
_:
|
||||||
|
info['state'] = ReleaseState.STABLE
|
||||||
|
|
||||||
|
info['state_version'] = int(result.get_string('stateversion'))
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
func request_update_download() -> void:
|
||||||
|
# Safeguard the actual dialogue manager repo from accidentally updating itself
|
||||||
|
if DirAccess.dir_exists_absolute("res://test-project/"):
|
||||||
|
prints("[Dialogic] Looks like you are working on the addon. You can't update the addon from within itself.")
|
||||||
|
downdload_completed.emit(DownloadResult.FAILURE)
|
||||||
|
return
|
||||||
|
|
||||||
|
$DownloadRequest.request(update_info.zipball_url)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_DownloadRequest_completed(result:int, response_code:int, headers:PackedStringArray, body:PackedByteArray):
|
||||||
|
if result != HTTPRequest.RESULT_SUCCESS:
|
||||||
|
downdload_completed.emit(DownloadResult.FAILURE)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Save the downloaded zip
|
||||||
|
var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
|
||||||
|
zip_file.store_buffer(body)
|
||||||
|
zip_file.close()
|
||||||
|
|
||||||
|
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/dialogic"))
|
||||||
|
|
||||||
|
var zip_reader: ZIPReader = ZIPReader.new()
|
||||||
|
zip_reader.open(TEMP_FILE_NAME)
|
||||||
|
var files: PackedStringArray = zip_reader.get_files()
|
||||||
|
|
||||||
|
var base_path = files[0].path_join('addons/')
|
||||||
|
for path in files:
|
||||||
|
if not "dialogic/" in path:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var new_file_path: String = path.replace(base_path, "")
|
||||||
|
if path.ends_with("/"):
|
||||||
|
DirAccess.make_dir_recursive_absolute("res://addons/".path_join(new_file_path))
|
||||||
|
else:
|
||||||
|
var file: FileAccess = FileAccess.open("res://addons/".path_join(new_file_path), FileAccess.WRITE)
|
||||||
|
file.store_buffer(zip_reader.read_file(path))
|
||||||
|
|
||||||
|
zip_reader.close()
|
||||||
|
DirAccess.remove_absolute(TEMP_FILE_NAME)
|
||||||
|
|
||||||
|
downdload_completed.emit(DownloadResult.SUCCESS)
|
||||||
|
|
||||||
|
|
||||||
|
###################### SOME UI MANAGEMENT #####################################
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func setup_version_indicator():
|
||||||
|
version_indicator = %Sidebar.get_node('%CurrentVersion')
|
||||||
|
version_indicator.pressed.connect($Window/UpdateInstallWindow.open)
|
||||||
|
version_indicator.text = get_current_version()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_update_check_completed(result:int):
|
||||||
|
var result_color : Color
|
||||||
|
match result:
|
||||||
|
UpdateCheckResult.UPDATE_AVAILABLE:
|
||||||
|
result_color = version_indicator.get_theme_color("warning_color", "Editor")
|
||||||
|
version_indicator.icon = version_indicator.get_theme_icon("StatusWarning", "EditorIcons")
|
||||||
|
$Window/UpdateInstallWindow.load_info(update_info, result)
|
||||||
|
UpdateCheckResult.UP_TO_DATE:
|
||||||
|
result_color = version_indicator.get_theme_color("success_color", "Editor")
|
||||||
|
version_indicator.icon = version_indicator.get_theme_icon("StatusSuccess", "EditorIcons")
|
||||||
|
$Window/UpdateInstallWindow.load_info(current_info, result)
|
||||||
|
UpdateCheckResult.NO_ACCESS:
|
||||||
|
result_color = version_indicator.get_theme_color("success_color", "Editor")
|
||||||
|
version_indicator.icon = version_indicator.get_theme_icon("GuiRadioCheckedDisabled", "EditorIcons")
|
||||||
|
$Window/UpdateInstallWindow.load_info(update_info, result)
|
||||||
|
|
||||||
|
version_indicator.add_theme_color_override('font_color', result_color)
|
||||||
|
version_indicator.add_theme_color_override('font_hover_color', result_color.lightened(0.5))
|
||||||
|
version_indicator.add_theme_color_override('font_pressed_color', result_color)
|
||||||
|
version_indicator.add_theme_color_override('font_focus_color', result_color)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
## A scene shown at the end of events that contain other events
|
||||||
|
|
||||||
|
var resource: DialogicEndBranchEvent
|
||||||
|
|
||||||
|
# References
|
||||||
|
var parent_node: Control = null
|
||||||
|
var end_control: Control = null
|
||||||
|
|
||||||
|
# Indent
|
||||||
|
var indent_size := 22
|
||||||
|
var current_indent_level := 1
|
||||||
|
|
||||||
|
var selected := false
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
$Icon.icon = get_theme_icon("GuiSpinboxUpdown", "EditorIcons")
|
||||||
|
$Spacer.custom_minimum_size.x = 90 * DialogicUtil.get_editor_scale()
|
||||||
|
visual_deselect()
|
||||||
|
parent_node_changed()
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor
|
||||||
|
func visual_select() -> void:
|
||||||
|
modulate = get_theme_color("highlighted_font_color", "Editor")
|
||||||
|
selected = true
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor
|
||||||
|
func visual_deselect() -> void:
|
||||||
|
if !parent_node:return
|
||||||
|
selected = false
|
||||||
|
modulate = parent_node.resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.3)
|
||||||
|
|
||||||
|
|
||||||
|
func is_selected() -> bool:
|
||||||
|
return selected
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor
|
||||||
|
func highlight() -> void:
|
||||||
|
if !parent_node:return
|
||||||
|
modulate = parent_node.resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.6)
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor
|
||||||
|
func unhighlight() -> void:
|
||||||
|
modulate = parent_node.resource.event_color
|
||||||
|
|
||||||
|
|
||||||
|
func update_hidden_events_indicator(hidden_events_count:int = 0) -> void:
|
||||||
|
$HiddenEventsLabel.visible = hidden_events_count > 0
|
||||||
|
if hidden_events_count == 1:
|
||||||
|
$HiddenEventsLabel.text = "[1 event hidden]"
|
||||||
|
else:
|
||||||
|
$HiddenEventsLabel.text = "["+str(hidden_events_count)+ " events hidden]"
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor
|
||||||
|
func set_indent(indent: int) -> void:
|
||||||
|
$Indent.custom_minimum_size = Vector2(indent_size * indent * DialogicUtil.get_editor_scale(), 0)
|
||||||
|
$Indent.visible = indent != 0
|
||||||
|
current_indent_level = indent
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
## Called by the visual timeline editor if something was edited on the parent event block
|
||||||
|
func parent_node_changed() -> void:
|
||||||
|
if parent_node and end_control and end_control.has_method('refresh'):
|
||||||
|
end_control.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
## Called on creation if the parent event provides an end control
|
||||||
|
func add_end_control(control:Control) -> void:
|
||||||
|
if !control:
|
||||||
|
return
|
||||||
|
add_child(control)
|
||||||
|
control.size_flags_vertical = SIZE_SHRINK_CENTER
|
||||||
|
if "parent_resource" in control:
|
||||||
|
control.parent_resource = parent_node.resource
|
||||||
|
if control.has_method('refresh'):
|
||||||
|
control.refresh()
|
||||||
|
end_control = control
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://de13fdeebrkcb"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/BranchEnd.gd" id="1"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_8jrl8"]
|
||||||
|
data = {
|
||||||
|
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||||
|
"format": "RGBA8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id="ImageTexture_44ap0"]
|
||||||
|
image = SubResource("Image_8jrl8")
|
||||||
|
|
||||||
|
[node name="EndBranch" type="HBoxContainer"]
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 24.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
script = ExtResource("1")
|
||||||
|
|
||||||
|
[node name="Indent" type="Control" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 0
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="."]
|
||||||
|
custom_minimum_size = Vector2(90, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 0
|
||||||
|
|
||||||
|
[node name="Icon" type="Button" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(20, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 4
|
||||||
|
tooltip_text = "Click and drag"
|
||||||
|
focus_mode = 0
|
||||||
|
mouse_filter = 1
|
||||||
|
icon = SubResource("ImageTexture_44ap0")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="HiddenEventsLabel" type="Label" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
text = "XX Events hidden"
|
@ -0,0 +1,414 @@
|
|||||||
|
@tool
|
||||||
|
extends MarginContainer
|
||||||
|
|
||||||
|
## Scene that represents an event in the visual timeline editor.
|
||||||
|
|
||||||
|
signal content_changed()
|
||||||
|
|
||||||
|
## REFERENCES
|
||||||
|
var resource : DialogicEvent
|
||||||
|
var editor_reference
|
||||||
|
# for choice and condition
|
||||||
|
var end_node: Node = null:
|
||||||
|
get:
|
||||||
|
return end_node
|
||||||
|
set(node):
|
||||||
|
end_node = node
|
||||||
|
%ToggleChildrenVisibilityButton.visible = true if end_node else false
|
||||||
|
|
||||||
|
|
||||||
|
## FLAGS
|
||||||
|
var selected := false
|
||||||
|
# Whether the body is visible
|
||||||
|
var expanded := true
|
||||||
|
var body_was_build := false
|
||||||
|
var has_any_enabled_body_content := false
|
||||||
|
# Whether contained events (e.g. in choices) are visible
|
||||||
|
var collapsed := false
|
||||||
|
|
||||||
|
|
||||||
|
## CONSTANTS
|
||||||
|
const icon_size := 28
|
||||||
|
const indent_size := 22
|
||||||
|
|
||||||
|
## STATE
|
||||||
|
# List that stores visibility conditions
|
||||||
|
var field_list := []
|
||||||
|
var current_indent_level := 1
|
||||||
|
|
||||||
|
|
||||||
|
#region UI AND LOGIC INITIALIZATION
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if get_parent() is SubViewport:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not resource:
|
||||||
|
printerr("[Dialogic] Event block was added without a resource specified.")
|
||||||
|
return
|
||||||
|
|
||||||
|
initialize_ui()
|
||||||
|
initialize_logic()
|
||||||
|
|
||||||
|
|
||||||
|
func initialize_ui() -> void:
|
||||||
|
var _scale := DialogicUtil.get_editor_scale()
|
||||||
|
|
||||||
|
$PanelContainer.self_modulate = get_theme_color("accent_color", "Editor")
|
||||||
|
|
||||||
|
# Warning Icon
|
||||||
|
%Warning.texture = get_theme_icon("NodeWarning", "EditorIcons")
|
||||||
|
%Warning.size = Vector2(16 * _scale, 16 * _scale)
|
||||||
|
%Warning.position = Vector2(-5 * _scale, -10 * _scale)
|
||||||
|
|
||||||
|
# Expand Button
|
||||||
|
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldedRightArrow", "EditorIcons")
|
||||||
|
%ToggleBodyVisibilityButton.modulate = get_theme_color("contrast_color_1", "Editor")
|
||||||
|
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_normal_color", get_theme_color("contrast_color_1", "Editor"))
|
||||||
|
%ToggleBodyVisibilityButton.set("theme_override_colors/icon_pressed_color", get_theme_color("contrast_color_1", "Editor"))
|
||||||
|
|
||||||
|
# Icon Panel
|
||||||
|
%IconPanel.tooltip_text = resource.event_name
|
||||||
|
%IconPanel.self_modulate = resource.event_color
|
||||||
|
|
||||||
|
# Event Icon
|
||||||
|
%IconTexture.texture = resource._get_icon()
|
||||||
|
|
||||||
|
%IconPanel.custom_minimum_size = Vector2(icon_size, icon_size) * _scale
|
||||||
|
%IconTexture.custom_minimum_size = %IconPanel.custom_minimum_size
|
||||||
|
|
||||||
|
var custom_style: StyleBoxFlat = %IconPanel.get_theme_stylebox('panel')
|
||||||
|
custom_style.set_corner_radius_all(5 * _scale)
|
||||||
|
|
||||||
|
# Focus Mode
|
||||||
|
set_focus_mode(1) # Allowing this node to grab focus
|
||||||
|
|
||||||
|
# Separation on the header
|
||||||
|
%Header.add_theme_constant_override("custom_constants/separation", 5 * _scale)
|
||||||
|
|
||||||
|
# Collapse Button
|
||||||
|
%ToggleChildrenVisibilityButton.toggled.connect(_on_collapse_toggled)
|
||||||
|
%ToggleChildrenVisibilityButton.icon = get_theme_icon("Collapse", "EditorIcons")
|
||||||
|
%ToggleChildrenVisibilityButton.hide()
|
||||||
|
|
||||||
|
%Body.add_theme_constant_override("margin_left", icon_size * _scale)
|
||||||
|
|
||||||
|
visual_deselect()
|
||||||
|
|
||||||
|
|
||||||
|
func initialize_logic() -> void:
|
||||||
|
resized.connect(get_parent().get_parent().queue_redraw)
|
||||||
|
|
||||||
|
resource.ui_update_needed.connect(_on_resource_ui_update_needed)
|
||||||
|
resource.ui_update_warning.connect(set_warning)
|
||||||
|
|
||||||
|
content_changed.connect(recalculate_field_visibility)
|
||||||
|
|
||||||
|
_on_ToggleBodyVisibility_toggled(resource.expand_by_default or resource.created_by_button)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region VISUAL METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func visual_select() -> void:
|
||||||
|
$PanelContainer.add_theme_stylebox_override('panel', load("res://addons/dialogic/Editor/Events/styles/selected_styleboxflat.tres"))
|
||||||
|
selected = true
|
||||||
|
%IconPanel.self_modulate = resource.event_color
|
||||||
|
%IconTexture.modulate = get_theme_color("icon_saturation", "Editor")
|
||||||
|
|
||||||
|
|
||||||
|
func visual_deselect() -> void:
|
||||||
|
$PanelContainer.add_theme_stylebox_override('panel', load("res://addons/dialogic/Editor/Events/styles/unselected_stylebox.tres"))
|
||||||
|
selected = false
|
||||||
|
%IconPanel.self_modulate = resource.event_color.lerp(Color.DARK_SLATE_GRAY, 0.1)
|
||||||
|
%IconTexture.modulate = get_theme_color('font_color', 'Label')
|
||||||
|
|
||||||
|
|
||||||
|
func is_selected() -> bool:
|
||||||
|
return selected
|
||||||
|
|
||||||
|
|
||||||
|
func set_warning(text:String= "") -> void:
|
||||||
|
if !text.is_empty():
|
||||||
|
%Warning.show()
|
||||||
|
%Warning.tooltip_text = text
|
||||||
|
else:
|
||||||
|
%Warning.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func set_indent(indent: int) -> void:
|
||||||
|
add_theme_constant_override("margin_left", indent_size * indent * DialogicUtil.get_editor_scale())
|
||||||
|
current_indent_level = indent
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENT FIELDS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
var FIELD_SCENES := {
|
||||||
|
DialogicEvent.ValueType.MULTILINE_TEXT: "res://addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn",
|
||||||
|
DialogicEvent.ValueType.SINGLELINE_TEXT: "res://addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn",
|
||||||
|
DialogicEvent.ValueType.FILE: "res://addons/dialogic/Editor/Events/Fields/field_file.tscn",
|
||||||
|
DialogicEvent.ValueType.BOOL: "res://addons/dialogic/Editor/Events/Fields/field_bool_check.tscn",
|
||||||
|
DialogicEvent.ValueType.BOOL_BUTTON: "res://addons/dialogic/Editor/Events/Fields/field_bool_button.tscn",
|
||||||
|
DialogicEvent.ValueType.CONDITION: "res://addons/dialogic/Editor/Events/Fields/field_condition.tscn",
|
||||||
|
DialogicEvent.ValueType.ARRAY: "res://addons/dialogic/Editor/Events/Fields/field_array.tscn",
|
||||||
|
DialogicEvent.ValueType.DICTIONARY: "res://addons/dialogic/Editor/Events/Fields/field_dictionary.tscn",
|
||||||
|
DialogicEvent.ValueType.DYNAMIC_OPTIONS: "res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn",
|
||||||
|
DialogicEvent.ValueType.FIXED_OPTIONS : "res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn",
|
||||||
|
DialogicEvent.ValueType.NUMBER: "res://addons/dialogic/Editor/Events/Fields/field_number.tscn",
|
||||||
|
DialogicEvent.ValueType.VECTOR2: "res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn",
|
||||||
|
DialogicEvent.ValueType.VECTOR3: "res://addons/dialogic/Editor/Events/Fields/field_vector3.tscn",
|
||||||
|
DialogicEvent.ValueType.VECTOR4: "res://addons/dialogic/Editor/Events/Fields/field_vector4.tscn",
|
||||||
|
DialogicEvent.ValueType.COLOR: "res://addons/dialogic/Editor/Events/Fields/field_color.tscn"
|
||||||
|
}
|
||||||
|
|
||||||
|
func build_editor(build_header:bool = true, build_body:bool = false) -> void:
|
||||||
|
var current_body_container: HFlowContainer = null
|
||||||
|
|
||||||
|
if build_body and body_was_build:
|
||||||
|
build_body = false
|
||||||
|
|
||||||
|
if build_body:
|
||||||
|
if body_was_build:
|
||||||
|
return
|
||||||
|
current_body_container = HFlowContainer.new()
|
||||||
|
%BodyContent.add_child(current_body_container)
|
||||||
|
body_was_build = true
|
||||||
|
|
||||||
|
for p in resource.get_event_editor_info():
|
||||||
|
field_list.append({'node':null, 'location':p.location})
|
||||||
|
if p.has('condition'):
|
||||||
|
field_list[-1]['condition'] = p.condition
|
||||||
|
|
||||||
|
if !build_body and p.location == 1:
|
||||||
|
continue
|
||||||
|
elif !build_header and p.location == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
### --------------------------------------------------------------------
|
||||||
|
### 1. CREATE A NODE OF THE CORRECT TYPE FOR THE PROPERTY
|
||||||
|
var editor_node : Control
|
||||||
|
|
||||||
|
### LINEBREAK
|
||||||
|
if p.name == "linebreak":
|
||||||
|
field_list.remove_at(field_list.size()-1)
|
||||||
|
if !current_body_container.get_child_count():
|
||||||
|
current_body_container.queue_free()
|
||||||
|
current_body_container = HFlowContainer.new()
|
||||||
|
%BodyContent.add_child(current_body_container)
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif p.field_type in FIELD_SCENES:
|
||||||
|
editor_node = load(FIELD_SCENES[p.field_type]).instantiate()
|
||||||
|
|
||||||
|
elif p.field_type == resource.ValueType.LABEL:
|
||||||
|
editor_node = Label.new()
|
||||||
|
editor_node.text = p.display_info.text
|
||||||
|
editor_node.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
editor_node.set('custom_colors/font_color', Color("#7b7b7b"))
|
||||||
|
editor_node.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
|
||||||
|
|
||||||
|
elif p.field_type == resource.ValueType.BUTTON:
|
||||||
|
editor_node = Button.new()
|
||||||
|
editor_node.text = p.display_info.text
|
||||||
|
if typeof(p.display_info.icon) == TYPE_ARRAY:
|
||||||
|
editor_node.icon = callv('get_theme_icon', p.display_info.icon)
|
||||||
|
else:
|
||||||
|
editor_node.icon = p.display_info.icon
|
||||||
|
editor_node.flat = true
|
||||||
|
editor_node.custom_minimum_size.x = 30 * DialogicUtil.get_editor_scale()
|
||||||
|
editor_node.pressed.connect(p.display_info.callable)
|
||||||
|
|
||||||
|
## CUSTOM
|
||||||
|
elif p.field_type == resource.ValueType.CUSTOM:
|
||||||
|
if p.display_info.has('path'):
|
||||||
|
editor_node = load(p.display_info.path).instantiate()
|
||||||
|
|
||||||
|
## ELSE
|
||||||
|
else:
|
||||||
|
editor_node = Label.new()
|
||||||
|
editor_node.text = p.name
|
||||||
|
editor_node.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
|
||||||
|
|
||||||
|
|
||||||
|
field_list[-1]['node'] = editor_node
|
||||||
|
### --------------------------------------------------------------------
|
||||||
|
# Some things need to be called BEFORE the field is added to the tree
|
||||||
|
if editor_node is DialogicVisualEditorField:
|
||||||
|
editor_node.event_resource = resource
|
||||||
|
|
||||||
|
editor_node.property_name = p.name
|
||||||
|
field_list[-1]['property'] = p.name
|
||||||
|
|
||||||
|
editor_node._load_display_info(p.display_info)
|
||||||
|
|
||||||
|
var location: Control = %HeaderContent
|
||||||
|
if p.location == 1:
|
||||||
|
location = current_body_container
|
||||||
|
location.add_child(editor_node)
|
||||||
|
|
||||||
|
# Some things need to be called AFTER the field is added to the tree
|
||||||
|
if editor_node is DialogicVisualEditorField:
|
||||||
|
# Only set the value if the field is visible
|
||||||
|
#
|
||||||
|
# This prevents events with varied value types (event_setting, event_variable)
|
||||||
|
# from injecting incorrect types into hidden fields, which then throw errors
|
||||||
|
# in the console.
|
||||||
|
if p.has('condition') and not p.condition.is_empty():
|
||||||
|
if _evaluate_visibility_condition(p):
|
||||||
|
editor_node._set_value(resource.get(p.name))
|
||||||
|
else:
|
||||||
|
editor_node._set_value(resource.get(p.name))
|
||||||
|
|
||||||
|
editor_node.value_changed.connect(set_property)
|
||||||
|
|
||||||
|
editor_node.tooltip_text = p.display_info.get('tooltip', '')
|
||||||
|
|
||||||
|
# Apply autofocus
|
||||||
|
if resource.created_by_button and p.display_info.get('autofocus', false):
|
||||||
|
editor_node.call_deferred('take_autofocus')
|
||||||
|
|
||||||
|
### --------------------------------------------------------------------
|
||||||
|
### 4. ADD LEFT AND RIGHT TEXT
|
||||||
|
var left_label: Label = null
|
||||||
|
var right_label: Label = null
|
||||||
|
if !p.get('left_text', '').is_empty():
|
||||||
|
left_label = Label.new()
|
||||||
|
left_label.text = p.get('left_text')
|
||||||
|
left_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
left_label.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
|
||||||
|
location.add_child(left_label)
|
||||||
|
location.move_child(left_label, editor_node.get_index())
|
||||||
|
if !p.get('right_text', '').is_empty():
|
||||||
|
right_label = Label.new()
|
||||||
|
right_label.text = p.get('right_text')
|
||||||
|
right_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
right_label.add_theme_color_override('font_color', resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8))
|
||||||
|
location.add_child(right_label)
|
||||||
|
location.move_child(right_label, editor_node.get_index()+1)
|
||||||
|
|
||||||
|
### --------------------------------------------------------------------
|
||||||
|
### 5. REGISTER CONDITION
|
||||||
|
if p.has('condition'):
|
||||||
|
field_list[-1]['condition'] = p.condition
|
||||||
|
if left_label:
|
||||||
|
field_list.append({'node': left_label, 'condition':p.condition, 'location':p.location})
|
||||||
|
if right_label:
|
||||||
|
field_list.append({'node': right_label, 'condition':p.condition, 'location':p.location})
|
||||||
|
|
||||||
|
|
||||||
|
if build_body:
|
||||||
|
if current_body_container.get_child_count() == 0:
|
||||||
|
expanded = false
|
||||||
|
%Body.visible = false
|
||||||
|
|
||||||
|
recalculate_field_visibility()
|
||||||
|
|
||||||
|
|
||||||
|
func recalculate_field_visibility() -> void:
|
||||||
|
has_any_enabled_body_content = false
|
||||||
|
for p in field_list:
|
||||||
|
if !p.has('condition') or p.condition.is_empty():
|
||||||
|
if p.node != null:
|
||||||
|
p.node.show()
|
||||||
|
if p.location == 1:
|
||||||
|
has_any_enabled_body_content = true
|
||||||
|
else:
|
||||||
|
if _evaluate_visibility_condition(p):
|
||||||
|
if p.node != null:
|
||||||
|
p.node.show()
|
||||||
|
if p.location == 1:
|
||||||
|
has_any_enabled_body_content = true
|
||||||
|
else:
|
||||||
|
if p.node != null:
|
||||||
|
p.node.hide()
|
||||||
|
%ToggleBodyVisibilityButton.visible = has_any_enabled_body_content
|
||||||
|
|
||||||
|
|
||||||
|
func set_property(property_name:String, value:Variant) -> void:
|
||||||
|
resource.set(property_name, value)
|
||||||
|
content_changed.emit()
|
||||||
|
if end_node:
|
||||||
|
end_node.parent_node_changed()
|
||||||
|
|
||||||
|
|
||||||
|
func _evaluate_visibility_condition(p: Dictionary) -> bool:
|
||||||
|
var expr := Expression.new()
|
||||||
|
expr.parse(p.condition)
|
||||||
|
var result: bool
|
||||||
|
if expr.execute([], resource):
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
result = false
|
||||||
|
if expr.has_execute_failed():
|
||||||
|
printerr("[Dialogic] Failed executing visibility condition for '",p.get('property', 'unnamed'),"': " + expr.get_error_text())
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func _on_resource_ui_update_needed() -> void:
|
||||||
|
for node_info in field_list:
|
||||||
|
if node_info.node and node_info.node.has_method('set_value'):
|
||||||
|
# Only set the value if the field is visible
|
||||||
|
#
|
||||||
|
# This prevents events with varied value types (event_setting, event_variable)
|
||||||
|
# from injecting incorrect types into hidden fields, which then throw errors
|
||||||
|
# in the console.
|
||||||
|
if node_info.has('condition') and not node_info.condition.is_empty():
|
||||||
|
if _evaluate_visibility_condition(node_info):
|
||||||
|
node_info.node.set_value(resource.get(node_info.property))
|
||||||
|
else:
|
||||||
|
node_info.node.set_value(resource.get(node_info.property))
|
||||||
|
recalculate_field_visibility()
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNALS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_collapse_toggled(toggled:bool) -> void:
|
||||||
|
collapsed = toggled
|
||||||
|
var timeline_editor = find_parent('VisualEditor')
|
||||||
|
if (timeline_editor != null):
|
||||||
|
# @todo select item and clear selection is marked as "private" in TimelineEditor.gd
|
||||||
|
# consider to make it "public" or add a public helper function
|
||||||
|
timeline_editor.indent_events()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _on_ToggleBodyVisibility_toggled(button_pressed:bool) -> void:
|
||||||
|
if button_pressed and !body_was_build:
|
||||||
|
build_editor(false, true)
|
||||||
|
%ToggleBodyVisibilityButton.set_pressed_no_signal(button_pressed)
|
||||||
|
|
||||||
|
if button_pressed:
|
||||||
|
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldDownArrow", "EditorIcons")
|
||||||
|
else:
|
||||||
|
%ToggleBodyVisibilityButton.icon = get_theme_icon("CodeFoldedRightArrow", "EditorIcons")
|
||||||
|
|
||||||
|
expanded = button_pressed
|
||||||
|
%Body.visible = button_pressed
|
||||||
|
|
||||||
|
if find_parent('VisualEditor') != null:
|
||||||
|
find_parent('VisualEditor').indent_events()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_EventNode_gui_input(event:InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1:
|
||||||
|
grab_focus() # Grab focus to avoid copy pasting text or events
|
||||||
|
if event.double_click:
|
||||||
|
if has_any_enabled_body_content:
|
||||||
|
_on_ToggleBodyVisibility_toggled(!expanded)
|
||||||
|
# For opening the context menu
|
||||||
|
if event is InputEventMouseButton:
|
||||||
|
if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
|
||||||
|
var popup :PopupMenu = get_parent().get_parent().get_node('EventPopupMenu')
|
||||||
|
popup.current_event = self
|
||||||
|
popup.popup_on_parent(Rect2(get_global_mouse_position(),Vector2()))
|
||||||
|
if resource.help_page_path == "":
|
||||||
|
popup.set_item_disabled(2, true)
|
||||||
|
else:
|
||||||
|
popup.set_item_disabled(2, false)
|
@ -0,0 +1,129 @@
|
|||||||
|
[gd_scene load_steps=8 format=3 uid="uid://bwaxj1n401fp4"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/EventBlock/event_block.gd" id="1"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://cl75ikyq2is7c" path="res://addons/dialogic/Editor/Events/styles/unselected_stylebox.tres" id="2_axj84"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="6"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_otutu"]
|
||||||
|
bg_color = Color(1, 1, 1, 1)
|
||||||
|
corner_radius_top_left = 5
|
||||||
|
corner_radius_top_right = 5
|
||||||
|
corner_radius_bottom_right = 5
|
||||||
|
corner_radius_bottom_left = 5
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_wcwsv"]
|
||||||
|
data = {
|
||||||
|
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||||
|
"format": "RGBA8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id="ImageTexture_rc1wh"]
|
||||||
|
image = SubResource("Image_wcwsv")
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ee4ub"]
|
||||||
|
|
||||||
|
[node name="EventNode" type="MarginContainer"]
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 9
|
||||||
|
focus_mode = 1
|
||||||
|
script = ExtResource("1")
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||||
|
self_modulate = Color(0, 0, 0, 1)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = ExtResource("2_axj84")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="Header" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="IconPanel" type="Panel" parent="PanelContainer/VBoxContainer/Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 4
|
||||||
|
mouse_filter = 1
|
||||||
|
mouse_default_cursor_shape = 6
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_otutu")
|
||||||
|
|
||||||
|
[node name="IconTexture" type="TextureRect" parent="PanelContainer/VBoxContainer/Header/IconPanel"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
texture = ExtResource("6")
|
||||||
|
expand_mode = 1
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="Warning" type="TextureRect" parent="PanelContainer/VBoxContainer/Header/IconPanel"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = -5.5
|
||||||
|
offset_top = -11.0
|
||||||
|
offset_right = 12.1
|
||||||
|
offset_bottom = 6.6
|
||||||
|
texture = SubResource("ImageTexture_rc1wh")
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="HeaderContent" type="HBoxContainer" parent="PanelContainer/VBoxContainer/Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ToggleBodyVisibilityButton" type="Button" parent="PanelContainer/VBoxContainer/Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
modulate = Color(0, 0, 0, 1)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
tooltip_text = "Fold/Unfold Settings"
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_ee4ub")
|
||||||
|
toggle_mode = true
|
||||||
|
icon = SubResource("ImageTexture_rc1wh")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="ToggleChildrenVisibilityButton" type="Button" parent="PanelContainer/VBoxContainer/Header"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 10
|
||||||
|
tooltip_text = "Collapse Contained Events"
|
||||||
|
toggle_mode = true
|
||||||
|
icon = SubResource("ImageTexture_rc1wh")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="Body" type="MarginContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/margin_left = 4
|
||||||
|
|
||||||
|
[node name="BodyContent" type="VBoxContainer" parent="PanelContainer/VBoxContainer/Body"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[connection signal="gui_input" from="." to="." method="_on_EventNode_gui_input"]
|
||||||
|
[connection signal="toggled" from="PanelContainer/VBoxContainer/Header/ToggleBodyVisibilityButton" to="." method="_on_ToggleBodyVisibility_toggled"]
|
@ -0,0 +1,22 @@
|
|||||||
|
@tool
|
||||||
|
extends PopupMenu
|
||||||
|
|
||||||
|
var current_event : Node = null
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
clear()
|
||||||
|
add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), "Duplicate")
|
||||||
|
add_separator()
|
||||||
|
add_icon_item(get_theme_icon("Help", "EditorIcons"), "Documentation")
|
||||||
|
add_icon_item(get_theme_icon("CodeHighlighter", "EditorIcons"), "Open Code")
|
||||||
|
add_separator()
|
||||||
|
add_icon_item(get_theme_icon("ArrowUp", "EditorIcons"), "Move up")
|
||||||
|
add_icon_item(get_theme_icon("ArrowDown", "EditorIcons"), "Move down")
|
||||||
|
add_separator()
|
||||||
|
add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Delete")
|
||||||
|
|
||||||
|
var menu_background := StyleBoxFlat.new()
|
||||||
|
menu_background.bg_color = get_parent().get_theme_color("base_color", "Editor")
|
||||||
|
add_theme_stylebox_override('panel', menu_background)
|
||||||
|
add_theme_stylebox_override('hover', get_theme_stylebox("FocusViewport", "EditorStyles"))
|
||||||
|
add_theme_color_override('font_color_hover', get_parent().get_theme_color("accent_color", "Editor"))
|
@ -0,0 +1,148 @@
|
|||||||
|
@tool
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
## Event block field part for the Array field.
|
||||||
|
|
||||||
|
signal value_changed()
|
||||||
|
|
||||||
|
var value_field: Node
|
||||||
|
var value_type: int = -1
|
||||||
|
|
||||||
|
var current_value: Variant
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
%ValueType.options = [{
|
||||||
|
'label': 'String',
|
||||||
|
'icon': ["String", "EditorIcons"],
|
||||||
|
'value': TYPE_STRING
|
||||||
|
},{
|
||||||
|
'label': 'Number (int)',
|
||||||
|
'icon': ["int", "EditorIcons"],
|
||||||
|
'value': TYPE_INT
|
||||||
|
},{
|
||||||
|
'label': 'Number (float)',
|
||||||
|
'icon': ["float", "EditorIcons"],
|
||||||
|
'value': TYPE_FLOAT
|
||||||
|
},{
|
||||||
|
'label': 'Boolean',
|
||||||
|
'icon': ["bool", "EditorIcons"],
|
||||||
|
'value': TYPE_BOOL
|
||||||
|
},{
|
||||||
|
'label': 'Expression',
|
||||||
|
'icon': ["Variant", "EditorIcons"],
|
||||||
|
'value': TYPE_MAX
|
||||||
|
}
|
||||||
|
]
|
||||||
|
%ValueType.symbol_only = true
|
||||||
|
%ValueType.value_changed.connect(_on_type_changed.bind())
|
||||||
|
%ValueType.tooltip_text = "Change type"
|
||||||
|
|
||||||
|
%Delete.icon = get_theme_icon("Remove", "EditorIcons")
|
||||||
|
|
||||||
|
|
||||||
|
func set_value(value:Variant):
|
||||||
|
change_field_type(deduce_type(value))
|
||||||
|
%ValueType.set_value(deduce_type(value))
|
||||||
|
current_value = value
|
||||||
|
match value_type:
|
||||||
|
TYPE_BOOL:
|
||||||
|
value_field.button_pressed = value
|
||||||
|
TYPE_STRING:
|
||||||
|
value_field.text = value
|
||||||
|
TYPE_FLOAT, TYPE_INT:
|
||||||
|
value_field.set_value(value)
|
||||||
|
TYPE_MAX, _:
|
||||||
|
value_field.text = value.trim_prefix('@')
|
||||||
|
|
||||||
|
|
||||||
|
func deduce_type(value:Variant) -> int:
|
||||||
|
if value is String and value.begins_with('@'):
|
||||||
|
return TYPE_MAX
|
||||||
|
else:
|
||||||
|
return typeof(value)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_type_changed(prop:String, type:Variant) -> void:
|
||||||
|
if type == value_type:
|
||||||
|
return
|
||||||
|
|
||||||
|
match type:
|
||||||
|
TYPE_BOOL:
|
||||||
|
if typeof(current_value) == TYPE_STRING:
|
||||||
|
current_value = DialogicUtil.str_to_bool(current_value)
|
||||||
|
elif value_type == TYPE_FLOAT or value_type == TYPE_INT:
|
||||||
|
current_value = bool(current_value)
|
||||||
|
else:
|
||||||
|
current_value = true if current_value else false
|
||||||
|
set_value(current_value)
|
||||||
|
TYPE_STRING:
|
||||||
|
current_value = str(current_value).trim_prefix('@')
|
||||||
|
set_value(current_value)
|
||||||
|
TYPE_FLOAT, TYPE_INT:
|
||||||
|
current_value = float(current_value)
|
||||||
|
set_value(current_value)
|
||||||
|
TYPE_MAX,_:
|
||||||
|
current_value = var_to_str(current_value)
|
||||||
|
set_value('@'+current_value)
|
||||||
|
|
||||||
|
|
||||||
|
emit_signal.call_deferred('value_changed')
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> Variant:
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
func _on_delete_pressed() -> void:
|
||||||
|
queue_free()
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func change_field_type(type:int) -> void:
|
||||||
|
if type == value_type:
|
||||||
|
return
|
||||||
|
|
||||||
|
value_type = type
|
||||||
|
|
||||||
|
if value_field:
|
||||||
|
value_field.queue_free()
|
||||||
|
match type:
|
||||||
|
TYPE_BOOL:
|
||||||
|
value_field = CheckBox.new()
|
||||||
|
value_field.toggled.connect(_on_bool_toggled)
|
||||||
|
TYPE_STRING:
|
||||||
|
value_field = LineEdit.new()
|
||||||
|
value_field.text_changed.connect(_on_str_text_changed)
|
||||||
|
value_field.expand_to_text_length = true
|
||||||
|
TYPE_FLOAT, TYPE_INT:
|
||||||
|
value_field = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate()
|
||||||
|
if type == TYPE_FLOAT:
|
||||||
|
value_field.use_float_mode()
|
||||||
|
else:
|
||||||
|
value_field.use_int_mode()
|
||||||
|
value_field.value_changed.connect(_on_number_value_changed.bind(type == TYPE_INT))
|
||||||
|
TYPE_MAX, _:
|
||||||
|
value_field = LineEdit.new()
|
||||||
|
value_field.expand_to_text_length = true
|
||||||
|
value_field.text_changed.connect(_on_expression_changed)
|
||||||
|
$Value.add_child(value_field)
|
||||||
|
$Value.move_child(value_field, 1)
|
||||||
|
|
||||||
|
func _on_bool_toggled(value:bool) -> void:
|
||||||
|
current_value = value
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
func _on_str_text_changed(value:String) -> void:
|
||||||
|
current_value = value
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
func _on_expression_changed(value:String) -> void:
|
||||||
|
current_value = '@'+value
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
func _on_number_value_changed(prop:String, value:float, int := false) -> void:
|
||||||
|
if int:
|
||||||
|
current_value = int(value)
|
||||||
|
else:
|
||||||
|
current_value = value
|
||||||
|
value_changed.emit()
|
@ -0,0 +1,58 @@
|
|||||||
|
[gd_scene load_steps=7 format=3 uid="uid://ch4j2lesn1sis"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/array_part.gd" id="1"]
|
||||||
|
[ext_resource type="Theme" uid="uid://d3g4i4dshtdpu" path="res://addons/dialogic/Editor/Events/styles/InputFieldsStyle.tres" id="2"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d3bhehatwoio" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn" id="3_otpho"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fe32l"]
|
||||||
|
content_margin_left = 2.0
|
||||||
|
content_margin_top = 2.0
|
||||||
|
content_margin_right = 2.0
|
||||||
|
content_margin_bottom = 2.0
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(0.282353, 0.486275, 0.458824, 1)
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_sbk5s"]
|
||||||
|
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_16rly"]
|
||||||
|
image = SubResource("Image_sbk5s")
|
||||||
|
|
||||||
|
[node name="ArrayValue" type="PanelContainer"]
|
||||||
|
offset_left = 2.0
|
||||||
|
offset_right = 76.0
|
||||||
|
offset_bottom = 24.0
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_fe32l")
|
||||||
|
script = ExtResource("1")
|
||||||
|
|
||||||
|
[node name="Value" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme = ExtResource("2")
|
||||||
|
|
||||||
|
[node name="ValueType" parent="Value" instance=ExtResource("3_otpho")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Change type"
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
[node name="Delete" type="Button" parent="Value"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_16rly")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[connection signal="pressed" from="Value/Delete" to="." method="_on_delete_pressed"]
|
@ -0,0 +1,39 @@
|
|||||||
|
@tool
|
||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
## Event block field part for the Array field.
|
||||||
|
|
||||||
|
signal value_changed()
|
||||||
|
|
||||||
|
|
||||||
|
func set_key(value:String) -> void:
|
||||||
|
$Key.text = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
func get_key() -> String:
|
||||||
|
return $Key.text
|
||||||
|
|
||||||
|
|
||||||
|
func set_value(value:String):
|
||||||
|
$Value.text = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> String:
|
||||||
|
return $Value.text
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
$Delete.icon = get_theme_icon("Remove", "EditorIcons")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Delete_pressed() -> void:
|
||||||
|
queue_free()
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Key_text_changed(new_text:String) -> void:
|
||||||
|
value_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Value_text_changed(new_text:String) -> void:
|
||||||
|
value_changed.emit()
|
@ -0,0 +1,38 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://b27yweami3mxi"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://d3g4i4dshtdpu" path="res://addons/dialogic/Editor/Events/styles/InputFieldsStyle.tres" id="1_4ehmb"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/dictionary_part.gd" id="2_q88pg"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_esvau"]
|
||||||
|
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_bywig"]
|
||||||
|
image = SubResource("Image_esvau")
|
||||||
|
|
||||||
|
[node name="Value" type="HBoxContainer"]
|
||||||
|
theme = ExtResource("1_4ehmb")
|
||||||
|
script = ExtResource("2_q88pg")
|
||||||
|
|
||||||
|
[node name="Key" type="LineEdit" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
expand_to_text_length = true
|
||||||
|
|
||||||
|
[node name="Value" type="LineEdit" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
expand_to_text_length = true
|
||||||
|
|
||||||
|
[node name="Delete" type="Button" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_bywig")
|
||||||
|
|
||||||
|
[connection signal="text_changed" from="Key" to="." method="_on_Key_text_changed"]
|
||||||
|
[connection signal="text_changed" from="Value" to="." method="_on_Value_text_changed"]
|
||||||
|
[connection signal="pressed" from="Delete" to="." method="_on_Delete_pressed"]
|
@ -0,0 +1,48 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for editing arrays.
|
||||||
|
|
||||||
|
|
||||||
|
const ArrayValue := "res://addons/dialogic/Editor/Events/Fields/array_part.tscn"
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
%Add.icon = get_theme_icon("Add", "EditorIcons")
|
||||||
|
%Add.pressed.connect(_on_AddButton_pressed)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
value = value as Array
|
||||||
|
for child in get_children():
|
||||||
|
if child != %Add:
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
for item in value:
|
||||||
|
var x: Node = load(ArrayValue).instantiate()
|
||||||
|
add_child(x)
|
||||||
|
x.set_value(item)
|
||||||
|
x.value_changed.connect(recalculate_values)
|
||||||
|
move_child(%Add, -1)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_changed(value:Variant) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
|
||||||
|
|
||||||
|
func recalculate_values() -> void:
|
||||||
|
var arr := []
|
||||||
|
for child in get_children():
|
||||||
|
if child != %Add and !child.is_queued_for_deletion():
|
||||||
|
arr.append(child.get_value())
|
||||||
|
_on_value_changed(arr)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_AddButton_pressed() -> void:
|
||||||
|
var x :Control = load(ArrayValue).instantiate()
|
||||||
|
add_child(x)
|
||||||
|
x.set_value("")
|
||||||
|
x.value_changed.connect(recalculate_values)
|
||||||
|
recalculate_values()
|
||||||
|
move_child(%Add, -1)
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://btmy7ageqpyq1"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_array.gd" id="2"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_u0aqk"]
|
||||||
|
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_7iwuk"]
|
||||||
|
image = SubResource("Image_u0aqk")
|
||||||
|
|
||||||
|
[node name="Field_Array" type="HFlowContainer"]
|
||||||
|
offset_right = 329.0
|
||||||
|
offset_bottom = 256.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
script = ExtResource("2")
|
||||||
|
|
||||||
|
[node name="Add" type="Button" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Add another value"
|
||||||
|
icon = SubResource("ImageTexture_7iwuk")
|
@ -0,0 +1,36 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for boolean values.
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
add_theme_color_override("icon_normal_color", get_theme_color("disabled_font_color", "Editor"))
|
||||||
|
add_theme_color_override("icon_hover_color", get_theme_color("warning_color", "Editor"))
|
||||||
|
add_theme_color_override("icon_pressed_color", get_theme_color("icon_saturation", "Editor"))
|
||||||
|
add_theme_color_override("icon_hover_pressed_color", get_theme_color("warning_color", "Editor"))
|
||||||
|
add_theme_color_override("icon_focus_color", get_theme_color("disabled_font_color", "Editor"))
|
||||||
|
self.toggled.connect(_on_value_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
if info.has('editor_icon'):
|
||||||
|
self.icon = callv('get_theme_icon', info.editor_icon)
|
||||||
|
else:
|
||||||
|
self.icon = info.get('icon', null)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
self.button_pressed = true if value else false
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_value_changed(value:bool) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
#endregion
|
@ -0,0 +1,13 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://iypxcctv080u"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_bool_button.gd" id="1_t1n1f"]
|
||||||
|
|
||||||
|
[node name="Field_BoolButton" type="Button"]
|
||||||
|
theme_override_colors/icon_normal_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_colors/icon_pressed_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_colors/icon_hover_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_colors/icon_hover_pressed_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_colors/icon_focus_color = Color(0, 0, 0, 1)
|
||||||
|
toggle_mode = true
|
||||||
|
flat = true
|
||||||
|
script = ExtResource("1_t1n1f")
|
@ -0,0 +1,30 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for boolean values.
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
func _ready() -> void:
|
||||||
|
self.toggled.connect(_on_value_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
match DialogicUtil.get_variable_value_type(value):
|
||||||
|
DialogicUtil.VarTypes.STRING:
|
||||||
|
self.button_pressed = value and not value.strip_edges() == "false"
|
||||||
|
_:
|
||||||
|
self.button_pressed = value and true
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
func _on_value_changed(value:bool) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,8 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dm5hxmhyyxgq"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.gd" id="1_ckmtx"]
|
||||||
|
|
||||||
|
[node name="Field_BoolCheck" type="CheckButton"]
|
||||||
|
offset_right = 44.0
|
||||||
|
offset_bottom = 24.0
|
||||||
|
script = ExtResource("1_ckmtx")
|
@ -0,0 +1,30 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for color values.
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
self.color_changed.connect(_on_value_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
self.edit_alpha = info.get("edit_alpha", true)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
if value is Color:
|
||||||
|
self.color = Color(value)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_value_changed(value: Color) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,12 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://4e0kjekan5e7"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_color.gd" id="1_l666a"]
|
||||||
|
|
||||||
|
[node name="Field_Color" type="ColorPickerButton"]
|
||||||
|
custom_minimum_size = Vector2(48, 0)
|
||||||
|
offset_right = 64.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
text = " "
|
||||||
|
color = Color(1, 1, 1, 1)
|
||||||
|
script = ExtResource("1_l666a")
|
@ -0,0 +1,267 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for displaying conditions in either a simple or complex way.
|
||||||
|
|
||||||
|
var _current_value1 :Variant = ""
|
||||||
|
var _current_value2 :Variant = ""
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
var too_complex := is_too_complex(value)
|
||||||
|
%ToggleComplex.disabled = too_complex
|
||||||
|
%ToggleComplex.button_pressed = too_complex
|
||||||
|
%ComplexEditor.visible = too_complex
|
||||||
|
%SimpleEditor.visible = !too_complex
|
||||||
|
%ComplexEditor.text = value
|
||||||
|
if not too_complex:
|
||||||
|
load_simple_editor(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _autofocus():
|
||||||
|
%Value1Variable.grab_focus()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
for i in [%Value1Type, %Value2Type]:
|
||||||
|
i.options = [{
|
||||||
|
'label': 'String',
|
||||||
|
'icon': ["String", "EditorIcons"],
|
||||||
|
'value': 0
|
||||||
|
},{
|
||||||
|
'label': 'Number',
|
||||||
|
'icon': ["float", "EditorIcons"],
|
||||||
|
'value': 1
|
||||||
|
},{
|
||||||
|
'label': 'Variable',
|
||||||
|
'icon': load("res://addons/dialogic/Editor/Images/Pieces/variable.svg"),
|
||||||
|
'value': 2
|
||||||
|
},{
|
||||||
|
'label': 'Bool',
|
||||||
|
'icon': ["bool", "EditorIcons"],
|
||||||
|
'value': 3
|
||||||
|
},{
|
||||||
|
'label': 'Expression',
|
||||||
|
'icon': ["Variant", "EditorIcons"],
|
||||||
|
'value': 4
|
||||||
|
}]
|
||||||
|
i.symbol_only = true
|
||||||
|
i.value_changed.connect(value_type_changed.bind(i.name))
|
||||||
|
i.value_changed.connect(something_changed)
|
||||||
|
i.tooltip_text = "Change type"
|
||||||
|
|
||||||
|
|
||||||
|
for i in [%Value1Variable, %Value2Variable]:
|
||||||
|
i.get_suggestions_func = get_variable_suggestions
|
||||||
|
i.value_changed.connect(something_changed)
|
||||||
|
|
||||||
|
%Value1Number.value_changed.connect(something_changed)
|
||||||
|
%Value2Number.value_changed.connect(something_changed)
|
||||||
|
%Value1Text.value_changed.connect(something_changed)
|
||||||
|
%Value2Text.value_changed.connect(something_changed)
|
||||||
|
%Value1Bool.value_changed.connect(something_changed)
|
||||||
|
%Value2Bool.value_changed.connect(something_changed)
|
||||||
|
|
||||||
|
%ToggleComplex.icon = get_theme_icon("Enum", "EditorIcons")
|
||||||
|
|
||||||
|
%Operator.value_changed.connect(something_changed)
|
||||||
|
%Operator.options = [
|
||||||
|
{'label': '==', 'value': '=='},
|
||||||
|
{'label': '>', 'value': '>'},
|
||||||
|
{'label': '<', 'value': '<'},
|
||||||
|
{'label': '<=', 'value': '<='},
|
||||||
|
{'label': '>=', 'value': '>='},
|
||||||
|
{'label': '!=', 'value': '!='}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
func load_simple_editor(condition_string:String) -> void:
|
||||||
|
var data := complex2simple(condition_string)
|
||||||
|
%Value1Type.set_value(get_value_type(data[0], 2))
|
||||||
|
_current_value1 = data[0]
|
||||||
|
value_type_changed('', get_value_type(data[0], 2), 'Value1')
|
||||||
|
%Operator.set_value(data[1].strip_edges())
|
||||||
|
%Value2Type.set_value(get_value_type(data[2], 0))
|
||||||
|
_current_value2 = data[2]
|
||||||
|
value_type_changed('', get_value_type(data[2], 0), 'Value2')
|
||||||
|
|
||||||
|
|
||||||
|
func value_type_changed(property:String, value_type:int, value_name:String) -> void:
|
||||||
|
value_name = value_name.trim_suffix('Type')
|
||||||
|
get_node('%'+value_name+'Variable').hide()
|
||||||
|
get_node('%'+value_name+'Text').hide()
|
||||||
|
get_node('%'+value_name+'Number').hide()
|
||||||
|
get_node('%'+value_name+'Bool').hide()
|
||||||
|
var current_val :Variant = ""
|
||||||
|
if '1' in value_name:
|
||||||
|
current_val = _current_value1
|
||||||
|
else:
|
||||||
|
current_val = _current_value2
|
||||||
|
match value_type:
|
||||||
|
0:
|
||||||
|
get_node('%'+value_name+'Text').show()
|
||||||
|
get_node('%'+value_name+'Text').set_value(trim_value(current_val, value_type))
|
||||||
|
1:
|
||||||
|
get_node('%'+value_name+'Number').show()
|
||||||
|
get_node('%'+value_name+'Number').set_value(float(current_val.strip_edges()))
|
||||||
|
2:
|
||||||
|
get_node('%'+value_name+'Variable').show()
|
||||||
|
get_node('%'+value_name+'Variable').set_value(trim_value(current_val, value_type))
|
||||||
|
3:
|
||||||
|
get_node('%'+value_name+'Bool').show()
|
||||||
|
get_node('%'+value_name+'Bool').set_value(trim_value(current_val, value_type))
|
||||||
|
4:
|
||||||
|
get_node('%'+value_name+'Text').show()
|
||||||
|
get_node('%'+value_name+'Text').set_value(str(current_val))
|
||||||
|
|
||||||
|
|
||||||
|
func get_value_type(value:String, default:int) -> int:
|
||||||
|
value = value.strip_edges()
|
||||||
|
if value.begins_with('"') and value.ends_with('"') and value.count('"')-value.count('\\"') == 2:
|
||||||
|
return 0
|
||||||
|
elif value.begins_with('{') and value.ends_with('}') and value.count('{') == 1:
|
||||||
|
return 2
|
||||||
|
elif value == "true" or value == "false":
|
||||||
|
return 3
|
||||||
|
else:
|
||||||
|
if value.is_empty():
|
||||||
|
return default
|
||||||
|
if value.is_valid_float():
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
|
||||||
|
func prep_value(value:Variant, value_type:int) -> String:
|
||||||
|
if value != null: value = str(value)
|
||||||
|
else: value = ""
|
||||||
|
value = value.strip_edges()
|
||||||
|
match value_type:
|
||||||
|
0: return '"'+value.replace('"', '\\"')+'"'
|
||||||
|
2: return '{'+value+'}'
|
||||||
|
_: return value
|
||||||
|
|
||||||
|
|
||||||
|
func trim_value(value:Variant, value_type:int) -> String:
|
||||||
|
value = value.strip_edges()
|
||||||
|
match value_type:
|
||||||
|
0: return value.trim_prefix('"').trim_suffix('"').replace('\\"', '"')
|
||||||
|
2: return value.trim_prefix('{').trim_suffix('}')
|
||||||
|
3:
|
||||||
|
if value == "true" or (value and (typeof(value) != TYPE_STRING or value != "false")):
|
||||||
|
return "true"
|
||||||
|
else:
|
||||||
|
return "false"
|
||||||
|
_: return value
|
||||||
|
|
||||||
|
|
||||||
|
func something_changed(fake_arg1=null, fake_arg2 = null):
|
||||||
|
if %ComplexEditor.visible:
|
||||||
|
value_changed.emit(property_name, %ComplexEditor.text)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
match %Value1Type.current_value:
|
||||||
|
0: _current_value1 = prep_value(%Value1Text.text, %Value1Type.current_value)
|
||||||
|
1: _current_value1 = str(%Value1Number.get_value())
|
||||||
|
2: _current_value1 = prep_value(%Value1Variable.current_value, %Value1Type.current_value)
|
||||||
|
3: _current_value1 = prep_value(%Value1Bool.button_pressed, %Value1Type.current_value)
|
||||||
|
_: _current_value1 = prep_value(%Value1Text.text, %Value1Type.current_value)
|
||||||
|
|
||||||
|
match %Value2Type.current_value:
|
||||||
|
0: _current_value2 = prep_value(%Value2Text.text, %Value2Type.current_value)
|
||||||
|
1: _current_value2 = str(%Value2Number.get_value())
|
||||||
|
2: _current_value2 = prep_value(%Value2Variable.current_value, %Value2Type.current_value)
|
||||||
|
3: _current_value2 = prep_value(%Value2Bool.button_pressed, %Value2Type.current_value)
|
||||||
|
_: _current_value2 = prep_value(%Value2Text.text, %Value2Type.current_value)
|
||||||
|
|
||||||
|
if event_resource:
|
||||||
|
if not %Operator.text in ['==', '!='] and get_value_type(_current_value2, 0) in [0, 3]:
|
||||||
|
event_resource.ui_update_warning.emit("This operator doesn't work with strings and booleans.")
|
||||||
|
else:
|
||||||
|
event_resource.ui_update_warning.emit("")
|
||||||
|
|
||||||
|
value_changed.emit(property_name, get_simple_condition())
|
||||||
|
|
||||||
|
|
||||||
|
func is_too_complex(condition:String) -> bool:
|
||||||
|
if condition.strip_edges().is_empty():
|
||||||
|
return false
|
||||||
|
|
||||||
|
var comparison_count: int = 0
|
||||||
|
for i in ['==', '!=', '<=', '<', '>', '>=']:
|
||||||
|
comparison_count += condition.count(i)
|
||||||
|
if comparison_count == 1:
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
## Combines the info from the simple editor fields into a string condition
|
||||||
|
func get_simple_condition() -> String:
|
||||||
|
return _current_value1 +" "+ %Operator.text +" "+ _current_value2
|
||||||
|
|
||||||
|
|
||||||
|
func complex2simple(condition:String) -> Array:
|
||||||
|
if is_too_complex(condition) or condition.strip_edges().is_empty():
|
||||||
|
return ['', '==','']
|
||||||
|
|
||||||
|
for i in ['==', '!=', '<=', '<', '>', '>=']:
|
||||||
|
if i in condition:
|
||||||
|
var cond_split := Array(condition.split(i, false))
|
||||||
|
return [cond_split[0], i, cond_split[1]]
|
||||||
|
|
||||||
|
return ['', '==','']
|
||||||
|
|
||||||
|
|
||||||
|
func _on_toggle_complex_toggled(button_pressed:bool) -> void:
|
||||||
|
if button_pressed:
|
||||||
|
%ComplexEditor.show()
|
||||||
|
%SimpleEditor.hide()
|
||||||
|
%ComplexEditor.text = get_simple_condition()
|
||||||
|
else:
|
||||||
|
if !is_too_complex(%ComplexEditor.text):
|
||||||
|
%ComplexEditor.hide()
|
||||||
|
%SimpleEditor.show()
|
||||||
|
load_simple_editor(%ComplexEditor.text)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_complex_editor_text_changed(new_text:String) -> void:
|
||||||
|
%ToggleComplex.disabled = is_too_complex(%ComplexEditor.text)
|
||||||
|
something_changed()
|
||||||
|
|
||||||
|
|
||||||
|
func get_variable_suggestions(filter:String) -> Dictionary:
|
||||||
|
var suggestions := {}
|
||||||
|
var vars :Dictionary= ProjectSettings.get_setting('dialogic/variables', {})
|
||||||
|
for var_path in DialogicUtil.list_variables(vars):
|
||||||
|
suggestions[var_path] = {'value':var_path, 'editor_icon':["ClassList", "EditorIcons"]}
|
||||||
|
return suggestions
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_1_variable_value_changed(property_name: Variant, value: Variant) -> void:
|
||||||
|
var type := DialogicUtil.get_variable_type(value)
|
||||||
|
match type:
|
||||||
|
DialogicUtil.VarTypes.BOOL:
|
||||||
|
if not %Operator.text in ["==", "!="]:
|
||||||
|
%Operator.text = "=="
|
||||||
|
if get_value_type(_current_value2, 3) in [0, 1]:
|
||||||
|
%Value2Type.insert_options()
|
||||||
|
%Value2Type.index_pressed(3)
|
||||||
|
DialogicUtil.VarTypes.STRING:
|
||||||
|
if not %Operator.text in ["==", "!="]:
|
||||||
|
%Operator.text = "=="
|
||||||
|
if get_value_type(_current_value2, 0) in [1, 3]:
|
||||||
|
%Value2Type.insert_options()
|
||||||
|
%Value2Type.index_pressed(0)
|
||||||
|
DialogicUtil.VarTypes.FLOAT, DialogicUtil.VarTypes.INT:
|
||||||
|
if get_value_type(_current_value2, 1) in [0,3]:
|
||||||
|
%Value2Type.insert_options()
|
||||||
|
%Value2Type.index_pressed(1)
|
||||||
|
|
||||||
|
something_changed()
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
[gd_scene load_steps=9 format=3 uid="uid://ir6334lqtuwt"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_condition.gd" id="1_owjj0"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d3bhehatwoio" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn" id="2_f6v80"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c0vkcehgjsjy" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn" id="3_3kfwc"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="4_6q3a6"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dm5hxmhyyxgq" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.tscn" id="5_1x02a"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="6_5a2xd"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_cgfp5"]
|
||||||
|
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_4jujf"]
|
||||||
|
image = SubResource("Image_cgfp5")
|
||||||
|
|
||||||
|
[node name="Field_Condition" type="HBoxContainer"]
|
||||||
|
offset_right = 77.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
script = ExtResource("1_owjj0")
|
||||||
|
|
||||||
|
[node name="SimpleEditor" type="HBoxContainer" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value1Type" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Change type"
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
[node name="Value1Text" parent="SimpleEditor" instance=ExtResource("3_3kfwc")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value1Number" parent="SimpleEditor" instance=ExtResource("4_6q3a6")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value1Bool" parent="SimpleEditor" instance=ExtResource("5_1x02a")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value1Variable" parent="SimpleEditor" instance=ExtResource("6_5a2xd")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
placeholder_text = "Variable"
|
||||||
|
|
||||||
|
[node name="Operator" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value2Type" parent="SimpleEditor" instance=ExtResource("2_f6v80")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Change type"
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
[node name="Value2Text" parent="SimpleEditor" instance=ExtResource("3_3kfwc")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value2Number" parent="SimpleEditor" instance=ExtResource("4_6q3a6")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value2Variable" parent="SimpleEditor" instance=ExtResource("6_5a2xd")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
placeholder_text = "Variable"
|
||||||
|
|
||||||
|
[node name="Value2Bool" parent="SimpleEditor" instance=ExtResource("5_1x02a")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ComplexEditor" type="LineEdit" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
custom_minimum_size = Vector2(150, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 1
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
text = "VAR.Player.Health > 20 and VAR.Counter < 3 and randi()%3 == 2"
|
||||||
|
placeholder_text = "Enter condition"
|
||||||
|
expand_to_text_length = true
|
||||||
|
|
||||||
|
[node name="ToggleComplex" type="Button" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
tooltip_text = "Use complex expression"
|
||||||
|
toggle_mode = true
|
||||||
|
icon = SubResource("ImageTexture_4jujf")
|
||||||
|
|
||||||
|
[connection signal="value_changed" from="SimpleEditor/Value1Variable" to="." method="_on_value_1_variable_value_changed"]
|
||||||
|
[connection signal="text_changed" from="ComplexEditor" to="." method="_on_complex_editor_text_changed"]
|
||||||
|
[connection signal="toggled" from="ToggleComplex" to="." method="_on_toggle_complex_toggled"]
|
@ -0,0 +1,60 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for editing arrays.
|
||||||
|
|
||||||
|
const PairValue = "res://addons/dialogic/Editor/Events/Fields/dictionary_part.tscn"
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
%Add.icon = get_theme_icon("Add", "EditorIcons")
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
for child in %Values.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
var dict : Dictionary
|
||||||
|
|
||||||
|
# attempt to take dictionary values, create a fresh one if not possible
|
||||||
|
if typeof(value) == TYPE_DICTIONARY:
|
||||||
|
dict = value
|
||||||
|
elif typeof(value) == TYPE_STRING:
|
||||||
|
if value.begins_with('{'):
|
||||||
|
var result = JSON.parse_string(value)
|
||||||
|
if result != null:
|
||||||
|
dict = result as Dictionary
|
||||||
|
else:
|
||||||
|
dict = Dictionary()
|
||||||
|
else:
|
||||||
|
dict = Dictionary()
|
||||||
|
|
||||||
|
var keys := dict.keys()
|
||||||
|
var values := dict.values()
|
||||||
|
|
||||||
|
for index in dict.size():
|
||||||
|
var x :Node = load(PairValue).instantiate()
|
||||||
|
%Values.add_child(x)
|
||||||
|
x.set_key(keys[index])
|
||||||
|
x.set_value(values[index])
|
||||||
|
x.value_changed.connect(recalculate_values)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_changed(value:Variant) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
|
||||||
|
|
||||||
|
func recalculate_values() -> void:
|
||||||
|
var dict := {}
|
||||||
|
for child in %Values.get_children():
|
||||||
|
if !child.is_queued_for_deletion():
|
||||||
|
dict[child.get_key()] = child.get_value()
|
||||||
|
_on_value_changed(dict)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_AddButton_pressed() -> void:
|
||||||
|
var x :Control = load(PairValue).instantiate()
|
||||||
|
%Values.add_child(x)
|
||||||
|
x.set_key("")
|
||||||
|
x.set_value("")
|
||||||
|
x.value_changed.connect(recalculate_values)
|
||||||
|
recalculate_values()
|
@ -0,0 +1,46 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://c74bnmhefu72w"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_dictionary.gd" id="1_p4kmu"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b27yweami3mxi" path="res://addons/dialogic/Editor/Events/Fields/dictionary_part.tscn" id="2_fg1gy"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_5s534"]
|
||||||
|
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_bnwpy"]
|
||||||
|
image = SubResource("Image_5s534")
|
||||||
|
|
||||||
|
[node name="Pairs" type="VBoxContainer"]
|
||||||
|
script = ExtResource("1_p4kmu")
|
||||||
|
|
||||||
|
[node name="Editing" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
alignment = 2
|
||||||
|
|
||||||
|
[node name="LeftText" type="Label" parent="Editing"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Add" type="Button" parent="Editing"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_bnwpy")
|
||||||
|
|
||||||
|
[node name="Values" type="VBoxContainer" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value" parent="Values" instance=ExtResource("2_fg1gy")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Value2" parent="Values" instance=ExtResource("2_fg1gy")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[connection signal="pressed" from="Editing/Add" to="." method="_on_AddButton_pressed"]
|
@ -0,0 +1,127 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for selecting a file or directory.
|
||||||
|
|
||||||
|
#region VARIABLES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
@export var file_filter := ""
|
||||||
|
@export var placeholder := ""
|
||||||
|
@export var file_mode : EditorFileDialog.FileMode = EditorFileDialog.FILE_MODE_OPEN_FILE
|
||||||
|
var resource_icon:Texture:
|
||||||
|
get:
|
||||||
|
return resource_icon
|
||||||
|
set(new_icon):
|
||||||
|
resource_icon = new_icon
|
||||||
|
%Icon.texture = new_icon
|
||||||
|
if new_icon == null:
|
||||||
|
%Field.theme_type_variation = ""
|
||||||
|
else:
|
||||||
|
%Field.theme_type_variation = "LineEditWithIcon"
|
||||||
|
|
||||||
|
var max_width := 200
|
||||||
|
var current_value : String
|
||||||
|
var hide_reset:bool = false
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
$FocusStyle.add_theme_stylebox_override('panel', get_theme_stylebox('focus', 'DialogicEventEdit'))
|
||||||
|
|
||||||
|
%OpenButton.icon = get_theme_icon("Folder", "EditorIcons")
|
||||||
|
%OpenButton.button_down.connect(_on_OpenButton_pressed)
|
||||||
|
|
||||||
|
%ClearButton.icon = get_theme_icon("Reload", "EditorIcons")
|
||||||
|
%ClearButton.button_up.connect(clear_path)
|
||||||
|
%ClearButton.visible = !hide_reset
|
||||||
|
|
||||||
|
%Field.set_drag_forwarding(Callable(), self._can_drop_data_fw, self._drop_data_fw)
|
||||||
|
%Field.placeholder_text = placeholder
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
file_filter = info.get('file_filter', '')
|
||||||
|
placeholder = info.get('placeholder', '')
|
||||||
|
resource_icon = info.get('icon', null)
|
||||||
|
await ready
|
||||||
|
if resource_icon == null and info.has('editor_icon'):
|
||||||
|
resource_icon = callv('get_theme_icon', info.editor_icon)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
current_value = value
|
||||||
|
var text := value
|
||||||
|
if file_mode != EditorFileDialog.FILE_MODE_OPEN_DIR:
|
||||||
|
text = value.get_file()
|
||||||
|
%Field.tooltip_text = value
|
||||||
|
|
||||||
|
if %Field.get_theme_font('font').get_string_size(
|
||||||
|
text, 0, -1,
|
||||||
|
%Field.get_theme_font_size('font_size')).x > max_width:
|
||||||
|
%Field.expand_to_text_length = false
|
||||||
|
%Field.custom_minimum_size.x = max_width
|
||||||
|
%Field.size.x = 0
|
||||||
|
else:
|
||||||
|
%Field.custom_minimum_size.x = 0
|
||||||
|
%Field.expand_to_text_length = true
|
||||||
|
|
||||||
|
%Field.text = text
|
||||||
|
|
||||||
|
%ClearButton.visible = !value.is_empty() and !hide_reset
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region BUTTONS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_OpenButton_pressed() -> void:
|
||||||
|
find_parent('EditorView').godot_file_dialog(_on_file_dialog_selected, file_filter, file_mode, "Open "+ property_name)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_file_dialog_selected(path:String) -> void:
|
||||||
|
_set_value(path)
|
||||||
|
emit_signal("value_changed", property_name, path)
|
||||||
|
|
||||||
|
|
||||||
|
func clear_path() -> void:
|
||||||
|
_set_value("")
|
||||||
|
emit_signal("value_changed", property_name, "")
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region DRAG AND DROP
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _can_drop_data_fw(at_position: Vector2, data: Variant) -> bool:
|
||||||
|
if typeof(data) == TYPE_DICTIONARY and data.has('files') and len(data.files) == 1:
|
||||||
|
if file_filter:
|
||||||
|
if '*.'+data.files[0].get_extension() in file_filter:
|
||||||
|
return true
|
||||||
|
else: return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
func _drop_data_fw(at_position: Vector2, data: Variant) -> void:
|
||||||
|
_on_file_dialog_selected(data.files[0])
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region VISUALS FOR FOCUS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_field_focus_entered():
|
||||||
|
$FocusStyle.show()
|
||||||
|
|
||||||
|
func _on_field_focus_exited():
|
||||||
|
$FocusStyle.hide()
|
||||||
|
_on_file_dialog_selected(%Field.text)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,87 @@
|
|||||||
|
[gd_scene load_steps=8 format=3 uid="uid://7mvxuaulctcq"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_file.gd" id="1_0grcf"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tr837"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wq6bt"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6b7on"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_kg01j"]
|
||||||
|
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_j8aof"]
|
||||||
|
image = SubResource("Image_kg01j")
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_raavq"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(1, 0.365, 0.365, 1)
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
corner_detail = 1
|
||||||
|
|
||||||
|
[node name="Field_File" type="MarginContainer"]
|
||||||
|
offset_right = 314.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
script = ExtResource("1_0grcf")
|
||||||
|
|
||||||
|
[node name="BG" type="PanelContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
|
||||||
|
[node name="HBox" type="HBoxContainer" parent="BG"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 2
|
||||||
|
|
||||||
|
[node name="Icon" type="TextureRect" parent="BG/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 4
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="Field" type="LineEdit" parent="BG/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(100, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
mouse_filter = 1
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_tr837")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_wq6bt")
|
||||||
|
theme_override_styles/read_only = SubResource("StyleBoxEmpty_6b7on")
|
||||||
|
expand_to_text_length = true
|
||||||
|
|
||||||
|
[node name="OpenButton" type="Button" parent="BG/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_j8aof")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="ClearButton" type="Button" parent="BG/HBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
icon = SubResource("ImageTexture_j8aof")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="FocusStyle" type="Panel" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_raavq")
|
||||||
|
|
||||||
|
[connection signal="focus_entered" from="BG/HBox/Field" to="." method="_on_field_focus_entered"]
|
||||||
|
[connection signal="focus_exited" from="BG/HBox/Field" to="." method="_on_field_focus_exited"]
|
||||||
|
[connection signal="text_submitted" from="BG/HBox/Field" to="." method="_on_file_dialog_selected"]
|
@ -0,0 +1,198 @@
|
|||||||
|
@tool
|
||||||
|
class_name DialogicVisualEditorFieldNumber
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for integers and floats. Improved version of the native spinbox.
|
||||||
|
|
||||||
|
@export var allow_string : bool = false
|
||||||
|
@export var step: float = 0.1
|
||||||
|
@export var enforce_step: bool = true
|
||||||
|
@export var min: float = 0
|
||||||
|
@export var max: float= 999
|
||||||
|
@export var value = 0.0
|
||||||
|
@export var prefix: String = ""
|
||||||
|
@export var suffix: String = ""
|
||||||
|
|
||||||
|
var _is_holding_button: bool = false #For handling incrementing while holding key or click
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if %Value.text.is_empty():
|
||||||
|
set_value(value)
|
||||||
|
|
||||||
|
update_prefix(prefix)
|
||||||
|
update_suffix(suffix)
|
||||||
|
$Value_Panel.add_theme_stylebox_override('panel', get_theme_stylebox('panel', 'DialogicEventEdit'))
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info: Dictionary) -> void:
|
||||||
|
match info.get('mode', 0):
|
||||||
|
0: #FLOAT
|
||||||
|
use_float_mode(info.get('step', 0.1))
|
||||||
|
1: #INT
|
||||||
|
use_int_mode(info.get('step', 1))
|
||||||
|
2: #DECIBLE:
|
||||||
|
use_decibel_mode(info.get('step', step))
|
||||||
|
|
||||||
|
for option in info.keys():
|
||||||
|
match option:
|
||||||
|
'min': min = info[option]
|
||||||
|
'max': max = info[option]
|
||||||
|
'prefix': update_prefix(info[option])
|
||||||
|
'suffix': update_suffix(info[option])
|
||||||
|
'step':
|
||||||
|
enforce_step = true
|
||||||
|
step = info[option]
|
||||||
|
'hide_step_button': %Spin.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(new_value: Variant) -> void:
|
||||||
|
_on_value_text_submitted(str(new_value), true)
|
||||||
|
%Value.tooltip_text = tooltip_text
|
||||||
|
|
||||||
|
|
||||||
|
func _autofocus():
|
||||||
|
%Value.grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> float:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
func use_float_mode(value_step: float = 0.1) -> void:
|
||||||
|
step = value_step
|
||||||
|
update_suffix("")
|
||||||
|
enforce_step = false
|
||||||
|
|
||||||
|
|
||||||
|
func use_int_mode(value_step: float = 1) -> void:
|
||||||
|
step = value_step
|
||||||
|
update_suffix("")
|
||||||
|
enforce_step = true
|
||||||
|
|
||||||
|
|
||||||
|
func use_decibel_mode(value_step: float = step) -> void:
|
||||||
|
max = 6
|
||||||
|
update_suffix("dB")
|
||||||
|
min = -80
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UI FUNCTIONALITY
|
||||||
|
################################################################################
|
||||||
|
var _stop_button_holding: Callable = func(button: BaseButton) -> void:
|
||||||
|
_is_holding_button = false
|
||||||
|
if button.button_up.get_connections().find(_stop_button_holding):
|
||||||
|
button.button_up.disconnect(_stop_button_holding)
|
||||||
|
if button.focus_exited.get_connections().find(_stop_button_holding):
|
||||||
|
button.focus_exited.disconnect(_stop_button_holding)
|
||||||
|
if button.mouse_exited.get_connections().find(_stop_button_holding):
|
||||||
|
button.mouse_exited.disconnect(_stop_button_holding)
|
||||||
|
|
||||||
|
|
||||||
|
func _holding_button(value_direction: int, button: BaseButton) -> void:
|
||||||
|
if _is_holding_button:
|
||||||
|
return
|
||||||
|
if _stop_button_holding.get_bound_arguments_count() > 0:
|
||||||
|
_stop_button_holding.unbind(0)
|
||||||
|
|
||||||
|
_is_holding_button = true
|
||||||
|
|
||||||
|
#Ensure removal of our value changing routine when it shouldn't run anymore
|
||||||
|
button.button_up.connect(_stop_button_holding.bind(button))
|
||||||
|
button.focus_exited.connect(_stop_button_holding.bind(button))
|
||||||
|
button.mouse_exited.connect(_stop_button_holding.bind(button))
|
||||||
|
|
||||||
|
var scene_tree: SceneTree = get_tree()
|
||||||
|
var delay_timer_ms: int = 600
|
||||||
|
|
||||||
|
#Instead of awaiting for the duration, await per-frame so we can catch any changes in _is_holding_button and exit completely
|
||||||
|
while(delay_timer_ms > 0):
|
||||||
|
if _is_holding_button == false:
|
||||||
|
return
|
||||||
|
var pre_time: int = Time.get_ticks_msec()
|
||||||
|
await scene_tree.process_frame
|
||||||
|
delay_timer_ms -= Time.get_ticks_msec() - pre_time
|
||||||
|
|
||||||
|
var change_speed: float = 0.25
|
||||||
|
|
||||||
|
while(_is_holding_button == true):
|
||||||
|
await scene_tree.create_timer(change_speed).timeout
|
||||||
|
change_speed = maxf(0.05, change_speed - 0.01)
|
||||||
|
_on_value_text_submitted(str(value+(step * value_direction)))
|
||||||
|
|
||||||
|
|
||||||
|
func update_prefix(to_prefix: String) -> void:
|
||||||
|
prefix = to_prefix
|
||||||
|
%Prefix.visible = to_prefix != null and to_prefix != ""
|
||||||
|
%Prefix.text = prefix
|
||||||
|
|
||||||
|
|
||||||
|
func update_suffix(to_suffix: String) -> void:
|
||||||
|
suffix = to_suffix
|
||||||
|
%Suffix.visible = to_suffix != null and to_suffix != ""
|
||||||
|
%Suffix.text = suffix
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
func _on_gui_input(event: InputEvent) -> void:
|
||||||
|
if event.is_action('ui_up') and event.get_action_strength('ui_up') > 0.5:
|
||||||
|
_on_value_text_submitted(str(value+step))
|
||||||
|
elif event.is_action('ui_down') and event.get_action_strength('ui_down') > 0.5:
|
||||||
|
_on_value_text_submitted(str(value-step))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_increment_button_down(button: NodePath) -> void:
|
||||||
|
_on_value_text_submitted(str(value+step))
|
||||||
|
_holding_button(1.0, get_node(button) as BaseButton)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_decrement_button_down(button: NodePath) -> void:
|
||||||
|
_on_value_text_submitted(str(value-step))
|
||||||
|
_holding_button(-1.0, get_node(button) as BaseButton)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_text_submitted(new_text: String, no_signal:= false) -> void:
|
||||||
|
if new_text.is_valid_float():
|
||||||
|
var temp: float = min(max(new_text.to_float(), min), max)
|
||||||
|
if !enforce_step:
|
||||||
|
value = temp
|
||||||
|
else:
|
||||||
|
value = snapped(temp, step)
|
||||||
|
elif allow_string:
|
||||||
|
value = new_text
|
||||||
|
%Value.text = str(value).pad_decimals(len(str(float(step)-floorf(step)))-2)
|
||||||
|
if not no_signal:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
# Visually disable Up or Down arrow when limit is reached to better indicate a limit has been hit
|
||||||
|
%Spin/Decrement.disabled = value <= min
|
||||||
|
%Spin/Increment.disabled = value >= max
|
||||||
|
|
||||||
|
|
||||||
|
# If prefix or suffix was clicked, select the actual value box instead and move the caret to the closest side.
|
||||||
|
func _on_sublabel_clicked(event: InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
var mousePos: Vector2 = get_global_mouse_position()
|
||||||
|
mousePos.x -= get_minimum_size().x / 2
|
||||||
|
if mousePos.x > global_position.x:
|
||||||
|
(%Value as LineEdit).caret_column = (%Value as LineEdit).text.length()
|
||||||
|
else:
|
||||||
|
(%Value as LineEdit).caret_column = 0
|
||||||
|
(%Value as LineEdit).grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_focus_exited() -> void:
|
||||||
|
_on_value_text_submitted(%Value.text)
|
||||||
|
$Value_Panel.add_theme_stylebox_override('panel', get_theme_stylebox('panel', 'DialogicEventEdit'))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_focus_entered() -> void:
|
||||||
|
$Value_Panel.add_theme_stylebox_override('panel', get_theme_stylebox('focus', 'DialogicEventEdit'))
|
||||||
|
%Value.select_all.call_deferred()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
@ -0,0 +1,173 @@
|
|||||||
|
[gd_scene load_steps=9 format=3 uid="uid://kdpp3mibml33"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_number.gd" id="1_0jdnn"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dh1ycbmw8anqh" path="res://addons/dialogic/Editor/Images/Interactable/increment_icon.svg" id="3_v5cne"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://brjikovneb63n" path="res://addons/dialogic/Editor/Images/Interactable/decrement_icon.svg" id="4_ph52o"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_sj3oj"]
|
||||||
|
content_margin_left = 3.0
|
||||||
|
content_margin_right = 1.0
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8yqsu"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_smq50"]
|
||||||
|
content_margin_left = 2.0
|
||||||
|
content_margin_right = 1.0
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_increment"]
|
||||||
|
content_margin_left = 2.0
|
||||||
|
content_margin_top = 6.0
|
||||||
|
content_margin_right = 2.0
|
||||||
|
content_margin_bottom = 2.0
|
||||||
|
bg_color = Color(0.94, 0.94, 0.94, 0)
|
||||||
|
border_color = Color(0, 0, 0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_decrement"]
|
||||||
|
content_margin_left = 2.0
|
||||||
|
content_margin_top = 2.0
|
||||||
|
content_margin_right = 2.0
|
||||||
|
content_margin_bottom = 6.0
|
||||||
|
bg_color = Color(0.94, 0.94, 0.94, 0)
|
||||||
|
border_color = Color(0, 0, 0, 0)
|
||||||
|
|
||||||
|
[node name="Field_Number" type="HBoxContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = -1102.0
|
||||||
|
offset_bottom = -617.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
script = ExtResource("1_0jdnn")
|
||||||
|
prefix = null
|
||||||
|
|
||||||
|
[node name="Value_Panel" type="PanelContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Layout" type="HBoxContainer" parent="Value_Panel"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="Prefix" type="RichTextLabel" parent="Value_Panel/Layout"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
clip_contents = false
|
||||||
|
layout_direction = 2
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
size_flags_vertical = 4
|
||||||
|
mouse_filter = 1
|
||||||
|
mouse_default_cursor_shape = 1
|
||||||
|
theme_override_colors/default_color = Color(0.54099, 0.540991, 0.54099, 1)
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_sj3oj")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_sj3oj")
|
||||||
|
bbcode_enabled = true
|
||||||
|
fit_content = true
|
||||||
|
scroll_active = false
|
||||||
|
autowrap_mode = 0
|
||||||
|
tab_size = 2
|
||||||
|
shortcut_keys_enabled = false
|
||||||
|
drag_and_drop_selection_enabled = false
|
||||||
|
text_direction = 1
|
||||||
|
|
||||||
|
[node name="Value" type="LineEdit" parent="Value_Panel/Layout"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
focus_mode = 1
|
||||||
|
theme_override_constants/minimum_character_width = 0
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_8yqsu")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_8yqsu")
|
||||||
|
theme_override_styles/read_only = SubResource("StyleBoxEmpty_8yqsu")
|
||||||
|
text = "0"
|
||||||
|
alignment = 1
|
||||||
|
expand_to_text_length = true
|
||||||
|
virtual_keyboard_type = 3
|
||||||
|
|
||||||
|
[node name="Suffix" type="RichTextLabel" parent="Value_Panel/Layout"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
clip_contents = false
|
||||||
|
layout_direction = 2
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 8
|
||||||
|
size_flags_vertical = 4
|
||||||
|
mouse_default_cursor_shape = 1
|
||||||
|
theme_override_colors/default_color = Color(0.435192, 0.435192, 0.435192, 1)
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_smq50")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_smq50")
|
||||||
|
bbcode_enabled = true
|
||||||
|
fit_content = true
|
||||||
|
scroll_active = false
|
||||||
|
autowrap_mode = 0
|
||||||
|
tab_size = 2
|
||||||
|
shortcut_keys_enabled = false
|
||||||
|
drag_and_drop_selection_enabled = false
|
||||||
|
text_direction = 1
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="Value_Panel/Layout"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="Spacer" type="MarginContainer" parent="Value_Panel/Layout/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_constants/margin_right = 1
|
||||||
|
|
||||||
|
[node name="Spin" type="VBoxContainer" parent="Value_Panel/Layout/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="Increment" type="Button" parent="Value_Panel/Layout/HBoxContainer/Spin"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
auto_translate = false
|
||||||
|
focus_neighbor_left = NodePath("../../../Value")
|
||||||
|
focus_neighbor_top = NodePath(".")
|
||||||
|
focus_neighbor_bottom = NodePath("../Decrement")
|
||||||
|
theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1)
|
||||||
|
theme_override_colors/icon_focus_color = Color(0.412738, 0.550094, 0.760917, 1)
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_increment")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_increment")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxFlat_increment")
|
||||||
|
theme_override_styles/disabled = SubResource("StyleBoxFlat_increment")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxFlat_increment")
|
||||||
|
icon = ExtResource("3_v5cne")
|
||||||
|
flat = true
|
||||||
|
vertical_icon_alignment = 2
|
||||||
|
|
||||||
|
[node name="Decrement" type="Button" parent="Value_Panel/Layout/HBoxContainer/Spin"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
auto_translate = false
|
||||||
|
focus_neighbor_left = NodePath("../../../Value")
|
||||||
|
focus_neighbor_top = NodePath("../Increment")
|
||||||
|
focus_neighbor_bottom = NodePath(".")
|
||||||
|
theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1)
|
||||||
|
theme_override_colors/icon_focus_color = Color(0.412738, 0.550094, 0.760917, 1)
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_decrement")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_decrement")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxFlat_decrement")
|
||||||
|
theme_override_styles/disabled = SubResource("StyleBoxFlat_decrement")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxFlat_decrement")
|
||||||
|
icon = ExtResource("4_ph52o")
|
||||||
|
flat = true
|
||||||
|
vertical_icon_alignment = 2
|
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="."]
|
||||||
|
custom_minimum_size = Vector2(3, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[connection signal="gui_input" from="Value_Panel/Layout/Prefix" to="." method="_on_sublabel_clicked"]
|
||||||
|
[connection signal="focus_entered" from="Value_Panel/Layout/Value" to="." method="_on_value_focus_entered"]
|
||||||
|
[connection signal="focus_exited" from="Value_Panel/Layout/Value" to="." method="_on_value_focus_exited"]
|
||||||
|
[connection signal="gui_input" from="Value_Panel/Layout/Value" to="." method="_on_gui_input"]
|
||||||
|
[connection signal="text_submitted" from="Value_Panel/Layout/Value" to="." method="_on_value_text_submitted"]
|
||||||
|
[connection signal="gui_input" from="Value_Panel/Layout/Suffix" to="." method="_on_sublabel_clicked"]
|
||||||
|
[connection signal="button_down" from="Value_Panel/Layout/HBoxContainer/Spin/Increment" to="." method="_on_increment_button_down" binds= [NodePath("%Spin/Increment")]]
|
||||||
|
[connection signal="gui_input" from="Value_Panel/Layout/HBoxContainer/Spin/Increment" to="." method="_on_gui_input"]
|
||||||
|
[connection signal="button_down" from="Value_Panel/Layout/HBoxContainer/Spin/Decrement" to="." method="_on_decrement_button_down" binds= [NodePath("%Spin/Decrement")]]
|
||||||
|
[connection signal="gui_input" from="Value_Panel/Layout/HBoxContainer/Spin/Decrement" to="." method="_on_gui_input"]
|
@ -0,0 +1,285 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
## Event block field for strings. Options are determined by a function.
|
||||||
|
|
||||||
|
|
||||||
|
## SETTINGS
|
||||||
|
@export var placeholder_text := "Select Resource"
|
||||||
|
@export var empty_text := ""
|
||||||
|
enum Modes {PURE_STRING, PRETTY_PATH, IDENTIFIER}
|
||||||
|
@export var mode := Modes.PURE_STRING
|
||||||
|
@export var fit_text_length := true
|
||||||
|
var collapse_when_empty := false
|
||||||
|
var valid_file_drop_extension := ""
|
||||||
|
var get_suggestions_func: Callable
|
||||||
|
|
||||||
|
var resource_icon: Texture = null:
|
||||||
|
get:
|
||||||
|
return resource_icon
|
||||||
|
set(new_icon):
|
||||||
|
resource_icon = new_icon
|
||||||
|
%Icon.texture = new_icon
|
||||||
|
|
||||||
|
## STATE
|
||||||
|
var current_value: String
|
||||||
|
var current_selected := 0
|
||||||
|
|
||||||
|
## SUGGESTIONS ITEM LIST
|
||||||
|
var _v_separation := 0
|
||||||
|
var _h_separation := 0
|
||||||
|
var _icon_margin := 0
|
||||||
|
var _line_height := 24
|
||||||
|
var _max_height := 200 * DialogicUtil.get_editor_scale()
|
||||||
|
|
||||||
|
|
||||||
|
#region FIELD METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
if value == null or value.is_empty():
|
||||||
|
%Search.text = empty_text
|
||||||
|
else:
|
||||||
|
match mode:
|
||||||
|
Modes.PRETTY_PATH:
|
||||||
|
%Search.text = DialogicUtil.pretty_name(value)
|
||||||
|
Modes.IDENTIFIER when value.begins_with("res://"):
|
||||||
|
%Search.text = DialogicResourceUtil.get_unique_identifier(value)
|
||||||
|
_:
|
||||||
|
%Search.text = str(value)
|
||||||
|
|
||||||
|
%Search.visible = not collapse_when_empty or value
|
||||||
|
current_value = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
valid_file_drop_extension = info.get('file_extension', '')
|
||||||
|
collapse_when_empty = info.get('collapse_when_empty', false)
|
||||||
|
get_suggestions_func = info.get('suggestions_func', get_suggestions_func)
|
||||||
|
empty_text = info.get('empty_text', '')
|
||||||
|
placeholder_text = info.get('placeholder', 'Select Resource')
|
||||||
|
mode = info.get("mode", 0)
|
||||||
|
resource_icon = info.get('icon', null)
|
||||||
|
await ready
|
||||||
|
if resource_icon == null and info.has('editor_icon'):
|
||||||
|
resource_icon = callv('get_theme_icon', info.editor_icon)
|
||||||
|
|
||||||
|
|
||||||
|
func _autofocus() -> void:
|
||||||
|
%Search.grab_focus()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region BASIC
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
%Focus.add_theme_stylebox_override('panel', get_theme_stylebox('focus', 'DialogicEventEdit'))
|
||||||
|
|
||||||
|
%Search.text_changed.connect(_on_Search_text_changed)
|
||||||
|
%Search.text_submitted.connect(_on_Search_text_entered)
|
||||||
|
%Search.placeholder_text = placeholder_text
|
||||||
|
%Search.expand_to_text_length = fit_text_length
|
||||||
|
|
||||||
|
%SelectButton.icon = get_theme_icon("Collapse", "EditorIcons")
|
||||||
|
|
||||||
|
%Suggestions.add_theme_stylebox_override('bg', load("res://addons/dialogic/Editor/Events/styles/ResourceMenuPanelBackground.tres"))
|
||||||
|
%Suggestions.hide()
|
||||||
|
%Suggestions.item_selected.connect(suggestion_selected)
|
||||||
|
%Suggestions.item_clicked.connect(suggestion_selected)
|
||||||
|
%Suggestions.fixed_icon_size = Vector2i(16, 16) * DialogicUtil.get_editor_scale()
|
||||||
|
|
||||||
|
_v_separation = %Suggestions.get_theme_constant("v_separation")
|
||||||
|
_h_separation = %Suggestions.get_theme_constant("h_separation")
|
||||||
|
_icon_margin = %Suggestions.get_theme_constant("icon_margin")
|
||||||
|
|
||||||
|
if resource_icon == null:
|
||||||
|
self.resource_icon = null
|
||||||
|
|
||||||
|
|
||||||
|
func change_to_empty() -> void:
|
||||||
|
value_changed.emit(property_name, "")
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SEARCH & SUGGESTION POPUP
|
||||||
|
################################################################################
|
||||||
|
func _on_Search_text_entered(new_text:String) -> void:
|
||||||
|
if %Suggestions.get_item_count():
|
||||||
|
if %Suggestions.is_anything_selected():
|
||||||
|
suggestion_selected(%Suggestions.get_selected_items()[0])
|
||||||
|
else:
|
||||||
|
suggestion_selected(0)
|
||||||
|
else:
|
||||||
|
change_to_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Search_text_changed(new_text:String, just_update:bool = false) -> void:
|
||||||
|
%Suggestions.clear()
|
||||||
|
|
||||||
|
if new_text == "" and !just_update:
|
||||||
|
change_to_empty()
|
||||||
|
else:
|
||||||
|
%Search.show()
|
||||||
|
|
||||||
|
var suggestions: Dictionary = get_suggestions_func.call(new_text)
|
||||||
|
|
||||||
|
var line_length = 0
|
||||||
|
var idx: int = 0
|
||||||
|
for element in suggestions:
|
||||||
|
if new_text.is_empty() or new_text.to_lower() in element.to_lower() or new_text.to_lower() in str(suggestions[element].value).to_lower() or new_text.to_lower() in suggestions[element].get('tooltip', '').to_lower():
|
||||||
|
var curr_line_length: int = 0
|
||||||
|
curr_line_length = get_theme_font('font', 'Label').get_string_size(
|
||||||
|
element, HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size", 'Label')
|
||||||
|
).x
|
||||||
|
|
||||||
|
%Suggestions.add_item(element)
|
||||||
|
if suggestions[element].has('icon'):
|
||||||
|
%Suggestions.set_item_icon(idx, suggestions[element].icon)
|
||||||
|
curr_line_length += %Suggestions.fixed_icon_size.x * %Suggestions.get_icon_scale() + _icon_margin * 2 + _h_separation
|
||||||
|
elif suggestions[element].has('editor_icon'):
|
||||||
|
%Suggestions.set_item_icon(idx, get_theme_icon(suggestions[element].editor_icon[0],suggestions[element].editor_icon[1]))
|
||||||
|
curr_line_length += %Suggestions.fixed_icon_size.x * %Suggestions.get_icon_scale() + _icon_margin * 2 + _h_separation
|
||||||
|
|
||||||
|
line_length = max(line_length, curr_line_length)
|
||||||
|
|
||||||
|
%Suggestions.set_item_tooltip(idx, suggestions[element].get('tooltip', ''))
|
||||||
|
%Suggestions.set_item_metadata(idx, suggestions[element].value)
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
if not %Suggestions.visible:
|
||||||
|
%Suggestions.show()
|
||||||
|
%Suggestions.global_position = $PanelContainer.global_position+Vector2(0,1)*$PanelContainer.size.y
|
||||||
|
|
||||||
|
if %Suggestions.item_count:
|
||||||
|
%Suggestions.select(0)
|
||||||
|
current_selected = 0
|
||||||
|
else:
|
||||||
|
current_selected = -1
|
||||||
|
%Search.grab_focus()
|
||||||
|
|
||||||
|
var total_height: int = 0
|
||||||
|
for item in %Suggestions.item_count:
|
||||||
|
total_height += _line_height * DialogicUtil.get_editor_scale() + _v_separation
|
||||||
|
total_height += _v_separation * 2
|
||||||
|
if total_height > _max_height:
|
||||||
|
line_length += %Suggestions.get_v_scroll_bar().get_minimum_size().x
|
||||||
|
|
||||||
|
%Suggestions.size.x = max(%PanelContainer.size.x, line_length)
|
||||||
|
%Suggestions.size.y = min(total_height, _max_height)
|
||||||
|
|
||||||
|
# Defer setting width to give PanelContainer
|
||||||
|
# time to update it's size
|
||||||
|
await get_tree().process_frame
|
||||||
|
await get_tree().process_frame
|
||||||
|
|
||||||
|
%Suggestions.size.x = max(%PanelContainer.size.x, line_length)
|
||||||
|
|
||||||
|
|
||||||
|
func suggestion_selected(index: int, position := Vector2(), button_index := MOUSE_BUTTON_LEFT) -> void:
|
||||||
|
if button_index != MOUSE_BUTTON_LEFT:
|
||||||
|
return
|
||||||
|
if %Suggestions.is_item_disabled(index):
|
||||||
|
return
|
||||||
|
|
||||||
|
%Search.text = %Suggestions.get_item_text(index)
|
||||||
|
|
||||||
|
if %Suggestions.get_item_metadata(index) == null:
|
||||||
|
current_value = ""
|
||||||
|
|
||||||
|
else:
|
||||||
|
current_value = %Suggestions.get_item_metadata(index)
|
||||||
|
|
||||||
|
hide_suggestions()
|
||||||
|
|
||||||
|
grab_focus()
|
||||||
|
value_changed.emit(property_name, current_value)
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event:InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
if %Suggestions.visible:
|
||||||
|
if !%Suggestions.get_global_rect().has_point(get_global_mouse_position()) and \
|
||||||
|
!%SelectButton.get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
hide_suggestions()
|
||||||
|
|
||||||
|
|
||||||
|
func hide_suggestions() -> void:
|
||||||
|
%SelectButton.set_pressed_no_signal(false)
|
||||||
|
%Suggestions.hide()
|
||||||
|
if !current_value and collapse_when_empty:
|
||||||
|
%Search.hide()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_SelectButton_toggled(button_pressed:bool) -> void:
|
||||||
|
if button_pressed:
|
||||||
|
_on_Search_text_changed('', true)
|
||||||
|
else:
|
||||||
|
hide_suggestions()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_focus_entered() -> void:
|
||||||
|
%Search.grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_search_gui_input(event: InputEvent) -> void:
|
||||||
|
if event is InputEventKey and (event.keycode == KEY_DOWN or event.keycode == KEY_UP) and event.pressed:
|
||||||
|
if !%Suggestions.visible:
|
||||||
|
_on_Search_text_changed('', true)
|
||||||
|
current_selected = -1
|
||||||
|
if event.keycode == KEY_DOWN:
|
||||||
|
current_selected = wrapi(current_selected+1, 0, %Suggestions.item_count)
|
||||||
|
if event.keycode == KEY_UP:
|
||||||
|
current_selected = wrapi(current_selected-1, 0, %Suggestions.item_count)
|
||||||
|
%Suggestions.select(current_selected)
|
||||||
|
%Suggestions.ensure_current_is_visible()
|
||||||
|
|
||||||
|
if Input.is_key_pressed(KEY_CTRL):
|
||||||
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
if valid_file_drop_extension in [".dch", ".dtl"] and not current_value.is_empty():
|
||||||
|
EditorInterface.edit_resource(DialogicResourceUtil.get_resource_from_identifier(current_value, valid_file_drop_extension))
|
||||||
|
|
||||||
|
if valid_file_drop_extension in [".dch", ".dtl"] and not current_value.is_empty():
|
||||||
|
%Search.mouse_default_cursor_shape = CURSOR_POINTING_HAND
|
||||||
|
else:
|
||||||
|
%Search.mouse_default_cursor_shape = CURSOR_IBEAM
|
||||||
|
|
||||||
|
|
||||||
|
func _on_search_focus_entered() -> void:
|
||||||
|
if %Search.text == "":
|
||||||
|
_on_Search_text_changed("")
|
||||||
|
%Search.call_deferred('select_all')
|
||||||
|
%Focus.show()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_search_focus_exited() -> void:
|
||||||
|
%Focus.hide()
|
||||||
|
if !%Suggestions.get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
hide_suggestions()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region DRAG AND DROP
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _can_drop_data(position:Vector2, data:Variant) -> bool:
|
||||||
|
if typeof(data) == TYPE_DICTIONARY and data.has('files') and len(data.files) == 1:
|
||||||
|
if valid_file_drop_extension:
|
||||||
|
if data.files[0].ends_with(valid_file_drop_extension):
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _drop_data(position:Vector2, data:Variant) -> void:
|
||||||
|
var path := str(data.files[0])
|
||||||
|
if mode == Modes.IDENTIFIER:
|
||||||
|
path = DialogicResourceUtil.get_unique_identifier(path)
|
||||||
|
_set_value(path)
|
||||||
|
value_changed.emit(property_name, path)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,135 @@
|
|||||||
|
[gd_scene load_steps=7 format=3 uid="uid://dpwhshre1n4t6"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd" id="1_b07gq"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tmt5n"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_vennf"]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_jcy4w"]
|
||||||
|
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_8v6yx"]
|
||||||
|
image = SubResource("Image_jcy4w")
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2yd2x"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(1, 0.365, 0.365, 1)
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
corner_detail = 1
|
||||||
|
|
||||||
|
[node name="Field_DynamicStringOptions" type="HBoxContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -2.0
|
||||||
|
offset_top = -2.0
|
||||||
|
offset_right = -1005.0
|
||||||
|
offset_bottom = -622.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
focus_mode = 2
|
||||||
|
script = ExtResource("1_b07gq")
|
||||||
|
placeholder_text = ""
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="MarginContainer" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/margin_left = 0
|
||||||
|
theme_override_constants/margin_top = 0
|
||||||
|
theme_override_constants/margin_right = 0
|
||||||
|
theme_override_constants/margin_bottom = 0
|
||||||
|
|
||||||
|
[node name="BG" type="Panel" parent="PanelContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
metadata/_edit_use_anchors_ = true
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/margin_left = 2
|
||||||
|
theme_override_constants/margin_top = 2
|
||||||
|
theme_override_constants/margin_right = 2
|
||||||
|
theme_override_constants/margin_bottom = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Icon" type="TextureRect" parent="PanelContainer/MarginContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
mouse_filter = 2
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="Search" type="LineEdit" parent="PanelContainer/MarginContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 4
|
||||||
|
focus_neighbor_bottom = NodePath("Suggestions")
|
||||||
|
focus_mode = 1
|
||||||
|
mouse_filter = 1
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_tmt5n")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_vennf")
|
||||||
|
expand_to_text_length = true
|
||||||
|
flat = true
|
||||||
|
caret_blink = true
|
||||||
|
|
||||||
|
[node name="Suggestions" type="ItemList" parent="PanelContainer/MarginContainer/HBoxContainer/Search"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
top_level = true
|
||||||
|
custom_minimum_size = Vector2(-1086, 0)
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = -5.0
|
||||||
|
offset_top = 36.0
|
||||||
|
offset_right = 195.0
|
||||||
|
offset_bottom = 71.0
|
||||||
|
size_flags_vertical = 0
|
||||||
|
auto_translate = false
|
||||||
|
focus_neighbor_top = NodePath("..")
|
||||||
|
max_text_lines = 3
|
||||||
|
item_count = 1
|
||||||
|
fixed_icon_size = Vector2i(16, 16)
|
||||||
|
item_0/text = "Hello"
|
||||||
|
|
||||||
|
[node name="SelectButton" type="Button" parent="PanelContainer/MarginContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
focus_mode = 0
|
||||||
|
toggle_mode = true
|
||||||
|
shortcut_in_tooltip = false
|
||||||
|
icon = SubResource("ImageTexture_8v6yx")
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="Focus" type="Panel" parent="PanelContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_2yd2x")
|
||||||
|
metadata/_edit_use_anchors_ = true
|
||||||
|
|
||||||
|
[connection signal="focus_entered" from="." to="." method="_on_focus_entered"]
|
||||||
|
[connection signal="focus_entered" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_entered"]
|
||||||
|
[connection signal="focus_exited" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_exited"]
|
||||||
|
[connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_gui_input"]
|
||||||
|
[connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search/Suggestions" to="." method="_on_suggestions_gui_input"]
|
||||||
|
[connection signal="toggled" from="PanelContainer/MarginContainer/HBoxContainer/SelectButton" to="." method="_on_SelectButton_toggled"]
|
@ -0,0 +1,62 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for constant options. For varying options use ComplexPicker.
|
||||||
|
|
||||||
|
var options : Array = []
|
||||||
|
|
||||||
|
## if true, only the symbol will be displayed. In the dropdown text will be visible.
|
||||||
|
## Useful for making UI simpler
|
||||||
|
var symbol_only := false:
|
||||||
|
set(value):
|
||||||
|
symbol_only = value
|
||||||
|
if value: self.text = ""
|
||||||
|
|
||||||
|
var current_value: Variant = -1
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
add_theme_color_override("font_disabled_color", get_theme_color("font_color", "MenuButton"))
|
||||||
|
self.about_to_popup.connect(insert_options)
|
||||||
|
call("get_popup").index_pressed.connect(index_pressed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
options = info.get('options', [])
|
||||||
|
self.disabled = info.get('disabled', false)
|
||||||
|
symbol_only = info.get('symbol_only', false)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
for option in options:
|
||||||
|
if option['value'] == value:
|
||||||
|
if typeof(option.get('icon')) == TYPE_ARRAY:
|
||||||
|
option.icon = callv('get_theme_icon', option.get('icon'))
|
||||||
|
if !symbol_only:
|
||||||
|
self.text = option['label']
|
||||||
|
self.icon = option.get('icon', null)
|
||||||
|
current_value = value
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> Variant:
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
func insert_options() -> void:
|
||||||
|
call("get_popup").clear()
|
||||||
|
|
||||||
|
var idx := 0
|
||||||
|
for option in options:
|
||||||
|
if typeof(option.get('icon')) == TYPE_ARRAY:
|
||||||
|
option.icon = callv('get_theme_icon', option.get('icon'))
|
||||||
|
call("get_popup").add_icon_item(option.get('icon', null), option['label'])
|
||||||
|
call("get_popup").set_item_metadata(idx, option['value'])
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
|
||||||
|
func index_pressed(idx:int) -> void:
|
||||||
|
current_value = idx
|
||||||
|
if !symbol_only:
|
||||||
|
self.text = call("get_popup").get_item_text(idx)
|
||||||
|
self.icon =call("get_popup").get_item_icon(idx)
|
||||||
|
value_changed.emit(property_name, call("get_popup").get_item_metadata(idx))
|
@ -0,0 +1,13 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://d3bhehatwoio"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.gd" id="1"]
|
||||||
|
|
||||||
|
[node name="Field_FixedOptions" type="MenuButton"]
|
||||||
|
offset_right = 137.0
|
||||||
|
offset_bottom = 43.0
|
||||||
|
focus_mode = 2
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
theme_override_colors/font_disabled_color = Color(0.875, 0.875, 0.875, 1)
|
||||||
|
text = "Placeholder Text"
|
||||||
|
flat = false
|
||||||
|
script = ExtResource("1")
|
@ -0,0 +1,74 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field that allows entering multiline text (mainly text event).
|
||||||
|
|
||||||
|
@onready var code_completion_helper: Node = find_parent('EditorsManager').get_node('CodeCompletionHelper')
|
||||||
|
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
self.text_changed.connect(_on_text_changed)
|
||||||
|
self.syntax_highlighter = code_completion_helper.text_syntax_highlighter
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
self.text = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
func _autofocus() -> void:
|
||||||
|
grab_focus()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_text_changed(value := "") -> void:
|
||||||
|
value_changed.emit(property_name, self.text)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region AUTO COMPLETION
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## Called if something was typed
|
||||||
|
func _request_code_completion(force:bool):
|
||||||
|
code_completion_helper.request_code_completion(force, self, 0)
|
||||||
|
|
||||||
|
|
||||||
|
## Filters the list of all possible options, depending on what was typed
|
||||||
|
## Purpose of the different Kinds is explained in [_request_code_completion]
|
||||||
|
func _filter_code_completion_candidates(candidates:Array) -> Array:
|
||||||
|
return code_completion_helper.filter_code_completion_candidates(candidates, self)
|
||||||
|
|
||||||
|
|
||||||
|
## Called when code completion was activated
|
||||||
|
## Inserts the selected item
|
||||||
|
func _confirm_code_completion(replace:bool) -> void:
|
||||||
|
code_completion_helper.confirm_code_completion(replace, self)
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SYMBOL CLICKING
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## Performs an action (like opening a link) when a valid symbol was clicked
|
||||||
|
func _on_symbol_lookup(symbol, line, column):
|
||||||
|
code_completion_helper.symbol_lookup(symbol, line, column)
|
||||||
|
|
||||||
|
|
||||||
|
## Called to test if a symbol can be clicked
|
||||||
|
func _on_symbol_validate(symbol:String) -> void:
|
||||||
|
code_completion_helper.symbol_validate(symbol, self)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,29 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://dyp7m2nvab1aj"]
|
||||||
|
|
||||||
|
[ext_resource type="StyleBox" uid="uid://cu8otiwksn8ma" path="res://addons/dialogic/Editor/Events/styles/TextBackground.tres" id="1_xq18n"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd" id="2_ww6ga"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_text_multiline.gd" id="3_q7600"]
|
||||||
|
|
||||||
|
[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_2q5dk"]
|
||||||
|
script = ExtResource("2_ww6ga")
|
||||||
|
|
||||||
|
[node name="Field_Text_Multiline" type="CodeEdit"]
|
||||||
|
offset_right = 413.0
|
||||||
|
offset_bottom = 15.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_styles/normal = ExtResource("1_xq18n")
|
||||||
|
wrap_mode = 1
|
||||||
|
scroll_fit_content_height = true
|
||||||
|
syntax_highlighter = SubResource("SyntaxHighlighter_2q5dk")
|
||||||
|
symbol_lookup_on_click = true
|
||||||
|
delimiter_strings = Array[String]([])
|
||||||
|
code_completion_enabled = true
|
||||||
|
code_completion_prefixes = Array[String](["[", "{"])
|
||||||
|
indent_automatic_prefixes = Array[String]([":", "{", "[", ")"])
|
||||||
|
auto_brace_completion_enabled = true
|
||||||
|
auto_brace_completion_pairs = {
|
||||||
|
"[": "]",
|
||||||
|
"{": "}"
|
||||||
|
}
|
||||||
|
script = ExtResource("3_q7600")
|
@ -0,0 +1,40 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
|
||||||
|
## Event block field for a single line of text.
|
||||||
|
|
||||||
|
|
||||||
|
var placeholder :String= "":
|
||||||
|
set(value):
|
||||||
|
placeholder = value
|
||||||
|
self.placeholder_text = placeholder
|
||||||
|
|
||||||
|
|
||||||
|
#region MAIN METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
self.text_changed.connect(_on_text_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
self.placeholder = info.get('placeholder', '')
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
self.text = str(value)
|
||||||
|
|
||||||
|
|
||||||
|
func _autofocus():
|
||||||
|
grab_focus()
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region SIGNAL METHODS
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
func _on_text_changed(value := "") -> void:
|
||||||
|
value_changed.emit(property_name, self.text)
|
||||||
|
|
||||||
|
#endregion
|
@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://c0vkcehgjsjy"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.gd" id="1_4vnxv"]
|
||||||
|
|
||||||
|
[node name="Field_Text_Singleline" type="LineEdit"]
|
||||||
|
offset_right = 1152.0
|
||||||
|
offset_bottom = 81.0
|
||||||
|
theme_type_variation = &"DialogicEventEdit"
|
||||||
|
expand_to_text_length = true
|
||||||
|
script = ExtResource("1_4vnxv")
|
@ -0,0 +1,26 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorFieldVector
|
||||||
|
## Event block field for a Vector2.
|
||||||
|
|
||||||
|
var current_value := Vector2()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value: Variant) -> void:
|
||||||
|
current_value = value
|
||||||
|
super(value)
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> Vector2:
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
func _on_sub_value_changed(sub_component: String, value: float) -> void:
|
||||||
|
match sub_component:
|
||||||
|
'X': current_value.x = value
|
||||||
|
'Y': current_value.y = value
|
||||||
|
_on_value_changed(current_value)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_sub_component_text(value: Variant) -> void:
|
||||||
|
$X._on_value_text_submitted(str(value.x), true)
|
||||||
|
$Y._on_value_text_submitted(str(value.y), true)
|
@ -0,0 +1,29 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://dtimnsj014cu"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.gd" id="1_v6lp0"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="2_a0b6y"]
|
||||||
|
|
||||||
|
[node name="Field_Vector2" type="HBoxContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = -1033.0
|
||||||
|
offset_bottom = -617.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 2
|
||||||
|
script = ExtResource("1_v6lp0")
|
||||||
|
|
||||||
|
[node name="X" parent="." instance=ExtResource("2_a0b6y")]
|
||||||
|
layout_mode = 2
|
||||||
|
step = 0.001
|
||||||
|
min = -9999.0
|
||||||
|
max = 9999.0
|
||||||
|
prefix = ""
|
||||||
|
|
||||||
|
[node name="Y" parent="." instance=ExtResource("2_a0b6y")]
|
||||||
|
layout_mode = 2
|
||||||
|
step = 0.001
|
||||||
|
min = -9999.0
|
||||||
|
max = 9999.0
|
||||||
|
prefix = ""
|
@ -0,0 +1,28 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorFieldVector
|
||||||
|
## Event block field for a Vector3.
|
||||||
|
|
||||||
|
var current_value := Vector3()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value: Variant) -> void:
|
||||||
|
current_value = value
|
||||||
|
super(value)
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> Vector3:
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
func _on_sub_value_changed(sub_component: String, value: float) -> void:
|
||||||
|
match sub_component:
|
||||||
|
'X': current_value.x = value
|
||||||
|
'Y': current_value.y = value
|
||||||
|
'Z': current_value.z = value
|
||||||
|
_on_value_changed(current_value)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_sub_component_text(value: Variant) -> void:
|
||||||
|
$X._on_value_text_submitted(str(value.x), true)
|
||||||
|
$Y._on_value_text_submitted(str(value.y), true)
|
||||||
|
$Z._on_value_text_submitted(str(value.z), true)
|
@ -0,0 +1,16 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://cklkpfrcvopgw"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="1_l3y0o"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_vector3.gd" id="2_gktf1"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="3_k0u0p"]
|
||||||
|
|
||||||
|
[node name="Field_Vector3" instance=ExtResource("1_l3y0o")]
|
||||||
|
offset_right = -973.0
|
||||||
|
script = ExtResource("2_gktf1")
|
||||||
|
|
||||||
|
[node name="Z" parent="." index="2" instance=ExtResource("3_k0u0p")]
|
||||||
|
layout_mode = 2
|
||||||
|
step = 0.001
|
||||||
|
min = -9999.0
|
||||||
|
max = 9999.0
|
||||||
|
affix = "z:"
|
@ -0,0 +1,30 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicVisualEditorFieldVector
|
||||||
|
## Event block field for a Vector4.
|
||||||
|
|
||||||
|
var current_value := Vector4()
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value: Variant) -> void:
|
||||||
|
current_value = value
|
||||||
|
super(value)
|
||||||
|
|
||||||
|
|
||||||
|
func get_value() -> Vector4:
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
func _on_sub_value_changed(sub_component: String, value: float) -> void:
|
||||||
|
match sub_component:
|
||||||
|
'X': current_value.x = value
|
||||||
|
'Y': current_value.y = value
|
||||||
|
'Z': current_value.z = value
|
||||||
|
'W': current_value.w = value
|
||||||
|
_on_value_changed(current_value)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_sub_component_text(value: Variant) -> void:
|
||||||
|
$X._on_value_text_submitted(str(value.x), true)
|
||||||
|
$Y._on_value_text_submitted(str(value.y), true)
|
||||||
|
$Z._on_value_text_submitted(str(value.z), true)
|
||||||
|
$W._on_value_text_submitted(str(value.w), true)
|
@ -0,0 +1,16 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dykss037r2rsc"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cklkpfrcvopgw" path="res://addons/dialogic/Editor/Events/Fields/field_vector3.tscn" id="1_20tvl"]
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/field_vector4.gd" id="2_yksrc"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="3_1jogk"]
|
||||||
|
|
||||||
|
[node name="Field_Vector4" instance=ExtResource("1_20tvl")]
|
||||||
|
offset_right = -908.0
|
||||||
|
script = ExtResource("2_yksrc")
|
||||||
|
|
||||||
|
[node name="W" parent="." index="3" instance=ExtResource("3_1jogk")]
|
||||||
|
layout_mode = 2
|
||||||
|
step = 0.001
|
||||||
|
min = -9999.0
|
||||||
|
max = 9999.0
|
||||||
|
affix = "w:"
|
@ -0,0 +1,38 @@
|
|||||||
|
class_name DialogicVisualEditorFieldVector
|
||||||
|
extends DialogicVisualEditorField
|
||||||
|
## Base type for Vector event blocks
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
for child in get_children():
|
||||||
|
child.tooltip_text = tooltip_text
|
||||||
|
child.property_name = child.name #to identify the name of the changed sub-component
|
||||||
|
child.value_changed.connect(_on_sub_value_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _load_display_info(info: Dictionary) -> void:
|
||||||
|
for child in get_children():
|
||||||
|
if child is DialogicVisualEditorFieldNumber:
|
||||||
|
if info.get('no_prefix', false):
|
||||||
|
child._load_display_info(info)
|
||||||
|
else:
|
||||||
|
var prefixed_info := info.duplicate()
|
||||||
|
prefixed_info.merge({'prefix':child.name.to_lower()})
|
||||||
|
child._load_display_info(prefixed_info)
|
||||||
|
|
||||||
|
|
||||||
|
func _set_value(value: Variant) -> void:
|
||||||
|
_update_sub_component_text(value)
|
||||||
|
_on_value_changed(value)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_changed(value: Variant) -> void:
|
||||||
|
value_changed.emit(property_name, value)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_sub_value_changed(sub_component: String, value: float) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _update_sub_component_text(value: Variant) -> void:
|
||||||
|
pass
|
@ -0,0 +1,35 @@
|
|||||||
|
@tool
|
||||||
|
class_name DialogicVisualEditorField
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
signal value_changed(property_name:String, value:Variant)
|
||||||
|
var property_name := ""
|
||||||
|
|
||||||
|
var event_resource: DialogicEvent = null
|
||||||
|
|
||||||
|
#region OVERWRITES
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
## To be overwritten
|
||||||
|
func _load_display_info(info:Dictionary) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
## To be overwritten
|
||||||
|
func _set_value(value:Variant) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
## To be overwritten
|
||||||
|
func _autofocus() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
func set_value(value:Variant) -> void:
|
||||||
|
_set_value(value)
|
||||||
|
|
||||||
|
|
||||||
|
func take_autofocus() -> void:
|
||||||
|
_autofocus()
|
@ -0,0 +1,50 @@
|
|||||||
|
[gd_resource type="Theme" load_steps=3 format=3 uid="uid://d3g4i4dshtdpu"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="1"]
|
||||||
|
content_margin_left = 30.0
|
||||||
|
content_margin_top = 5.0
|
||||||
|
content_margin_right = 20.0
|
||||||
|
content_margin_bottom = 5.0
|
||||||
|
bg_color = Color(0.12549, 0.141176, 0.192157, 1)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(0.0980392, 0.113725, 0.152941, 1)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="2"]
|
||||||
|
content_margin_left = 11.0
|
||||||
|
content_margin_top = 5.0
|
||||||
|
content_margin_right = 20.0
|
||||||
|
content_margin_bottom = 5.0
|
||||||
|
bg_color = Color(0.12549, 0.141176, 0.192157, 1)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(0.0980392, 0.113725, 0.152941, 1)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
LineEdit/colors/clear_button_color = Color(0, 0, 0, 1)
|
||||||
|
LineEdit/colors/clear_button_color_pressed = Color(0, 0, 0, 1)
|
||||||
|
LineEdit/colors/cursor_color = Color(1, 1, 1, 1)
|
||||||
|
LineEdit/colors/font_color = Color(1, 1, 1, 1)
|
||||||
|
LineEdit/colors/font_color_selected = Color(1, 1, 1, 1)
|
||||||
|
LineEdit/colors/font_color_uneditable = Color(1, 1, 1, 1)
|
||||||
|
LineEdit/colors/selection_color = Color(1, 1, 1, 0.235294)
|
||||||
|
LineEdit/constants/minimum_spaces = 10
|
||||||
|
LineEdit/fonts/font = null
|
||||||
|
LineEdit/icons/clear = null
|
||||||
|
LineEdit/styles/focus = SubResource("1")
|
||||||
|
LineEdit/styles/normal = SubResource("2")
|
||||||
|
LineEdit/styles/read_only = SubResource("1")
|
||||||
|
LineEditWithIcon/base_type = &"LineEdit"
|
||||||
|
LineEditWithIcon/styles/normal = SubResource("1")
|
@ -0,0 +1,11 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 25.0
|
||||||
|
content_margin_right = 10.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color( 0.466667, 0.466667, 0.466667, 0.141176 )
|
||||||
|
border_width_bottom = 2
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
@ -0,0 +1,13 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 25.0
|
||||||
|
content_margin_right = 10.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color( 0.180392, 0.180392, 0.180392, 0.219608 )
|
||||||
|
draw_center = false
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color( 0.8, 0.8, 0.8, 0.286275 )
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
@ -0,0 +1,17 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://c8k6tbipodsg"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 10.0
|
||||||
|
content_margin_top = 10.0
|
||||||
|
content_margin_right = 10.0
|
||||||
|
content_margin_bottom = 10.0
|
||||||
|
bg_color = Color(0, 0, 0, 1)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(0.8, 0.8, 0.8, 0.109804)
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
@ -0,0 +1,17 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 6.0
|
||||||
|
content_margin_right = 6.0
|
||||||
|
content_margin_top = 5.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color( 0.6, 0.6, 0.6, 0 )
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color( 0.2, 0.227451, 0.309804, 1 )
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
@ -0,0 +1,17 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 3.0
|
||||||
|
content_margin_right = 3.0
|
||||||
|
content_margin_top = 3.0
|
||||||
|
content_margin_bottom = 3.0
|
||||||
|
bg_color = Color( 0.2, 0.231373, 0.309804, 0.317647 )
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color( 0.8, 0.8, 0.8, 0.109804 )
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
@ -0,0 +1,17 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 3.0
|
||||||
|
content_margin_right = 3.0
|
||||||
|
content_margin_top = 3.0
|
||||||
|
content_margin_bottom = 3.0
|
||||||
|
bg_color = Color( 0.2, 0.231373, 0.309804, 0.235294 )
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color( 0.8, 0.8, 0.8, 0.109804 )
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
@ -0,0 +1,12 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://cu8otiwksn8ma"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 10.0
|
||||||
|
content_margin_top = 13.0
|
||||||
|
content_margin_bottom = 2.0
|
||||||
|
bg_color = Color(1, 1, 1, 0.0784314)
|
||||||
|
border_color = Color(0.454902, 0.454902, 0.454902, 1)
|
||||||
|
corner_radius_top_left = 8
|
||||||
|
corner_radius_top_right = 8
|
||||||
|
corner_radius_bottom_right = 8
|
||||||
|
corner_radius_bottom_left = 8
|
@ -0,0 +1,16 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://obyrr26pqk2p"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 3.0
|
||||||
|
content_margin_top = 1.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 1.0
|
||||||
|
bg_color = Color(0.776471, 0.776471, 0.776471, 0.207843)
|
||||||
|
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 = 1.0
|
||||||
|
expand_margin_top = 1.0
|
||||||
|
expand_margin_bottom = 2.0
|
@ -0,0 +1,7 @@
|
|||||||
|
[gd_resource type="StyleBoxEmpty" format=3 uid="uid://cl75ikyq2is7c"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 3.0
|
||||||
|
content_margin_top = 1.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 1.0
|
@ -0,0 +1,86 @@
|
|||||||
|
@tool
|
||||||
|
extends DialogicEditor
|
||||||
|
|
||||||
|
## A Main page in the dialogic editor.
|
||||||
|
|
||||||
|
var tips : Array = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _get_icon() -> Texture:
|
||||||
|
return load("res://addons/dialogic/Editor/Images/plugin-icon.svg")
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
self_modulate = get_theme_color("font_color", "Editor")
|
||||||
|
self_modulate.a = 0.2
|
||||||
|
|
||||||
|
var edit_scale := DialogicUtil.get_editor_scale()
|
||||||
|
%HomePageBox.custom_minimum_size = Vector2(600, 350)*edit_scale
|
||||||
|
%TopPanel.custom_minimum_size.y = 100*edit_scale
|
||||||
|
%VersionLabel.set('theme_override_font_sizes/font_size', 10 * edit_scale)
|
||||||
|
var plugin_cfg := ConfigFile.new()
|
||||||
|
plugin_cfg.load("res://addons/dialogic/plugin.cfg")
|
||||||
|
%VersionLabel.text = plugin_cfg.get_value('plugin', 'version', 'unknown version')
|
||||||
|
|
||||||
|
%BottomPanel.self_modulate = get_theme_color("dark_color_3", "Editor")
|
||||||
|
|
||||||
|
%RandomTipLabel.add_theme_color_override("font_color", get_theme_color("property_color_z", "Editor"))
|
||||||
|
%RandomTipMoreButton.icon = get_theme_icon("ExternalLink", "EditorIcons")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _register():
|
||||||
|
editors_manager.register_simple_editor(self)
|
||||||
|
|
||||||
|
self.alternative_text = "Welcome to dialogic!"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _open(extra_info:Variant="") -> void:
|
||||||
|
if tips.is_empty():
|
||||||
|
var file := FileAccess.open('res://addons/dialogic/Editor/HomePage/tips.txt', FileAccess.READ)
|
||||||
|
tips = file.get_as_text().split('\n')
|
||||||
|
tips = tips.filter(func(item): return !item.is_empty())
|
||||||
|
|
||||||
|
randomize()
|
||||||
|
var tip :String = tips[randi()%len(tips)]
|
||||||
|
var text := tip.get_slice(';',0).strip_edges()
|
||||||
|
var action := tip.get_slice(';',1).strip_edges()
|
||||||
|
if action == text:
|
||||||
|
action = ""
|
||||||
|
show_tip(text, action)
|
||||||
|
|
||||||
|
|
||||||
|
func show_tip(text:String='', action:String='') -> void:
|
||||||
|
if text.is_empty():
|
||||||
|
%TipBox.hide()
|
||||||
|
%RandomTipLabel.hide()
|
||||||
|
return
|
||||||
|
|
||||||
|
%TipBox.show()
|
||||||
|
%RandomTipLabel.show()
|
||||||
|
%RandomTip.text = '[i]'+text
|
||||||
|
|
||||||
|
if action.is_empty():
|
||||||
|
%RandomTipMoreButton.hide()
|
||||||
|
return
|
||||||
|
|
||||||
|
%RandomTipMoreButton.show()
|
||||||
|
|
||||||
|
if %RandomTipMoreButton.pressed.is_connected(_on_tip_action):
|
||||||
|
%RandomTipMoreButton.pressed.disconnect(_on_tip_action)
|
||||||
|
%RandomTipMoreButton.pressed.connect(_on_tip_action.bind(action))
|
||||||
|
|
||||||
|
|
||||||
|
func _on_tip_action(action:String) -> void:
|
||||||
|
if action.begins_with('https://'):
|
||||||
|
OS.shell_open(action)
|
||||||
|
return
|
||||||
|
elif action.begins_with('editor://'):
|
||||||
|
var editor_name := action.trim_prefix('editor://').get_slice('->',0)
|
||||||
|
var extra_info := action.trim_prefix('editor://').get_slice('->',1)
|
||||||
|
if editor_name in editors_manager.editors:
|
||||||
|
editors_manager.open_editor(editors_manager.editors[editor_name].node, false, extra_info)
|
||||||
|
return
|
||||||
|
print("Tip button doesn't do anything (", action, ")")
|
@ -0,0 +1,373 @@
|
|||||||
|
[gd_scene load_steps=23 format=3 uid="uid://cqy73hshqqgga"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/dialogic/Editor/HomePage/home_page.gd" id="1_6g38w"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cvmlp5nxb2rer" path="res://addons/dialogic/Editor/HomePage/icon_bg.png" id="1_ed1g1"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bt87p6qlso0ya" path="res://addons/dialogic/Editor/Images/dialogic-logo.svg" id="3_3leok"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imi2d"]
|
||||||
|
draw_center = false
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
shadow_color = Color(0.796078, 0.572549, 0.933333, 0.0627451)
|
||||||
|
shadow_size = 24
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_n2afh"]
|
||||||
|
corner_radius_top_left = 15
|
||||||
|
corner_radius_top_right = 15
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_lt7uf"]
|
||||||
|
colors = PackedColorArray(0.296484, 0.648457, 1, 1, 0.732014, 0.389374, 1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_2klx3"]
|
||||||
|
gradient = SubResource("Gradient_lt7uf")
|
||||||
|
fill_from = Vector2(0.151515, 0.272727)
|
||||||
|
fill_to = Vector2(1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_1gns2"]
|
||||||
|
offsets = PackedFloat32Array(0.302013, 0.872483)
|
||||||
|
colors = PackedColorArray(0.365323, 0.360806, 0.260695, 0, 0.615686, 0.615686, 0.615686, 0.592157)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_u0aw3"]
|
||||||
|
gradient = SubResource("Gradient_1gns2")
|
||||||
|
fill = 1
|
||||||
|
fill_from = Vector2(0.497835, 0.493506)
|
||||||
|
fill_to = Vector2(1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_vepxx"]
|
||||||
|
variation_embolden = 2.0
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_w8q1h"]
|
||||||
|
font = SubResource("FontVariation_vepxx")
|
||||||
|
font_size = 40
|
||||||
|
outline_size = 14
|
||||||
|
outline_color = Color(0.0901961, 0.0901961, 0.0901961, 0.258824)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_p7ka2"]
|
||||||
|
content_margin_left = 10.0
|
||||||
|
content_margin_top = 10.0
|
||||||
|
content_margin_right = 10.0
|
||||||
|
content_margin_bottom = 10.0
|
||||||
|
bg_color = Color(1, 1, 1, 1)
|
||||||
|
corner_radius_bottom_right = 15
|
||||||
|
corner_radius_bottom_left = 15
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_es88k"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ce6uo"]
|
||||||
|
content_margin_left = 7.0
|
||||||
|
content_margin_top = 7.0
|
||||||
|
content_margin_right = 7.0
|
||||||
|
content_margin_bottom = 14.0
|
||||||
|
bg_color = Color(0.803922, 0.352941, 1, 0.141176)
|
||||||
|
corner_radius_top_left = 10
|
||||||
|
corner_radius_top_right = 10
|
||||||
|
corner_radius_bottom_right = 10
|
||||||
|
corner_radius_bottom_left = 10
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_elu6e"]
|
||||||
|
variation_embolden = 1.1
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_5kbdj"]
|
||||||
|
variation_transform = Transform2D(1, 0.239, 0, 1, 0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_g0m61"]
|
||||||
|
variation_embolden = 1.43
|
||||||
|
variation_transform = Transform2D(1, 0.343, 0, 1, 0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_a8dvw"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ckyhx"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.470588, 0.196078, 0.6, 1)
|
||||||
|
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_l1doy"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.470588, 0.196078, 0.6, 1)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
corner_radius_top_left = 5
|
||||||
|
corner_radius_top_right = 5
|
||||||
|
corner_radius_bottom_right = 5
|
||||||
|
corner_radius_bottom_left = 5
|
||||||
|
|
||||||
|
[sub_resource type="Image" id="Image_ubn0t"]
|
||||||
|
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_jsefb"]
|
||||||
|
image = SubResource("Image_ubn0t")
|
||||||
|
|
||||||
|
[node name="HomePage" type="TextureRect"]
|
||||||
|
self_modulate = Color(0, 0, 0, 0.2)
|
||||||
|
clip_contents = true
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = -2.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = ExtResource("1_ed1g1")
|
||||||
|
expand_mode = 1
|
||||||
|
stretch_mode = 3
|
||||||
|
script = ExtResource("1_6g38w")
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="HomePageBox" type="VBoxContainer" parent="CenterContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(600, 350)
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TopPanel" type="Panel" parent="CenterContainer/HomePageBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(0, 100)
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_imi2d")
|
||||||
|
|
||||||
|
[node name="Header2" type="Panel" parent="CenterContainer/HomePageBox/TopPanel"]
|
||||||
|
clip_children = 1
|
||||||
|
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
|
||||||
|
size_flags_stretch_ratio = 0.4
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_n2afh")
|
||||||
|
|
||||||
|
[node name="BG" type="TextureRect" parent="CenterContainer/HomePageBox/TopPanel/Header2"]
|
||||||
|
modulate = Color(0.65098, 0.65098, 0.65098, 1)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
size_flags_stretch_ratio = 0.3
|
||||||
|
texture = SubResource("GradientTexture2D_2klx3")
|
||||||
|
expand_mode = 1
|
||||||
|
|
||||||
|
[node name="Vignette" type="TextureRect" parent="CenterContainer/HomePageBox/TopPanel/Header2"]
|
||||||
|
modulate = Color(0, 0, 0, 1)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -166.0
|
||||||
|
offset_bottom = 166.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = SubResource("GradientTexture2D_u0aw3")
|
||||||
|
expand_mode = 1
|
||||||
|
|
||||||
|
[node name="Logo" type="TextureRect" parent="CenterContainer/HomePageBox/TopPanel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 19.0
|
||||||
|
offset_top = 10.0
|
||||||
|
offset_right = -23.0
|
||||||
|
offset_bottom = -10.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
size_flags_stretch_ratio = 0.3
|
||||||
|
texture = ExtResource("3_3leok")
|
||||||
|
expand_mode = 1
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="CenterContainer/HomePageBox/TopPanel/Logo"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = 155.0
|
||||||
|
offset_top = -37.0
|
||||||
|
offset_right = 185.0
|
||||||
|
offset_bottom = 21.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
rotation = -0.201447
|
||||||
|
text = "2"
|
||||||
|
label_settings = SubResource("LabelSettings_w8q1h")
|
||||||
|
|
||||||
|
[node name="BottomPanel" type="PanelContainer" parent="CenterContainer/HomePageBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
self_modulate = Color(0, 0, 0, 1)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_p7ka2")
|
||||||
|
|
||||||
|
[node name="VersionLabel" type="Label" parent="CenterContainer/HomePageBox/BottomPanel"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 8
|
||||||
|
theme_override_font_sizes/font_size = 10
|
||||||
|
text = "2.0-Alpha-13 (Godot 4.2+)"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="CenterContainer/HomePageBox/BottomPanel"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/separation = 50
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="VBoxContainer" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_stretch_ratio = 0.4
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicSection"
|
||||||
|
theme_override_constants/line_spacing = 0
|
||||||
|
text = "Documentation"
|
||||||
|
|
||||||
|
[node name="WikiButton" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Wiki"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://docs.dialogic.pro/"
|
||||||
|
|
||||||
|
[node name="WikiGettingStartedButton" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Getting Started"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://docs.dialogic.pro/getting-started.html"
|
||||||
|
|
||||||
|
[node name="Separator" type="Control" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
custom_minimum_size = Vector2(0, 10)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicSection"
|
||||||
|
text = "Get in touch"
|
||||||
|
|
||||||
|
[node name="BugRequestButton" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Bug / Request"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://github.com/dialogic-godot/dialogic/issues/new/choose"
|
||||||
|
|
||||||
|
[node name="DiscordButton" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Discord"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://discord.gg/2hHQzkf2pX"
|
||||||
|
|
||||||
|
[node name="Website" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Website"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://dialogic.pro/"
|
||||||
|
|
||||||
|
[node name="DonateButton" type="LinkButton" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicLink"
|
||||||
|
text = " Donate"
|
||||||
|
underline = 2
|
||||||
|
uri = "https://www.patreon.com/coppolaemilio"
|
||||||
|
|
||||||
|
[node name="CenterContainer2" type="VBoxContainer" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/separation = 15
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="WelcomeText" type="RichTextLabel" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_es88k")
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "[center]Welcome to dialogic, a plugin that lets you easily create stories and dialogs for your game!"
|
||||||
|
fit_content = true
|
||||||
|
|
||||||
|
[node name="RandomTipSection" type="VBoxContainer" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = -4
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="RandomTipLabel" type="Label" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2/RandomTipSection"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_type_variation = &"DialogicSection"
|
||||||
|
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||||
|
text = "Random Tip"
|
||||||
|
|
||||||
|
[node name="TipBox" type="PanelContainer" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2/RandomTipSection"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_ce6uo")
|
||||||
|
|
||||||
|
[node name="RandomTip" type="RichTextLabel" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2/RandomTipSection/TipBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
clip_contents = false
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/bold_font = SubResource("FontVariation_elu6e")
|
||||||
|
theme_override_fonts/italics_font = SubResource("FontVariation_5kbdj")
|
||||||
|
theme_override_fonts/bold_italics_font = SubResource("FontVariation_g0m61")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_a8dvw")
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "[i]You can[/i] [b]create custom[/b] events, [i][b]subsystems, text effects and even editors for[/b][i] [code]dialogic!"
|
||||||
|
fit_content = true
|
||||||
|
|
||||||
|
[node name="RandomTipMoreButton" type="Button" parent="CenterContainer/HomePageBox/BottomPanel/ScrollContainer/HBoxContainer/CenterContainer2/RandomTipSection/TipBox/RandomTip"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 3
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -30.0
|
||||||
|
offset_top = 1.0
|
||||||
|
offset_right = -8.0
|
||||||
|
offset_bottom = 23.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
tooltip_text = "Check it out!"
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_ckyhx")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_l1doy")
|
||||||
|
icon = SubResource("ImageTexture_jsefb")
|
||||||
|
expand_icon = true
|
After Width: | Height: | Size: 147 KiB |
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cvmlp5nxb2rer"
|
||||||
|
path="res://.godot/imported/icon_bg.png-5937ce0a857c4a8a9d624ea9ebf09a97.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/dialogic/Editor/HomePage/icon_bg.png"
|
||||||
|
dest_files=["res://.godot/imported/icon_bg.png-5937ce0a857c4a8a9d624ea9ebf09a97.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
@ -0,0 +1,11 @@
|
|||||||
|
Dialogic variables can be changed from timelines [b]and[/b] scripts! They can be used in conditions and inside of texts!; editor://VariablesEditor
|
||||||
|
You can create [b]custom modules[/b] for dialogic, including events, subsystems, text effects, ui layouts and even editors!; editor://Settings->General
|
||||||
|
If there are events you never need, you can hide them from the list in the editor!; editor://Settings->Modules
|
||||||
|
Did you know that dialogic supports translations? It does!; editor://Settings->Translations
|
||||||
|
You can use [b]bbcode effects[/b] in text events! What are they though???; https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html
|
||||||
|
Writing [/i]<Oh hi/Hello you/Well, well>[i] in a text event will pick a random one of the three strings!
|
||||||
|
There are a number of cool text effects like [pause=x], [speed=x] and [portrait=x]. Try them out!; editor://Settings->Text
|
||||||
|
You can use scenes as portraits! This gives you basically limiteless freedom.; https://dialogic-docs.coppolaemilio.com/custom-portraits.html
|
||||||
|
You can use scenes as backgrounds. This way they can be animated or whatever you want!
|
||||||
|
Dialogic has a built in save and load system! It's pretty powerful!; editor://Settings->Saving
|
||||||
|
You can add multiple glossary files, each containing words that can be hovered for information!; editor://GlossaryEditor
|
After Width: | Height: | Size: 148 B |
@ -0,0 +1,38 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bsx8dtqf3vych"
|
||||||
|
path="res://.godot/imported/default.svg-3f34de5e45bef5de4d9c15ef78c00c6c.ctex"
|
||||||
|
metadata={
|
||||||
|
"has_editor_variant": true,
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/dialogic/Editor/Images/Dropdown/default.svg"
|
||||||
|
dest_files=["res://.godot/imported/default.svg-3f34de5e45bef5de4d9c15ef78c00c6c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=true
|
||||||
|
editor/convert_colors_with_editor_theme=true
|
After Width: | Height: | Size: 1.1 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue