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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,21 @@
[gd_scene load_steps=4 format=3 uid="uid://dbpkta2tjsqim"]
[ext_resource type="Script" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.gd" id="1_x8t45"]
[sub_resource type="Image" id="Image_eiyxd"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id="ImageTexture_lseut"]
image = SubResource("Image_eiyxd")
[node name="HintTooltip" type="TextureRect"]
modulate = Color(0, 0, 0, 1)
texture = SubResource("ImageTexture_lseut")
stretch_mode = 3
script = ExtResource("1_x8t45")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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