From dc846f95caab369725a306d5a5775b7df4f52420 Mon Sep 17 00:00:00 2001 From: Mew Pur Pur <85438892+MewPurPur@users.noreply.github.com> Date: Wed, 10 Apr 2024 17:15:40 +0300 Subject: [PATCH] Ensure decent performance of GoodFileDialog (#647) --- src/Indications.gd | 2 +- src/SVG.gd | 2 +- src/data_classes/Attribute.gd | 2 +- src/data_classes/AttributeColor.gd | 2 +- src/data_classes/AttributeEnum.gd | 2 +- src/data_classes/AttributeList.gd | 2 +- src/data_classes/AttributeNumeric.gd | 2 +- src/data_classes/AttributePath.gd | 2 +- src/data_classes/AttributeTransform.gd | 2 +- src/data_classes/AttributeUnknown.gd | 2 +- src/data_classes/ColorPalette.gd | 6 ++++ src/data_classes/Tag.gd | 2 +- src/data_classes/TagEllipse.gd | 2 +- src/data_classes/TagLine.gd | 2 +- src/data_classes/TagPath.gd | 2 +- src/data_classes/TagRect.gd | 2 +- src/data_classes/TagSVG.gd | 2 +- src/data_classes/TagStop.gd | 2 +- src/data_classes/TagUnknown.gd | 2 +- src/ui_elements/palette_config.gd | 4 ++- src/ui_parts/good_file_dialog.gd | 48 ++++++++++++++++---------- 21 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/Indications.gd b/src/Indications.gd index 5acc5071..89726204 100644 --- a/src/Indications.gd +++ b/src/Indications.gd @@ -1,5 +1,5 @@ -## This singleton handles editor information like zoom level and selections. extends Node +## This singleton handles editor information like zoom level and selections. const ContextPopup = preload("res://src/ui_elements/context_popup.tscn") const PathCommandPopup = preload("res://src/ui_elements/path_popup.tscn") diff --git a/src/SVG.gd b/src/SVG.gd index 1bffae45..839c2792 100644 --- a/src/SVG.gd +++ b/src/SVG.gd @@ -1,6 +1,6 @@ +extends Node ## This singleton handles the two representations of the SVG: ## The SVG text, and the native [TagSVG] representation. -extends Node signal parsing_finished(error_id: SVGParser.ParseError) diff --git a/src/data_classes/Attribute.gd b/src/data_classes/Attribute.gd index 9c7dc95a..5fc2d992 100644 --- a/src/data_classes/Attribute.gd +++ b/src/data_classes/Attribute.gd @@ -1,5 +1,5 @@ -## Abstract class for an attribute inside a [Tag], i.e. class_name Attribute extends RefCounted +## Abstract class for an attribute inside a [Tag], i.e. signal value_changed(new_value: String) signal propagate_value_changed(undo_redo: bool) diff --git a/src/data_classes/AttributeColor.gd b/src/data_classes/AttributeColor.gd index be11a01c..fa61d9fd 100644 --- a/src/data_classes/AttributeColor.gd +++ b/src/data_classes/AttributeColor.gd @@ -1,5 +1,5 @@ -## An attribute representing a color string, or an url to an ID. class_name AttributeColor extends Attribute +## An attribute representing a color string, or an url to an ID. # No direct color representation for this attribute type. There are too many quirks. diff --git a/src/data_classes/AttributeEnum.gd b/src/data_classes/AttributeEnum.gd index 38fd0716..23b35676 100644 --- a/src/data_classes/AttributeEnum.gd +++ b/src/data_classes/AttributeEnum.gd @@ -1,5 +1,5 @@ -## An attribute with only a set of meaningful values. class_name AttributeEnum extends Attribute +## An attribute with only a set of meaningful values. var possible_values: Array[String] diff --git a/src/data_classes/AttributeList.gd b/src/data_classes/AttributeList.gd index 5df3d54f..a61f2a52 100644 --- a/src/data_classes/AttributeList.gd +++ b/src/data_classes/AttributeList.gd @@ -1,5 +1,5 @@ -## An attribute representing a list of numbers. class_name AttributeList extends Attribute +## An attribute representing a list of numbers. var _list: PackedFloat32Array diff --git a/src/data_classes/AttributeNumeric.gd b/src/data_classes/AttributeNumeric.gd index dfb07fde..8917ffb0 100644 --- a/src/data_classes/AttributeNumeric.gd +++ b/src/data_classes/AttributeNumeric.gd @@ -1,5 +1,5 @@ -## An attribute representing a number. class_name AttributeNumeric extends Attribute +## An attribute representing a number. var _number := NAN enum Mode {FLOAT, UFLOAT, NFLOAT} # UFLOAT is positive-only, NFLOAT is in [0, 1]. diff --git a/src/data_classes/AttributePath.gd b/src/data_classes/AttributePath.gd index 35d33885..36cf0ad2 100644 --- a/src/data_classes/AttributePath.gd +++ b/src/data_classes/AttributePath.gd @@ -1,5 +1,5 @@ -## The "d" attribute of [TagPath]. class_name AttributePath extends Attribute +## The "d" attribute of [TagPath]. var _commands: Array[PathCommand] diff --git a/src/data_classes/AttributeTransform.gd b/src/data_classes/AttributeTransform.gd index 59776d7c..f2bc2013 100644 --- a/src/data_classes/AttributeTransform.gd +++ b/src/data_classes/AttributeTransform.gd @@ -1,5 +1,5 @@ -## An attribute representing a list of transforms. class_name AttributeTransform extends Attribute +## An attribute representing a list of transforms. class Transform extends RefCounted: func compute_transform() -> Transform2D: diff --git a/src/data_classes/AttributeUnknown.gd b/src/data_classes/AttributeUnknown.gd index d99b0282..5f3a2c2c 100644 --- a/src/data_classes/AttributeUnknown.gd +++ b/src/data_classes/AttributeUnknown.gd @@ -1,5 +1,5 @@ -## An attribute not recognized by GodSVG. class_name AttributeUnknown extends Attribute +## An attribute not recognized by GodSVG. var name := "" diff --git a/src/data_classes/ColorPalette.gd b/src/data_classes/ColorPalette.gd index 04f07990..2d9cf3e5 100644 --- a/src/data_classes/ColorPalette.gd +++ b/src/data_classes/ColorPalette.gd @@ -1,4 +1,7 @@ class_name ColorPalette extends Resource +## A resource for the color palettes that are listed in the color picker. + +signal layout_changed @export var title: String # Color palettes must be uniquely named. @export var colors: Array[String] # Colors must be unique within a palette. @@ -16,11 +19,13 @@ func add_color() -> void: colors.append("none") color_names.append("") emit_changed() + layout_changed.emit() func remove_color(idx: int) -> void: colors.remove_at(idx) color_names.remove_at(idx) emit_changed() + layout_changed.emit() func move_color(old_idx: int, new_idx: int) -> void: if old_idx == new_idx: @@ -32,6 +37,7 @@ func move_color(old_idx: int, new_idx: int) -> void: colors.insert(new_idx, colors.pop_at(old_idx)) color_names.insert(new_idx, color_names.pop_at(old_idx)) emit_changed() + layout_changed.emit() func modify_title(new_title: String) -> void: title = new_title diff --git a/src/data_classes/Tag.gd b/src/data_classes/Tag.gd index 3fd0fc08..808a3ad9 100644 --- a/src/data_classes/Tag.gd +++ b/src/data_classes/Tag.gd @@ -1,5 +1,5 @@ -## A SVG tag, standalone ([code][/code]) or container ([code][/code]). class_name Tag extends RefCounted +## A SVG tag, standalone ([code][/code]) or container ([code][/code]). var child_tags: Array[Tag] diff --git a/src/data_classes/TagEllipse.gd b/src/data_classes/TagEllipse.gd index cb8135bf..35ad806f 100644 --- a/src/data_classes/TagEllipse.gd +++ b/src/data_classes/TagEllipse.gd @@ -1,5 +1,5 @@ -## An tag. class_name TagEllipse extends Tag +## An tag. const name = "ellipse" const possible_conversions = ["circle", "rect", "path"] diff --git a/src/data_classes/TagLine.gd b/src/data_classes/TagLine.gd index 54831c29..ac4d4cd6 100644 --- a/src/data_classes/TagLine.gd +++ b/src/data_classes/TagLine.gd @@ -1,5 +1,5 @@ -## A tag. class_name TagLine extends Tag +## A tag. const name = "line" const possible_conversions = ["path"] diff --git a/src/data_classes/TagPath.gd b/src/data_classes/TagPath.gd index 8f3ee23d..6fe775a9 100644 --- a/src/data_classes/TagPath.gd +++ b/src/data_classes/TagPath.gd @@ -1,5 +1,5 @@ -## A tag. class_name TagPath extends Tag +## A tag. const name = "path" const possible_conversions = [] diff --git a/src/data_classes/TagRect.gd b/src/data_classes/TagRect.gd index f3ea8eba..12fdb111 100644 --- a/src/data_classes/TagRect.gd +++ b/src/data_classes/TagRect.gd @@ -1,5 +1,5 @@ -## A tag. class_name TagRect extends Tag +## A tag. const name = "rect" const possible_conversions = ["circle", "ellipse", "path"] diff --git a/src/data_classes/TagSVG.gd b/src/data_classes/TagSVG.gd index b3dc610d..3934c15b 100644 --- a/src/data_classes/TagSVG.gd +++ b/src/data_classes/TagSVG.gd @@ -1,5 +1,5 @@ -## A tag. class_name TagSVG extends Tag +## A tag. var width: float var height: float diff --git a/src/data_classes/TagStop.gd b/src/data_classes/TagStop.gd index a8d7c899..2793bb79 100644 --- a/src/data_classes/TagStop.gd +++ b/src/data_classes/TagStop.gd @@ -1,5 +1,5 @@ -## A tag. class_name TagStop extends Tag +## A tag. const name = "stop" const possible_conversions = [] diff --git a/src/data_classes/TagUnknown.gd b/src/data_classes/TagUnknown.gd index abc4e1ca..fea637a4 100644 --- a/src/data_classes/TagUnknown.gd +++ b/src/data_classes/TagUnknown.gd @@ -1,5 +1,5 @@ -## A tag not recognized by GodSVG. class_name TagUnknown extends Tag +## A tag not recognized by GodSVG. var name: String const possible_conversions = [] diff --git a/src/ui_elements/palette_config.gd b/src/ui_elements/palette_config.gd index 6aca02b3..18149a80 100644 --- a/src/ui_elements/palette_config.gd +++ b/src/ui_elements/palette_config.gd @@ -20,7 +20,7 @@ var currently_edited_idx := -1 # Used to setup a palette for this element. func assign_palette(palette: ColorPalette) -> void: current_palette = palette - current_palette.changed.connect(rebuild_colors) + current_palette.layout_changed.connect(rebuild_colors) rebuild_colors() # Rebuilds the content of the colors container. @@ -232,8 +232,10 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void: return if data[0] == current_palette: + currently_edited_idx = -1 current_palette.move_color(data[1], proposed_drop_idx) else: + currently_edited_idx = -1 current_palette.colors.insert(proposed_drop_idx, data[0].colors[data[1]]) current_palette.color_names.insert(proposed_drop_idx, data[0].color_names[data[1]]) current_palette.emit_changed() diff --git a/src/ui_parts/good_file_dialog.gd b/src/ui_parts/good_file_dialog.gd index 031cf937..1d96079e 100644 --- a/src/ui_parts/good_file_dialog.gd +++ b/src/ui_parts/good_file_dialog.gd @@ -78,6 +78,7 @@ new_extension: String) -> void: extension = new_extension func _ready() -> void: + file_list.get_v_scroll_bar().value_changed.connect(_setup_file_images.unbind(1)) if mode == FileMode.SELECT: file_container.hide() if mode == FileMode.SAVE: @@ -163,24 +164,11 @@ func set_dir(dir: String) -> void: (not search_text.is_empty() and not search_text.is_subsequence_ofn(file)): continue - match extension: - "svg": - # Setup a clean SVG graphic by using the scaling parameter. - var svg_text := FileAccess.open(current_dir.path_join(file), - FileAccess.READ).get_as_text() - var img := Image.new() - img.load_svg_from_string(svg_text) - img.load_svg_from_string(svg_text, - item_height / maxf(img.get_width(), img.get_height())) - var item_idx := file_list.add_item(file, ImageTexture.create_from_image(img)) - file_list.set_item_metadata(item_idx, - Actions.new(select_file, focus_file.bind(file))) - "png": - var item_idx := file_list.add_item(file, ImageTexture.create_from_image( - Image.load_from_file(current_dir.path_join(file)))) - file_list.set_item_metadata(item_idx, - Actions.new(select_file, focus_file.bind(file))) - file = DA.get_next() + var item_idx := file_list.add_item(file, null) + file_list.set_item_metadata(item_idx, + Actions.new(select_file, focus_file.bind(file))) + await get_tree().process_frame + _setup_file_images() func set_file(file: String) -> void: if mode == FileMode.SELECT: @@ -193,9 +181,33 @@ func set_file(file: String) -> void: if not file.is_empty(): if file.get_extension() != extension: file += "." + extension + file_list.ensure_current_is_visible() current_file = file file_field.text = current_file +# For optimization, only generate the visible files' images. +func _setup_file_images() -> void: + var visible_start := file_list.position.y + file_list.get_v_scroll_bar().value + var visible_end := visible_start + file_list.size.y + for item_idx in file_list.item_count: + var file_rect := file_list.get_item_rect(item_idx) + if file_list.get_item_icon(item_idx) == null and\ + file_rect.end.y > visible_start and file_rect.position.y < visible_end: + var file := file_list.get_item_text(item_idx) + match file.get_extension(): + "png": + file_list.set_item_icon(item_idx, ImageTexture.create_from_image( + Image.load_from_file(current_dir.path_join(file)))) + "svg": + # Setup a clean SVG graphic by using the scaling parameter. + var svg_text := FileAccess.open(current_dir.path_join(file), + FileAccess.READ).get_as_text() + var img := Image.new() + img.load_svg_from_string(svg_text) + img.load_svg_from_string(svg_text, + item_height / maxf(img.get_width(), img.get_height())) + file_list.set_item_icon(item_idx, ImageTexture.create_from_image(img)) + func select_file() -> void: if mode == FileMode.SAVE and current_file in DirAccess.get_files_at(current_dir):