diff --git a/.github/disabled_classes.build b/.github/disabled_classes.build index bf04932..8b90d55 100644 --- a/.github/disabled_classes.build +++ b/.github/disabled_classes.build @@ -118,7 +118,6 @@ "RichTextEffect", "SceneReplicationConfig", "ScriptExtension", - "ShaderInclude", "Shape2D", "Shape3D", "SkeletonModification2D", @@ -151,4 +150,4 @@ "X509Certificate" ], "type": "build_profile" -} \ No newline at end of file +} diff --git a/assets/icons/ShortcutPanel.svg b/assets/icons/ShortcutPanel.svg new file mode 100644 index 0000000..ab16abe --- /dev/null +++ b/assets/icons/ShortcutPanel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ShortcutPanel.svg.import b/assets/icons/ShortcutPanel.svg.import new file mode 100644 index 0000000..ea2fa98 --- /dev/null +++ b/assets/icons/ShortcutPanel.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqmx4oyj8c5mm" +path="res://.godot/imported/ShortcutPanel.svg-954786637bc59adfc322367d34feba33.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/ShortcutPanel.svg" +dest_files=["res://.godot/imported/ShortcutPanel.svg-954786637bc59adfc322367d34feba33.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/godot_only/scripts/tests.gd b/godot_only/scripts/tests.gd index 1ba6fb5..8372d6e 100644 --- a/godot_only/scripts/tests.gd +++ b/godot_only/scripts/tests.gd @@ -15,10 +15,8 @@ func _run() -> void: for report_line in report: print_rich(report_line) -func add_to_report(test_category: String, test: String, result: String, -expected: String) -> void: - report.append('%s: [b]"%s"[/b] returned [b]"%s"[/b], expected [b]"%s"[/b]' %\ - [test_category, test, result, expected]) +func add_to_report(test_category: String, test: String, result: String, expected: String) -> void: + report.append('%s: [b]"%s"[/b] returned [b]"%s"[/b], expected [b]"%s"[/b]' % [test_category, test, result, expected]) # This test is dependent on specifics of the Formatter and AttributePathdata classes. diff --git a/godot_only/scripts/update_translations.gd b/godot_only/scripts/update_translations.gd index 4628d26..8b79a80 100644 --- a/godot_only/scripts/update_translations.gd +++ b/godot_only/scripts/update_translations.gd @@ -2,7 +2,7 @@ @tool extends EditorScript -const COMMENTS_DICT = { +const COMMENTS_DICT: Dictionary[String, String] = { "Viewport": "The viewport is the area where the graphic is displayed. In similar applications, it's often called the canvas.", "CDATA color": "CDATA shouldn't be translated. It's a type of XML section.", "Editor formatter": "Refers to the formatter used for VectorTouch's code editor.", @@ -16,6 +16,7 @@ const COMMENTS_DICT = { "Dark": "Refers to a theme preset.", "Light": "Refers to a theme preset.", "Black (OLED)": "Refers to a theme preset.", + "translation-credits": "Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets .\nUsed for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries.", } const TRANSLATIONS_DIR = "translations" @@ -104,19 +105,21 @@ func update_translations() -> void: fa.store_string(HEADER) for msg in messages: if COMMENTS_DICT.has(msg.msgid): - fa.store_string("#. %s\n" % COMMENTS_DICT[msg.msgid]) + var comment_lines := COMMENTS_DICT[msg.msgid].split("\n") + var comment := "" + for line in comment_lines: + comment += "#. %s\n" % line + fa.store_string(comment) used_comments.append(msg.msgid) fa.store_string(msg.to_string()) fa = null - print("Created %s with %d strings" % [TRANSLATIONS_DIR.path_join("/VectorTouch.pot"), - (messages.size() + 1)]) + print("Created %s with %d strings" % [TRANSLATIONS_DIR.path_join("/GodSVG.pot"), (messages.size() + 1)]) for file in DirAccess.get_files_at(folder_location): if not (file.get_extension() == "po" or file == "VectorTouch.pot"): continue - var args := PackedStringArray(["--update", "--quiet", "--verbose", "--backup=off", - folder_location.path_join(file), pot_location]) + var args := PackedStringArray(["--update", "--quiet", "--verbose", "--backup=off", folder_location.path_join(file), pot_location]) var output: Array = [] var result := OS.execute("msgmerge", args, output, true) if not result == -1: diff --git a/src/autoload/HandlerGUI.gd b/src/autoload/HandlerGUI.gd index aef6f63..08f0680 100644 --- a/src/autoload/HandlerGUI.gd +++ b/src/autoload/HandlerGUI.gd @@ -63,7 +63,24 @@ func toogle_status_bar(visible: bool, override := false) -> void: activity.runOnUiThread(android_runtime.createRunnableFromGodotCallable(callable)) +var shortcut_registrations: Dictionary[Node, ShortcutsRegistration] = {} + func _enter_tree() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("quit", prompt_quit, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("toggle_fullscreen", toggle_fullscreen, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("about_info", open_about, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("about_donate", open_donate, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("check_updates", open_update_checker, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("open_settings", open_settings, ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("about_repo", OS.shell_open.bind("https://github.com/MewPurPur/GodSVG"), ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("about_website", OS.shell_open.bind("https://godsvg.com"), ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("open_externally", func() -> void: FileUtils.open_svg(Configs.savedata.get_active_tab().svg_file_path), + ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + shortcuts.add_shortcut("open_in_folder", func() -> void: FileUtils.open_svg_folder(Configs.savedata.get_active_tab().svg_file_path), + ShortcutsRegistration.Behavior.PASS_THROUGH_ALL) + register_shortcuts(self, shortcuts) + var window := get_window() window.files_dropped.connect(_on_files_dropped) window.dpi_changed.connect(update_ui_scale) @@ -107,6 +124,11 @@ func _on_files_dropped(files: PackedStringArray) -> void: FileUtils.apply_svgs_from_paths(files) +func register_shortcuts(node: Node, registrations: ShortcutsRegistration) -> void: + shortcut_registrations[node] = registrations + node.tree_exiting.connect(func() -> void: shortcut_registrations.erase(node)) + + func add_menu(new_menu: Control) -> void: if not menu_stack.is_empty(): menu_stack.back().hide() @@ -224,8 +246,7 @@ func popup_under_rect(popup: Control, rect: Rect2, vp: Viewport) -> void: var screen_h := vp.get_visible_rect().size.y var popup_pos := Vector2(rect.position.x, 0) # Popup below if there's enough space or we're in the bottom half of the screen. - if rect.position.y + rect.size.y + top_popup.size.y < screen_h or\ - rect.position.y + rect.size.y / 2 <= screen_h / 2.0: + if rect.position.y + rect.size.y + top_popup.size.y < screen_h or rect.position.y + rect.size.y / 2 <= screen_h / 2.0: popup_pos.y = rect.position.y + rect.size.y else: popup_pos.y = rect.position.y - top_popup.size.y @@ -239,8 +260,7 @@ func popup_under_rect_center(popup: Control, rect: Rect2, vp: Viewport) -> void: var screen_h := vp.get_visible_rect().size.y var popup_pos := Vector2(rect.position.x - top_popup.size.x / 2.0 + rect.size.x / 2, 0) # Popup below if there's enough space or we're in the bottom half of the screen. - if rect.position.y + rect.size.y + top_popup.size.y < screen_h or\ - rect.position.y + rect.size.y / 2 <= screen_h / 2.0: + if rect.position.y + rect.size.y + top_popup.size.y < screen_h or rect.position.y + rect.size.y / 2 <= screen_h / 2.0: popup_pos.y = rect.position.y + rect.size.y else: popup_pos.y = rect.position.y - top_popup.size.y @@ -260,8 +280,7 @@ func popup_clamp_pos(popup: Control, attempt_pos: Vector2, vp: Viewport) -> Vect var screen_transform := vp.get_screen_transform() var vp_pos := screen_transform.get_origin() / screen_transform.get_scale() for axis in 2: - attempt_pos[axis] = clampf(attempt_pos[axis], vp_pos[axis], - vp_pos[axis] + vp.get_visible_rect().size[axis] - popup.size[axis]) + attempt_pos[axis] = clampf(attempt_pos[axis], vp_pos[axis], vp_pos[axis] + vp.get_visible_rect().size[axis] - popup.size[axis]) return attempt_pos @@ -284,149 +303,59 @@ func _input(event: InputEvent) -> void: elif last_mouse_click_double and event.is_released(): event.double_click = true last_mouse_click_double = false + + # Prioritize clearing popups over letting controls receive ui_cancel. + if ShortcutUtils.is_action_pressed(event, "ui_cancel") and not popup_stack.is_empty(): + get_viewport().set_input_as_handled() + remove_popup() func _unhandled_input(event: InputEvent) -> void: - # Clear popups or overlays. - if ShortcutUtils.is_action_pressed(event, "ui_cancel"): - if not popup_stack.is_empty(): - get_viewport().set_input_as_handled() - remove_popup() - return - elif not menu_stack.is_empty(): - get_viewport().set_input_as_handled() - _remove_control() - return - - for action in ShortcutUtils.UNIVERSAL_ACTIONS: - if ShortcutUtils.is_action_pressed(event, action): - match action: - "quit": prompt_quit() - "toggle_fullscreen": toggle_fullscreen() - "about_info": open_about() - "about_donate": open_donate() - "check_updates": open_update_checker() - "open_settings": open_settings() - "about_repo": OS.shell_open("https://github.com/syntaxerror247/VectorTouch") - "about_website": OS.shell_open("https://godsvg.com") - "open_externally": FileUtils.open_svg( - Configs.savedata.get_active_tab().svg_file_path) - "open_in_folder": FileUtils.open_svg_folder( - Configs.savedata.get_active_tab().svg_file_path) - return - - # Stop the logic below from running if there's menu overlays. - if not menu_stack.is_empty(): - return - - for action in ShortcutUtils.EFFECT_ACTIONS: - if ShortcutUtils.is_action_pressed(event, action): - match action: - "view_show_grid": State.toggle_show_grid() - "view_show_handles": State.toggle_show_handles() - "view_rasterized_svg": State.toggle_view_rasterized() - "view_show_reference": State.toggle_show_reference() - "view_overlay_reference": State.toggle_overlay_reference() - "load_reference": FileUtils.open_image_import_dialog() - "toggle_snap": Configs.savedata.snap *= -1 - - if not popup_stack.is_empty(): + if not (event is InputEventAction or event is InputEventKey): return - # Global actions that should happen regardless of the context. - for action in ShortcutUtils.EDITOR_ACTIONS: - if ShortcutUtils.is_action_pressed(event, action): - match action: - "import": FileUtils.open_svg_import_dialog() - "export": open_export() - "save": FileUtils.save_svg() - "save_as": FileUtils.save_svg_as() - "close_tab": FileUtils.close_tabs(Configs.savedata.get_active_tab_index()) - "close_all_other_tabs": FileUtils.close_tabs( - Configs.savedata.get_active_tab_index(), - FileUtils.TabCloseMode.ALL_OTHERS) - "close_tabs_to_left": FileUtils.close_tabs( - Configs.savedata.get_active_tab_index(), - FileUtils.TabCloseMode.TO_LEFT) - "close_tabs_to_right": FileUtils.close_tabs( - Configs.savedata.get_active_tab_index(), - FileUtils.TabCloseMode.TO_RIGHT) - "close_empty_tabs": FileUtils.close_tabs( - Configs.savedata.get_active_tab_index(), - FileUtils.TabCloseMode.EMPTY) - "close_saved_tabs": FileUtils.close_tabs( - Configs.savedata.get_active_tab_index(), - FileUtils.TabCloseMode.SAVED) - "new_tab": Configs.savedata.add_empty_tab() - "select_next_tab": Configs.savedata.set_active_tab_index( - posmod(Configs.savedata.get_active_tab_index() + 1, - Configs.savedata.get_tab_count())) - "select_previous_tab": Configs.savedata.set_active_tab_index( - posmod(Configs.savedata.get_active_tab_index() - 1, - Configs.savedata.get_tab_count())) - "copy_svg_text": DisplayServer.clipboard_set(State.svg_text) - "optimize": State.optimize() - "reset_svg": FileUtils.reset_svg() - "debug": State.toggle_show_debug() - return - - # Stop the logic below from running while GUI dragging is going on. - if get_viewport().gui_is_dragging(): + if ShortcutUtils.is_action_pressed(event, "ui_cancel") and not menu_stack.is_empty(): + get_viewport().set_input_as_handled() + _remove_control() return - for action in ShortcutUtils.PRISTINE_ACTIONS: - if ShortcutUtils.is_action_pressed(event, action): - match action: - "ui_undo": Configs.savedata.get_active_tab().undo() - "ui_redo": Configs.savedata.get_active_tab().redo() - "ui_cancel": State.clear_all_selections() - "delete": State.delete_selected() - "move_up": State.move_up_selected() - "move_down": State.move_down_selected() - "duplicate": State.duplicate_selected() - "select_all": State.select_all() - return - - if ShortcutUtils.is_action_pressed(event, "move_absolute"): - State.respond_to_key_input("M") - elif ShortcutUtils.is_action_pressed(event, "move_relative"): - State.respond_to_key_input("m") - elif ShortcutUtils.is_action_pressed(event, "line_absolute"): - State.respond_to_key_input("L") - elif ShortcutUtils.is_action_pressed(event, "line_relative"): - State.respond_to_key_input("l") - elif ShortcutUtils.is_action_pressed(event, "horizontal_line_absolute"): - State.respond_to_key_input("H") - elif ShortcutUtils.is_action_pressed(event, "horizontal_line_relative"): - State.respond_to_key_input("h") - elif ShortcutUtils.is_action_pressed(event, "vertical_line_absolute"): - State.respond_to_key_input("V") - elif ShortcutUtils.is_action_pressed(event, "vertical_line_relative"): - State.respond_to_key_input("v") - elif ShortcutUtils.is_action_pressed(event, "close_path_absolute"): - State.respond_to_key_input("Z") - elif ShortcutUtils.is_action_pressed(event, "close_path_relative"): - State.respond_to_key_input("z") - elif ShortcutUtils.is_action_pressed(event, "elliptical_arc_absolute"): - State.respond_to_key_input("A") - elif ShortcutUtils.is_action_pressed(event, "elliptical_arc_relative"): - State.respond_to_key_input("a") - elif ShortcutUtils.is_action_pressed(event, "cubic_bezier_absolute"): - State.respond_to_key_input("C") - elif ShortcutUtils.is_action_pressed(event, "cubic_bezier_relative"): - State.respond_to_key_input("c") - elif ShortcutUtils.is_action_pressed(event, "shorthand_cubic_bezier_absolute"): - State.respond_to_key_input("S") - elif ShortcutUtils.is_action_pressed(event, "shorthand_cubic_bezier_relative"): - State.respond_to_key_input("s") - elif ShortcutUtils.is_action_pressed(event, "quadratic_bezier_absolute"): - State.respond_to_key_input("Q") - elif ShortcutUtils.is_action_pressed(event, "quadratic_bezier_relative"): - State.respond_to_key_input("q") - elif ShortcutUtils.is_action_pressed(event, "shorthand_quadratic_bezier_absolute"): - State.respond_to_key_input("T") - elif ShortcutUtils.is_action_pressed(event, "shorthand_quadratic_bezier_relative"): - State.respond_to_key_input("t") + for node in shortcut_registrations: + if node is CanvasItem and not node.visible: + continue + + var registrations := shortcut_registrations[node] + for idx in registrations.actions.size(): + var action := registrations.actions[idx] + if ShortcutUtils.is_action_pressed(event, action): + var should_execute := false + var should_clear_popups := false + + match registrations.behaviors[idx]: + ShortcutsRegistration.Behavior.PASS_THROUGH_ALL: + should_execute = true + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS: + if menu_stack.is_empty() or menu_stack[-1].is_ancestor_of(node): + should_execute = true + should_clear_popups = true + ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS: + if menu_stack.is_empty() or menu_stack[-1].is_ancestor_of(node): + should_execute = true + ShortcutsRegistration.Behavior.NO_PASSTHROUGH: + if (menu_stack.is_empty() and popup_stack.is_empty()) or (popup_stack.is_empty() and menu_stack[-1].is_ancestor_of(node)) or\ + (not popup_stack.is_empty() and popup_stack[-1].is_ancestor_of(node)): + should_execute = true + ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH: + if not get_viewport().gui_is_dragging() and ((menu_stack.is_empty() and popup_stack.is_empty()) or (popup_stack.is_empty() and\ + menu_stack[-1].is_ancestor_of(node)) or (not popup_stack.is_empty() and popup_stack[-1].is_ancestor_of(node))): + should_execute = true + + if should_execute: + registrations.activated.emit(action) + registrations.callbacks[idx].call() + if should_clear_popups: + remove_all_popups() + get_viewport().set_input_as_handled() + return func get_window_default_size() -> Vector2i: @@ -435,9 +364,7 @@ func get_window_default_size() -> Vector2i: func get_usable_rect() -> Vector2i: var window := get_window() - return Vector2i(DisplayServer.screen_get_usable_rect( - DisplayServer.window_get_current_screen()).size -\ - window.get_size_with_decorations() + window.size) + return Vector2i(DisplayServer.screen_get_usable_rect(DisplayServer.window_get_current_screen()).size - window.get_size_with_decorations() + window.size) func get_max_ui_scale(usable_screen_size: Vector2i) -> float: var window_default_size := get_window_default_size() @@ -541,8 +468,7 @@ func open_export() -> void: var width := State.root_element.width var height := State.root_element.height - var dimensions_valid := (is_finite(width) and is_finite(height) and\ - width > 0.0 and height > 0.0) + var dimensions_valid := (is_finite(width) and is_finite(height) and width > 0.0 and height > 0.0) var dimensions_too_different := false if dimensions_valid: @@ -567,8 +493,7 @@ func open_export() -> void: Translator.translate("Export"), FileUtils.open_export_dialog.bind(svg_export_data)) func update_window_title() -> void: - if Configs.savedata.use_filename_for_window_title and\ - not Configs.savedata.get_active_tab().svg_file_path.is_empty(): + if Configs.savedata.use_filename_for_window_title and not Configs.savedata.get_active_tab().svg_file_path.is_empty(): get_window().title = Configs.savedata.get_active_tab().presented_name + " - VectorTouch" else: get_window().title = "VectorTouch" @@ -585,7 +510,7 @@ func throw_mouse_motion_event() -> void: var mouse_position = window.get_mouse_position() # TODO This is a workaround because the returned mouse position is sometimes (0, 0), # likely a Godot issue. This has been reproduced on Android and on Web. - # Reproducing on web is especially easy with zoom at something like 110% on Web. + # Reproducing on web is especially easy with zoom at something like 110%. if mouse_position == Vector2.ZERO: return diff --git a/src/autoload/State.gd b/src/autoload/State.gd index 263bf7f..1e7b81e 100644 --- a/src/autoload/State.gd +++ b/src/autoload/State.gd @@ -79,8 +79,7 @@ func setup_from_tab() -> void: apply_svg_text(new_text, false) return - if active_tab.fully_loaded and not active_tab.empty_unsaved and\ - FileAccess.file_exists(active_tab.get_edited_file_path()): + if active_tab.fully_loaded and not active_tab.empty_unsaved and FileAccess.file_exists(active_tab.get_edited_file_path()): var user_facing_path := active_tab.svg_file_path var message := Translator.translate( "The last edited state of this tab could not be found.") @@ -92,14 +91,10 @@ func setup_from_tab() -> void: options_dialog.add_option(Translator.translate("Close tab"), Configs.savedata.remove_active_tab) else: - options_dialog.setup(Translator.translate("Alert!"), - message + "\n\n" + Translator.translate( - "The tab is bound to the file path {file_path}. Do you want to restore the SVG from this path?").\ - format({"file_path": user_facing_path})) - options_dialog.add_option(Translator.translate("Close tab"), - Configs.savedata.remove_active_tab) - options_dialog.add_option(Translator.translate("Restore"), - FileUtils.reset_svg, true) + options_dialog.setup(Translator.translate("Alert!"), message + "\n\n" + Translator.translate( + "The tab is bound to the file path {file_path}. Do you want to restore the SVG from this path?").format({"file_path": user_facing_path})) + options_dialog.add_option(Translator.translate("Close tab"), Configs.savedata.remove_active_tab) + options_dialog.add_option(Translator.translate("Restore"), FileUtils.reset_svg, true) apply_svg_text(TabData.DEFAULT_SVG, false) return @@ -252,7 +247,7 @@ func set_viewport_size(new_value: Vector2i) -> void: var view_rasterized := false var show_grid := true var show_handles := true -var show_reference := false +var show_reference := true var overlay_reference := false var show_debug := false @@ -310,8 +305,7 @@ func normal_select(xid: PackedInt32Array, inner_idx := -1) -> void: xid = xid.duplicate() _clear_selection_no_signal() - if semi_selected_xid == xid and\ - inner_selections.size() == 1 and inner_selections[0] == inner_idx: + if semi_selected_xid == xid and inner_selections.size() == 1 and inner_selections[0] == inner_idx: return semi_selected_xid = xid.duplicate() @@ -449,8 +443,7 @@ func _clear_inner_selection_no_signal() -> void: # Clear the selected elements or the inner selection. func clear_all_selections() -> void: - if not inner_selections.is_empty() or not semi_selected_xid.is_empty() or\ - not selected_xids.is_empty(): + if not inner_selections.is_empty() or not semi_selected_xid.is_empty() or not selected_xids.is_empty(): _clear_selection_no_signal() _clear_inner_selection_no_signal() selection_changed.emit() @@ -516,8 +509,7 @@ func is_hovered(xid: PackedInt32Array, inner_idx := -1, propagate := false) -> b if inner_idx == -1: return XIDUtils.is_parent_or_self(hovered_xid, xid) else: - return (inner_hovered == inner_idx and semi_hovered_xid == xid) or\ - XIDUtils.is_parent_or_self(hovered_xid, xid) + return (inner_hovered == inner_idx and semi_hovered_xid == xid) or XIDUtils.is_parent_or_self(hovered_xid, xid) else: if inner_idx == -1: return hovered_xid == xid @@ -631,8 +623,7 @@ func respond_to_key_input(path_cmd_char: String) -> void: var path_attrib: AttributePathdata = xnode_ref.get_attribute("d") var path_cmd_count := path_attrib.get_command_count() # Z after a Z is syntactically invalid. - if (path_cmd_count == 0 and not path_cmd_char in "Mm") or\ - (path_cmd_char in "Zz" and path_cmd_count > 0 and\ + if (path_cmd_count == 0 and not path_cmd_char in "Mm") or (path_cmd_char in "Zz" and path_cmd_count > 0 and\ path_attrib.get_command(path_cmd_count - 1) is PathCommand.CloseCommand): return path_attrib.insert_command(path_cmd_count, path_cmd_char, Vector2.ZERO) @@ -645,10 +636,8 @@ func respond_to_key_input(path_cmd_char: String) -> void: var path_attrib: AttributePathdata = xnode_ref.get_attribute("d") var last_selection: int = inner_selections.max() # Z after a Z is syntactically invalid. - if path_cmd_char in "Zz" and (path_attrib.get_command(last_selection) is\ - PathCommand.CloseCommand or (path_attrib.get_command_count() >\ - last_selection + 1 and path_attrib.get_command(last_selection + 1) is\ - PathCommand.CloseCommand)): + if path_cmd_char in "Zz" and (path_attrib.get_command(last_selection) is PathCommand.CloseCommand or\ + (path_attrib.get_command_count() > last_selection + 1 and path_attrib.get_command(last_selection + 1) is PathCommand.CloseCommand)): return path_attrib.insert_command(last_selection + 1, path_cmd_char, Vector2.ZERO) normal_select(semi_selected_xid, last_selection + 1) @@ -708,8 +697,7 @@ func insert_path_command_after_selection(new_command: String) -> void: semi_selected_xid).get_attribute("d") var last_selection: int = inner_selections.max() # Z after a Z is syntactically invalid. - if path_attrib.get_command(last_selection) is PathCommand.CloseCommand and\ - new_command in "Zz": + if path_attrib.get_command(last_selection) is PathCommand.CloseCommand and new_command in "Zz": return path_attrib.insert_command(last_selection + 1, new_command) normal_select(semi_selected_xid, last_selection + 1) @@ -756,8 +744,7 @@ func get_selection_context(popup_method: Callable, context: Utils.LayoutPart) -> btn_arr.append(ContextPopup.create_shortcut_button("duplicate")) var xnode := root_element.get_xnode(selected_xids[0]) - if selected_xids.size() == 1 and (not xnode.is_element() or\ - (xnode.is_element() and not xnode.possible_conversions.is_empty())): + if selected_xids.size() == 1 and (not xnode.is_element() or (xnode.is_element() and not xnode.possible_conversions.is_empty())): btn_arr.append(ContextPopup.create_button(Translator.translate("Convert To"), popup_convert_to_context.bind(popup_method), false, load("res://assets/icons/Reload.svg"))) @@ -783,14 +770,11 @@ func get_selection_context(popup_method: Callable, context: Utils.LayoutPart) -> match element_ref.name: "path": if inner_selections.size() == 1: - btn_arr.append(ContextPopup.create_button( - Translator.translate("Insert After"), + btn_arr.append(ContextPopup.create_button(Translator.translate("Insert After"), popup_insert_command_after_context.bind(popup_method), false, load("res://assets/icons/Plus.svg"))) - if inner_selections[0] != 0 or\ - element_ref.get_attribute("d").get_command(0).command_char != "M": - btn_arr.append(ContextPopup.create_button( - Translator.translate("Convert To"), + if inner_selections[0] != 0 or element_ref.get_attribute("d").get_command(0).command_char != "M": + btn_arr.append(ContextPopup.create_button(Translator.translate("Convert To"), popup_convert_to_context.bind(popup_method), false, load("res://assets/icons/Reload.svg"))) if is_selection_subpath(): @@ -853,8 +837,7 @@ func popup_convert_to_context(popup_method: Callable) -> void: disabled_commands = PackedStringArray(["L", "H", "V", "A", "Z", "Q", "T", "C", "S"]) else: disabled_commands = PackedStringArray([cmd_char.to_upper()]) - if cmd_char_upper != "Z" and\ - path_attrib.get_command_count() > selection_idx + 1 and\ + if cmd_char_upper != "Z" and path_attrib.get_command_count() > selection_idx + 1 and\ path_attrib.get_command(selection_idx + 1).command_char.to_upper() == "Z": disabled_commands.append("Z") @@ -883,8 +866,7 @@ func popup_insert_command_after_context(popup_method: Callable) -> void: "C", "S": warned_commands = PackedStringArray(["T"]) "Q", "T": warned_commands = PackedStringArray(["S"]) - if (cmd_char in "Zz") or (path_attrib.get_command_count() > selection_idx + 1 and\ - path_attrib.get_command(selection_idx + 1).command_char.to_upper() == "Z"): + if (cmd_char in "Zz") or (path_attrib.get_command_count() > selection_idx + 1 and path_attrib.get_command(selection_idx + 1).command_char.to_upper() == "Z"): disabled_commands = PackedStringArray(["Z"]) command_picker.mark_invalid(warned_commands, disabled_commands) diff --git a/src/config_classes/Formatter.gd b/src/config_classes/Formatter.gd index 12005a7..a7bfb17 100644 --- a/src/config_classes/Formatter.gd +++ b/src/config_classes/Formatter.gd @@ -63,14 +63,12 @@ func get_setting_default(setting: String) -> Variant: "color_capital_hex": return false "xml_keep_comments": return preset == Preset.PRETTY - "xml_shorthand_tags": return ShorthandTags.ALWAYS if\ - preset == Preset.COMPACT else ShorthandTags.ALL_EXCEPT_CONTAINERS + "xml_shorthand_tags": return ShorthandTags.ALWAYS if preset == Preset.COMPACT else ShorthandTags.ALL_EXCEPT_CONTAINERS "xml_shorthand_tags_space_out_slash": return preset == Preset.PRETTY "xml_pretty_formatting": return preset == Preset.PRETTY "number_remove_leading_zero": return preset == Preset.COMPACT "number_use_exponent_if_shorter": return preset == Preset.COMPACT - "color_use_named_colors": return NamedColorUse.WHEN_SHORTER if\ - preset == Preset.COMPACT else NamedColorUse.ALWAYS + "color_use_named_colors": return NamedColorUse.WHEN_SHORTER if preset == Preset.COMPACT else NamedColorUse.ALWAYS "pathdata_remove_spacing_after_flags": return preset == Preset.COMPACT "transform_list_compress_numbers": return preset == Preset.COMPACT "transform_list_minimize_spacing": return preset == Preset.COMPACT diff --git a/src/config_classes/Palette.gd b/src/config_classes/Palette.gd index 4b701f4..b2eb430 100644 --- a/src/config_classes/Palette.gd +++ b/src/config_classes/Palette.gd @@ -187,6 +187,5 @@ static func is_valid_palette(text: String) -> bool: XMLParser.NODE_UNKNOWN]: continue - return parser.get_node_type() == XMLParser.NODE_ELEMENT and\ - parser.get_node_name() == "palette" + return parser.get_node_type() == XMLParser.NODE_ELEMENT and parser.get_node_name() == "palette" return false diff --git a/src/config_classes/SVGHighlighter.gd b/src/config_classes/SVGHighlighter.gd index 7a7772e..cd3674b 100644 --- a/src/config_classes/SVGHighlighter.gd +++ b/src/config_classes/SVGHighlighter.gd @@ -71,8 +71,7 @@ func _get_line_syntax_highlighting(line: int) -> Dictionary: if expecting_end: if c in " \t\n\r": expecting_attribute_name = true - elif c == ">" or (c == "/" and offset < svg_text.length() - 1 and\ - svg_text[offset + 1] == ">"): + elif c == ">" or (c == "/" and offset < svg_text.length() - 1 and svg_text[offset + 1] == ">"): color_map[offset] = {"color": symbol_color} break else: @@ -135,8 +134,7 @@ func _get_line_syntax_highlighting(line: int) -> Dictionary: return color_map offset += 1 if not current_attribute_name.is_empty(): - color_map[svg_text.length() - current_attribute_name.length() - 1] =\ - {"color": get_attribute_color(element_name, current_attribute_name)} + color_map[svg_text.length() - current_attribute_name.length() - 1] = {"color": get_attribute_color(element_name, current_attribute_name)} XMLParser.NODE_ELEMENT_END: offset = svg_text.find("<", offset) var element_name := parser.get_node_name() @@ -157,9 +155,7 @@ func _get_line_syntax_highlighting(line: int) -> Dictionary: # Helpers. func get_element_color(element_name: String) -> Color: - return element_color if element_name in DB.recognized_elements\ - else unrecognized_element_color + return element_color if element_name in DB.recognized_elements else unrecognized_element_color func get_attribute_color(element_name: String, attribute_name: String) -> Color: - return attribute_color if DB.is_attribute_recognized(element_name, - attribute_name) else unrecognized_attribute_color + return attribute_color if DB.is_attribute_recognized(element_name, attribute_name) else unrecognized_attribute_color diff --git a/src/config_classes/SaveData.gd b/src/config_classes/SaveData.gd index 71eae4d..9e13341 100644 --- a/src/config_classes/SaveData.gd +++ b/src/config_classes/SaveData.gd @@ -800,8 +800,7 @@ const SHORTCUT_PANEL_MAX_SLOTS = 7 set(new_value): # Validation for key in new_value: - if key < 0 or key >= SHORTCUT_PANEL_MAX_SLOTS or\ - not new_value[key] in ShortcutUtils.get_all_actions(): + if key < 0 or key >= SHORTCUT_PANEL_MAX_SLOTS or not new_value[key] in ShortcutUtils.get_all_actions(): new_value.erase(key) # Main part if _shortcut_panel_slots != new_value: @@ -1006,8 +1005,7 @@ func remove_active_tab() -> void: remove_tab(_active_tab_index) func move_tab(old_idx: int, new_idx: int) -> void: - if old_idx == new_idx or old_idx < 0 or old_idx > get_tab_count() or\ - new_idx < 0 or new_idx > get_tab_count(): + if old_idx == new_idx or old_idx < 0 or old_idx > get_tab_count() or new_idx < 0 or new_idx > get_tab_count(): return var tab: TabData = _tabs.pop_at(old_idx) @@ -1031,8 +1029,7 @@ enum LayoutLocation { NONE, EXCLUDED, SIDE_PANEL_TOP, SIDE_PANEL_BOTTOM } # Ensure arrays correspond to layout parts. var arr := new_value[key] for i in range(arr.size() - 1, -1, -1): - if not arr[i] is Utils.LayoutPart or arr[i] < 0 or\ - arr[i] >= Utils.LayoutPart.size(): + if not arr[i] is Utils.LayoutPart or arr[i] < 0 or arr[i] >= Utils.LayoutPart.size(): arr.remove_at(i) # Ensure non-duplicate layout parts and no empty arrays. var used_layout_parts: Array[Utils.LayoutPart] = [] @@ -1060,8 +1057,7 @@ enum LayoutLocation { NONE, EXCLUDED, SIDE_PANEL_TOP, SIDE_PANEL_BOTTOM } func set_layout_parts(location: LayoutLocation, parts: Array[Utils.LayoutPart], notify_layout_changed := true) -> void: - if (_layout.has(location) and parts == _layout[location]) or\ - (not _layout.has(location) and parts.is_empty()): + if (_layout.has(location) and parts == _layout[location]) or (not _layout.has(location) and parts.is_empty()): return if parts.is_empty(): @@ -1117,8 +1113,7 @@ func get_layout_part_index(part: Utils.LayoutPart) -> int: # Utility func get_validity_color(error_condition: bool, warning_condition := false) -> Color: - return basic_color_error if error_condition else\ - basic_color_warning if warning_condition else basic_color_valid + return basic_color_error if error_condition else basic_color_warning if warning_condition else basic_color_valid func get_active_tab_dir() -> String: var tab := get_active_tab() diff --git a/src/config_classes/TabData.gd b/src/config_classes/TabData.gd index 167fec5..1d33c28 100644 --- a/src/config_classes/TabData.gd +++ b/src/config_classes/TabData.gd @@ -165,14 +165,12 @@ func _sync() -> void: FileAccess.get_file_as_string(get_edited_file_path())) if is_instance_valid(edited_text_parse_result.svg): - marked_unsaved = FileAccess.get_file_as_string(svg_file_path) !=\ - SVGParser.root_to_export_text(edited_text_parse_result.svg) + marked_unsaved = FileAccess.get_file_as_string(svg_file_path) != SVGParser.root_to_export_text(edited_text_parse_result.svg) else: marked_unsaved = true - elif not FileAccess.file_exists(get_edited_file_path()) or\ - SVGParser.text_check_is_root_empty(get_true_svg_text()): + elif not FileAccess.file_exists(get_edited_file_path()) or SVGParser.text_check_is_root_empty(get_true_svg_text()): empty_unsaved = true marked_unsaved = false presented_name = "[ %s ]" % Translator.translate("Empty") diff --git a/src/data_classes/Attribute.gd b/src/data_classes/Attribute.gd index eff3ce0..1813540 100644 --- a/src/data_classes/Attribute.gd +++ b/src/data_classes/Attribute.gd @@ -41,13 +41,10 @@ static func get_name_validity(id: String) -> NameValidityLevel: for id_char in id: if id_char in ":_-.": continue - var u := id_char.unicode_at(0) - if (u >= 48 and u <= 57) or (u >= 65 and u <= 90) or (u >= 97 and u <= 122) or\ - (u >= 0xC0 and u <= 0xD6) or (u >= 0xD8 and u <= 0xF6) or\ - (u >= 0xF8 and u <= 0x2FF) or (u >= 0x370 and u <= 0x37D) or\ - (u >= 0x37F and u <= 0x1FFF) or (u >= 0x200C and u <= 0x200D) or\ - (u >= 0x2070 and u <= 0x218F) or (u >= 0x2C00 and u <= 0x2FEF) or\ - (u >= 0x3001 and u <= 0xD7FF) or (u >= 0xF900 and u <= 0xFDCF) or\ + var u := ord(id_char) + if (u >= 48 and u <= 57) or (u >= 65 and u <= 90) or (u >= 97 and u <= 122) or (u >= 0xC0 and u <= 0xD6) or (u >= 0xD8 and u <= 0xF6) or\ + (u >= 0xF8 and u <= 0x2FF) or (u >= 0x370 and u <= 0x37D) or (u >= 0x37F and u <= 0x1FFF) or (u >= 0x200C and u <= 0x200D) or\ + (u >= 0x2070 and u <= 0x218F) or (u >= 0x2C00 and u <= 0x2FEF) or (u >= 0x3001 and u <= 0xD7FF) or (u >= 0xF900 and u <= 0xFDCF) or\ (u >= 0xFDF0 and u <= 0xFFFD) or (u >= 0x10000 and u <= 0xEFFFF): continue diff --git a/src/data_classes/AttributeColor.gd b/src/data_classes/AttributeColor.gd index b958e51..6f948d7 100644 --- a/src/data_classes/AttributeColor.gd +++ b/src/data_classes/AttributeColor.gd @@ -25,8 +25,7 @@ func format(text: String, formatter: Formatter) -> String: var r := String.num_uint64(args[0].strip_edges(false, true).to_int(), 16) var g := String.num_uint64(args[1].strip_edges(false, true).to_int(), 16) var b := String.num_uint64(args[2].strip_edges(false, true).to_int(), 16) - text = "#" + (r if r.length() == 2 else "0" + r) +\ - (g if g.length() == 2 else "0" + g) + (b if b.length() == 2 else "0" + b) + text = "#" + (r if r.length() == 2 else "0" + r) + (g if g.length() == 2 else "0" + g) + (b if b.length() == 2 else "0" + b) elif ColorParser.is_valid_hsl(text): var args_start_pos := text.find("(") + 1 var inside_brackets := text.substr(args_start_pos, text.length() - args_start_pos - 1) @@ -37,8 +36,7 @@ func format(text: String, formatter: Formatter) -> String: var r := String.num_uint64(ColorParser.hsl_get_r(h, s, l), 16) var g := String.num_uint64(ColorParser.hsl_get_g(h, s, l), 16) var b := String.num_uint64(ColorParser.hsl_get_b(h, s, l), 16) - text = "#" + (r if r.length() == 2 else "0" + r) +\ - (g if g.length() == 2 else "0" + g) + (b if b.length() == 2 else "0" + b) + text = "#" + (r if r.length() == 2 else "0" + r) + (g if g.length() == 2 else "0" + g) + (b if b.length() == 2 else "0" + b) if text in get_named_colors(): text = get_named_colors()[text] if ColorParser.is_valid_hex(text) and text.length() == 4: @@ -51,9 +49,9 @@ func format(text: String, formatter: Formatter) -> String: text[1] == text[2] and text[3] == text[4] and text[5] == text[6]: text = "#" + text[1] + text[3] + text[5] Formatter.PrimaryColorSyntax.RGB: - text = "rgb(" + String.num_uint64(text.substr(1, 2).hex_to_int()) +\ - ", " + String.num_uint64(text.substr(3, 2).hex_to_int()) +\ - ", " + String.num_uint64(text.substr(5, 2).hex_to_int()) + ")" + text = "rgb(" + String.num_uint64(text.substr(1, 2).hex_to_int()) + ", " +\ + String.num_uint64(text.substr(3, 2).hex_to_int()) + ", " +\ + String.num_uint64(text.substr(5, 2).hex_to_int()) + ")" if named_colors_usage != Formatter.NamedColorUse.NEVER: var hex := text.to_lower() @@ -66,8 +64,7 @@ func format(text: String, formatter: Formatter) -> String: else: var named_color_text: String = AttributeColor.get_named_colors().find_key(hex) if named_color_text.length() < text.length() or\ - (named_colors_usage == Formatter.NamedColorUse.WHEN_SHORTER_OR_EQUAL and\ - named_color_text.length() == text.length()): + (named_colors_usage == Formatter.NamedColorUse.WHEN_SHORTER_OR_EQUAL and named_color_text.length() == text.length()): text = named_color_text return text diff --git a/src/data_classes/AttributeEnum.gd b/src/data_classes/AttributeEnum.gd index 932d99f..e28c59f 100644 --- a/src/data_classes/AttributeEnum.gd +++ b/src/data_classes/AttributeEnum.gd @@ -2,5 +2,4 @@ class_name AttributeEnum extends Attribute func set_value(new_value: String) -> void: - super(new_value if (new_value.is_empty() or\ - new_value in DB.attribute_enum_values[name]) else "") + super(new_value if (new_value.is_empty() or new_value in DB.attribute_enum_values[name]) else "") diff --git a/src/data_classes/AttributeList.gd b/src/data_classes/AttributeList.gd index ccfbb06..2b8ccf1 100644 --- a/src/data_classes/AttributeList.gd +++ b/src/data_classes/AttributeList.gd @@ -81,8 +81,7 @@ static func text_to_list(string: String) -> PackedFloat64Array: return nums_parsed -func list_to_text(list: PackedFloat64Array, -formatter := Configs.savedata.editor_formatter) -> String: +func list_to_text(list: PackedFloat64Array, formatter := Configs.savedata.editor_formatter) -> String: var params := PackedStringArray() for element in list: # It's fine to use this parser, AttributeList is just a list of numbers. diff --git a/src/data_classes/AttributePathdata.gd b/src/data_classes/AttributePathdata.gd index 72e4611..6291c36 100644 --- a/src/data_classes/AttributePathdata.gd +++ b/src/data_classes/AttributePathdata.gd @@ -36,10 +36,8 @@ func parse_properties() -> void: if command is PathCommand.MoveCommand: subpath_start_indices.append(idx) - curr_subpath_start_x = command.start_x + command.x if\ - command.relative else command.x - curr_subpath_start_y = command.start_y + command.y if\ - command.relative else command.y + curr_subpath_start_x = command.start_x + command.x if command.relative else command.x + curr_subpath_start_y = command.start_y + command.y if command.relative else command.y elif idx > 0 and _commands[idx - 1] is PathCommand.CloseCommand: subpath_start_indices.append(idx) elif command is PathCommand.CloseCommand: @@ -86,8 +84,7 @@ func get_implied_S_control(cmd_idx: int) -> Vector2: var v := Vector2.ZERO if cmd.relative else cmd.get_start_coords() if prev_cmd.command_char in "CcSs": var prev_control_pt := Vector2(prev_cmd.x2, prev_cmd.y2) - v = (cmd.get_start_coords() if\ - cmd.relative else cmd.get_start_coords() * 2) - prev_control_pt + v = (cmd.get_start_coords() if cmd.relative else cmd.get_start_coords() * 2) - prev_control_pt if prev_cmd.relative: v -= prev_cmd.get_start_coords() return v @@ -107,12 +104,9 @@ func get_implied_T_control(idx: int) -> Vector2: var prevQ_x: float = prevQ_cmd.x if "x" in prevQ_cmd else prevQ_cmd.start_x var prevQ_y: float = prevQ_cmd.y if "y" in prevQ_cmd else prevQ_cmd.start_y var prevQ_v := Vector2(prevQ_x, prevQ_y) - var prevQ_v1 := Vector2(prevQ_cmd.x1, prevQ_cmd.y1) if\ - prevQ_cmd.command_char in "Qq" else prevQ_v - var prevQ_end := prevQ_cmd.get_start_coords() + prevQ_v if\ - prevQ_cmd.relative else prevQ_v - var prevQ_control_pt := prevQ_cmd.get_start_coords() + prevQ_v1 if\ - prevQ_cmd.relative else prevQ_v1 + var prevQ_v1 := Vector2(prevQ_cmd.x1, prevQ_cmd.y1) if prevQ_cmd.command_char in "Qq" else prevQ_v + var prevQ_end := prevQ_cmd.get_start_coords() + prevQ_v if prevQ_cmd.relative else prevQ_v + var prevQ_control_pt := prevQ_cmd.get_start_coords() + prevQ_v1 if prevQ_cmd.relative else prevQ_v1 var v := prevQ_end * 2 - prevQ_control_pt for T_idx in range(prevQ_idx + 1, idx): @@ -362,10 +356,8 @@ formatter := Configs.savedata.editor_formatter) -> String: for i in commands_arr.size(): var cmd := commands_arr[i] var cmd_char_capitalized := cmd.command_char.to_upper() - if not (formatter.pathdata_remove_consecutive_commands and\ - ((cmd_char_capitalized != "M" and last_command == cmd.command_char) or\ - (last_command == "m" and cmd.command_char == "l") or\ - (last_command == "M" and cmd.command_char == "L"))): + if not (formatter.pathdata_remove_consecutive_commands and ((cmd_char_capitalized != "M" and last_command == cmd.command_char) or\ + (last_command == "m" and cmd.command_char == "l") or (last_command == "M" and cmd.command_char == "L"))): output += cmd.command_char if not formatter.pathdata_minimize_spacing: output += " " @@ -391,42 +383,33 @@ formatter := Configs.savedata.editor_formatter) -> String: "V": current_char = num_parser.num_to_text(cmd.y)[0] prev_numstr = num_parser.num_to_text(+commands_arr[i - 1].y) - if not formatter.pathdata_minimize_spacing or not\ - (("." in prev_numstr and current_char == ".") or current_char in "-+"): + if not formatter.pathdata_minimize_spacing or not (("." in prev_numstr and current_char == ".") or current_char in "-+"): output += " " last_command = cmd.command_char match cmd_char_capitalized: "A": - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.rx), - num_parser.num_to_text(cmd.ry), num_parser.num_to_text(cmd.rot, true)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.rx), num_parser.num_to_text(cmd.ry), num_parser.num_to_text(cmd.rot, true)]) if formatter.pathdata_remove_spacing_after_flags: - output += (" 0" if cmd.large_arc_flag == 0 else " 1") +\ - ("0" if cmd.sweep_flag == 0 else "1") + output += (" 0" if cmd.large_arc_flag == 0 else " 1") + ("0" if cmd.sweep_flag == 0 else "1") else: output += " 0 " if cmd.large_arc_flag == 0 else " 1 " if num_parser.num_to_text(cmd.x)[0] == "-": output += "0" if cmd.sweep_flag == 0 else "1" else: output += "0 " if cmd.sweep_flag == 0 else "1 " - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x), - num_parser.num_to_text(cmd.y)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x), num_parser.num_to_text(cmd.y)]) "C": - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x1), - num_parser.num_to_text(cmd.y1), num_parser.num_to_text(cmd.x2), - num_parser.num_to_text(cmd.y2), num_parser.num_to_text(cmd.x), - num_parser.num_to_text(cmd.y)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x1), num_parser.num_to_text(cmd.y1), + num_parser.num_to_text(cmd.x2), num_parser.num_to_text(cmd.y2), num_parser.num_to_text(cmd.x), num_parser.num_to_text(cmd.y)]) "Q": - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x1), - num_parser.num_to_text(cmd.y1), num_parser.num_to_text(cmd.x), - num_parser.num_to_text(cmd.y)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x1), num_parser.num_to_text(cmd.y1), + num_parser.num_to_text(cmd.x), num_parser.num_to_text(cmd.y)]) "S": - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x2), - num_parser.num_to_text(cmd.y2), num_parser.num_to_text(cmd.x), - num_parser.num_to_text(cmd.y)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x2), num_parser.num_to_text(cmd.y2), + num_parser.num_to_text(cmd.x), num_parser.num_to_text(cmd.y)]) "L", "M", "T": - output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x), - num_parser.num_to_text(cmd.y)]) + output += num_parser.numstr_arr_to_text([num_parser.num_to_text(cmd.x), num_parser.num_to_text(cmd.y)]) "H": output += num_parser.num_to_text(cmd.x) "V": diff --git a/src/data_classes/AttributeTransformList.gd b/src/data_classes/AttributeTransformList.gd index 5fe266b..8d433fa 100644 --- a/src/data_classes/AttributeTransformList.gd +++ b/src/data_classes/AttributeTransformList.gd @@ -61,8 +61,7 @@ func insert_transform(idx: int, type: String) -> void: sync_after_transforms_change() -func transform_list_to_text(transform_list: Array[Transform], -formatter := Configs.savedata.editor_formatter) -> String: +func transform_list_to_text(transform_list: Array[Transform], formatter := Configs.savedata.editor_formatter) -> String: var output := "" var num_parser := NumstringParser.new() num_parser.compress_numbers = formatter.transform_list_compress_numbers @@ -78,21 +77,18 @@ formatter := Configs.savedata.editor_formatter) -> String: if t.y == 0 and formatter.transform_list_remove_unnecessary_params: output += "translate(%s) " % num_parser.num_to_text(t.x) else: - output += "translate(%s) " % num_parser.numstr_arr_to_text([ - num_parser.num_to_text(t.x), num_parser.num_to_text(t.y)]) + output += "translate(%s) " % num_parser.numstr_arr_to_text([num_parser.num_to_text(t.x), num_parser.num_to_text(t.y)]) elif t is Transform.TransformRotate: if t.x == 0 and t.y == 0 and formatter.transform_list_remove_unnecessary_params: output += "rotate(%s) " % num_parser.num_to_text(t.deg, true) else: - output += "rotate(%s) " % num_parser.numstr_arr_to_text([ - num_parser.num_to_text(t.deg, true), + output += "rotate(%s) " % num_parser.numstr_arr_to_text([num_parser.num_to_text(t.deg, true), num_parser.num_to_text(t.x), num_parser.num_to_text(t.y)]) elif t is Transform.TransformScale: if t.x == t.y and formatter.transform_list_remove_unnecessary_params: output += "scale(%s) " % num_parser.num_to_text(t.x) else: - output += "scale(%s) " % num_parser.numstr_arr_to_text([ - num_parser.num_to_text(t.x), num_parser.num_to_text(t.y)]) + output += "scale(%s) " % num_parser.numstr_arr_to_text([num_parser.num_to_text(t.x), num_parser.num_to_text(t.y)]) elif t is Transform.TransformSkewX: output += "skewX(%s) " % num_parser.num_to_text(t.x, true) elif t is Transform.TransformSkewY: @@ -122,8 +118,7 @@ static func text_to_transform_list(text: String) -> Array[Transform]: var result := NumstringParser.text_to_number_arr(transform_params, 0, 6) if result.is_empty() or result[1] < transform_params.length(): return [] - output.append(Transform.TransformMatrix.new(result[0][0], result[0][1], - result[0][2], result[0][3], result[0][4], result[0][5])) + output.append(Transform.TransformMatrix.new(result[0][0], result[0][1], result[0][2], result[0][3], result[0][4], result[0][5])) "translate": var result1 := NumstringParser.text_to_number_arr(transform_params, 0, 1) if result1.is_empty(): diff --git a/src/data_classes/BasicXNode.gd b/src/data_classes/BasicXNode.gd index f51b9f5..9fb0d9a 100644 --- a/src/data_classes/BasicXNode.gd +++ b/src/data_classes/BasicXNode.gd @@ -32,8 +32,7 @@ static func get_type_string(node_type: NodeType) -> String: func get_possible_conversions() -> Array[NodeType]: var conversions: Array[NodeType] = [] - if (_type == NodeType.TEXT or _type == NodeType.CDATA) and\ - Configs.savedata.editor_formatter.xml_keep_comments: + if (_type == NodeType.TEXT or _type == NodeType.CDATA) and Configs.savedata.editor_formatter.xml_keep_comments: conversions.append(NodeType.COMMENT) if _type == NodeType.COMMENT or _type == NodeType.CDATA: diff --git a/src/data_classes/ColorParser.gd b/src/data_classes/ColorParser.gd index a9397d9..58882e9 100644 --- a/src/data_classes/ColorParser.gd +++ b/src/data_classes/ColorParser.gd @@ -7,19 +7,15 @@ static func add_hash_if_hex(color: String) -> String: color = "#" + color return color -static func is_valid(color: String, allow_alpha := false, allow_url := false, -allow_none := false, allow_current_color := false) -> bool: - return is_valid_hex(color, allow_alpha) or is_valid_rgb(color, allow_alpha) or\ - is_valid_hsl(color, allow_alpha) or is_valid_named(color, allow_alpha) or\ - (allow_url and is_valid_url(color)) or (allow_none and\ - color.strip_edges() == "none") or (allow_current_color and\ - color.strip_edges() == "currentColor") +static func is_valid(color: String, allow_alpha := false, allow_url := false, allow_none := false, allow_current_color := false) -> bool: + return is_valid_hex(color, allow_alpha) or is_valid_rgb(color, allow_alpha) or is_valid_hsl(color, allow_alpha) or is_valid_named(color, allow_alpha) or\ + (allow_url and is_valid_url(color)) or (allow_none and color.strip_edges() == "none") or\ + (allow_current_color and color.strip_edges() == "currentColor") static func is_valid_hex(color: String, allow_alpha := false) -> bool: color = color.strip_edges() if color.begins_with("#") and color.is_valid_html_color(): - if color.length() == 4 or color.length() == 7 or (allow_alpha and\ - (color.length() == 5 or color.length() == 9)): + if color.length() == 4 or color.length() == 7 or (allow_alpha and (color.length() == 5 or color.length() == 9)): return true return false @@ -35,10 +31,8 @@ static func is_valid_rgb(color: String, allow_alpha := false) -> bool: var channels := channels_str.split(",") if channels.size() != 4: return false - return _is_valid_number_or_percentage(channels[0]) and\ - _is_valid_number_or_percentage(channels[1]) and\ - _is_valid_number_or_percentage(channels[2]) and\ - _is_valid_number_or_percentage(channels[3]) + return _is_valid_number_or_percentage(channels[0]) and _is_valid_number_or_percentage(channels[1]) and\ + _is_valid_number_or_percentage(channels[2]) and _is_valid_number_or_percentage(channels[3]) else: return _rgb_check(color) @@ -51,9 +45,7 @@ static func _rgb_check(stripped_color: String) -> bool: if channels.size() != 3: return false - return _is_valid_number_or_percentage(channels[0]) and\ - _is_valid_number_or_percentage(channels[1]) and\ - _is_valid_number_or_percentage(channels[2]) + return _is_valid_number_or_percentage(channels[0]) and _is_valid_number_or_percentage(channels[1]) and _is_valid_number_or_percentage(channels[2]) static func is_valid_hsl(color: String, allow_alpha := false) -> bool: @@ -71,8 +63,7 @@ static func is_valid_hsl(color: String, allow_alpha := false) -> bool: return false return _is_valid_number(channels[0]) and _is_valid_percentage(channels[1]) and\ - _is_valid_percentage(channels[2]) and\ - _is_valid_number_or_percentage(channels[3]) + _is_valid_percentage(channels[2]) and _is_valid_number_or_percentage(channels[3]) else: return _hsl_check(color) @@ -85,8 +76,7 @@ static func _hsl_check(stripped_color: String) -> bool: if channels.size() != 3: return false - return _is_valid_number(channels[0]) and _is_valid_percentage(channels[1]) and\ - _is_valid_percentage(channels[2]) + return _is_valid_number(channels[0]) and _is_valid_percentage(channels[1]) and _is_valid_percentage(channels[2]) static func is_valid_named(color: String, allow_alpha := false) -> bool: return AttributeColor.get_named_colors(allow_alpha).has(color.strip_edges()) @@ -98,8 +88,7 @@ static func is_valid_url(color: String) -> bool: return AttributeID.get_validity(_get_url_id(color)) != Attribute.NameValidityLevel.INVALID static func _get_url_id(stripped_color: String) -> String: - return stripped_color.substr(4, - stripped_color.length() - 5).strip_edges().right(-1) + return stripped_color.substr(4, stripped_color.length() - 5).strip_edges().right(-1) # URL doesn't have a color interpretation, so it'll give the backup. static func text_to_color(color: String, backup := Color.BLACK, @@ -126,10 +115,8 @@ allow_alpha := false) -> Color: return Color.from_rgba8(clampi(r, 0, 255), clampi(g, 0, 255), clampi(b, 0, 255)) else: var a3 := args[3].strip_edges(false, true) - var a := int(a3.to_float() * 255) if _is_valid_number(a3) else\ - int(a3.left(-1).to_float() * 2.55) - return Color.from_rgba8(clampi(r, 0, 255), clampi(g, 0, 255), clampi(b, 0, 255), - clampi(a, 0, 255)) + var a := int(a3.to_float() * 255) if _is_valid_number(a3) else int(a3.left(-1).to_float() * 2.55) + return Color.from_rgba8(clampi(r, 0, 255), clampi(g, 0, 255), clampi(b, 0, 255), clampi(a, 0, 255)) elif is_valid_hsl(color, allow_alpha): var args_start_pos := color.find("(") + 1 var inside_brackets := color.substr(args_start_pos, color.length() - args_start_pos - 1) @@ -144,10 +131,8 @@ allow_alpha := false) -> Color: return Color.from_rgba8(hsl_get_r(h, s, l), hsl_get_g(h, s, l), hsl_get_b(h, s, l)) else: var a3 := args[3].strip_edges(false, true) - var a := int(a3.to_float() * 255) if _is_valid_number(a3) else\ - int(a3.left(-1).to_float() * 2.55) - return Color.from_rgba8(hsl_get_r(h, s, l), hsl_get_g(h, s, l), hsl_get_b(h, s, l), - clampi(a, 0, 255)) + var a := int(a3.to_float() * 255) if _is_valid_number(a3) else int(a3.left(-1).to_float() * 2.55) + return Color.from_rgba8(hsl_get_r(h, s, l), hsl_get_g(h, s, l), hsl_get_b(h, s, l), clampi(a, 0, 255)) elif is_valid_hex(color, allow_alpha): return Color.from_string(color, backup) else: @@ -159,8 +144,7 @@ static func are_colors_same(col1: String, col2: String) -> bool: # Handle color keywords that can't be represented as hex. if col1 == col2: return true - elif col1 == "none" or col2 == "none" or col1 == "currentColor" or\ - col2 == "currentColor": + elif col1 == "none" or col2 == "none" or col1 == "currentColor" or col2 == "currentColor": return false else: var is_col1_url := is_valid_url(col1) @@ -191,8 +175,7 @@ static func are_colors_same(col1: String, col2: String) -> bool: # Helpers static func _is_valid_number_or_percentage(numstr: String) -> bool: numstr = numstr.strip_edges() - return numstr.is_valid_float() or (not numstr.is_empty() and numstr[-1] == "%" and\ - numstr.left(-1).is_valid_float()) + return numstr.is_valid_float() or (not numstr.is_empty() and numstr[-1] == "%" and numstr.left(-1).is_valid_float()) static func _is_valid_number(numstr: String) -> bool: return numstr.strip_edges().is_valid_float() diff --git a/src/data_classes/DB.gd b/src/data_classes/DB.gd index 782a4ed..873f61a 100644 --- a/src/data_classes/DB.gd +++ b/src/data_classes/DB.gd @@ -5,9 +5,8 @@ enum PercentageHandling {FRACTION, HORIZONTAL, VERTICAL, NORMALIZED} enum NumberRange {ARBITRARY, POSITIVE, UNIT} -const recognized_elements: Array[String] = ["svg", "g", "circle", "ellipse", "rect", - "path", "line", "polyline", "polygon", "stop", "linearGradient", "radialGradient", - "use"] +const recognized_elements: Array[String] = ["svg", "g", "circle", "ellipse", "rect", "path", "line", "polyline", "polygon", + "stop", "linearGradient", "radialGradient", "use"] const _element_icons: Dictionary[String, Texture2D] = { "circle": preload("res://assets/icons/element/circle.svg"), @@ -36,8 +35,7 @@ const recognized_attributes: Dictionary[String, Array] = { # TODO this is just propagated_attributes, but it ruins the const because of Godot bug. # TODO Add "color" to "g" when we're ready. "svg": ["xmlns", "x", "y", "width", "height", "viewBox", "fill", "fill-opacity", - "stroke", "stroke-opacity", "stroke-width", "stroke-linecap", "stroke-linejoin", - "color"], + "stroke", "stroke-opacity", "stroke-width", "stroke-linecap", "stroke-linejoin", "color"], "g": ["transform", "opacity", "fill", "fill-opacity", "stroke", "stroke-opacity", "stroke-width", "stroke-linecap", "stroke-linejoin"], "linearGradient": ["id", "gradientTransform", "gradientUnits", "spreadMethod", @@ -63,10 +61,8 @@ const recognized_attributes: Dictionary[String, Array] = { } const _valid_children: Dictionary[String, Array] = { - "svg": ["svg", "path", "circle", "ellipse", "rect", "line", "polygon", "polyline", - "g", "linearGradient", "radialGradient", "use"], - "g": ["svg", "path", "circle", "ellipse", "rect", "line", "polygon", "polyline", - "g", "linearGradient", "radialGradient", "use"], + "svg": ["svg", "path", "circle", "ellipse", "rect", "line", "polygon", "polyline", "g", "linearGradient", "radialGradient", "use"], + "g": ["svg", "path", "circle", "ellipse", "rect", "line", "polygon", "polyline", "g", "linearGradient", "radialGradient", "use"], "linearGradient": ["stop"], "radialGradient": ["stop"], "circle": [], @@ -80,8 +76,7 @@ const _valid_children: Dictionary[String, Array] = { "use": [], } -const propagated_attributes: Array[String] = ["fill", "fill-opacity", "stroke", - "stroke-opacity", "stroke-width", "stroke-linecap", "stroke-linejoin", "color"] +const propagated_attributes: Array[String] = ["fill", "fill-opacity", "stroke", "stroke-opacity", "stroke-width", "stroke-linecap", "stroke-linejoin", "color"] const _attribute_types: Dictionary[String, AttributeType] = { "viewBox": AttributeType.LIST, @@ -155,16 +150,14 @@ const attribute_number_range: Dictionary[String, NumberRange] = { const attribute_color_url_allowed: Array[String] = ["fill", "stroke"] const attribute_color_none_allowed: Array[String] = ["fill", "stroke"] -const attribute_color_current_color_allowed: Array[String] = ["fill", "stroke", - "stop-color"] +const attribute_color_current_color_allowed: Array[String] = ["fill", "stroke", "stop-color"] static func get_recognized_attributes(element_name: String) -> Array: return recognized_attributes.get(element_name, []) static func is_attribute_recognized(element_name: String, attribute_name: String) -> bool: - return recognized_attributes.has(element_name) and\ - attribute_name in recognized_attributes[element_name] + return recognized_attributes.has(element_name) and attribute_name in recognized_attributes[element_name] static func is_child_element_valid(parent_name: String, child_name: String) -> bool: if not parent_name in recognized_elements or not child_name in recognized_elements: diff --git a/src/data_classes/Element.gd b/src/data_classes/Element.gd index 97a4c26..75b4634 100644 --- a/src/data_classes/Element.gd +++ b/src/data_classes/Element.gd @@ -101,8 +101,7 @@ func insert_child(idx: int, new_xnode: XNode) -> void: if new_xnode is Element: for xnode_descendant in new_xnode.get_all_xnode_descendants(): - xnode_descendant.svg = xnode_descendant if xnode_descendant is ElementSVG else\ - xnode_descendant.parent.svg + xnode_descendant.svg = xnode_descendant if xnode_descendant is ElementSVG else xnode_descendant.parent.svg xnode_descendant.root = root var new_xid := xid.duplicate() @@ -171,9 +170,7 @@ func get_attribute_true_color(attribute_name: String) -> String: func get_attribute_num(attribute_name: String) -> float: if DB.get_attribute_type(attribute_name) != DB.AttributeType.NUMERIC: push_error("Attribute not the correct type.") - var num: float = _attributes[attribute_name].get_num() if\ - has_attribute(attribute_name) else\ - AttributeNumeric.text_to_num(get_default(attribute_name)) + var num: float = _attributes[attribute_name].get_num() if has_attribute(attribute_name) else AttributeNumeric.text_to_num(get_default(attribute_name)) # Possibly adjust for percentage. if is_attribute_percentage(attribute_name): var percentage_handling := get_percentage_handling(attribute_name) @@ -195,20 +192,17 @@ func get_attribute_num(attribute_name: String) -> float: func is_attribute_percentage(attribute_name: String) -> bool: if DB.get_attribute_type(attribute_name) != DB.AttributeType.NUMERIC: push_error("Attribute not the correct type.") - return _attributes[attribute_name].is_percentage() if has_attribute(attribute_name) else\ - AttributeNumeric.text_check_percentage(get_default(attribute_name)) + return _attributes[attribute_name].is_percentage() if has_attribute(attribute_name) else AttributeNumeric.text_check_percentage(get_default(attribute_name)) func get_attribute_list(attribute_name: String) -> PackedFloat64Array: if DB.get_attribute_type(attribute_name) != DB.AttributeType.LIST: push_error("Attribute not the correct type.") - return _attributes[attribute_name].get_list() if has_attribute(attribute_name) else\ - AttributeList.text_to_list(get_default(attribute_name)) + return _attributes[attribute_name].get_list() if has_attribute(attribute_name) else AttributeList.text_to_list(get_default(attribute_name)) func get_attribute_final_precise_transform(attribute_name: String) -> PackedFloat64Array: if DB.get_attribute_type(attribute_name) != DB.AttributeType.TRANSFORM_LIST: push_error("Attribute not the correct type.") - var attrib: AttributeTransformList = _attributes[attribute_name] if\ - has_attribute(attribute_name) else new_default_attribute(attribute_name) + var attrib: AttributeTransformList = _attributes[attribute_name] if has_attribute(attribute_name) else new_default_attribute(attribute_name) return attrib.get_final_precise_transform() @@ -319,8 +313,7 @@ func get_precise_transform() -> PackedFloat64Array: if is_parent_g(): result = Utils64Bit.transforms_mult(result, parent.get_precise_transform()) if has_attribute("transform"): - result = Utils64Bit.transforms_mult(result, - get_attribute_final_precise_transform("transform")) + result = Utils64Bit.transforms_mult(result, get_attribute_final_precise_transform("transform")) return result func get_transform() -> Transform2D: diff --git a/src/data_classes/ElementCircle.gd b/src/data_classes/ElementCircle.gd index 0a45fec..43fb968 100644 --- a/src/data_classes/ElementCircle.gd +++ b/src/data_classes/ElementCircle.gd @@ -25,8 +25,7 @@ func get_replacement(new_element: String) -> Element: element.set_attribute("rx", get_attribute_value("r")) element.set_attribute("ry", get_attribute_value("r")) "rect": - dropped_attributes = PackedStringArray(["r", "cx", "cy", "rx", "ry", - "width", "height"]) + dropped_attributes = PackedStringArray(["r", "cx", "cy", "rx", "ry", "width", "height"]) element.set_attribute("x", get_attribute_num("cx") - get_attribute_num("r")) element.set_attribute("y", get_attribute_num("cy") - get_attribute_num("r")) element.set_attribute("width", get_attribute_num("r") * 2) @@ -36,12 +35,9 @@ func get_replacement(new_element: String) -> Element: "path": dropped_attributes = PackedStringArray(["r", "cx", "cy", "d"]) var commands: Array[PathCommand] = [] - commands.append(PathCommand.MoveCommand.new(get_attribute_num("cx"), - get_attribute_num("cy") - get_attribute_num("r"), true)) - commands.append(PathCommand.EllipticalArcCommand.new(get_attribute_num("r"), - get_attribute_num("r"), 0, 0, 0, 0, get_attribute_num("r") * 2, true)) - commands.append(PathCommand.EllipticalArcCommand.new(get_attribute_num("r"), - get_attribute_num("r"), 0, 0, 0, 0, -get_attribute_num("r") * 2, true)) + commands.append(PathCommand.MoveCommand.new(get_attribute_num("cx"), get_attribute_num("cy") - get_attribute_num("r"), true)) + commands.append(PathCommand.EllipticalArcCommand.new(get_attribute_num("r"), get_attribute_num("r"), 0, 0, 0, 0, get_attribute_num("r") * 2, true)) + commands.append(PathCommand.EllipticalArcCommand.new(get_attribute_num("r"), get_attribute_num("r"), 0, 0, 0, 0, -get_attribute_num("r") * 2, true)) commands.append(PathCommand.CloseCommand.new(true)) element.set_attribute("d", commands) apply_to(element, dropped_attributes) @@ -57,5 +53,4 @@ func _get_own_default(attribute_name: String) -> String: func get_bounding_box() -> Rect2: var d := get_attribute_num("r") * 2.0 - return Rect2(get_attribute_num("cx") - get_attribute_num("r"), - get_attribute_num("cy") - get_attribute_num("r"), d, d) + return Rect2(get_attribute_num("cx") - get_attribute_num("r"), get_attribute_num("cy") - get_attribute_num("r"), d, d) diff --git a/src/data_classes/ElementEllipse.gd b/src/data_classes/ElementEllipse.gd index dbd47d2..dc4e1d8 100644 --- a/src/data_classes/ElementEllipse.gd +++ b/src/data_classes/ElementEllipse.gd @@ -36,12 +36,9 @@ func get_replacement(new_element: String) -> Element: "path": dropped_attributes = PackedStringArray(["cx", "cy", "rx", "ry", "d"]) var commands: Array[PathCommand] = [] - commands.append(PathCommand.MoveCommand.new(get_attribute_num("cx"), - get_attribute_num("cy") - get_ry(), true)) - commands.append(PathCommand.EllipticalArcCommand.new(get_rx(), get_ry(), 0, 0, 0, 0, - get_ry() * 2, true)) - commands.append(PathCommand.EllipticalArcCommand.new(get_rx(), get_ry(), 0, 0, 0, 0, - -get_ry() * 2, true)) + commands.append(PathCommand.MoveCommand.new(get_attribute_num("cx"), get_attribute_num("cy") - get_ry(), true)) + commands.append(PathCommand.EllipticalArcCommand.new(get_rx(), get_ry(), 0, 0, 0, 0, get_ry() * 2, true)) + commands.append(PathCommand.EllipticalArcCommand.new(get_rx(), get_ry(), 0, 0, 0, 0, -get_ry() * 2, true)) commands.append(PathCommand.CloseCommand.new(true)) element.set_attribute("d", commands) apply_to(element, dropped_attributes) @@ -49,12 +46,10 @@ func get_replacement(new_element: String) -> Element: func get_rx() -> float: - return get_attribute_num("rx") if has_attribute("rx") else\ - get_attribute_num("ry") if has_attribute("ry") else 0.0 + return get_attribute_num("rx") if has_attribute("rx") else get_attribute_num("ry") if has_attribute("ry") else 0.0 func get_ry() -> float: - return get_attribute_num("ry") if has_attribute("ry") else\ - get_attribute_num("rx") if has_attribute("rx") else 0.0 + return get_attribute_num("ry") if has_attribute("ry") else get_attribute_num("rx") if has_attribute("rx") else 0.0 func _get_own_default(attribute_name: String) -> String: @@ -66,5 +61,4 @@ func _get_own_default(attribute_name: String) -> String: _: return "" func get_bounding_box() -> Rect2: - return Rect2(get_attribute_num("cx") - get_rx(), - get_attribute_num("cy") - get_ry(), get_rx() * 2, get_ry() * 2) + return Rect2(get_attribute_num("cx") - get_rx(), get_attribute_num("cy") - get_ry(), get_rx() * 2, get_ry() * 2) diff --git a/src/data_classes/ElementLinearGradient.gd b/src/data_classes/ElementLinearGradient.gd index 561b7a1..dcdd9ed 100644 --- a/src/data_classes/ElementLinearGradient.gd +++ b/src/data_classes/ElementLinearGradient.gd @@ -12,8 +12,7 @@ func _get_own_default(attribute_name: String) -> String: _: return "" func get_percentage_handling(attribute_name: String) -> DB.PercentageHandling: - if get_attribute_value("gradientUnits") in ["objectBoundingBox", ""] and\ - attribute_name in ["x1", "y1", "x2", "y2"]: + if get_attribute_value("gradientUnits") in ["objectBoundingBox", ""] and attribute_name in ["x1", "y1", "x2", "y2"]: return DB.PercentageHandling.FRACTION else: return super(attribute_name) @@ -41,11 +40,10 @@ func generate_texture() -> SVGTexture: if has_attribute("gradientTransform"): if is_user_space_on_use: - svg_texture_text += """gradientTransform="scale(%f %f) %s scale(%f %f)" """ %\ - [scaling.x, scaling.y, get_attribute_value("gradientTransform"), 1/scaling.x, 1/scaling.y] + svg_texture_text += """gradientTransform="scale(%f %f) %s scale(%f %f)" """ % [scaling.x, scaling.y, + get_attribute_value("gradientTransform"), 1 / scaling.x, 1 / scaling.y] else: - svg_texture_text += """gradientTransform="%s" """ %\ - get_attribute_value("gradientTransform") + svg_texture_text += """gradientTransform="%s" """ % get_attribute_value("gradientTransform") for attrib in ["spreadMethod", "gradientUnits"]: if has_attribute(attrib): diff --git a/src/data_classes/ElementPath.gd b/src/data_classes/ElementPath.gd index 054a07a..758bffe 100644 --- a/src/data_classes/ElementPath.gd +++ b/src/data_classes/ElementPath.gd @@ -54,8 +54,7 @@ func get_bounding_box() -> Rect2: "C", "S": # Cubic Bezier curve var v := Vector2(cmd.x, cmd.y) - var v1 := Vector2(cmd.x1, cmd.y1) if cmd_char == "C" else\ - pathdata.get_implied_S_control(cmd_idx) + var v1 := Vector2(cmd.x1, cmd.y1) if cmd_char == "C" else pathdata.get_implied_S_control(cmd_idx) var v2 := Vector2(cmd.x2, cmd.y2) var cp1 := cmd.get_start_coords() var cp4 := cp1 + v if relative else v @@ -91,8 +90,7 @@ func get_bounding_box() -> Rect2: "Q", "T": # Quadratic Bezier curve var v := Vector2(cmd.x, cmd.y) - var v1 := Vector2(cmd.x1, cmd.y1) if cmd_char == "Q" else\ - pathdata.get_implied_T_control(cmd_idx) + var v1 := Vector2(cmd.x1, cmd.y1) if cmd_char == "Q" else pathdata.get_implied_T_control(cmd_idx) var cp1 := cmd.get_start_coords() var cp2 := cp1 + v1 if relative else v1 @@ -167,11 +165,9 @@ func get_bounding_box() -> Rect2: var extreme1 := atan2(-r.y * rot_h, r.x) var extreme2 := atan2(r.y, r.x * rot_h) for angle: float in [extreme1, extreme2, PI + extreme1, PI + extreme2]: - if (angle < theta1 or angle > theta1 + delta_theta) and\ - (angle + TAU < theta1 or angle + TAU > theta1 + delta_theta): + if (angle < theta1 or angle > theta1 + delta_theta) and (angle + TAU < theta1 or angle + TAU > theta1 + delta_theta): continue - var extreme_point := Vector2( - c.x + r.x * cos(angle) * cosine - r.y * sin(angle) * sine, + var extreme_point := Vector2(c.x + r.x * cos(angle) * cosine - r.y * sin(angle) * sine, c.y + r.x * cos(angle) * sine + r.y * sin(angle) * cosine) min_x = minf(min_x, extreme_point.x) min_y = minf(min_y, extreme_point.y) diff --git a/src/data_classes/ElementPolygon.gd b/src/data_classes/ElementPolygon.gd index fdc0e9c..89a8f49 100644 --- a/src/data_classes/ElementPolygon.gd +++ b/src/data_classes/ElementPolygon.gd @@ -43,9 +43,8 @@ func can_replace(new_element: String) -> bool: if list.size() != 8: return false # Do the x or y coordinates match between opposite pairs of points? - return (list[0] == list[2] and list[3] == list[5] and list[4] == list[6] and\ - list[7] == list[1]) or (list[1] == list[3] and list[2] == list[4] and\ - list[5] == list[7] and list[6] == list[0]) + return (list[0] == list[2] and list[3] == list[5] and list[4] == list[6] and list[7] == list[1]) or\ + (list[1] == list[3] and list[2] == list[4] and list[5] == list[7] and list[6] == list[0]) else: return new_element == "path" @@ -57,8 +56,7 @@ func get_replacement(new_element: String) -> Element: var dropped_attributes: PackedStringArray match new_element: "rect": - dropped_attributes = PackedStringArray(["points", "rx", "ry", "cx", "cy", - "width", "height"]) + dropped_attributes = PackedStringArray(["points", "rx", "ry", "cx", "cy", "width", "height"]) simplify() var list: PackedFloat64Array = get_attribute_list("points") var x1 := list[0] diff --git a/src/data_classes/ElementPolyline.gd b/src/data_classes/ElementPolyline.gd index 97f4d55..7232c3e 100644 --- a/src/data_classes/ElementPolyline.gd +++ b/src/data_classes/ElementPolyline.gd @@ -53,8 +53,7 @@ func get_replacement(new_element: String) -> Element: var dropped_attributes: PackedStringArray match new_element: "line": - dropped_attributes = PackedStringArray(["points", "rx", "ry", "cx", "cy", - "width", "height", "fill", "fill-opacity", "stroke-linejoin"]) + dropped_attributes = PackedStringArray(["points", "rx", "ry", "cx", "cy", "width", "height", "fill", "fill-opacity", "stroke-linejoin"]) simplify() var list := get_attribute_list("points") element.set_attribute("x1", list[0]) @@ -83,9 +82,8 @@ func simplify() -> void: @warning_ignore("integer_division") for idx in range(1, list.size() / 2 - 1): var prev_point := Vector2(list[idx * 2 - 2], list[idx * 2 - 1]) - if not is_equal_approx(prev_point.angle_to_point( - Vector2(list[idx * 2], list[idx * 2 + 1])), prev_point.angle_to_point( - Vector2(list[idx * 2 + 2], list[idx * 2 + 3]))): + if not is_equal_approx(prev_point.angle_to_point(Vector2(list[idx * 2], list[idx * 2 + 1])), + prev_point.angle_to_point(Vector2(list[idx * 2 + 2], list[idx * 2 + 3]))): new_list_points.append(list[idx * 2]) new_list_points.append(list[idx * 2 + 1]) new_list_points.append(list[-2]) diff --git a/src/data_classes/ElementRadialGradient.gd b/src/data_classes/ElementRadialGradient.gd index b678557..93b5ba0 100644 --- a/src/data_classes/ElementRadialGradient.gd +++ b/src/data_classes/ElementRadialGradient.gd @@ -13,15 +13,13 @@ func _get_own_default(attribute_name: String) -> String: _: return "" func get_percentage_handling(attribute_name: String) -> DB.PercentageHandling: - if get_attribute_value("gradientUnits") in ["objectBoundingBox", ""] and\ - attribute_name in ["cx", "cy", "r", "fx", "fy"]: + if get_attribute_value("gradientUnits") in ["objectBoundingBox", ""] and attribute_name in ["cx", "cy", "r", "fx", "fy"]: return DB.PercentageHandling.FRACTION else: return super(attribute_name) func generate_texture() -> SVGTexture: - var svg_texture_text := """ SVGTexture: if has_attribute("gradientTransform"): if is_user_space_on_use: - svg_texture_text += """gradientTransform="scale(%f %f) %s scale(%f %f)" """ %\ - [scaling.x, scaling.y, get_attribute_value("gradientTransform"), 1/scaling.x, 1/scaling.y] + svg_texture_text += """gradientTransform="scale(%f %f) %s scale(%f %f)" """ % [scaling.x, scaling.y, + get_attribute_value("gradientTransform"), 1/scaling.x, 1/scaling.y] else: - svg_texture_text += """gradientTransform="%s" """ %\ - get_attribute_value("gradientTransform") + svg_texture_text += """gradientTransform="%s" """ % get_attribute_value("gradientTransform") for attrib in ["spreadMethod", "gradientUnits"]: if has_attribute(attrib): diff --git a/src/data_classes/ElementRect.gd b/src/data_classes/ElementRect.gd index 883825b..59a120d 100644 --- a/src/data_classes/ElementRect.gd +++ b/src/data_classes/ElementRect.gd @@ -18,12 +18,10 @@ func can_replace(new_element: String) -> bool: "polygon": return get_rx() == 0 and get_ry() == 0 "ellipse": - return get_rx() >= get_attribute_num("width") / 2 and\ - get_ry() >= get_attribute_num("height") / 2 + return get_rx() >= get_attribute_num("width") / 2 and get_ry() >= get_attribute_num("height") / 2 "circle": var side := get_attribute_num("width") - return get_attribute_num("height") == side and get_rx() >= side / 2 and\ - get_ry() >= side / 2 + return get_attribute_num("height") == side and get_rx() >= side / 2 and get_ry() >= side / 2 return false func get_replacement(new_element: String) -> Element: @@ -40,27 +38,22 @@ func get_replacement(new_element: String) -> Element: match new_element: "ellipse": - dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", - "cx", "cy"]) + dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", "cx", "cy"]) element.set_attribute("rx", width_num / 2) element.set_attribute("ry", height_num / 2) element.set_attribute("cx", x_num + width_num / 2) element.set_attribute("cy", y_num + height_num / 2) "circle": - dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", - "r", "cx", "cy"]) + dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", "r", "cx", "cy"]) element.set_attribute("r", width_num / 2) element.set_attribute("cx", x_num + width_num / 2) element.set_attribute("cy", y_num + height_num / 2) "polygon": - dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", - "points"]) - var points := PackedFloat64Array([x_num, y_num, x_num + width_num, y_num, - x_num + width_num, y_num + height_num, x_num, y_num + height_num]) + dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", "points"]) + var points := PackedFloat64Array([x_num, y_num, x_num + width_num, y_num, x_num + width_num, y_num + height_num, x_num, y_num + height_num]) element.get_attribute("points").set_list(points) "path": - dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", - "d"]) + dropped_attributes = PackedStringArray(["x", "y", "width", "height", "rx", "ry", "d"]) var commands: Array[PathCommand] = [] var rx := get_rx() var ry := get_ry() @@ -77,40 +70,30 @@ func get_replacement(new_element: String) -> Element: if w > 0.0 and h > 0.0: commands.append(PathCommand.MoveCommand.new(x_num, y_num + ry, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, rx, -ry, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, rx, -ry, true)) commands.append(PathCommand.HorizontalLineCommand.new(w, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, rx, ry, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, rx, ry, true)) commands.append(PathCommand.VerticalLineCommand.new(h, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, -rx, ry, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, -rx, ry, true)) commands.append(PathCommand.HorizontalLineCommand.new(-w, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, -rx, -ry, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, -rx, -ry, true)) commands.append(PathCommand.CloseCommand.new(true)) elif w > 0.0: commands.append(PathCommand.MoveCommand.new(x_num + rx + w, y_num, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, 0, height_num, true)) + commands.append(PathCommand.EllipticalArcCommand.new( rx, ry, 0, 0, 1, 0, height_num, true)) commands.append(PathCommand.HorizontalLineCommand.new(-w, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, 0, -height_num, true)) + commands.append(PathCommand.EllipticalArcCommand.new( rx, ry, 0, 0, 1, 0, -height_num, true)) commands.append(PathCommand.CloseCommand.new(true)) elif h > 0.0: commands.append(PathCommand.MoveCommand.new(x_num, y_num + ry, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, width_num, 0, true)) + commands.append(PathCommand.EllipticalArcCommand.new( rx, ry, 0, 0, 1, width_num, 0, true)) commands.append(PathCommand.VerticalLineCommand.new(h, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, -width_num, 0, true)) + commands.append(PathCommand.EllipticalArcCommand.new( rx, ry, 0, 0, 1, -width_num, 0, true)) commands.append(PathCommand.CloseCommand.new(true)) else: commands.append(PathCommand.MoveCommand.new(x_num + rx, y_num, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, 0, height_num, true)) - commands.append(PathCommand.EllipticalArcCommand.new( - rx, ry, 0, 0, 1, 0, -height_num, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, 0, height_num, true)) + commands.append(PathCommand.EllipticalArcCommand.new(rx, ry, 0, 0, 1, 0, -height_num, true)) commands.append(PathCommand.CloseCommand.new(true)) element.set_attribute("d", commands) apply_to(element, dropped_attributes) @@ -143,5 +126,4 @@ func _get_own_default(attribute_name: String) -> String: _: return "" func get_bounding_box() -> Rect2: - return Rect2(Vector2(get_attribute_num("x"), get_attribute_num("y")), - Vector2(get_attribute_num("width"), get_attribute_num("height"))) + return Rect2(Vector2(get_attribute_num("x"), get_attribute_num("y")), Vector2(get_attribute_num("width"), get_attribute_num("height"))) diff --git a/src/data_classes/ElementRoot.gd b/src/data_classes/ElementRoot.gd index 1bd2758..7638465 100644 --- a/src/data_classes/ElementRoot.gd +++ b/src/data_classes/ElementRoot.gd @@ -145,8 +145,7 @@ func move_xnodes_to(xids: Array[PackedInt32Array], location: PackedInt32Array) - get_xnode(XIDUtils.get_parent_xid(location)).insert_child(location[-1], xnode) # Check if this actually chagned the layout. for id in xids_stored: - if not XIDUtils.are_siblings_or_same(id, location) or id[-1] < location[-1] or\ - id[-1] >= location[-1] + xids_stored.size(): + if not XIDUtils.are_siblings_or_same(id, location) or id[-1] < location[-1] or id[-1] >= location[-1] + xids_stored.size(): # If this condition is passed, then there was a layout change. xnodes_moved_to.emit(xids, location) xnode_layout_changed.emit() diff --git a/src/data_classes/ElementSVG.gd b/src/data_classes/ElementSVG.gd index 2ee5fe4..edd3925 100644 --- a/src/data_classes/ElementSVG.gd +++ b/src/data_classes/ElementSVG.gd @@ -46,14 +46,12 @@ func update_cache() -> void: if has_valid_width: width = get_attribute_num("width") if not has_valid_height: - height = width / get_attribute("viewBox").get_list_element(2) *\ - get_attribute("viewBox").get_list_element(3) + height = width / get_attribute("viewBox").get_list_element(2) * get_attribute("viewBox").get_list_element(3) else: height = get_attribute_num("height") elif has_valid_height: height = get_attribute_num("height") - width = height / get_attribute("viewBox").get_list_element(3) *\ - get_attribute("viewBox").get_list_element(2) + width = height / get_attribute("viewBox").get_list_element(3) * get_attribute("viewBox").get_list_element(2) else: width = get_attribute("viewBox").get_list_element(2) height = get_attribute("viewBox").get_list_element(3) @@ -69,12 +67,10 @@ func update_cache() -> void: var width_ratio := width / viewbox.size.x var height_ratio := height / viewbox.size.y if width_ratio < height_ratio: - canvas_precise_transform = PackedFloat64Array([ - width_ratio, 0.0, 0.0, width_ratio, -viewbox.position.x * width_ratio, + canvas_precise_transform = PackedFloat64Array([width_ratio, 0.0, 0.0, width_ratio, -viewbox.position.x * width_ratio, -viewbox.position.y * width_ratio + (height - width_ratio * viewbox.size.y) / 2.0]) else: - canvas_precise_transform = PackedFloat64Array([ - height_ratio, 0.0, 0.0, height_ratio, -viewbox.position.x * height_ratio +\ + canvas_precise_transform = PackedFloat64Array([height_ratio, 0.0, 0.0, height_ratio, -viewbox.position.x * height_ratio +\ (width - height_ratio * viewbox.size.x) / 2, -viewbox.position.y * height_ratio]) if not canvas_transform.is_finite(): canvas_precise_transform = PackedFloat64Array([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]) @@ -88,8 +84,7 @@ func world_to_canvas(pos: Vector2) -> Vector2: return canvas_transform.affine_inverse() * pos func world_to_canvas_64_bit(pos: PackedFloat64Array) -> PackedFloat64Array: - return Utils64Bit.transform_vector_mult(Utils64Bit.get_transform_affine_inverse( - canvas_precise_transform), pos) + return Utils64Bit.transform_vector_mult(Utils64Bit.get_transform_affine_inverse(canvas_precise_transform), pos) func get_size() -> Vector2: return Vector2(width, height) diff --git a/src/data_classes/ListParser.gd b/src/data_classes/ListParser.gd index f791182..cb20be9 100644 --- a/src/data_classes/ListParser.gd +++ b/src/data_classes/ListParser.gd @@ -4,9 +4,11 @@ static func rect_to_list(rect: Rect2) -> PackedFloat64Array: return PackedFloat64Array([rect.position.x, rect.position.y, rect.size.x, rect.size.y]) +# Converts the list of floats into a list of Vector2s. static func list_to_points(list: PackedFloat64Array) -> PackedVector2Array: var points := PackedVector2Array() @warning_ignore("integer_division") - for idx in list.size() / 2: - points.append(Vector2(list[idx * 2], list[idx * 2 + 1])) + points.resize(list.size() / 2) + for idx in points.size(): + points[idx] = Vector2(list[idx * 2], list[idx * 2 + 1]) return points diff --git a/src/data_classes/NumberParser.gd b/src/data_classes/NumberParser.gd index 8008f56..fc59f7d 100644 --- a/src/data_classes/NumberParser.gd +++ b/src/data_classes/NumberParser.gd @@ -19,8 +19,7 @@ static func num_to_text(number: float, formatter: Formatter) -> String: else: var numstr_abs := numstr.trim_prefix("-") # Leading zeros aren't removed yet. - if numstr_abs.begins_with("0.00") and\ - (not formatter.number_remove_leading_zero or numstr_abs.begins_with("0.000")): + if numstr_abs.begins_with("0.00") and (not formatter.number_remove_leading_zero or numstr_abs.begins_with("0.000")): var is_num_negative := numstr.begins_with("-") var e := 3 while e + 1 < numstr.length() and numstr_abs[e + 1] == "0": diff --git a/src/data_classes/NumstringParser.gd b/src/data_classes/NumstringParser.gd index 2354b0e..5682e90 100644 --- a/src/data_classes/NumstringParser.gd +++ b/src/data_classes/NumstringParser.gd @@ -7,15 +7,13 @@ var compress_numbers: bool var minimize_spacing: bool static func basic_num_to_text(num: float, is_angle := false) -> String: - var text := Utils.num_simple(num, Utils.MAX_ANGLE_PRECISION if is_angle\ - else Utils.MAX_NUMERIC_PRECISION) + var text := Utils.num_simple(num, Utils.MAX_ANGLE_PRECISION if is_angle else Utils.MAX_NUMERIC_PRECISION) if text == "-0": text = "0" return text func num_to_text(num: float, is_angle := false) -> String: - var text := Utils.num_simple(num, Utils.MAX_ANGLE_PRECISION if is_angle\ - else Utils.MAX_NUMERIC_PRECISION) + var text := Utils.num_simple(num, Utils.MAX_ANGLE_PRECISION if is_angle else Utils.MAX_NUMERIC_PRECISION) if compress_numbers: if text.begins_with("0."): text = text.right(-1) @@ -31,8 +29,7 @@ func numstr_arr_to_text(numstr_arr: PackedStringArray) -> String: var current_numstr := numstr_arr[i] var next_char := numstr_arr[i + 1][0] output += current_numstr - if not minimize_spacing or not (("." in current_numstr and next_char == ".") or\ - next_char in "-+"): + if not minimize_spacing or not (("." in current_numstr and next_char == ".") or next_char in "-+"): output += " " return output + numstr_arr[-1] @@ -83,8 +80,7 @@ allow_starting_comma := false) -> Array: if current_index >= text_length: return [] - var state := NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_ALLOWED if \ - allow_starting_comma else NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_FORBIDDEN + var state := NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_ALLOWED if allow_starting_comma else NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_FORBIDDEN var current_number_start_idx := -1 var parsed_numbers := PackedFloat64Array() while true: @@ -134,18 +130,15 @@ allow_starting_comma := false) -> Array: if current_char in "1234567890": pass elif current_char in " \t\n\r": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_ALLOWED current_number_start_idx = -1 elif current_char == ",": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_FORBIDDEN current_number_start_idx = -1 elif current_char in "-+": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.DIRECTLY_AFTER_SIGN current_number_start_idx = current_index elif current_char == ".": @@ -156,25 +149,21 @@ allow_starting_comma := false) -> Array: unrecognized_symbol = true elif state == NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_NON_LEADING_FLOATING_POINT: if current_char == ".": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_LEADING_FLOATING_POINT current_number_start_idx = current_index elif current_char in "-+": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.DIRECTLY_AFTER_SIGN current_number_start_idx = current_index elif current_char in "1234567890": state = NumberJumbleParseState.INSIDE_NUMBER_INDIRECTLY_AFTER_FLOATING_POINT elif current_char in " \t\n\r": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_ALLOWED current_number_start_idx = -1 elif current_char == ",": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_FORBIDDEN current_number_start_idx = -1 elif current_char == "eE": @@ -190,23 +179,19 @@ allow_starting_comma := false) -> Array: if current_char in "1234567890": pass elif current_char == ".": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_LEADING_FLOATING_POINT current_number_start_idx = current_index elif current_char in " \t\n\r": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_ALLOWED current_number_start_idx = -1 elif current_char == ",": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.OUTSIDE_NUMBER_COMMA_FORBIDDEN current_number_start_idx = -1 elif current_char in "-+": - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) state = NumberJumbleParseState.DIRECTLY_AFTER_SIGN current_number_start_idx = current_index elif current_char in "eE": @@ -253,12 +238,9 @@ allow_starting_comma := false) -> Array: if unrecognized_symbol: if current_number_start_idx >= 0 and parsed_numbers.size() == expected_count - 1 and\ - not state in [NumberJumbleParseState.DIRECTLY_AFTER_SIGN, - NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_EXPONENT, - NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_LEADING_FLOATING_POINT, - NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_EXPONENT_SIGN]: - parsed_numbers.append(text.substr(current_number_start_idx, - current_index - current_number_start_idx).to_float()) + not state in [NumberJumbleParseState.DIRECTLY_AFTER_SIGN, NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_EXPONENT, + NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_LEADING_FLOATING_POINT, NumberJumbleParseState.INSIDE_NUMBER_DIRECTLY_AFTER_EXPONENT_SIGN]: + parsed_numbers.append(text.substr(current_number_start_idx, current_index - current_number_start_idx).to_float()) return [parsed_numbers, current_index] elif (current_number_start_idx < 0 and parsed_numbers.size() == expected_count): return [parsed_numbers, current_index] diff --git a/src/data_classes/PathCommand.gd b/src/data_classes/PathCommand.gd index 08517d9..36f0ece 100644 --- a/src/data_classes/PathCommand.gd +++ b/src/data_classes/PathCommand.gd @@ -2,15 +2,19 @@ @abstract class_name PathCommand const translation_dict: Dictionary[String, GDScript] = { - "M": MoveCommand, "L": LineCommand, "H": HorizontalLineCommand, - "V": VerticalLineCommand, "Z": CloseCommand, "A": EllipticalArcCommand, - "Q": QuadraticBezierCommand, "T": ShorthandQuadraticBezierCommand, - "C": CubicBezierCommand, "S": ShorthandCubicBezierCommand + "M": MoveCommand, + "L": LineCommand, + "H": HorizontalLineCommand, + "V": VerticalLineCommand, + "Z": CloseCommand, + "A": EllipticalArcCommand, + "Q": QuadraticBezierCommand, + "T": ShorthandQuadraticBezierCommand, + "C": CubicBezierCommand, + "S": ShorthandCubicBezierCommand } -const arg_count_dict: Dictionary[String, int] = { - "M": 2, "L": 2, "H": 1, "V": 1, "Z": 0, "A": 7, "Q": 4, "T": 2, "C": 6, "S": 4 -} +const arg_count_dict: Dictionary[String, int] = { "M": 2, "L": 2, "H": 1, "V": 1, "Z": 0, "A": 7, "Q": 4, "T": 2, "C": 6, "S": 4 } var command_char := "" var relative := false @@ -96,8 +100,7 @@ class EllipticalArcCommand extends PathCommand: var sweep_flag: int var x: float var y: float - func _init(new_rx := 1.0, new_ry := 1.0, new_rot := 0.0, new_large_arc_flag := 0, - new_sweep_flag := 0, new_x := 0.0, new_y := 0.0, p_rel := false) -> void: + func _init(new_rx := 1.0, new_ry := 1.0, new_rot := 0.0, new_large_arc_flag := 0, new_sweep_flag := 0, new_x := 0.0, new_y := 0.0, p_rel := false) -> void: relative = p_rel command_char = "a" if p_rel else "A" rx = new_rx @@ -113,8 +116,7 @@ class QuadraticBezierCommand extends PathCommand: var y1: float var x: float var y: float - func _init(new_x1 := 0.0, new_y1 := 0.0, new_x := 0.0, new_y := 0.0, - p_rel := false) -> void: + func _init(new_x1 := 0.0, new_y1 := 0.0, new_x := 0.0, new_y := 0.0, p_rel := false) -> void: relative = p_rel command_char = "q" if p_rel else "Q" x1 = new_x1 @@ -138,8 +140,7 @@ class CubicBezierCommand extends PathCommand: var y2: float var x: float var y: float - func _init(new_x1 := 0.0, new_y1 := 0.0, new_x2 := 0.0, new_y2 := 0.0, - new_x := 0.0, new_y := 0.0, p_rel := false) -> void: + func _init(new_x1 := 0.0, new_y1 := 0.0, new_x2 := 0.0, new_y2 := 0.0, new_x := 0.0, new_y := 0.0, p_rel := false) -> void: relative = p_rel command_char = "c" if p_rel else "C" x1 = new_x1 @@ -154,8 +155,7 @@ class ShorthandCubicBezierCommand extends PathCommand: var y2: float var x: float var y: float - func _init(new_x2 := 0.0, new_y2 := 0.0, new_x := 0.0, new_y := 0.0, - p_rel := false) -> void: + func _init(new_x2 := 0.0, new_y2 := 0.0, new_x := 0.0, new_y := 0.0, p_rel := false) -> void: relative = p_rel command_char = "s" if p_rel else "S" x2 = new_x2 diff --git a/src/data_classes/SVGParser.gd b/src/data_classes/SVGParser.gd index c6c8811..243f978 100644 --- a/src/data_classes/SVGParser.gd +++ b/src/data_classes/SVGParser.gd @@ -1,6 +1,6 @@ @abstract class_name SVGParser -# For checking if an SVG is empty. If the text errors out, it's as if the SVG is empty. +## Checks if the text describes an SVG without child elements. static func text_check_is_root_empty(text: String) -> bool: if text.is_empty(): return false @@ -14,45 +14,41 @@ static func text_check_is_root_empty(text: String) -> bool: # Parse the first svg tag that's encountered. while parser.read() == OK: - if parser.get_node_type() != XMLParser.NODE_ELEMENT or\ - parser.get_node_name() != "svg": + if parser.get_node_type() != XMLParser.NODE_ELEMENT or parser.get_node_name() != "svg": continue describes_svg = true - var node_offset := parser.get_node_offset() var closure_pos := _find_closure_string_in_utf8_buffer(buffer, node_offset) - if closure_pos != -1 and closure_pos <= buffer.find(">".unicode_at(0), node_offset): - return true + if closure_pos != -1 and closure_pos <= buffer.find(ord(">"), node_offset): + return true # If the svg tag is immediately closed, i.e. , then it's empty. break - if not describes_svg: - return false - - if parser.read() == OK: - if parser.get_node_type() == XMLParser.NODE_ELEMENT_END: - return parser.get_node_name() == "svg" - return false + # If the SVG tag isn't immediately closed, then check if the next XML node is an element end. + return describes_svg and parser.read() == OK and parser.get_node_type() == XMLParser.NODE_ELEMENT_END and parser.get_node_name() == "svg" -# For rendering only a section of the SVG. -static func root_cutout_to_text(root_element: ElementRoot, custom_width: float, -custom_height: float, custom_viewbox: Rect2) -> String: +## Creates a new SVG with a custom viewport that shows only a rectangular section of the original. +static func root_cutout_to_text(root_element: ElementRoot, custom_width: float, custom_height: float, custom_viewbox: Rect2) -> String: + # Build a new root element, set it up, and convert it to text. var new_root_element: ElementRoot = root_element.duplicate(false) new_root_element.set_attribute("viewBox", ListParser.rect_to_list(custom_viewbox)) new_root_element.set_attribute("width", custom_width) new_root_element.set_attribute("height", custom_height) var text := _xnode_to_text(new_root_element, Configs.savedata.editor_formatter) + # Since we only converted a single root element to text, it would have closed. + # Remove the closure and add all the other elements' text before closing it manually. text = text.left(maxi(text.find("/>"), text.find(""))) + ">" for child_idx in root_element.get_child_count(): - text += _xnode_to_text(root_element.get_xnode( - PackedInt32Array([child_idx])), Configs.savedata.editor_formatter, true) + text += _xnode_to_text(root_element.get_xnode(PackedInt32Array([child_idx])), Configs.savedata.editor_formatter, true) return text + "" +## Converts the child elements of a root element into text, excluding the svg tag itself. static func root_children_to_text(root_element: ElementRoot, formatter: Formatter) -> String: var text := "" for child in root_element.get_children(): var new_text := _xnode_to_text(child, formatter) + # Remove one level of indentation from each line to maintain proper formatting. var lines := new_text.split('\n') for i in lines.size(): lines[i] = lines[i].trim_prefix(formatter.get_indent_string()) @@ -65,14 +61,16 @@ static func root_to_editor_text(root_element: ElementRoot) -> String: static func root_to_export_text(root_element: ElementRoot) -> String: return root_to_text(root_element, Configs.savedata.export_formatter) +## Converts a root element into text using a specific formatter. static func root_to_text(root_element: ElementRoot, formatter: Formatter) -> String: var text := _xnode_to_text(root_element, formatter).trim_suffix('\n') if formatter.xml_add_trailing_newline: text += "\n" return text -static func _xnode_to_text(xnode: XNode, formatter: Formatter, -make_attributes_absolute := false) -> String: +## The main entry point for converting any XML node and its descendants into text. +## If make_attributes_absolute is true, converts percentage-based attributes into absolute values so cutouts can be safely made. +static func _xnode_to_text(xnode: XNode, formatter: Formatter, make_attributes_absolute := false) -> String: var text := "" if formatter.xml_pretty_formatting: text = formatter.get_indent_string().repeat(xnode.xid.size()) @@ -124,10 +122,8 @@ make_attributes_absolute := false) -> String: else: text += " %s='%s'" % [attribute.name, value] - if not element.has_children() and (formatter.xml_shorthand_tags ==\ - Formatter.ShorthandTags.ALWAYS or (formatter.xml_shorthand_tags ==\ - Formatter.ShorthandTags.ALL_EXCEPT_CONTAINERS and\ - not element.name in Formatter.container_elements)): + if not element.has_children() and (formatter.xml_shorthand_tags == Formatter.ShorthandTags.ALWAYS or\ + (formatter.xml_shorthand_tags == Formatter.ShorthandTags.ALL_EXCEPT_CONTAINERS and not element.name in Formatter.container_elements)): text += ' />' if formatter.xml_shorthand_tags_space_out_slash else '/>' if formatter.xml_pretty_formatting: text += '\n' @@ -163,7 +159,8 @@ static func get_error_string(parse_error: ParseError) -> String: return Translator.translate("Improper nesting.") _: return "" -# The root always uses the editor formatter. +## The main entry point for converting SVG markup into the internal element tree structure. +## Returns a parse result, which contains either the ElementRoot or an error from an enum. static func text_to_root(text: String) -> ParseResult: if text.is_empty(): return ParseResult.new(ParseError.ERR_NOT_SVG) @@ -179,20 +176,18 @@ static func text_to_root(text: String) -> ParseResult: # Parse the first svg tag that's encountered. while parser.read() == OK: - if parser.get_node_type() != XMLParser.NODE_ELEMENT or\ - parser.get_node_name() != "svg": + if parser.get_node_type() != XMLParser.NODE_ELEMENT or parser.get_node_name() != "svg": continue describes_svg = true for i in parser.get_attribute_count(): - root_element.set_attribute(parser.get_attribute_name(i), - parser.get_attribute_value(i)) + root_element.set_attribute(parser.get_attribute_name(i), parser.get_attribute_value(i)) var node_offset := parser.get_node_offset() var closure_pos := _find_closure_string_in_utf8_buffer(buffer, node_offset) - if closure_pos == -1 or closure_pos > buffer.find(">".unicode_at(0), node_offset): + if closure_pos == -1 or closure_pos > buffer.find(ord(">"), node_offset): unclosed_element_stack.append(root_element) break else: @@ -212,10 +207,9 @@ static func text_to_root(text: String) -> ParseResult: unclosed_element_stack.back().insert_child(-1, element) for i in parser.get_attribute_count(): - element.set_attribute(parser.get_attribute_name(i), - parser.get_attribute_value(i)) + element.set_attribute(parser.get_attribute_name(i), parser.get_attribute_value(i)) - if closure_pos == -1 or closure_pos > buffer.find(">".unicode_at(0), node_offset): + if closure_pos == -1 or closure_pos > buffer.find(ord(">"), node_offset): unclosed_element_stack.append(element) XMLParser.NODE_ELEMENT_END: @@ -230,16 +224,13 @@ static func text_to_root(text: String) -> ParseResult: XMLParser.NODE_COMMENT: if Configs.savedata.editor_formatter.xml_keep_comments: - unclosed_element_stack.back().insert_child(-1, - BasicXNode.new(BasicXNode.NodeType.COMMENT, parser.get_node_name())) + unclosed_element_stack.back().insert_child(-1, BasicXNode.new(BasicXNode.NodeType.COMMENT, parser.get_node_name())) XMLParser.NODE_TEXT: var real_text := parser.get_node_data().strip_edges() if not real_text.is_empty(): - unclosed_element_stack.back().insert_child(-1, - BasicXNode.new(BasicXNode.NodeType.TEXT, real_text)) + unclosed_element_stack.back().insert_child(-1, BasicXNode.new(BasicXNode.NodeType.TEXT, real_text)) XMLParser.NODE_CDATA: - unclosed_element_stack.back().insert_child(-1, - BasicXNode.new(BasicXNode.NodeType.CDATA, parser.get_node_name())) + unclosed_element_stack.back().insert_child(-1, BasicXNode.new(BasicXNode.NodeType.CDATA, parser.get_node_name())) if not unclosed_element_stack.is_empty(): return ParseResult.new(ParseError.ERR_IMPROPER_NESTING) @@ -250,10 +241,10 @@ static func text_to_root(text: String) -> ParseResult: # Helper to find "/>" strings inside a buffer. static func _find_closure_string_in_utf8_buffer(buffer: PackedByteArray, offset: int) -> int: while true: - offset = buffer.find("/".unicode_at(0), offset) + offset = buffer.find(ord("/"), offset) if offset == -1: return -1 - elif buffer[offset + 1] == ">".unicode_at(0): + elif buffer[offset + 1] == ord(">"): return offset offset += 1 return -1 diff --git a/src/data_classes/ShortcutRegistration.gd b/src/data_classes/ShortcutRegistration.gd new file mode 100644 index 0000000..56299f5 --- /dev/null +++ b/src/data_classes/ShortcutRegistration.gd @@ -0,0 +1,16 @@ +class_name ShortcutsRegistration extends RefCounted + +@warning_ignore("unused_signal") +signal activated(activated_action: String) + +enum Behavior {PASS_THROUGH_ALL, PASS_THROUGH_POPUPS, PASS_THROUGH_AND_PRESERVE_POPUPS, NO_PASSTHROUGH, STRICT_NO_PASSTHROUGH} + +# The elements with the same indices from these 3 arrays corresponds to a shortcut registration. +var actions := PackedStringArray() +var behaviors: Array[Behavior] = [] +var callbacks: Array[Callable] = [] + +func add_shortcut(new_action: String, new_callback: Callable, new_behavior := Behavior.NO_PASSTHROUGH) -> void: + actions.append(new_action) + behaviors.append(new_behavior) + callbacks.append(new_callback) diff --git a/src/data_classes/ShortcutRegistration.gd.uid b/src/data_classes/ShortcutRegistration.gd.uid new file mode 100644 index 0000000..4b9034e --- /dev/null +++ b/src/data_classes/ShortcutRegistration.gd.uid @@ -0,0 +1 @@ +uid://bssv7pdsnjec0 diff --git a/src/data_classes/Transform.gd b/src/data_classes/Transform.gd index 7fbf087..c77d50d 100644 --- a/src/data_classes/Transform.gd +++ b/src/data_classes/Transform.gd @@ -8,8 +8,7 @@ class TransformMatrix extends Transform: var o1: float var o2: float - func _init(new_x1: float, new_x2: float, new_y1: float, new_y2: float, new_o1: float, - new_o2: float) -> void: + func _init(new_x1: float, new_x2: float, new_y1: float, new_y2: float, new_o1: float, new_o2: float) -> void: x1 = new_x1 x2 = new_x2 y1 = new_y1 diff --git a/src/shaders/color_wheel.gdshader b/src/shaders/color_wheel.gdshader index f5d2217..cc40a25 100644 --- a/src/shaders/color_wheel.gdshader +++ b/src/shaders/color_wheel.gdshader @@ -16,7 +16,5 @@ void fragment() { x += 0.002; float b4 = float(sqrt(x * x + y * y) < 0.5); - COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + - vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), - ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.0); + COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.0); } diff --git a/src/ui_parts/about_menu.gd b/src/ui_parts/about_menu.gd index 9c91730..a98717c 100644 --- a/src/ui_parts/about_menu.gd +++ b/src/ui_parts/about_menu.gd @@ -13,6 +13,11 @@ extends PanelContainer @onready var tab_container: TabContainer = $VBoxContainer/TabContainer func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("select_next_tab", select_next_tab) + shortcuts.add_shortcut("select_previous_tab", select_previous_tab) + HandlerGUI.register_shortcuts(self, shortcuts) + var stylebox := get_theme_stylebox("panel").duplicate() stylebox.content_margin_top += 2.0 add_theme_stylebox_override("panel", stylebox) @@ -29,20 +34,20 @@ func _ready() -> void: tab_container.tab_changed.connect(_on_tab_changed) _on_tab_changed(0) -func _unhandled_input(event: InputEvent) -> void: + +func select_next_tab() -> void: + tab_container.current_tab = (tab_container.current_tab + 1) % tab_container.get_tab_count() + +func select_previous_tab() -> void: var tab_count := tab_container.get_tab_count() - if ShortcutUtils.is_action_pressed(event, "select_next_tab"): - tab_container.current_tab = (tab_container.current_tab + 1) % tab_count - elif ShortcutUtils.is_action_pressed(event, "select_previous_tab"): - tab_container.current_tab = (tab_container.current_tab + tab_count - 1) % tab_count + tab_container.current_tab = (tab_container.current_tab + tab_count - 1) % tab_count func _on_tab_changed(idx: int) -> void: match idx: 0: var app_info := get_app_info() - %ProjectFounderLabel.text = Translator.translate("Project Founder and Manager") +\ - ": " + app_info.project_founder_and_manager + %ProjectFounderLabel.text = Translator.translate("Project Founder and Manager") + ": " + app_info.project_founder_and_manager %DevelopersLabel.text = Translator.translate("Developers") %TranslatorsLabel.text = Translator.translate("Translators") @@ -53,8 +58,7 @@ func _on_tab_changed(idx: int) -> void: # There can be multiple translators for a single locale. for locale in TranslationServer.get_loaded_locales(): - var credits := TranslationServer.get_translation_object(locale).get_message( - "translation-credits").split(",", false) + var credits := TranslationServer.get_translation_object(locale).get_message("translation-credits").split(",", false) if credits.is_empty(): continue @@ -294,8 +298,7 @@ func get_app_info() -> Dictionary[String, Variant]: var arr := [] for elem in elements: var v := elem.strip_edges() - if (v.begins_with('"') and v.ends_with('"')) or\ - (v.begins_with("'") and v.ends_with("'")): + if (v.begins_with('"') and v.ends_with('"')) or (v.begins_with("'") and v.ends_with("'")): arr.append(v.substr(1, v.length() - 2)) elif v.is_valid_int(): arr.append(v.to_int()) @@ -304,8 +307,7 @@ func get_app_info() -> Dictionary[String, Variant]: result[key] = arr else: - if (raw_value.begins_with('"') and raw_value.ends_with('"')) or\ - (raw_value.begins_with("'") and raw_value.ends_with("'")): + if (raw_value.begins_with('"') and raw_value.ends_with('"')) or (raw_value.begins_with("'") and raw_value.ends_with("'")): result[key] = raw_value.substr(1, raw_value.length() - 2) elif raw_value.is_valid_int(): result[key] = raw_value.to_int() diff --git a/src/ui_parts/code_editor.gd b/src/ui_parts/code_editor.gd index 4c5018b..3cf6937 100644 --- a/src/ui_parts/code_editor.gd +++ b/src/ui_parts/code_editor.gd @@ -7,6 +7,10 @@ extends VBoxContainer @onready var options_button: Button = %MetaActions/OptionsButton func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("copy_svg_text", func() -> void: DisplayServer.clipboard_set(State.svg_text)) + HandlerGUI.register_shortcuts(self, shortcuts) + Configs.theme_changed.connect(sync_theming) sync_theming() State.parsing_finished.connect(update_error) @@ -109,8 +113,7 @@ func _on_options_button_pressed() -> void: btn_array.append(ContextPopup.create_shortcut_button("copy_svg_text")) var context_popup := ContextPopup.new() context_popup.setup(btn_array, true) - HandlerGUI.popup_under_rect_center(context_popup, options_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, options_button.get_global_rect(), get_viewport()) func update_syntax_highlighter() -> void: diff --git a/src/ui_parts/code_editor.tscn b/src/ui_parts/code_editor.tscn index d68f8b5..1d9d116 100644 --- a/src/ui_parts/code_editor.tscn +++ b/src/ui_parts/code_editor.tscn @@ -42,6 +42,7 @@ theme_override_constants/separation = -2 layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +indent_wrapped_lines = true script = ExtResource("8_ser4i") [node name="ErrorBar" type="PanelContainer" parent="ScriptEditor"] diff --git a/src/ui_parts/current_file_button.gd b/src/ui_parts/current_file_button.gd index b1c97df..3827af4 100644 --- a/src/ui_parts/current_file_button.gd +++ b/src/ui_parts/current_file_button.gd @@ -24,6 +24,5 @@ func _on_file_button_pressed() -> void: func update_file_button() -> void: var transient_tab_path := State.transient_tab_path - text = transient_tab_path.get_file() if not transient_tab_path.is_empty() else\ - Configs.savedata.get_active_tab().presented_name + text = transient_tab_path.get_file() if not transient_tab_path.is_empty() else Configs.savedata.get_active_tab().presented_name Utils.set_max_text_width(self, 140.0, 12.0) diff --git a/src/ui_parts/display.gd b/src/ui_parts/display.gd index b2b22f0..cf887af 100644 --- a/src/ui_parts/display.gd +++ b/src/ui_parts/display.gd @@ -15,8 +15,6 @@ const NumberEdit = preload("res://src/ui_widgets/number_edit.gd") var tabs_panel: PanelContainer -var reference_overlay := false - func _ready() -> void: Configs.language_changed.connect(sync_localization) sync_localization() @@ -54,19 +52,19 @@ func update_snap_config() -> void: func _on_reference_pressed() -> void: + var has_reference := is_instance_valid(reference_texture.texture) var btn_arr: Array[Button] = [ ContextPopup.create_shortcut_button("load_reference"), ContextPopup.create_button(Translator.translate("Paste reference image"), paste_reference_image, not Utils.has_clipboard_image_web_safe(), load("res://assets/icons/Paste.svg")), - ContextPopup.create_shortcut_checkbox("view_show_reference", reference_texture.visible), - ContextPopup.create_shortcut_checkbox("view_overlay_reference", reference_overlay) + ContextPopup.create_shortcut_checkbox("view_show_reference", State.show_reference and has_reference, not has_reference), + ContextPopup.create_shortcut_checkbox("view_overlay_reference", State.overlay_reference and has_reference, not has_reference) ] var reference_popup := ContextPopup.new() reference_popup.setup(btn_arr, true) - HandlerGUI.popup_under_rect_center(reference_popup, reference_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(reference_popup, reference_button.get_global_rect(), get_viewport()) func paste_reference_image() -> void: FileUtils.load_reference_from_image(DisplayServer.clipboard_get_image()) @@ -91,8 +89,7 @@ func sync_reference_image() -> void: reference_texture.hide() func _on_snap_button_toggled(toggled_on: bool) -> void: - Configs.savedata.snap = absf(Configs.savedata.snap) if toggled_on\ - else -absf(Configs.savedata.snap) + Configs.savedata.snap = absf(Configs.savedata.snap) if toggled_on else -absf(Configs.savedata.snap) func _on_snap_number_edit_value_changed(new_value: float) -> void: Configs.savedata.snap = new_value * signf(Configs.savedata.snap) @@ -110,8 +107,7 @@ func _on_show_debug_changed() -> void: func update_debug() -> void: var debug_text := "" debug_text += "FPS: %d\n" % Performance.get_monitor(Performance.TIME_FPS) - debug_text += "Static Mem: %s\n" % String.humanize_size(int(Performance.get_monitor( - Performance.MEMORY_STATIC))) + debug_text += "Static Mem: %s\n" % String.humanize_size(int(Performance.get_monitor(Performance.MEMORY_STATIC))) debug_text += "Nodes: %d\n" % Performance.get_monitor(Performance.OBJECT_NODE_COUNT) debug_text += "Stray nodes: %d\n" % Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT) debug_text += "Objects: %d\n" % Performance.get_monitor(Performance.OBJECT_COUNT) diff --git a/src/ui_parts/donate_menu.gd b/src/ui_parts/donate_menu.gd index 64ca28f..5e79c86 100644 --- a/src/ui_parts/donate_menu.gd +++ b/src/ui_parts/donate_menu.gd @@ -48,12 +48,12 @@ func _on_margin_container_gui_input(event: InputEvent) -> void: var hbox_pos := hbox.position - if (current_link == Link.GITHUB and not Rect2(hbox_pos + github_link.position - Vector2(13, 13), - github_link.size + Vector2(26, 26)).has_point(event.position)) or\ - (current_link == Link.KO_FI and not Rect2(hbox_pos + ko_fi_link.position - Vector2(13, 13), - ko_fi_link.size + Vector2(26, 26)).has_point(event.position)) or\ - (current_link == Link.PATREON and not Rect2(hbox_pos + patreon_link.position - Vector2(13, 13), - patreon_link.size + Vector2(26, 26)).has_point(event.position)): + var padding := Vector2(13, 13) + var double_padding := padding * 2.0 + + if (current_link == Link.GITHUB and not Rect2(hbox_pos + github_link.position - padding, github_link.size + double_padding).has_point(event.position)) or\ + (current_link == Link.KO_FI and not Rect2(hbox_pos + ko_fi_link.position - padding, ko_fi_link.size + double_padding).has_point(event.position)) or\ + (current_link == Link.PATREON and not Rect2(hbox_pos + patreon_link.position - padding, patreon_link.size + double_padding).has_point(event.position)): set_link(Link.NONE) @@ -72,8 +72,7 @@ func set_link(new_link: Link) -> void: match new_link: Link.GITHUB: title = "Github Sponsors" - pros = PackedStringArray(["Low extra fees", "Can donate an arbitrary amount", - "Includes all perks"]) + pros = PackedStringArray(["Low extra fees", "Can donate an arbitrary amount", "Includes all perks"]) cons = PackedStringArray() Link.KO_FI: title = "Ko-Fi" diff --git a/src/ui_parts/editor_scene.gd b/src/ui_parts/editor_scene.gd index 34168f9..b3c6ac9 100644 --- a/src/ui_parts/editor_scene.gd +++ b/src/ui_parts/editor_scene.gd @@ -11,6 +11,71 @@ var main_splitter: SplitContainer func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("view_show_grid", State.toggle_show_grid, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("view_show_handles", State.toggle_show_handles, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("view_rasterized_svg", State.toggle_view_rasterized, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("view_show_reference", State.toggle_show_reference, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("view_overlay_reference", State.toggle_overlay_reference, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("load_reference", FileUtils.open_image_import_dialog, ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("toggle_snap", func() -> void: Configs.savedata.snap *= -1, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("import", FileUtils.open_svg_import_dialog, ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("export", HandlerGUI.open_export, ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("save", FileUtils.save_svg, ShortcutsRegistration.Behavior.PASS_THROUGH_AND_PRESERVE_POPUPS) + shortcuts.add_shortcut("save_as", FileUtils.save_svg_as, ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_tab", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index()), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_all_other_tabs", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index(), FileUtils.TabCloseMode.ALL_OTHERS), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_tabs_to_left", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index(), FileUtils.TabCloseMode.TO_LEFT), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_tabs_to_right", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index(), FileUtils.TabCloseMode.TO_RIGHT), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_empty_tabs", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index(), FileUtils.TabCloseMode.EMPTY), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("close_saved_tabs", func() -> void: FileUtils.close_tabs(Configs.savedata.get_active_tab_index(), FileUtils.TabCloseMode.SAVED), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("new_tab", Configs.savedata.add_empty_tab, ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("select_next_tab", + func() -> void: Configs.savedata.set_active_tab_index(posmod(Configs.savedata.get_active_tab_index() + 1, Configs.savedata.get_tab_count())), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("select_previous_tab", + func() -> void: Configs.savedata.set_active_tab_index(posmod(Configs.savedata.get_active_tab_index() - 1, Configs.savedata.get_tab_count())), + ShortcutsRegistration.Behavior.PASS_THROUGH_POPUPS) + shortcuts.add_shortcut("optimize", State.optimize, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("reset_svg", FileUtils.reset_svg, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("debug", State.toggle_show_debug) + shortcuts.add_shortcut("ui_undo", func() -> void: Configs.savedata.get_active_tab().undo(), ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("ui_redo", func() -> void: Configs.savedata.get_active_tab().redo(), ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("ui_cancel", State.clear_all_selections, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("delete", State.delete_selected, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("move_up", State.move_up_selected, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("move_down", State.move_down_selected, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("duplicate", State.duplicate_selected, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + shortcuts.add_shortcut("select_all", State.select_all, ShortcutsRegistration.Behavior.STRICT_NO_PASSTHROUGH) + + shortcuts.add_shortcut("move_absolute", State.respond_to_key_input.bind("M")) + shortcuts.add_shortcut("move_relative", State.respond_to_key_input.bind("m")) + shortcuts.add_shortcut("line_absolute", State.respond_to_key_input.bind("L")) + shortcuts.add_shortcut("line_relative", State.respond_to_key_input.bind("l")) + shortcuts.add_shortcut("horizontal_line_absolute", State.respond_to_key_input.bind("H")) + shortcuts.add_shortcut("horizontal_line_relative", State.respond_to_key_input.bind("h")) + shortcuts.add_shortcut("vertical_line_absolute", State.respond_to_key_input.bind("V")) + shortcuts.add_shortcut("vertical_line_relative", State.respond_to_key_input.bind("v")) + shortcuts.add_shortcut("close_path_absolute", State.respond_to_key_input.bind("Z")) + shortcuts.add_shortcut("close_path_relative", State.respond_to_key_input.bind("z")) + shortcuts.add_shortcut("elliptical_arc_absolute", State.respond_to_key_input.bind("A")) + shortcuts.add_shortcut("elliptical_arc_relative", State.respond_to_key_input.bind("a")) + shortcuts.add_shortcut("cubic_bezier_absolute", State.respond_to_key_input.bind("C")) + shortcuts.add_shortcut("cubic_bezier_relative", State.respond_to_key_input.bind("c")) + shortcuts.add_shortcut("shorthand_cubic_bezier_absolute", State.respond_to_key_input.bind("S")) + shortcuts.add_shortcut("shorthand_cubic_bezier_relative", State.respond_to_key_input.bind("s")) + shortcuts.add_shortcut("quadratic_bezier_absolute", State.respond_to_key_input.bind("Q")) + shortcuts.add_shortcut("quadratic_bezier_relative", State.respond_to_key_input.bind("q")) + shortcuts.add_shortcut("shorthand_quadratic_bezier_absolute", State.respond_to_key_input.bind("T")) + shortcuts.add_shortcut("shorthand_quadratic_bezier_relative", State.respond_to_key_input.bind("t")) + HandlerGUI.register_shortcuts(self, shortcuts) + Configs.layout_changed.connect(update_layout) Configs.orientation_changed.connect(update_orientation) update_layout() @@ -120,8 +185,7 @@ func update_layout() -> void: btn.toggled.connect(func(_toggled_on: bool) -> void: layout_nodes[node_part].visible = (node_part == part)) if part == Utils.LayoutPart.INSPECTOR: - State.requested_scroll_to_selection.connect( - btn.set_pressed.bind(true).unbind(2)) + State.requested_scroll_to_selection.connect(btn.set_pressed.bind(true).unbind(2)) buttons_hbox.add_child(btn) if i == 0: btn.button_pressed = true diff --git a/src/ui_parts/element_container.gd b/src/ui_parts/element_container.gd index 996bbb8..8e89568 100644 --- a/src/ui_parts/element_container.gd +++ b/src/ui_parts/element_container.gd @@ -51,8 +51,7 @@ func update_proposed_xid() -> void: var xnode_rect := get_xnode_editor_rect(xnode.xid) var xnode_start := xnode_rect.position.y var xnode_end := xnode_rect.end.y - var buffer := minf(xnode_rect.size.y / 3, 26) if xnode.is_element() else\ - xnode_rect.size.y / 2 + 1 + var buffer := minf(xnode_rect.size.y / 3, 26) if xnode.is_element() else xnode_rect.size.y / 2 + 1 if y_pos < xnode_end and xnode_end < next_y: next_y = xnode_end next_xid = xnode.xid @@ -67,8 +66,7 @@ func update_proposed_xid() -> void: if in_top_buffer: State.set_proposed_drop_xid(prev_xid) elif in_bottom_buffer: - State.set_proposed_drop_xid(XIDUtils.get_parent_xid(next_xid) +\ - PackedInt32Array([next_xid[-1] + 1])) + State.set_proposed_drop_xid(XIDUtils.get_parent_xid(next_xid) + PackedInt32Array([next_xid[-1] + 1])) elif next_xid[0] >= State.root_element.get_child_count(): State.set_proposed_drop_xid(next_xid) elif XIDUtils.is_parent_or_self(prev_xid, next_xid): @@ -80,8 +78,7 @@ func update_proposed_xid() -> void: func _notification(what: int) -> void: # TODO This stuff easily passes through on unrelated drag & drops. What to do?! - if is_inside_tree() and visible and HandlerGUI.menu_stack.is_empty() and\ - HandlerGUI.popup_stack.is_empty(): + if is_inside_tree() and visible and HandlerGUI.menu_stack.is_empty() and HandlerGUI.popup_stack.is_empty(): if what == NOTIFICATION_DRAG_BEGIN: set_dragging(true) update_proposed_xid() @@ -92,25 +89,20 @@ func _notification(what: int) -> void: func _gui_input(event: InputEvent) -> void: if event is InputEventMouseButton: - if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() and\ - not (event.ctrl_pressed or event.shift_pressed): + if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() and not (event.ctrl_pressed or event.shift_pressed): State.clear_all_selections() elif event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): # Find where the new element should be added. var location := 0 var y_pos := get_local_mouse_position().y + scroll_container.scroll_vertical - while location < State.root_element.get_child_count() and\ - get_xnode_editor_rect(PackedInt32Array([location])).end.y < y_pos: + while location < State.root_element.get_child_count() and get_xnode_editor_rect(PackedInt32Array([location])).end.y < y_pos: location += 1 # Create the context popup. var btn_array: Array[Button] = [] - const CONST_ARR: PackedStringArray = ["path", "circle", "ellipse", "rect", - "line", "polygon", "polyline", "g", "linearGradient", "radialGradient", - "stop"] + const CONST_ARR: PackedStringArray = ["path", "circle", "ellipse", "rect", "line", "polygon", "polyline", + "g", "linearGradient", "radialGradient", "stop"] for element_name in CONST_ARR: - var btn := ContextPopup.create_button(element_name, - add_element.bind(element_name, location), false, - DB.get_element_icon(element_name)) + var btn := ContextPopup.create_button(element_name, add_element.bind(element_name, location), false, DB.get_element_icon(element_name)) btn.add_theme_font_override("font", ThemeUtils.mono_font) btn_array.append(btn) @@ -140,14 +132,12 @@ func get_xnode_editor_rect(xid: PackedInt32Array, inner_index := -1) -> Rect2: if not is_instance_valid(xnode_editor): return Rect2() - var xnode_pos := Vector2(xnode_editor.global_position -\ - scroll_container.global_position) + Vector2(0, scroll_container.scroll_vertical) + var xnode_pos := Vector2(xnode_editor.global_position - scroll_container.global_position) + Vector2(0, scroll_container.scroll_vertical) if inner_index == -1: return Rect2(xnode_pos, xnode_editor.size) else: - var inner_rect: Rect2 = xnode_editor.get_inner_rect(inner_index) if\ - State.root_element.get_xnode(xid).is_element() else Rect2() + var inner_rect: Rect2 = xnode_editor.get_inner_rect(inner_index) if State.root_element.get_xnode(xid).is_element() else Rect2() return Rect2(xnode_pos + inner_rect.position, inner_rect.size) # This function assumes there exists an element editor for the corresponding XID. @@ -156,5 +146,4 @@ func scroll_to_view_element_editor(xid: PackedInt32Array, inner_idx := -1) -> vo # since last being visible. # TODO The frame delay is quite noticable and that's sad. Look for another solution. await get_tree().process_frame - scroll_container.get_v_scroll_bar().value =\ - get_xnode_editor_rect(xid, inner_idx).position.y - scroll_container.size.y / 5 + scroll_container.get_v_scroll_bar().value = get_xnode_editor_rect(xid, inner_idx).position.y - scroll_container.size.y / 5 diff --git a/src/ui_parts/export_menu.gd b/src/ui_parts/export_menu.gd index d3aad73..c12826b 100644 --- a/src/ui_parts/export_menu.gd +++ b/src/ui_parts/export_menu.gd @@ -29,6 +29,11 @@ var dimensions := Vector2.ZERO func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("ui_undo", undo_redo.undo) + shortcuts.add_shortcut("ui_redo", undo_redo.redo) + HandlerGUI.register_shortcuts(self, shortcuts) + final_size_label.add_theme_color_override("font_color", ThemeUtils.subtle_text_color) cancel_button.pressed.connect(queue_free) export_button.pressed.connect(_on_export_button_pressed) @@ -47,26 +52,21 @@ func _ready() -> void: # Update dimensions label. dimensions = State.root_element.get_size() - dimensions_label.text = Translator.translate("Dimensions") + ": " +\ - get_dimensions_text(dimensions) + dimensions_label.text = Translator.translate("Dimensions") + ": " + get_dimensions_text(dimensions) update() export_data.changed.connect(update) # Setup the warning for when the image is too big to have a preview. var scaling_factor := texture_preview.MAX_IMAGE_DIMENSION / bigger_dimension - info_tooltip.tooltip_text = Translator.translate( - "Preview image size is limited to {dimensions}").format( - {"dimensions": get_dimensions_text(Vector2( - maxf(dimensions.x * scaling_factor, 1.0), - maxf(dimensions.y * scaling_factor, 1.0)), true)}) + info_tooltip.tooltip_text = Translator.translate("Preview image size is limited to {dimensions}").format( + {"dimensions": get_dimensions_text(Vector2(maxf(dimensions.x * scaling_factor, 1.0), maxf(dimensions.y * scaling_factor, 1.0)), true)}) info_tooltip.modulate = ThemeUtils.info_icon_color if Configs.savedata.get_active_tab().svg_file_path.is_empty(): file_title.add_theme_color_override("font_color", ThemeUtils.subtle_text_color) file_title.text = Configs.savedata.get_active_tab().presented_name - final_size_label.text = Translator.translate("Size") + ": " +\ - String.humanize_size(State.get_export_text().length()) + final_size_label.text = Translator.translate("Size") + ": " + String.humanize_size(State.get_export_text().length()) %TitleLabel.text = Translator.translate("Export Configuration") %FormatHBox/Label.text = Translator.translate("Format") + ":" %LosslessCheckBox.text = Translator.translate("Lossless") @@ -133,8 +133,7 @@ func _on_height_edit_value_changed(new_value: float) -> void: func update() -> void: # Determine which fields are visible. quality_related_container.visible = export_data.format in ["jpg", "jpeg", "webp"] - quality_hbox.visible = export_data.format in ["jpg", "jpeg"] or\ - export_data.format == "webp" and export_data.lossy + quality_hbox.visible = export_data.format in ["jpg", "jpeg"] or export_data.format == "webp" and export_data.lossy lossless_checkbox.visible = (export_data.format == "webp") size_container.visible = export_data.format in ["png", "jpg", "jpeg", "webp"] @@ -152,8 +151,7 @@ func update() -> void: # Sync width, height, and scale without affecting the upscale amount. width_edit.set_value(roundi(dimensions.x * export_data.upscale_amount), false) height_edit.set_value(roundi(dimensions.y * export_data.upscale_amount), false) - if roundi(dimensions.x * scale_edit.get_value()) != width_edit.get_value() and\ - roundi(dimensions.y * scale_edit.get_value()) != height_edit.get_value(): + if roundi(dimensions.x * scale_edit.get_value()) != width_edit.get_value() and roundi(dimensions.y * scale_edit.get_value()) != height_edit.get_value(): scale_edit.set_value(export_data.upscale_amount, false) # Sync all other widgets, so they are updated on changes from UndoRedo too. quality_edit.set_value(export_data.quality * 100, false) @@ -161,22 +159,8 @@ func update() -> void: format_dropdown.set_value(export_data.format, false) info_tooltip.visible = (export_data.format != "svg" and\ - roundi(export_data.upscale_amount * maxf(dimensions.x, dimensions.y)) >\ - texture_preview.MAX_IMAGE_DIMENSION) + roundi(export_data.upscale_amount * maxf(dimensions.x, dimensions.y)) > texture_preview.MAX_IMAGE_DIMENSION) func get_dimensions_text(sides: Vector2, integer := false) -> String: var precision := 0 if integer else 2 - return "%s×%s" % [Utils.num_simple(sides.x, precision), - Utils.num_simple(sides.y, precision)] - - -func _unhandled_input(event: InputEvent) -> void: - if not visible: - return - - if ShortcutUtils.is_action_pressed(event, "ui_undo"): - undo_redo.undo() - accept_event() - elif ShortcutUtils.is_action_pressed(event, "ui_redo"): - undo_redo.redo() - accept_event() + return "%s×%s" % [Utils.num_simple(sides.x, precision), Utils.num_simple(sides.y, precision)] diff --git a/src/ui_parts/eyedropper_popup.gd b/src/ui_parts/eyedropper_popup.gd index 2ec8178..41df2cf 100644 --- a/src/ui_parts/eyedropper_popup.gd +++ b/src/ui_parts/eyedropper_popup.gd @@ -43,8 +43,7 @@ func _draw() -> void: var frsq := FRAME_RADIUS * FRAME_RADIUS for x in range(ceili(-FRAME_RADIUS / 7.0), ceili(FRAME_RADIUS / 7.0)): for y in range(ceili(-FRAME_RADIUS / 7.0), ceili(FRAME_RADIUS / 7.0)): - if texture_pos.x + x < 0 or texture_pos.x + x >= texture.get_width() or\ - texture_pos.y + y < 0 or texture_pos.y + y >= texture.get_height(): + if texture_pos.x + x < 0 or texture_pos.x + x >= texture.get_width() or texture_pos.y + y < 0 or texture_pos.y + y >= texture.get_height(): continue var l := (x - 0.5) * PIXEL_SIZE - 0.5 @@ -63,8 +62,7 @@ func _draw() -> void: var bottom := clampf(pos.y + b, pos.y - max_vertical, pos.y + max_vertical) if left < right and top < bottom: - draw_rect(Rect2(Vector2(left, top), Vector2(right - left, bottom - top)), - texture_image.get_pixelv(texture_pos + Vector2(x, y))) + draw_rect(Rect2(Vector2(left, top), Vector2(right - left, bottom - top)), texture_image.get_pixelv(texture_pos + Vector2(x, y))) var grid_points := PackedVector2Array() for i in range(ceili(-FRAME_RADIUS / 7.0), ceili(FRAME_RADIUS / 7.0)): @@ -78,20 +76,15 @@ func _draw() -> void: var theme_color := Color(0.9, 0.9, 0.9) - draw_circle(pos, FRAME_RADIUS + FRAME_WIDTH / 2.0, theme_color, false, FRAME_WIDTH, - true) - draw_rect(Rect2(pos - Vector2(1, 1) * (PIXEL_SIZE / 2.0 + 0.5), - Vector2(1, 1) * PIXEL_SIZE), Color.WHITE, false, 1.0) - draw_rect(Rect2(pos - Vector2(1, 1) * (PIXEL_SIZE / 2.0 + 1.5), - Vector2(1, 1) * (PIXEL_SIZE + 2)), Color.BLACK, false, 1.0) + draw_circle(pos, FRAME_RADIUS + FRAME_WIDTH / 2.0, theme_color, false, FRAME_WIDTH, true) + draw_rect(Rect2(pos - Vector2(1, 1) * (PIXEL_SIZE / 2.0 + 0.5), Vector2(1, 1) * PIXEL_SIZE), Color.WHITE, false, 1.0) + draw_rect(Rect2(pos - Vector2(1, 1) * (PIXEL_SIZE / 2.0 + 1.5), Vector2(1, 1) * (PIXEL_SIZE + 2)), Color.BLACK, false, 1.0) var stylebox_width := FRAME_RADIUS * 2 var stylebox_height := 25 var stylebox_vertical_offset := FRAME_RADIUS - var stylebox_corner := Vector2(clampf(pos.x - FRAME_RADIUS, 0.0, - size.x - stylebox_width), pos.y + (stylebox_vertical_offset if\ - (pos.y + stylebox_vertical_offset + stylebox_height <= size.y) else\ - -stylebox_vertical_offset - stylebox_height)) + var stylebox_corner := Vector2(clampf(pos.x - FRAME_RADIUS, 0.0, size.x - stylebox_width), pos.y + (stylebox_vertical_offset if\ + (pos.y + stylebox_vertical_offset + stylebox_height <= size.y) else -stylebox_vertical_offset - stylebox_height)) var stylebox := StyleBoxFlat.new() stylebox.set_corner_radius_all(4) @@ -99,8 +92,7 @@ func _draw() -> void: stylebox.draw(ci, Rect2(stylebox_corner, Vector2(stylebox_width, stylebox_height))) color = texture_image.get_pixelv(texture_pos) - ThemeUtils.mono_font.draw_string(ci, stylebox_corner + Vector2(26, 19), "#" +\ - color.to_html(false), HORIZONTAL_ALIGNMENT_LEFT, -1, 16, Color.BLACK) + ThemeUtils.mono_font.draw_string(ci, stylebox_corner + Vector2(26, 19), "#" + color.to_html(false), HORIZONTAL_ALIGNMENT_LEFT, -1, 16, Color.BLACK) draw_rect(Rect2(stylebox_corner + Vector2(5, 5), Vector2(15, 15)), color) var border := Color.WHITE if color.get_luminance() > 0.455: diff --git a/src/ui_parts/good_file_dialog.gd b/src/ui_parts/good_file_dialog.gd index dedf846..f01be83 100644 --- a/src/ui_parts/good_file_dialog.gd +++ b/src/ui_parts/good_file_dialog.gd @@ -95,7 +95,16 @@ new_extensions: PackedStringArray) -> void: func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("find", func() -> void: search_button.button_pressed = not search_button.button_pressed) + shortcuts.add_shortcut("ui_accept", func() -> void: + var selected_item_indices := file_list.get_selected_items() + if not selected_item_indices.is_empty(): + call_activation_callback(file_list.get_item_metadata(selected_item_indices[0]))) + HandlerGUI.register_shortcuts(self, shortcuts) + # Signal connections. + file_field.text_changed.connect(_on_file_field_text_changed) folder_up_button.pressed.connect(_on_folder_up_button_pressed) file_list.item_selected.connect(_on_file_list_item_selected) file_list.multi_selected.connect(_on_file_list_item_multi_selected) @@ -118,8 +127,7 @@ func _ready() -> void: show_hidden_button.set_pressed_no_signal(true) folder_up_button.tooltip_text = Translator.translate("Go to parent folder") refresh_button.tooltip_text = Translator.translate("Refresh files") - show_hidden_button.tooltip_text =\ - Translator.translate("Toggle the visibility of hidden files") + show_hidden_button.tooltip_text = Translator.translate("Toggle the visibility of hidden files") search_button.tooltip_text = Translator.translate("Search files") search_field.placeholder_text = Translator.translate("Search files") @@ -131,8 +139,7 @@ func _ready() -> void: mode == FileMode.MULTI_SELECT, extensions) close_button.text = Translator.translate("Close") - special_button.text = Translator.translate("Save") if\ - mode == FileMode.SAVE else Translator.translate("Select") + special_button.text = Translator.translate("Save") if mode == FileMode.SAVE else Translator.translate("Select") path_label.text = Translator.translate("Path") + ":" # Should always be safe. @@ -151,7 +158,10 @@ func file_sort(file1: String, file2: String) -> bool: func refresh_dir() -> void: open_dir(current_dir) -func open_dir(dir: String) -> void: +func update_filtering() -> void: + open_dir(current_dir, true) + +func open_dir(dir: String, only_filtering_update := false) -> void: if dir != current_dir and search_button.button_pressed: search_button.button_pressed = false @@ -164,8 +174,11 @@ func open_dir(dir: String) -> void: file_list.get_v_scroll_bar().value = 0 # Basic setup. current_dir = dir - sync_to_selection() - sync_path_field() + + if not only_filtering_update: + sync_to_selection() + sync_path_field() + dir_cursor.include_hidden = Configs.savedata.file_dialog_show_hidden # Rebuild the system dirs, as we may now need to highlight the current one. drives_list.clear() @@ -177,8 +190,7 @@ func open_dir(dir: String) -> void: var item_idx := drives_list.add_item(drive_name, get_drive_icon(drive_path)) drives_list.set_item_icon_modulate(item_idx, ThemeUtils.tinted_contrast_color) - drives_list.set_item_metadata(item_idx, - Actions.new(Callable(), open_dir.bind(drive_path))) + drives_list.set_item_metadata(item_idx, Actions.new(Callable(), open_dir.bind(drive_path))) if current_dir == drive_path: drives_list.select(item_idx) drives_list.sort_items_by_text() @@ -206,17 +218,14 @@ func open_dir(dir: String) -> void: continue var item_idx := file_list.add_item(directory, folder_icon) var dir_path := current_dir.path_join(directory) - file_list.set_item_metadata(item_idx, Actions.new( - open_dir.bind(dir_path), sync_to_selection, open_dir_context.bind(dir_path))) + file_list.set_item_metadata(item_idx, Actions.new(open_dir.bind(dir_path), sync_to_selection, open_dir_context.bind(dir_path))) for file in files: - if not file.get_extension() in extensions or\ - (not search_text.is_empty() and not search_text.is_subsequence_ofn(file)): + if not file.get_extension() in extensions or (not search_text.is_empty() and not search_text.is_subsequence_ofn(file)): continue var item_idx := file_list.add_item(file, null) - file_list.set_item_metadata(item_idx, Actions.new( - select_files, sync_to_selection, open_file_context)) + file_list.set_item_metadata(item_idx, Actions.new(select_files, sync_to_selection, open_file_context)) # If we don't await this stuff, sometimes the item_rect we get is all wrong. await file_list.draw await get_tree().process_frame @@ -245,8 +254,7 @@ func _setup_file_images() -> void: 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 !is_instance_valid(file_list.get_item_icon(item_idx)) and\ - file_rect.end.y > visible_start and file_rect.position.y < visible_end: + if !is_instance_valid(file_list.get_item_icon(item_idx)) 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(): "xml": @@ -259,8 +267,7 @@ func _setup_file_images() -> void: if !is_instance_valid(img) or img.is_empty(): file_list.set_item_icon(item_idx, broken_file_icon) else: - var svg_texture := SVGTexture.create_from_string(svg_text, - minf(item_height / img.get_width(), item_height / img.get_height())) + var svg_texture := SVGTexture.create_from_string(svg_text, minf(item_height / img.get_width(), item_height / img.get_height())) file_list.set_item_icon(item_idx, svg_texture) _: var img := Image.load_from_file(current_dir.path_join(file)) @@ -287,19 +294,21 @@ func select_files() -> void: func sync_to_selection() -> void: file_list.ensure_current_is_visible() - if mode != FileMode.SAVE: - var paths := get_selected_file_paths() - if paths.is_empty(): - set_special_button_enabled(false) - else: - var has_folders := false - for path in paths: - if path.get_extension().is_empty(): - has_folders = true - break - set_special_button_enabled(not has_folders) - else: + if mode == FileMode.SAVE: sync_file_field() + return + + var paths := get_selected_file_paths() + if paths.is_empty(): + set_special_button_enabled(false) + return + + var has_folders := false + for path in paths: + if path.get_extension().is_empty(): + has_folders = true + break + set_special_button_enabled(not has_folders) func set_special_button_enabled(enabled: bool) -> void: if enabled: @@ -321,8 +330,7 @@ func copy_file_path() -> void: func create_folder() -> void: var create_folder_dialog := ChooseNameDialogScene.instantiate() HandlerGUI.add_dialog(create_folder_dialog) - create_folder_dialog.setup(Translator.translate("Create new folder"), - _on_create_folder_finished, _create_folder_error) + create_folder_dialog.setup(Translator.translate("Create new folder"), _on_create_folder_finished, _create_folder_error) func _create_folder_error(text: String) -> String: if text.is_empty(): @@ -429,7 +437,7 @@ func _on_search_button_toggled(toggled_on: bool) -> void: else: search_field.hide() search_field.clear() - refresh_dir() + update_filtering() func _on_file_field_text_submitted(new_text: String) -> void: @@ -451,7 +459,7 @@ func sync_path_field() -> void: func _on_search_field_text_changed(new_text: String) -> void: search_text = new_text - refresh_dir() + update_filtering() func _on_search_field_text_change_canceled() -> void: search_field.text = search_text @@ -461,6 +469,9 @@ func _on_file_field_text_changed(new_text: String) -> void: set_special_button_enabled(not new_text.is_empty() and is_valid_filename) file_field.add_theme_color_override("font_color", Configs.savedata.get_validity_color(not is_valid_filename)) + if search_button.button_pressed: + # Toggling search off will refresh the directory. + search_button.button_pressed = false func _on_file_field_text_change_canceled() -> void: file_field.remove_theme_color_override("font_color") @@ -492,13 +503,3 @@ func get_drive_icon(path: String) -> Texture2D: return load("res://assets/icons/DirPictures.svg") else: return folder_icon - -func _unhandled_input(event: InputEvent) -> void: - if ShortcutUtils.is_action_pressed(event, "find"): - search_button.button_pressed = not search_button.button_pressed - accept_event() - elif event.is_action_pressed("ui_accept"): - var selected_item_indices := file_list.get_selected_items() - if not selected_item_indices.is_empty(): - call_activation_callback(file_list.get_item_metadata(selected_item_indices[0])) - accept_event() diff --git a/src/ui_parts/good_file_dialog.tscn b/src/ui_parts/good_file_dialog.tscn index f8c9696..09c59ba 100644 --- a/src/ui_parts/good_file_dialog.tscn +++ b/src/ui_parts/good_file_dialog.tscn @@ -146,5 +146,4 @@ mouse_default_cursor_shape = 2 [connection signal="item_activated" from="VBoxContainer/MainContainer/FilePicker/VisualPicker/FileList" to="." method="_on_file_list_item_activated"] [connection signal="item_clicked" from="VBoxContainer/MainContainer/FilePicker/VisualPicker/FileList" to="." method="_on_file_list_item_clicked"] [connection signal="text_change_canceled" from="VBoxContainer/MainContainer/FilePicker/FileContainer/FileField" to="." method="_on_file_field_text_change_canceled"] -[connection signal="text_changed" from="VBoxContainer/MainContainer/FilePicker/FileContainer/FileField" to="." method="_on_file_field_text_changed"] [connection signal="text_submitted" from="VBoxContainer/MainContainer/FilePicker/FileContainer/FileField" to="." method="_on_file_field_text_submitted"] diff --git a/src/ui_parts/handles_manager.gd b/src/ui_parts/handles_manager.gd index 38d0bce..efb9398 100644 --- a/src/ui_parts/handles_manager.gd +++ b/src/ui_parts/handles_manager.gd @@ -42,20 +42,17 @@ func render_handle_textures() -> void: var normal_str := "#" + Configs.savedata.handle_color.to_html(false) var hovered_str := "#" + Configs.savedata.handle_hovered_color.to_html(false) var selected_str := "#" + Configs.savedata.handle_selected_color.to_html(false) - var hovered_selected_str := "#" +\ - Configs.savedata.handle_hovered_selected_color.to_html(false) + var hovered_selected_str := "#" + Configs.savedata.handle_hovered_selected_color.to_html(false) var s := Configs.savedata.handle_size # Shorthand var img := Image.new() var handles_dict: Dictionary[Handle.Display, String] = { Handle.Display.BIG: """""" % [s * 10, s * 10, - s * 5, s * 5, s * 3.25, "%s", "%s", s * 1.5], + fill="%s" stroke="%s" stroke-width="%s"/>""" % [s * 10, s * 10, s * 5, s * 5, s * 3.25, "%s", "%s", s * 1.5], Handle.Display.SMALL: """""" % [s * 8, s * 8, - s * 4, s * 4, s * 2.4, "%s", "%s", s * 1.2], + fill="%s" stroke="%s" stroke-width="%s"/>""" % [s * 8, s * 8, s * 4, s * 4, s * 2.4, "%s", "%s", s * 1.2], } const CONST_ARR: Array[Handle.Display] = [Handle.Display.BIG, Handle.Display.SMALL] @@ -81,17 +78,12 @@ func sync_selection_rectangle_shader() -> void: stroke_material.shader = stroke_shader_static else: stroke_material.shader = stroke_shader - stroke_material.set_shader_parameter("ant_speed", - Configs.savedata.selection_rectangle_speed) + stroke_material.set_shader_parameter("ant_speed", Configs.savedata.selection_rectangle_speed) - stroke_material.set_shader_parameter("ant_color_1", - Configs.savedata.selection_rectangle_color1) - stroke_material.set_shader_parameter("ant_color_2", - Configs.savedata.selection_rectangle_color2) - stroke_material.set_shader_parameter("ant_width", - Configs.savedata.selection_rectangle_width) - stroke_material.set_shader_parameter("ant_length", - Configs.savedata.selection_rectangle_dash_length) + stroke_material.set_shader_parameter("ant_color_1", Configs.savedata.selection_rectangle_color1) + stroke_material.set_shader_parameter("ant_color_2", Configs.savedata.selection_rectangle_color2) + stroke_material.set_shader_parameter("ant_width", Configs.savedata.selection_rectangle_width) + stroke_material.set_shader_parameter("ant_length", Configs.savedata.selection_rectangle_dash_length) RenderingServer.canvas_item_set_material(selections_surface, stroke_material.get_rid()) animated_stroke_hacky_fix_node.material = stroke_material # If the ant width was changed, the buffer must be updated. @@ -227,8 +219,7 @@ func _draw() -> void: match element.name: "circle": - var c := Vector2(element.get_attribute_num("cx"), - element.get_attribute_num("cy")) + var c := Vector2(element.get_attribute_num("cx"), element.get_attribute_num("cy")) var r := element.get_attribute_num("r") var points := PackedVector2Array() @@ -262,17 +253,14 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) "ellipse": - var c := Vector2(element.get_attribute_num("cx"), - element.get_attribute_num("cy")) + var c := Vector2(element.get_attribute_num("cx"), element.get_attribute_num("cy")) # Squished circle. var points := PackedVector2Array() points.resize(181) @@ -280,8 +268,7 @@ func _draw() -> void: var d := i * TAU/180 points[i] = c + Vector2(cos(d) * element.get_rx(), sin(d) * element.get_ry()) points[180] = points[0] - var extras := PackedVector2Array([ - c, c + Vector2(element.get_rx(), 0), c, c + Vector2(0, element.get_ry())]) + var extras := PackedVector2Array([c, c + Vector2(element.get_rx(), 0), c, c + Vector2(0, element.get_ry())]) var final_transform := element.get_transform() points = final_transform * points extras = final_transform * extras @@ -306,13 +293,11 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) "rect": var x := element.get_attribute_num("x") @@ -324,9 +309,7 @@ func _draw() -> void: var points := PackedVector2Array() if rx == 0 or ry == 0: # Basic rectangle. - points = [Vector2(x, y), Vector2(x + rect_width, y), - Vector2(x + rect_width, y + rect_height), - Vector2(x, y + rect_height), Vector2(x, y)] + points = [Vector2(x, y), Vector2(x + rect_width, y), Vector2(x + rect_width, y + rect_height), Vector2(x, y + rect_height), Vector2(x, y)] else: if rx == 0: rx = ry @@ -340,26 +323,21 @@ func _draw() -> void: points[1] = Vector2(x + rect_width - rx, y) for i in range(135, 180): var d := i * TAU/180 - points[i - 133] = Vector2(x + rect_width - rx, y + ry) +\ - Vector2(cos(d) * rx, sin(d) * ry) + points[i - 133] = Vector2(x + rect_width - rx, y + ry) + Vector2(cos(d) * rx, sin(d) * ry) points[47] = Vector2(x + rect_width, y + rect_height - ry) for i in range(0, 45): var d := i * TAU/180 - points[i + 48] = Vector2(x + rect_width - rx, y + rect_height - ry) +\ - Vector2(cos(d) * rx, sin(d) * ry) + points[i + 48] = Vector2(x + rect_width - rx, y + rect_height - ry) + Vector2(cos(d) * rx, sin(d) * ry) points[93] = Vector2(x + rx, y + rect_height) for i in range(45, 90): var d := i * TAU/180 - points[i + 49] = Vector2(x + rx, y + rect_height - ry) +\ - Vector2(cos(d) * rx, sin(d) * ry) + points[i + 49] = Vector2(x + rx, y + rect_height - ry) + Vector2(cos(d) * rx, sin(d) * ry) points[139] = Vector2(x, y + ry) for i in range(90, 135): var d := i * TAU/180 - points[i + 50] = Vector2(x + rx, y + ry) +\ - Vector2(cos(d) * rx, sin(d) * ry) + points[i + 50] = Vector2(x + rx, y + ry) + Vector2(cos(d) * rx, sin(d) * ry) points[185] = points[0] - var extras := PackedVector2Array([Vector2(x, y), Vector2(x + rect_width, y), - Vector2(x, y), Vector2(x, y + rect_height)]) + var extras := PackedVector2Array([Vector2(x, y), Vector2(x + rect_width, y), Vector2(x, y), Vector2(x, y + rect_height)]) var final_transform := element.get_transform() points = final_transform * points extras = final_transform * extras @@ -384,13 +362,11 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) "line": var x1 := element.get_attribute_num("x1") @@ -417,13 +393,11 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) "polygon", "polyline": var point_list := ListParser.list_to_points(element.get_attribute_list("points")) @@ -478,18 +452,15 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) "path": var pathdata: AttributePathdata = element.get_attribute("d") - if pathdata.get_command_count() == 0 or\ - not pathdata.get_command(0).command_char in "Mm": + if pathdata.get_command_count() == 0 or not pathdata.get_command(0).command_char in "Mm": continue # Nothing to draw. var current_mode := Utils.InteractionType.NONE @@ -518,14 +489,12 @@ func _draw() -> void: "H": # Horizontal line contour. var v := Vector2(cmd.x, 0) - var end := cmd.get_start_coords() + v if\ - relative else Vector2(v.x, cmd.start_y) + var end := cmd.get_start_coords() + v if relative else Vector2(v.x, cmd.start_y) points = PackedVector2Array([cmd.get_start_coords(), end]) "V": # Vertical line contour. var v := Vector2(0, cmd.y) - var end := cmd.get_start_coords() + v if\ - relative else Vector2(cmd.start_x, v.y) + var end := cmd.get_start_coords() + v if relative else Vector2(cmd.start_x, v.y) points = PackedVector2Array([cmd.get_start_coords(), end]) "C": # Cubic Bezier curve contour. @@ -538,8 +507,7 @@ func _draw() -> void: var cp3 := v2 - v points = Utils.get_cubic_bezier_points(cp1, cp2, cp3, cp4) - tangent_points.append_array(PackedVector2Array([cp1, - cp1 + cp2, cp1 + v2 if relative else v2, cp4])) + tangent_points.append_array(PackedVector2Array([cp1, cp1 + cp2, cp1 + v2 if relative else v2, cp4])) "S": # Shorthand cubic Bezier curve contour. if cmd_idx == 0: @@ -555,8 +523,7 @@ func _draw() -> void: var cp3 := v2 - v points = Utils.get_cubic_bezier_points(cp1, cp2, cp3, cp4) - tangent_points.append_array(PackedVector2Array([cp1, - cp1 + cp2, cp1 + v2 if relative else v2, cp4])) + tangent_points.append_array(PackedVector2Array([cp1, cp1 + cp2, cp1 + v2 if relative else v2, cp4])) "Q": # Quadratic Bezier curve contour. var v := Vector2(cmd.x, cmd.y) @@ -580,8 +547,7 @@ func _draw() -> void: points = PackedVector2Array([cp1, cp3]) else: points = Utils.get_quadratic_bezier_points(cp1, cp2, cp3) - tangent_points.append_array( - PackedVector2Array([cp1, cp2, cp2, cp3])) + tangent_points.append_array(PackedVector2Array([cp1, cp2, cp2, cp3])) "A": # Elliptical arc contour. var start := cmd.get_start_coords() @@ -617,12 +583,10 @@ func _draw() -> void: sc = -sc var ct := Vector2(r.x * sc * y1 / r.y, -r.y * sc * x1 / r.x) - var c := Vector2(ct.x * cosine - ct.y * sine, - ct.x * sine + ct.y * cosine) + start.lerp(end, 0.5) + var c := Vector2(ct.x * cosine - ct.y * sine, ct.x * sine + ct.y * cosine) + start.lerp(end, 0.5) var tv := Vector2(x1 - ct.x, y1 - ct.y) / r var theta1 := tv.angle() - var delta_theta := fposmod(tv.angle_to( - Vector2(-x1 - ct.x, -y1 - ct.y) / r), TAU) + var delta_theta := fposmod(tv.angle_to(Vector2(-x1 - ct.x, -y1 - ct.y) / r), TAU) if cmd.sweep_flag == 0: theta1 += delta_theta delta_theta = TAU - delta_theta @@ -699,17 +663,14 @@ func _draw() -> void: var canvas_transform := State.root_element.canvas_transform var canvas_scale := canvas_transform.get_scale().x var element_scale := element_transform.get_scale() - var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) /\ - State.zoom / canvas_scale + var grow_amount_unscaled := (2.0 + Configs.savedata.selection_rectangle_width) / State.zoom / canvas_scale var grow_amount_x := grow_amount_unscaled / element_scale.x var grow_amount_y := grow_amount_unscaled / element_scale.y selection_transforms.append(canvas_transform * element_transform) - selection_rects.append(bounding_box.grow_individual(grow_amount_x, - grow_amount_y, grow_amount_x, grow_amount_y)) + selection_rects.append(bounding_box.grow_individual(grow_amount_x, grow_amount_y, grow_amount_x, grow_amount_y)) draw_set_transform_matrix(State.root_element.canvas_transform) - RenderingServer.canvas_item_set_transform(surface, Transform2D(0.0, - Vector2(1, 1) / State.zoom, 0.0, Vector2.ZERO)) + RenderingServer.canvas_item_set_transform(surface, Transform2D(0.0, Vector2(1, 1) / State.zoom, 0.0, Vector2.ZERO)) # First gather all handles in 4 categories, to then draw them in the right order. var normal_handles: Array[Handle] = [] @@ -737,23 +698,17 @@ func _draw() -> void: RenderingServer.canvas_item_clear(surface) RenderingServer.canvas_item_clear(selections_surface) - draw_objects_of_type(normal_color, normal_polylines, - normal_multiline, normal_handles, normal_handle_textures) - draw_objects_of_type(hovered_color, hovered_polylines, - hovered_multiline, hovered_handles, hovered_handle_textures) - draw_objects_of_type(selected_color, selected_polylines, - selected_multiline, selected_handles, selected_handle_textures) - draw_objects_of_type(hovered_selected_color, hovered_selected_polylines, - hovered_selected_multiline, hovered_selected_handles, + draw_objects_of_interaction_type(normal_color, normal_polylines, normal_multiline, normal_handles, normal_handle_textures) + draw_objects_of_interaction_type(hovered_color, hovered_polylines, hovered_multiline, hovered_handles, hovered_handle_textures) + draw_objects_of_interaction_type(selected_color, selected_polylines, selected_multiline, selected_handles, selected_handle_textures) + draw_objects_of_interaction_type(hovered_selected_color, hovered_selected_polylines, hovered_selected_multiline, hovered_selected_handles, hovered_selected_handle_textures) for idx in selection_rects.size(): - RenderingServer.canvas_item_add_set_transform(selections_surface, - selection_transforms[idx]) - RenderingServer.canvas_item_add_rect(selections_surface, selection_rects[idx], - Color.WHITE) + RenderingServer.canvas_item_add_set_transform(selections_surface, selection_transforms[idx]) + RenderingServer.canvas_item_add_rect(selections_surface, selection_rects[idx], Color.WHITE) -func draw_objects_of_type(color: Color, polylines: Array[PackedVector2Array], +func draw_objects_of_interaction_type(color: Color, polylines: Array[PackedVector2Array], multiline: PackedVector2Array, handles_array: Array[Handle], handle_texture_dictionary: Dictionary[Handle.Display, Texture2D]) -> void: for polyline in polylines: @@ -762,20 +717,17 @@ handle_texture_dictionary: Dictionary[Handle.Display, Texture2D]) -> void: color_array.fill(color) for idx in polyline.size(): polyline[idx] = State.root_element.canvas_to_world(polyline[idx]) * State.zoom - RenderingServer.canvas_item_add_polyline(surface, polyline, - color_array, CONTOUR_WIDTH, true) + RenderingServer.canvas_item_add_polyline(surface, polyline, color_array, CONTOUR_WIDTH, true) if not multiline.is_empty(): for idx in multiline.size(): multiline[idx] = State.root_element.canvas_to_world(multiline[idx]) * State.zoom var color_array := PackedColorArray() color_array.resize(int(multiline.size() / 2.0)) color_array.fill(Color(color, TANGENT_ALPHA)) - RenderingServer.canvas_item_add_multiline(surface, multiline, - color_array, TANGENT_WIDTH, true) + RenderingServer.canvas_item_add_multiline(surface, multiline, color_array, TANGENT_WIDTH, true) for handle in handles_array: var texture := handle_texture_dictionary[handle.display_mode] - texture.draw(surface, State.root_element.canvas_to_world( - handle.transform * handle.pos) * State.zoom - texture.get_size() / 2) + texture.draw(surface, State.root_element.canvas_to_world(handle.transform * handle.pos) * State.zoom - texture.get_size() / 2) var dragged_handle: Handle = null @@ -789,16 +741,13 @@ func _unhandled_input(event: InputEvent) -> void: hovered_handle = null # Mouse events on the viewport clear hovered, but other events don't. if ((event is InputEventMouseMotion and event.button_mask == 0) or\ - (event is InputEventMouseButton and (event.button_index in [MOUSE_BUTTON_LEFT, - MOUSE_BUTTON_RIGHT]))): + (event is InputEventMouseButton and (event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]))): State.clear_all_hovered() # Set the nearest handle as hovered, if any handles are within range. - if visible and ((event is InputEventMouseMotion and !is_instance_valid(dragged_handle) and\ - event.button_mask == 0) or (event is InputEventMouseButton and\ - (event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]))): - var nearest_handle := find_nearest_handle(event.position / State.zoom +\ - get_parent().get_parent().camera_position) + if visible and ((event is InputEventMouseMotion and !is_instance_valid(dragged_handle) and event.button_mask == 0) or\ + (event is InputEventMouseButton and (event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]))): + var nearest_handle := find_nearest_handle(event.position / State.zoom + get_parent().get_parent().camera_position) if is_instance_valid(nearest_handle): hovered_handle = nearest_handle if hovered_handle is PathHandle: @@ -843,14 +792,12 @@ func _unhandled_input(event: InputEvent) -> void: if event.double_click and inner_idx != -1: # Unselect the element, so then it's selected again in the subpath. if dragged_handle is PathHandle: - var subpath_range: Vector2i =\ - dragged_handle.element.get_attribute("d").get_subpath(inner_idx) + var subpath_range: Vector2i = dragged_handle.element.get_attribute("d").get_subpath(inner_idx) State.normal_select(dragged_xid, subpath_range.x) State.shift_select(dragged_xid, subpath_range.y) elif dragged_handle is PolyHandle: State.normal_select(dragged_xid, 0) - State.shift_select(dragged_xid, - dragged_handle.element.get_attribute("points").get_list_size() / 2 - 1) + State.shift_select(dragged_xid, dragged_handle.element.get_attribute("points").get_list_size() / 2 - 1) elif event.is_command_or_control_pressed(): State.ctrl_select(dragged_xid, inner_idx) elif event.shift_pressed: @@ -886,23 +833,17 @@ func _unhandled_input(event: InputEvent) -> void: if hovered_handle is PolyHandle: inner_idx = hovered_handle.point_index - if not (State.semi_selected_xid == hovered_xid and\ - inner_idx in State.inner_selections) and\ + if not (State.semi_selected_xid == hovered_xid and inner_idx in State.inner_selections) and\ not (inner_idx == -1 and hovered_xid in State.selected_xids): State.normal_select(hovered_xid, inner_idx) - HandlerGUI.popup_under_pos(State.get_selection_context( - HandlerGUI.popup_under_pos.bind(popup_pos, vp), - Utils.LayoutPart.VIEWPORT), popup_pos, vp) + HandlerGUI.popup_under_pos(State.get_selection_context(HandlerGUI.popup_under_pos.bind(popup_pos, vp), Utils.LayoutPart.VIEWPORT), popup_pos, vp) func find_nearest_handle(event_pos: Vector2) -> Handle: var nearest_handle: Handle = null - var nearest_dist_squared := DEFAULT_GRAB_DISTANCE_SQUARED *\ - (Configs.savedata.handle_size * Configs.savedata.handle_size) /\ - (State.zoom * State.zoom) + var nearest_dist_squared := DEFAULT_GRAB_DISTANCE_SQUARED * (Configs.savedata.handle_size * Configs.savedata.handle_size) / (State.zoom * State.zoom) for handle in handles: - var dist_to_handle_squared := event_pos.distance_squared_to( - State.root_element.canvas_to_world(handle.transform * handle.pos)) + var dist_to_handle_squared := event_pos.distance_squared_to(State.root_element.canvas_to_world(handle.transform * handle.pos)) if dist_to_handle_squared < nearest_dist_squared: nearest_dist_squared = dist_to_handle_squared nearest_handle = handle @@ -919,8 +860,7 @@ func apply_snap(pos: Vector2) -> PackedFloat64Array: # If the snap is disabled, or the precision snap is bigger than the configured snap # and a multiple of it, use the precision snap. Otherwise use the user-configured snap. - if Configs.savedata.snap < 0.0 or (precision_snap > configured_snap and\ - is_zero_approx(fmod(precision_snap, configured_snap))): + if Configs.savedata.snap < 0.0 or (precision_snap > configured_snap and is_zero_approx(fmod(precision_snap, configured_snap))): snap_size = precision_snap else: snap_size = configured_snap @@ -934,28 +874,24 @@ func _on_view_changed() -> void: func _on_handle_added() -> void: if not get_viewport_rect().has_point(get_viewport().get_mouse_position()): if not State.semi_selected_xid.is_empty(): - State.root_element.get_xnode(State.semi_selected_xid).get_attribute("d").\ - sync_after_commands_change() + State.root_element.get_xnode(State.semi_selected_xid).get_attribute("d").sync_after_commands_change() State.queue_svg_save() return update_handles() var first_inner_selection := State.inner_selections[0] - if State.root_element.get_xnode(State.semi_selected_xid).get_attribute("d").\ - get_commands()[first_inner_selection].command_char in "Zz": + if State.root_element.get_xnode(State.semi_selected_xid).get_attribute("d").get_commands()[first_inner_selection].command_char in "Zz": dragged_handle = null State.queue_svg_save() return for handle in handles: - if handle is PathHandle and handle.element.xid == State.semi_selected_xid and\ - handle.command_index == first_inner_selection: + if handle is PathHandle and handle.element.xid == State.semi_selected_xid and handle.command_index == first_inner_selection: State.set_hovered(handle.element.xid, handle.command_index) dragged_handle = handle # Move the handle that's being dragged. var mouse_pos := apply_snap(get_global_mouse_position()) - var new_pos := Utils64Bit.transform_vector_mult( - Utils64Bit.get_transform_affine_inverse(dragged_handle.precise_transform), + var new_pos := Utils64Bit.transform_vector_mult(Utils64Bit.get_transform_affine_inverse(dragged_handle.precise_transform), State.root_element.world_to_canvas_64_bit(mouse_pos)) dragged_handle.set_pos(new_pos) was_handle_moved = true @@ -964,19 +900,15 @@ func _on_handle_added() -> void: # Creates a popup for adding a shape at a position. func create_element_context(precise_pos: PackedFloat64Array) -> ContextPopup: var btn_array: Array[Button] = [] - const CONST_ARR: PackedStringArray = ["path", "circle", "ellipse", "rect", "line", - "polygon", "polyline"] + const CONST_ARR: PackedStringArray = ["path", "circle", "ellipse", "rect", "line", "polygon", "polyline"] for shape in CONST_ARR: - var btn := ContextPopup.create_button(shape, - add_shape_at_pos.bind(shape, precise_pos), false, DB.get_element_icon(shape)) + var btn := ContextPopup.create_button(shape, add_shape_at_pos.bind(shape, precise_pos), false, DB.get_element_icon(shape)) btn.add_theme_font_override("font", ThemeUtils.mono_font) btn_array.append(btn) var element_context := ContextPopup.new() - element_context.setup_with_title(btn_array, Translator.translate("New shape"), - true, -1, -1, PackedInt32Array([1, 4])) + element_context.setup_with_title(btn_array, Translator.translate("New shape"), true, -1, -1, PackedInt32Array([1, 4])) return element_context func add_shape_at_pos(element_name: String, precise_pos: PackedFloat64Array) -> void: - State.root_element.add_xnode(DB.element_with_setup(element_name, [precise_pos]), - PackedInt32Array([State.root_element.get_child_count()])) + State.root_element.add_xnode(DB.element_with_setup(element_name, [precise_pos]), PackedInt32Array([State.root_element.get_child_count()])) State.queue_svg_save() diff --git a/src/ui_parts/import_warning_menu.gd b/src/ui_parts/import_warning_menu.gd index 2f23bc9..4e9db5c 100644 --- a/src/ui_parts/import_warning_menu.gd +++ b/src/ui_parts/import_warning_menu.gd @@ -34,15 +34,13 @@ func _ready() -> void: var preview_parse_result := SVGParser.text_to_root(preview_text) var preview := preview_parse_result.svg if is_instance_valid(preview): - texture_preview.setup_svg(SVGParser.root_to_editor_text(preview), - preview.get_size()) + texture_preview.setup_svg(SVGParser.root_to_editor_text(preview), preview.get_size()) if imported_text_parse_result.error != SVGParser.ParseError.OK: texture_preview.hide() margin_container.custom_minimum_size.y = 48 size.y = 0 - warnings_label.add_theme_color_override("default_color", - Configs.savedata.basic_color_error) + warnings_label.add_theme_color_override("default_color", Configs.savedata.basic_color_error) warnings_label.text = "[center]%s: %s" % [Translator.translate( "Syntax error"), SVGParser.get_error_string(imported_text_parse_result.error)] else: @@ -73,13 +71,11 @@ func get_svg_warnings(root_element: ElementRoot) -> PackedStringArray: unrecognized_elements.append(element.name) else: for attribute in element.get_all_attributes(): - if not DB.is_attribute_recognized(element.name, attribute.name) and\ - not attribute.name in unrecognized_attributes: + if not DB.is_attribute_recognized(element.name, attribute.name) and not attribute.name in unrecognized_attributes: unrecognized_attributes.append(attribute.name) var warnings := PackedStringArray() for element in unrecognized_elements: warnings.append("%s: %s" % [Translator.translate("Unrecognized element"), element]) for attribute in unrecognized_attributes: - warnings.append("%s: %s" % [Translator.translate("Unrecognized attribute"), - attribute]) + warnings.append("%s: %s" % [Translator.translate("Unrecognized attribute"), attribute]) return warnings diff --git a/src/ui_parts/layout_popup.gd b/src/ui_parts/layout_configuration.gd similarity index 76% rename from src/ui_parts/layout_popup.gd rename to src/ui_parts/layout_configuration.gd index b7bdc44..40d35fe 100644 --- a/src/ui_parts/layout_popup.gd +++ b/src/ui_parts/layout_configuration.gd @@ -1,7 +1,7 @@ extends Control -# This popup is mainly just one node doing a lot of things. This helps with drag & drop -# which can be defined only here. Buttons are used too, but just for graphics. +# This is the configuration area of the layout popup, which is just one node doing a lot of things. +# This helps with drag & drop which can be defined only here. Buttons are used too, but just for graphics. class DragData: var layout_part: Utils.LayoutPart @@ -15,7 +15,6 @@ class DragData: idx = new_idx const PART_UI_SIZE = 30 -const PANEL_MARGIN = 4 const BUFFER_SIZE = 2 var ci := get_canvas_item() @@ -30,8 +29,7 @@ var hovered_part := Utils.LayoutPart.NONE: set(new_value): if hovered_part != new_value: hovered_part = new_value - mouse_default_cursor_shape = CURSOR_ARROW if\ - hovered_part == Utils.LayoutPart.NONE else CURSOR_POINTING_HAND + mouse_default_cursor_shape = CURSOR_ARROW if hovered_part == Utils.LayoutPart.NONE else CURSOR_POINTING_HAND queue_redraw() var proposed_drop_location_pivot := SaveData.LayoutLocation.NONE: @@ -88,10 +86,8 @@ func _on_window_mouse_exited() -> void: # Drawing func _draw() -> void: - get_theme_stylebox("panel", "PanelContainer").draw(ci, Rect2(Vector2.ZERO, size)) - - var half_width := size.x / 2.0 - PANEL_MARGIN - var right_rect := Rect2(size.x / 2.0, PANEL_MARGIN, half_width, half_width * 1.25) + var half_width := size.x / 2.0 + var right_rect := Rect2(half_width, 18, half_width, half_width * 1.25) # Fixed viewport location for now. var stylebox := StyleBoxFlat.new() @@ -99,11 +95,10 @@ func _draw() -> void: stylebox.bg_color = ThemeUtils.hover_overlay_color var disabled_stylebox := stylebox.duplicate() - disabled_stylebox.bg_color = ThemeUtils.translucent_button_color_disabled + disabled_stylebox.bg_color = ThemeUtils.context_button_color_disabled disabled_stylebox.draw(ci, right_rect.grow(-BUFFER_SIZE)) var viewport_icon := Utils.get_layout_part_icon(Utils.LayoutPart.VIEWPORT) - viewport_icon.draw(ci, right_rect.get_center() - viewport_icon.get_size() / 2, - ThemeUtils.tinted_contrast_color) + viewport_icon.draw(ci, right_rect.get_center() - viewport_icon.get_size() / 2, ThemeUtils.tinted_contrast_color) for layout_location in section_areas: var area := section_areas[layout_location].grow(-BUFFER_SIZE) @@ -140,16 +135,14 @@ func _draw() -> void: else: stylebox.draw(ci, rect) if proposed_drop_idx >= 0: - if parts_in_proposed_drop.size() > proposed_drop_idx and\ - parts_in_proposed_drop[proposed_drop_idx] == layout_part: + if parts_in_proposed_drop.size() > proposed_drop_idx and parts_in_proposed_drop[proposed_drop_idx] == layout_part: var drop_sb := StyleBoxFlat.new() drop_sb.set_corner_radius_all(5) drop_sb.draw_center = false drop_sb.border_color = Configs.savedata.basic_color_valid drop_sb.border_width_left = 2 drop_sb.draw(ci, rect) - elif proposed_drop_idx >= 1 and\ - parts_in_proposed_drop.size() > proposed_drop_idx - 1 and\ + elif proposed_drop_idx >= 1 and parts_in_proposed_drop.size() > proposed_drop_idx - 1 and\ parts_in_proposed_drop[proposed_drop_idx - 1] == layout_part: var drop_sb := StyleBoxFlat.new() drop_sb.set_corner_radius_all(5) @@ -160,7 +153,11 @@ func _draw() -> void: icon.draw(ci, rect.get_center() - icon.get_size() / 2.0, ThemeUtils.tinted_contrast_color) - ThemeUtils.regular_font.draw_string(ci, Vector2(0, size.x * 0.75 - 5), + ThemeUtils.regular_font.draw_string(ci, Vector2(0, 12), + Translator.translate("Layout") + ":", HORIZONTAL_ALIGNMENT_CENTER, size.x, + get_theme_font_size("font_size", "Label"), ThemeUtils.text_color) + + ThemeUtils.regular_font.draw_string(ci, Vector2(0, size.x * 0.625 + 33), Translator.translate("Excluded") + ":", HORIZONTAL_ALIGNMENT_CENTER, size.x, get_theme_font_size("font_size", "Label"), ThemeUtils.text_color) @@ -186,13 +183,11 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void: if not data == dragged_data: return - if proposed_drop_location_direction == DropDirection.INSIDE and\ - proposed_drop_location_pivot == dragged_data.layout_location: + if proposed_drop_location_direction == DropDirection.INSIDE and proposed_drop_location_pivot == dragged_data.layout_location: var parts := Configs.savedata.get_layout_parts(proposed_drop_location_pivot) # We're just rearranging tabs. parts.remove_at(dragged_data.idx) - parts.insert(proposed_drop_idx if proposed_drop_idx <= dragged_data.idx else\ - proposed_drop_idx - 1, dragged_data.layout_part) + parts.insert(proposed_drop_idx if proposed_drop_idx <= dragged_data.idx else proposed_drop_idx - 1, dragged_data.layout_part) Configs.savedata.set_layout_parts(proposed_drop_location_pivot, parts) else: var old_parts := Configs.savedata.get_layout_parts(dragged_data.layout_location) @@ -205,8 +200,7 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void: parts.insert(proposed_drop_idx, dragged_data.layout_part) Configs.savedata.set_layout_parts(proposed_drop_location_pivot, parts) DropDirection.BELOW: - var bottom_left_parts := Configs.savedata.get_layout_parts( - SaveData.LayoutLocation.SIDE_PANEL_BOTTOM) + var bottom_left_parts := Configs.savedata.get_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM) if not bottom_left_parts.is_empty(): # If everything is on the bottom, then move them to the top so the # new dragged layout part can be on the bottom. @@ -214,19 +208,14 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void: # to be valid, then the dragged part should be the only one on the top side. # In either case, the stuff on the bottom should be moved to the top, # and the dragged one should move to the bottom. - Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_TOP, - bottom_left_parts, false) - Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM, - [dragged_data.layout_part]) + Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_TOP, bottom_left_parts, false) + Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM, [dragged_data.layout_part]) DropDirection.ABOVE: # Same logic as above, but with top and bottom flipped. - var top_left_parts := Configs.savedata.get_layout_parts( - SaveData.LayoutLocation.SIDE_PANEL_TOP) + var top_left_parts := Configs.savedata.get_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_TOP) if not top_left_parts.is_empty(): - Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM, - top_left_parts, false) - Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_TOP, - [dragged_data.layout_part]) + Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM, top_left_parts, false) + Configs.savedata.set_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_TOP, [dragged_data.layout_part]) clear_proposed_drop() update_areas() @@ -247,13 +236,9 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool: proposed_drop_location_pivot = section - - if at_position.y < lerpf(section_area.position.y, section_area.end.y, 0.25) and\ - ((section == SaveData.LayoutLocation.SIDE_PANEL_TOP and\ - not is_dragged_part_the_only_top_left and (bottom_left_parts.is_empty() or\ - is_dragged_part_the_only_bottom_left)) or\ - (section == SaveData.LayoutLocation.SIDE_PANEL_BOTTOM and top_left_parts.is_empty() and\ - not is_dragged_part_the_only_top_left)): + if at_position.y < lerpf(section_area.position.y, section_area.end.y, 0.25) and ((section == SaveData.LayoutLocation.SIDE_PANEL_TOP and\ + not is_dragged_part_the_only_top_left and (bottom_left_parts.is_empty() or is_dragged_part_the_only_bottom_left)) or\ + (section == SaveData.LayoutLocation.SIDE_PANEL_BOTTOM and top_left_parts.is_empty() and not is_dragged_part_the_only_top_left)): # Hovering over the top side of the section, when one of the following is true: # Case 1: The section is top left, and there's either nothing on the bottom left, # or the only thing on the bottom left is the dragged layout part. @@ -261,39 +246,31 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool: # the dragged layout part is not the only thing on the bottom left. proposed_drop_location_direction = DropDirection.ABOVE proposed_drop_idx = -1 - elif at_position.y > lerpf(section_area.position.y, section_area.end.y, 0.75) and\ - ((section == SaveData.LayoutLocation.SIDE_PANEL_BOTTOM and\ - not is_dragged_part_the_only_bottom_left and (top_left_parts.is_empty() or\ - is_dragged_part_the_only_top_left)) or\ - (section == SaveData.LayoutLocation.SIDE_PANEL_TOP and bottom_left_parts.is_empty() and\ - not is_dragged_part_the_only_bottom_left)): + elif at_position.y > lerpf(section_area.position.y, section_area.end.y, 0.75) and ((section == SaveData.LayoutLocation.SIDE_PANEL_BOTTOM and\ + not is_dragged_part_the_only_bottom_left and (top_left_parts.is_empty() or is_dragged_part_the_only_top_left)) or\ + (section == SaveData.LayoutLocation.SIDE_PANEL_TOP and bottom_left_parts.is_empty() and not is_dragged_part_the_only_bottom_left)): # Same logic as the previous big condition, but top and bottom are flipped. proposed_drop_location_direction = DropDirection.BELOW proposed_drop_idx = -1 - elif not (section == SaveData.LayoutLocation.EXCLUDED and\ - ((is_dragged_part_the_only_top_left and bottom_left_parts.is_empty()) or\ + elif not (section == SaveData.LayoutLocation.EXCLUDED and ((is_dragged_part_the_only_top_left and bottom_left_parts.is_empty()) or\ (is_dragged_part_the_only_bottom_left and top_left_parts.is_empty()))): # Ensure we're not dragging the last layout part into excluded. proposed_drop_location_direction = DropDirection.INSIDE var layout_parts_count := Configs.savedata.get_layout_parts(section).size() if proposed_drop_location_pivot == SaveData.LayoutLocation.EXCLUDED: - proposed_drop_idx = clampi(roundi(at_position.x / (PART_UI_SIZE + 8)), 0, - layout_parts_count) + proposed_drop_idx = clampi(roundi(at_position.x / (PART_UI_SIZE + 8)), 0, layout_parts_count) else: - proposed_drop_idx = clampi(roundi(((at_position.x -\ - section_areas[section].get_center().x) / PART_UI_SIZE) +\ - layout_parts_count / 2.0), 0, layout_parts_count) + proposed_drop_idx = clampi(roundi(((at_position.x - section_areas[section].get_center().x) / PART_UI_SIZE) + layout_parts_count / 2.0), + 0, layout_parts_count) if proposed_drop_location_pivot == dragged_data.layout_location and\ - (proposed_drop_idx == dragged_data.idx or\ - proposed_drop_idx == dragged_data.idx + 1): + (proposed_drop_idx == dragged_data.idx or proposed_drop_idx == dragged_data.idx + 1): proposed_drop_idx = -1 else: clear_proposed_drop() return false - if proposed_drop_idx != -1 or\ - proposed_drop_location_direction != DropDirection.INSIDE or\ + if proposed_drop_idx != -1 or proposed_drop_location_direction != DropDirection.INSIDE or\ proposed_drop_location_pivot != dragged_data.layout_location: return true else: @@ -312,9 +289,8 @@ func clear_proposed_drop() -> void: func _get_tooltip(at_position: Vector2) -> String: # TODO Hack for the viewport tooltip. - var half_width := size.x / 2.0 - PANEL_MARGIN - if Rect2(size.x / 2.0, PANEL_MARGIN, half_width, half_width * 1.25).\ - grow(-BUFFER_SIZE).has_point(at_position): + var half_width := size.x / 2.0 + if Rect2(half_width, 18, half_width, half_width * 1.25).grow(-BUFFER_SIZE).has_point(at_position): return TranslationUtils.get_layout_part_name(Utils.LayoutPart.VIEWPORT) for layout_part in layout_part_areas: @@ -350,50 +326,40 @@ func update_areas() -> void: var bottom_left := Configs.savedata.get_layout_parts(SaveData.LayoutLocation.SIDE_PANEL_BOTTOM) var excluded := Configs.savedata.get_layout_parts(SaveData.LayoutLocation.EXCLUDED) - var width := size.x - PANEL_MARGIN * 2 - var included_rect := Rect2(PANEL_MARGIN, PANEL_MARGIN, width, width / 1.6) + var included_rect_height := size.x * 0.625 + var half_width := size.x / 2.0 + var included_rect_half_height := included_rect_height / 2.0 + var v_offset := 18.0 section_areas.clear() - - section_areas[SaveData.LayoutLocation.EXCLUDED] =\ - Rect2(PANEL_MARGIN, size.x * 0.75, 160, PART_UI_SIZE + 8) + section_areas[SaveData.LayoutLocation.EXCLUDED] = Rect2(0, v_offset * 2 + included_rect_height + 2, size.x, PART_UI_SIZE + 8) if not top_left.is_empty() and not bottom_left.is_empty(): - section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP] =\ - Rect2(included_rect.position, included_rect.size * Vector2(0.5, 0.5)) - section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM] =\ - Rect2(included_rect.position + included_rect.size * Vector2(0.0, 0.5), - included_rect.size * Vector2(0.5, 0.5)) + section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP] = Rect2(0, v_offset, half_width, included_rect_half_height) + section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM] = Rect2(0, v_offset + included_rect_half_height, half_width, included_rect_half_height) elif bottom_left.is_empty(): - section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP] =\ - Rect2(included_rect.position, included_rect.size * Vector2(0.5, 1.0)) + section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP] = Rect2(0, v_offset, half_width, included_rect_height) elif top_left.is_empty(): - section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM] =\ - Rect2(included_rect.position, included_rect.size * Vector2(0.5, 1.0)) + section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM] = Rect2(0, v_offset, half_width, included_rect_height) if not top_left.is_empty(): var top_left_count := top_left.size() - var top_left_rect_center := section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP].\ - get_center() + var top_left_rect_center := section_areas[SaveData.LayoutLocation.SIDE_PANEL_TOP].get_center() for i in top_left_count: - layout_part_areas[top_left[i]] = Rect2(top_left_rect_center.x -\ - PART_UI_SIZE * (top_left_count * 0.5 - i), top_left_rect_center.y -\ - PART_UI_SIZE / 2.0, PART_UI_SIZE, PART_UI_SIZE) + layout_part_areas[top_left[i]] = Rect2(top_left_rect_center.x - PART_UI_SIZE * (top_left_count * 0.5 - i), + top_left_rect_center.y - PART_UI_SIZE / 2.0, PART_UI_SIZE, PART_UI_SIZE) if not bottom_left.is_empty(): var bottom_left_count := bottom_left.size() - var bottom_left_rect_center := section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM].\ - get_center() + var bottom_left_rect_center := section_areas[SaveData.LayoutLocation.SIDE_PANEL_BOTTOM].get_center() for i in bottom_left_count: - layout_part_areas[bottom_left[i]] = Rect2(bottom_left_rect_center.x -\ - PART_UI_SIZE * (bottom_left_count * 0.5 - i), bottom_left_rect_center.y -\ - PART_UI_SIZE / 2.0, PART_UI_SIZE, PART_UI_SIZE) + layout_part_areas[bottom_left[i]] = Rect2(bottom_left_rect_center.x - PART_UI_SIZE * (bottom_left_count * 0.5 - i), + bottom_left_rect_center.y - PART_UI_SIZE / 2.0, PART_UI_SIZE, PART_UI_SIZE) var excluded_count := excluded.size() for i in excluded_count: var part := excluded[i] - var rect := Rect2(section_areas[SaveData.LayoutLocation.EXCLUDED].position +\ - Vector2((PART_UI_SIZE + 4) * i, 0), + var rect := Rect2(section_areas[SaveData.LayoutLocation.EXCLUDED].position + Vector2((PART_UI_SIZE + 4) * i, 0), Vector2(PART_UI_SIZE + 8, PART_UI_SIZE + 8)).grow(-4) layout_part_areas[part] = rect diff --git a/src/ui_parts/layout_configuration.gd.uid b/src/ui_parts/layout_configuration.gd.uid new file mode 100644 index 0000000..3338fec --- /dev/null +++ b/src/ui_parts/layout_configuration.gd.uid @@ -0,0 +1 @@ +uid://dtmassdggpkom diff --git a/src/ui_parts/layout_popup.gd.uid b/src/ui_parts/layout_popup.gd.uid deleted file mode 100644 index a467359..0000000 --- a/src/ui_parts/layout_popup.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://tyh2836jivui diff --git a/src/ui_parts/layout_popup.tscn b/src/ui_parts/layout_popup.tscn index 9178b59..0ef0186 100644 --- a/src/ui_parts/layout_popup.tscn +++ b/src/ui_parts/layout_popup.tscn @@ -1,10 +1,20 @@ [gd_scene load_steps=2 format=3 uid="uid://bygxen40wv4nr"] -[ext_resource type="Script" uid="uid://tyh2836jivui" path="res://src/ui_parts/layout_popup.gd" id="1_1fo7n"] - -[node name="LayoutPopup" type="Control"] -custom_minimum_size = Vector2(168, 168) -layout_mode = 3 -offset_right = 168.0 -offset_bottom = 168.0 -script = ExtResource("1_1fo7n") +[ext_resource type="Script" uid="uid://dtmassdggpkom" path="res://src/ui_parts/layout_configuration.gd" id="2_lmeyv"] + +[node name="LayoutPopup" type="PanelContainer"] +anchors_preset = -1 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 2 +theme_override_constants/margin_top = 2 +theme_override_constants/margin_right = 2 +theme_override_constants/margin_bottom = 2 + +[node name="LayoutConfiguration" type="Control" parent="MarginContainer"] +custom_minimum_size = Vector2(160, 176) +layout_mode = 2 +script = ExtResource("2_lmeyv") diff --git a/src/ui_parts/root_element_editor.gd b/src/ui_parts/root_element_editor.gd index 362b85e..2cc0e3f 100644 --- a/src/ui_parts/root_element_editor.gd +++ b/src/ui_parts/root_element_editor.gd @@ -84,8 +84,7 @@ func update_editable() -> void: var is_width_valid := State.root_element.has_attribute("width") var is_height_valid := State.root_element.has_attribute("height") - var is_viewbox_valid: bool = State.root_element.has_attribute("viewBox") and\ - State.root_element.get_attribute("viewBox").get_list_size() >= 4 + var is_viewbox_valid: bool = State.root_element.has_attribute("viewBox") and State.root_element.get_attribute("viewBox").get_list_size() >= 4 width_button.set_pressed_no_signal(is_width_valid) height_button.set_pressed_no_signal(is_height_valid) @@ -128,15 +127,13 @@ func _on_viewbox_edit_y_value_changed(new_value: float) -> void: State.queue_svg_save() func _on_viewbox_edit_w_value_changed(new_value: float) -> void: - if State.root_element.has_attribute("viewBox") and\ - State.root_element.get_attribute("viewBox").get_list_element(2) != new_value: + if State.root_element.has_attribute("viewBox") and State.root_element.get_attribute("viewBox").get_list_element(2) != new_value: State.root_element.viewbox.size.x = new_value State.root_element.get_attribute("viewBox").set_list_element(2, new_value) State.queue_svg_save() func _on_viewbox_edit_h_value_changed(new_value: float) -> void: - if State.root_element.has_attribute("viewBox") and\ - State.root_element.get_attribute("viewBox").get_list_element(3) != new_value: + if State.root_element.has_attribute("viewBox") and State.root_element.get_attribute("viewBox").get_list_element(3) != new_value: State.root_element.viewbox.size.y = new_value State.root_element.get_attribute("viewBox").set_list_element(3, new_value) State.queue_svg_save() @@ -169,8 +166,7 @@ func _on_viewbox_button_toggled(toggled_on: bool) -> void: ListParser.rect_to_list(State.root_element.viewbox)) State.queue_svg_save() else: - if State.root_element.has_attribute("width") and\ - State.root_element.has_attribute("height"): + if State.root_element.has_attribute("width") and State.root_element.has_attribute("height"): State.root_element.set_attribute("viewBox", "") State.queue_svg_save() else: diff --git a/src/ui_parts/settings_menu.gd b/src/ui_parts/settings_menu.gd index e0d2bda..dcbec7e 100644 --- a/src/ui_parts/settings_menu.gd +++ b/src/ui_parts/settings_menu.gd @@ -27,6 +27,11 @@ func get_tab_localized_name(tab_index: TabIndex) -> String: var focused_tab_index := -1 as TabIndex func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("select_next_tab", select_next_tab) + shortcuts.add_shortcut("select_previous_tab", select_previous_tab) + HandlerGUI.register_shortcuts(self, shortcuts) + back_button.pressed.connect(queue_free) change_orientation() Configs.orientation_changed.connect(change_orientation) @@ -48,19 +53,18 @@ func change_orientation(): tabs.vertical = true $VBoxContainer/BoxContainer/PanelContainer.size_flags_horizontal = SIZE_EXPAND_FILL -func _unhandled_input(event: InputEvent) -> void: +func select_next_tab() -> void: + press_tab((focused_tab_index + 1) % TabIndex.size()) + +func select_previous_tab() -> void: var tab_count := TabIndex.size() - if ShortcutUtils.is_action_pressed(event, "select_next_tab"): - press_tab((focused_tab_index + 1) % tab_count) - elif ShortcutUtils.is_action_pressed(event, "select_previous_tab"): - press_tab((focused_tab_index + tab_count - 1) % tab_count) + press_tab((focused_tab_index + tab_count - 1) % tab_count) func press_tab(index: int) -> void: tabs.get_child(index).button_pressed = true func sync_localization() -> void: - lang_button.text = Translator.translate("Language") + ": " +\ - TranslationUtils.get_locale_string(TranslationServer.get_locale()) + lang_button.text = Translator.translate("Language") + ": " + TranslationUtils.get_locale_string(TranslationServer.get_locale()) setup_tabs() func adjust_right_margin() -> void: @@ -140,8 +144,7 @@ func _on_language_pressed() -> void: # Translation percentages. if locale != "en": var translation_obj := TranslationServer.get_translation_object(locale) - var translated_count := translation_obj.get_message_count() -\ - translation_obj.get_translated_message_list().count("") + var translated_count := translation_obj.get_message_count() - translation_obj.get_translated_message_list().count("") btn_arr.append(ContextPopup.create_button( TranslationUtils.get_locale_display(locale), @@ -154,8 +157,7 @@ func _on_language_pressed() -> void: var lang_popup := ContextPopup.new() lang_popup.setup(btn_arr, true) - HandlerGUI.popup_under_rect_center(lang_popup, lang_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(lang_popup, lang_button.get_global_rect(), get_viewport()) func _on_language_chosen(locale: String) -> void: Configs.savedata.language = locale diff --git a/src/ui_parts/tab_bar.gd b/src/ui_parts/tab_bar.gd index dd0fff8..1071d39 100644 --- a/src/ui_parts/tab_bar.gd +++ b/src/ui_parts/tab_bar.gd @@ -61,8 +61,7 @@ func _draw() -> void: if current_tab.marked_unsaved: current_tab_name = "* " + current_tab_name - if (has_transient_tab and drawing_transient_tab) or\ - (not has_transient_tab and tab_index == Configs.savedata.get_active_tab_index()): + if (has_transient_tab and drawing_transient_tab) or (not has_transient_tab and tab_index == Configs.savedata.get_active_tab_index()): draw_style_box(get_theme_stylebox("tab_selected", "TabContainer"), rect) var text_line_width := rect.size.x - size.y if text_line_width > 0: @@ -70,15 +69,13 @@ func _draw() -> void: text_line.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS text_line.add_string(current_tab_name, ThemeUtils.regular_font, 13) text_line.width = text_line_width - 2 - text_line.draw(ci, rect.position + Vector2(4, 3), - get_theme_color("font_selected_color", "TabContainer")) + text_line.draw(ci, rect.position + Vector2(4, 3), get_theme_color("font_selected_color", "TabContainer")) if not drawing_transient_tab: var close_rect := get_close_button_rect() if close_rect.has_area(): var close_icon_size := close_icon.get_size() - draw_texture_rect(close_icon, Rect2(close_rect.position +\ - (close_rect.size - close_icon_size) / 2.0, close_icon_size), false, - ThemeUtils.tinted_contrast_color) + draw_texture_rect(close_icon, Rect2(close_rect.position + (close_rect.size - close_icon_size) / 2.0, close_icon_size), + false, ThemeUtils.tinted_contrast_color) else: var is_hovered := rect.has_point(mouse_pos) var tab_style := "tab_hovered" if is_hovered else "tab_unselected" @@ -86,8 +83,7 @@ func _draw() -> void: var text_line_width := rect.size.x - 8 if text_line_width > 0: - var text_color := get_theme_color("font_hovered_color" if is_hovered else\ - "font_unselected_color", "TabContainer") + var text_color := get_theme_color("font_hovered_color" if is_hovered else "font_unselected_color", "TabContainer") var text_line := TextLine.new() text_line.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS @@ -97,9 +93,8 @@ func _draw() -> void: var add_button_rect := get_add_button_rect() var plus_icon_size := plus_icon.get_size() - draw_texture_rect(plus_icon, Rect2(add_button_rect.position +\ - (add_button_rect.size - plus_icon_size) / 2.0, plus_icon_size), false, - ThemeUtils.tinted_contrast_color) + draw_texture_rect(plus_icon, Rect2(add_button_rect.position + (add_button_rect.size - plus_icon_size) / 2.0, plus_icon_size), + false, ThemeUtils.tinted_contrast_color) var scroll_backwards_rect := get_scroll_backwards_area_rect() if scroll_backwards_rect.has_area(): @@ -109,15 +104,11 @@ func _draw() -> void: icon_modulate = get_theme_color("icon_disabled_color", "Button") else: var line_x := scroll_backwards_rect.end.x + 1 - draw_line(Vector2(line_x, 0), Vector2(line_x, size.y), - ThemeUtils.basic_panel_border_color) + draw_line(Vector2(line_x, 0), Vector2(line_x, size.y), ThemeUtils.basic_panel_border_color) if scroll_backwards_rect.has_point(mouse_pos): - var stylebox_theme := "pressed" if\ - Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) else "hover" - get_theme_stylebox(stylebox_theme, "FlatButton").draw(ci, - scroll_backwards_rect) - draw_texture_rect(scroll_backwards_icon, Rect2(scroll_backwards_rect.position +\ - (scroll_backwards_rect.size - scroll_backwards_icon_size) / 2.0, + var stylebox_theme := "pressed" if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) else "hover" + get_theme_stylebox(stylebox_theme, "FlatButton").draw(ci, scroll_backwards_rect) + draw_texture_rect(scroll_backwards_icon, Rect2(scroll_backwards_rect.position + (scroll_backwards_rect.size - scroll_backwards_icon_size) / 2.0, scroll_backwards_icon_size), false, icon_modulate) var scroll_forwards_rect := get_scroll_forwards_area_rect() @@ -131,11 +122,9 @@ func _draw() -> void: draw_line(Vector2(line_x, 0), Vector2(line_x, size.y), ThemeUtils.basic_panel_border_color) if scroll_forwards_rect.has_point(mouse_pos): - var stylebox_theme := "pressed" if\ - Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) else "hover" + var stylebox_theme := "pressed" if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) else "hover" get_theme_stylebox(stylebox_theme, "FlatButton").draw(ci, scroll_forwards_rect) - draw_texture_rect(scroll_forwards_icon, Rect2(scroll_forwards_rect.position +\ - (scroll_forwards_rect.size - scroll_forwards_icon_size) / 2.0, + draw_texture_rect(scroll_forwards_icon, Rect2(scroll_forwards_rect.position + (scroll_forwards_rect.size - scroll_forwards_icon_size) / 2.0, scroll_forwards_icon_size), false, icon_modulate) if proposed_drop_idx != -1: @@ -172,17 +161,13 @@ func _gui_input(event: InputEvent) -> void: Configs.savedata.set_active_tab_index.call_deferred(hovered_idx) if event.button_index == MOUSE_BUTTON_LEFT: var scroll_backwards_area_rect := get_scroll_backwards_area_rect() - if scroll_backwards_area_rect.has_area() and\ - scroll_backwards_area_rect.has_point(event.position) and\ - not is_scroll_backwards_disabled(): + if scroll_backwards_area_rect.has_area() and scroll_backwards_area_rect.has_point(event.position) and not is_scroll_backwards_disabled(): scrolling_backwards = true set_process(true) return var scroll_forwards_area_rect := get_scroll_forwards_area_rect() - if scroll_forwards_area_rect.has_area() and\ - scroll_forwards_area_rect.has_point(event.position) and\ - not is_scroll_forwards_disabled(): + if scroll_forwards_area_rect.has_area() and scroll_forwards_area_rect.has_point(event.position) and not is_scroll_forwards_disabled(): scrolling_forwards = true set_process(true) return @@ -190,8 +175,7 @@ func _gui_input(event: InputEvent) -> void: var btn_arr: Array[Button] = [] if hovered_idx == -1: - if get_add_button_rect().has_point(event.position) or\ - get_scroll_forwards_area_rect().has_point(event.position) or\ + if get_add_button_rect().has_point(event.position) or get_scroll_forwards_area_rect().has_point(event.position) or\ get_scroll_backwards_area_rect().has_point(event.position): return btn_arr.append(ContextPopup.create_shortcut_button("new_tab")) @@ -238,8 +222,7 @@ func _gui_input(event: InputEvent) -> void: tab_global_rect.position += get_global_rect().position HandlerGUI.popup_under_rect(tab_popup, tab_global_rect, get_viewport()) else: - HandlerGUI.popup_under_pos(tab_popup, get_global_mouse_position(), - get_viewport()) + HandlerGUI.popup_under_pos(tab_popup, get_global_mouse_position(), get_viewport()) elif event.button_index == MOUSE_BUTTON_MIDDLE: if Configs.savedata.tab_mmb_close: FileUtils.close_tabs(get_hovered_index()) @@ -256,15 +239,13 @@ func _process(_delta: float) -> void: var mouse_pos := get_local_mouse_position() var scroll_forwards_area_rect := get_scroll_forwards_area_rect() if ((scrolling_forwards and scroll_forwards_area_rect.has_point(mouse_pos)) or\ - (mouse_pos.x > size.x - size.y - scroll_forwards_area_rect.size.x)) and\ - scroll_forwards_area_rect.has_area(): + (mouse_pos.x > size.x - size.y - scroll_forwards_area_rect.size.x)) and scroll_forwards_area_rect.has_area(): scroll_forwards() return var scroll_backwards_area_rect := get_scroll_backwards_area_rect() if ((scrolling_backwards and scroll_backwards_area_rect.has_point(mouse_pos)) or\ - (mouse_pos.x < scroll_backwards_area_rect.size.x)) and\ - scroll_backwards_area_rect.has_area(): + (mouse_pos.x < scroll_backwards_area_rect.size.x)) and scroll_backwards_area_rect.has_area(): scroll_backwards() return @@ -289,11 +270,9 @@ func scroll_forwards(factor := 1.0) -> void: set_scroll(current_scroll + SCROLL_SPEED * factor) func scroll_to_active() -> void: - var idx := Configs.savedata.get_active_tab_index() if\ - State.transient_tab_path.is_empty() else Configs.savedata.get_tab_count() + var idx := Configs.savedata.get_active_tab_index() if State.transient_tab_path.is_empty() else Configs.savedata.get_tab_count() set_scroll(clampf(current_scroll, MIN_TAB_WIDTH * (idx + 1) - size.x + size.y +\ - get_scroll_forwards_area_rect().size.x + get_scroll_backwards_area_rect().size.x, - MIN_TAB_WIDTH * idx)) + get_scroll_forwards_area_rect().size.x + get_scroll_backwards_area_rect().size.x, MIN_TAB_WIDTH * idx)) func set_scroll(new_value: float) -> void: if get_scroll_limit() < 0: @@ -319,8 +298,7 @@ func get_tab_rect(idx: int) -> Rect2: var left_limit := scroll_backwards_button_width var right_limit := size.x - size.y - scroll_forwards_button_width - var tab_width := clampf((size.x - size.y - scroll_backwards_button_width -\ - scroll_forwards_button_width) / get_proper_tab_count(), + var tab_width := clampf((size.x - size.y - scroll_backwards_button_width - scroll_forwards_button_width) / get_proper_tab_count(), MIN_TAB_WIDTH, DEFAULT_TAB_WIDTH) var unclamped_tab_start := tab_width * idx - current_scroll + left_limit var tab_start := clampf(unclamped_tab_start, left_limit, right_limit) @@ -331,12 +309,10 @@ func get_tab_rect(idx: int) -> Rect2: return Rect2(tab_start, 0, tab_end - tab_start, size.y) func get_close_button_rect() -> Rect2: - var tab_rect := get_tab_rect(Configs.savedata.get_active_tab_index() if\ - State.transient_tab_path.is_empty() else Configs.savedata.get_tab_count()) + var tab_rect := get_tab_rect(Configs.savedata.get_active_tab_index() if State.transient_tab_path.is_empty() else Configs.savedata.get_tab_count()) var side := size.y - CLOSE_BUTTON_MARGIN * 2 var left_coords := tab_rect.position.x + tab_rect.size.x - CLOSE_BUTTON_MARGIN - side - if left_coords < get_scroll_backwards_area_rect().size.x or\ - tab_rect.size.x < size.y - CLOSE_BUTTON_MARGIN: + if left_coords < get_scroll_backwards_area_rect().size.x or tab_rect.size.x < size.y - CLOSE_BUTTON_MARGIN: return Rect2() return Rect2(left_coords, CLOSE_BUTTON_MARGIN, side, side) @@ -365,8 +341,7 @@ func get_scroll_limit() -> float: var scroll_backwards_button_width := get_scroll_backwards_area_rect().size.x var scroll_forwards_button_width := get_scroll_forwards_area_rect().size.x - var available_area := size.x - size.y - scroll_backwards_button_width -\ - scroll_forwards_button_width + var available_area := size.x - size.y - scroll_backwards_button_width - scroll_forwards_button_width return clampf(available_area / get_proper_tab_count(), MIN_TAB_WIDTH, DEFAULT_TAB_WIDTH) * get_proper_tab_count() - available_area @@ -446,12 +421,10 @@ func _make_custom_tooltip(for_text: String) -> Object: var path := hovered_tab.get_presented_svg_file_path() var label := Label.new() - label.add_theme_font_override("font", ThemeUtils.mono_font if is_saved\ - else ThemeUtils.regular_font) + label.add_theme_font_override("font", ThemeUtils.mono_font if is_saved else ThemeUtils.regular_font) label.add_theme_font_size_override("font_size", 12) label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - label.text = path if is_saved else\ - Translator.translate("This SVG is not bound to a file location yet.") + label.text = path if is_saved else Translator.translate("This SVG is not bound to a file location yet.") Utils.set_max_text_width(label, 192.0, 4.0) # If the tab is active or empty, no need for an SVG preview. @@ -461,12 +434,9 @@ func _make_custom_tooltip(for_text: String) -> Object: var margin_container := MarginContainer.new() var tooltip_panel_stylebox := get_theme_stylebox("panel", "TooltipPanel") margin_container.begin_bulk_theme_override() - margin_container.add_theme_constant_override("margin_top", - 8 - int(tooltip_panel_stylebox.content_margin_top)) - margin_container.add_theme_constant_override("margin_bottom", - 8 - int(tooltip_panel_stylebox.content_margin_bottom)) - margin_container.add_theme_constant_override("margin_left", - 8 - int(tooltip_panel_stylebox.content_margin_left)) + margin_container.add_theme_constant_override("margin_top", 8 - int(tooltip_panel_stylebox.content_margin_top)) + margin_container.add_theme_constant_override("margin_bottom", 8 - int(tooltip_panel_stylebox.content_margin_bottom)) + margin_container.add_theme_constant_override("margin_left", 8 - int(tooltip_panel_stylebox.content_margin_left)) margin_container.end_bulk_theme_override() var hbox := HBoxContainer.new() hbox.add_theme_constant_override("separation", 8) @@ -474,8 +444,7 @@ func _make_custom_tooltip(for_text: String) -> Object: hbox.add_child(preview_rect) preview_rect.custom_minimum_size = Vector2(96, 96) preview_rect.size = Vector2.ZERO - preview_rect.setup_svg_without_dimensions(FileAccess.get_file_as_string( - hovered_tab.get_edited_file_path())) + preview_rect.setup_svg_without_dimensions(FileAccess.get_file_as_string(hovered_tab.get_edited_file_path())) preview_rect.shrink_to_fit(16, 16) hbox.add_child(label) margin_container.add_child(hbox) @@ -500,8 +469,7 @@ func get_drop_index_at(pos: Vector2) -> int: var scroll_backwards_button_width := get_scroll_backwards_area_rect().size.x var scroll_forwards_button_width := get_scroll_forwards_area_rect().size.x - if pos.x < scroll_backwards_button_width or\ - pos.x > size.x - scroll_forwards_button_width - size.y: + if pos.x < scroll_backwards_button_width or pos.x > size.x - scroll_forwards_button_width - size.y: return -1 var first_tab_with_area := 0 @@ -510,14 +478,12 @@ func get_drop_index_at(pos: Vector2) -> int: first_tab_with_area = idx break - var tab_width := clampf((size.x - size.y - scroll_backwards_button_width -\ - scroll_forwards_button_width) / get_proper_tab_count(), + var tab_width := clampf((size.x - size.y - scroll_backwards_button_width - scroll_forwards_button_width) / get_proper_tab_count(), MIN_TAB_WIDTH, DEFAULT_TAB_WIDTH) for idx in range(first_tab_with_area, Configs.savedata.get_tab_count()): var tab_rect := get_tab_rect(idx) - if not tab_rect.has_area() or tab_width * (idx + 0.5) - current_scroll +\ - scroll_backwards_button_width > pos.x: + if not tab_rect.has_area() or tab_width * (idx + 0.5) - current_scroll + scroll_backwards_button_width > pos.x: return idx return Configs.savedata.get_tab_count() @@ -531,8 +497,7 @@ func _get_drag_data(at_position: Vector2) -> Variant: var preview := Panel.new() preview.modulate = Color(1, 1, 1, 0.85) preview.custom_minimum_size = Vector2(tab_width, size.y) - preview.add_theme_stylebox_override("panel", - get_theme_stylebox("tab_selected", "TabContainer")) + preview.add_theme_stylebox_override("panel", get_theme_stylebox("tab_selected", "TabContainer")) var label := Label.new() label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS label.text = Configs.savedata.get_active_tab().presented_name diff --git a/src/ui_parts/top_app_bar.gd b/src/ui_parts/top_app_bar.gd index f7b3655..271bcdb 100644 --- a/src/ui_parts/top_app_bar.gd +++ b/src/ui_parts/top_app_bar.gd @@ -1,7 +1,5 @@ extends HBoxContainer -const LayoutPopup = preload("res://src/ui_parts/layout_popup.gd") - const LayoutPopupScene = preload("res://src/ui_parts/layout_popup.tscn") @onready var more_options: Button = $MoreOptions @@ -41,8 +39,7 @@ func _on_size_button_pressed() -> void: ContextPopup.create_shortcut_button("optimize")] var context_popup := ContextPopup.new() context_popup.setup(btn_array, true) - HandlerGUI.popup_under_rect_center(context_popup, size_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, size_button.get_global_rect(), get_viewport()) func _on_more_options_pressed() -> void: var can_show_savedata_folder := DisplayServer.has_feature( @@ -65,8 +62,7 @@ func _on_more_options_pressed() -> void: var more_popup := ContextPopup.new() more_popup.setup(buttons_arr, true, -1, -1, separator_indices) - HandlerGUI.popup_under_rect_center(more_popup, more_options.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(more_popup, more_options.get_global_rect(), get_viewport()) func open_savedata_folder() -> void: @@ -97,8 +93,7 @@ func update_size_button_colors() -> void: func _on_layout_button_pressed() -> void: var layout_popup := LayoutPopupScene.instantiate() - HandlerGUI.popup_under_rect_center(layout_popup, layout_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(layout_popup, layout_button.get_global_rect(), get_viewport()) func _on_new_tab_button_pressed() -> void: diff --git a/src/ui_parts/update_menu.gd b/src/ui_parts/update_menu.gd index a7b2005..5b55195 100644 --- a/src/ui_parts/update_menu.gd +++ b/src/ui_parts/update_menu.gd @@ -22,15 +22,13 @@ func _ready() -> void: close_button.text = Translator.translate("Close") retry_button.tooltip_text = Translator.translate("Retry") prereleases_button.text = Translator.translate("Show prereleases") - current_version_label.text = Translator.translate("Current Version") + ": " +\ - current_version + current_version_label.text = Translator.translate("Current Version") + ": " + current_version request() func request() -> void: retry_button.hide() status_label.text = Translator.translate("Retrieving information...") - var err := http.request("https://api.github.com/repos/syntaxerror247/VectorTouch/releases", - ["User-Agent: syntaxerror247/VectorTouch"]) + var err := http.request("https://api.github.com/repos/syntaxerror247/VectorTouch/releases", ["User-Agent: syntaxerror247/VectorTouch"]) if err != OK: display_error_message(error_string(err)) diff --git a/src/ui_parts/viewport.gd b/src/ui_parts/viewport.gd index a534979..cdab875 100644 --- a/src/ui_parts/viewport.gd +++ b/src/ui_parts/viewport.gd @@ -72,21 +72,17 @@ func _unhandled_input(event: InputEvent) -> void: if State.get_viewport().gui_is_dragging(): return - if event is InputEventMouseMotion and\ - event.button_mask & (MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_MIDDLE): + if event is InputEventMouseMotion and event.button_mask & (MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_MIDDLE): # Zooming with Ctrl + MMB. if event.ctrl_pressed and event.button_mask == MOUSE_BUTTON_MASK_MIDDLE: if _zoom_to == Vector2.ZERO: # Set zoom position if starting action. _zoom_to = get_mouse_position() / Vector2(size) - zoom_menu.set_zoom(State.zoom * (1.0 +\ - (1 if Configs.savedata.invert_zoom else -1) *\ - (wrap_mouse(event.relative).y if Configs.savedata.wraparound_panning else\ - event.relative.y) / 128.0), _zoom_to) + zoom_menu.set_zoom(State.zoom * (1.0 + (1 if Configs.savedata.invert_zoom else -1) *\ + (wrap_mouse(event.relative).y if Configs.savedata.wraparound_panning else event.relative.y) / 128.0), _zoom_to) # Panning with LMB or MMB. This gives a reliable way to adjust the view # without dragging the things on it. else: - set_view(view.camera_unsnapped_position - (wrap_mouse(event.relative) if\ - Configs.savedata.wraparound_panning else event.relative) / State.zoom) + set_view(view.camera_unsnapped_position - (wrap_mouse(event.relative) if Configs.savedata.wraparound_panning else event.relative) / State.zoom) elif event is InputEventPanGesture and not DisplayServer.get_name() == "Android": # Zooming with Ctrl + touch? @@ -104,8 +100,7 @@ func _unhandled_input(event: InputEvent) -> void: var zoom_dir := 0 # Zooming with scrolling. - if (not event.ctrl_pressed and not event.shift_pressed and\ - not Configs.savedata.use_ctrl_for_zoom) or\ + if (not event.ctrl_pressed and not event.shift_pressed and not Configs.savedata.use_ctrl_for_zoom) or\ (event.ctrl_pressed and Configs.savedata.use_ctrl_for_zoom): match event.button_index: MOUSE_BUTTON_WHEEL_UP when Configs.savedata.invert_zoom: zoom_dir = -1 @@ -152,8 +147,7 @@ func _unhandled_input(event: InputEvent) -> void: func _on_zoom_changed(new_zoom_level: float, offset: Vector2) -> void: State.set_zoom(new_zoom_level) adjust_view(offset) - display.material.set_shader_parameter("uv_scale", - nearest_po2(int(State.zoom * 32.0)) / 32.0) + display.material.set_shader_parameter("uv_scale", nearest_po2(int(State.zoom * 32.0)) / 32.0) var last_size_adjusted := size / State.zoom @@ -161,10 +155,8 @@ func adjust_view(offset := Vector2(0.5, 0.5)) -> void: var old_size := last_size_adjusted last_size_adjusted = size / State.zoom - var svg_w := State.root_element.width if\ - State.root_element.has_attribute("width") else 16384.0 - var svg_h := State.root_element.height if\ - State.root_element.has_attribute("height") else 16384.0 + var svg_w := State.root_element.width if State.root_element.has_attribute("width") else 16384.0 + var svg_h := State.root_element.height if State.root_element.has_attribute("height") else 16384.0 var zoomed_size := BUFFER_VIEW_SPACE * size / State.zoom limit_left = -zoomed_size.x @@ -172,9 +164,8 @@ func adjust_view(offset := Vector2(0.5, 0.5)) -> void: limit_top = -zoomed_size.y limit_bottom = zoomed_size.y + svg_h - set_view(Vector2(lerpf(view.camera_unsnapped_position.x, view.camera_unsnapped_position.x +\ - old_size.x - size.x / State.zoom, offset.x), lerpf(view.camera_unsnapped_position.y, - view.camera_unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y))) + set_view(Vector2(lerpf(view.camera_unsnapped_position.x, view.camera_unsnapped_position.x + old_size.x - size.x / State.zoom, offset.x), + lerpf(view.camera_unsnapped_position.y, view.camera_unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y))) func _on_size_changed() -> void: State.set_viewport_size(size) @@ -185,9 +176,7 @@ func wrap_mouse(relative: Vector2) -> Vector2: var mouse_pos := get_mouse_position() if not view_rect.has_point(mouse_pos): - warp_mouse(Vector2(fposmod(mouse_pos.x, view_rect.size.x), - fposmod(mouse_pos.y, view_rect.size.y))) + warp_mouse(Vector2(fposmod(mouse_pos.x, view_rect.size.x), fposmod(mouse_pos.y, view_rect.size.y))) return Vector2(fmod(relative.x + signf(relative.x) * warp_margin.x, view_rect.size.x), - fmod(relative.y + signf(relative.y) * warp_margin.y, view_rect.size.y)) -\ - relative.sign() * warp_margin + fmod(relative.y + signf(relative.y) * warp_margin.y, view_rect.size.y)) - relative.sign() * warp_margin diff --git a/src/ui_widgets/BetterButton.gd b/src/ui_widgets/BetterButton.gd index 64819d8..fadcf09 100644 --- a/src/ui_widgets/BetterButton.gd +++ b/src/ui_widgets/BetterButton.gd @@ -9,6 +9,11 @@ var timer: SceneTreeTimer ## A shortcut that corresponds to the same action that this button does. @export var action := "" +var shortcuts_bind: ShortcutsRegistration: + set(new_value): + shortcuts_bind = new_value + if is_instance_valid(shortcuts_bind): + shortcuts_bind.activated.connect(_on_shortcut_activated) func _ready() -> void: @@ -21,26 +26,27 @@ func _on_pressed() -> void: set_deferred("just_pressed", false) HandlerGUI.throw_action_event(action) -func _unhandled_input(event: InputEvent) -> void: - if action.is_empty() or toggle_mode: +func _on_shortcut_activated(activated_action: String) -> void: + if activated_action != action or toggle_mode or just_pressed: return - if not just_pressed and ShortcutUtils.is_action_pressed(event, action): - begin_bulk_theme_override() - add_theme_color_override("icon_normal_color", get_theme_color("icon_pressed_color")) - add_theme_color_override("icon_hover_color", get_theme_color("icon_pressed_color")) - add_theme_stylebox_override("normal", get_theme_stylebox("pressed")) - add_theme_stylebox_override("hover", get_theme_stylebox("hover_pressed")) - end_bulk_theme_override() - if is_instance_valid(timer): - timer.timeout.disconnect(end_highlight) - timer = get_tree().create_timer(HIGHLIGHT_TIME) - timer.timeout.connect(end_highlight) + begin_bulk_theme_override() + add_theme_color_override("icon_normal_color", get_theme_color("icon_pressed_color")) + add_theme_color_override("icon_hover_color", get_theme_color("icon_pressed_color")) + add_theme_stylebox_override("normal", get_theme_stylebox("pressed")) + add_theme_stylebox_override("hover", get_theme_stylebox("hover_pressed")) + end_bulk_theme_override() + if is_instance_valid(timer): + timer.timeout.disconnect(end_highlight) + timer = get_tree().create_timer(HIGHLIGHT_TIME) + timer.timeout.connect(end_highlight) func end_highlight() -> void: + begin_bulk_theme_override() remove_theme_color_override("icon_normal_color") remove_theme_color_override("icon_hover_color") remove_theme_stylebox_override("normal") remove_theme_stylebox_override("hover") + end_bulk_theme_override() timer = null diff --git a/src/ui_widgets/BetterLineEdit.gd b/src/ui_widgets/BetterLineEdit.gd index c5c5b86..0a2c3e3 100644 --- a/src/ui_widgets/BetterLineEdit.gd +++ b/src/ui_widgets/BetterLineEdit.gd @@ -7,8 +7,6 @@ var original_selection_color: Color ## Emitted when Esc is pressed to cancel the current text change. signal text_change_canceled -var _hovered := false - ## When turned on, uses the mono font for the tooltip. @export var mono_font_tooltip := false @@ -29,7 +27,7 @@ func _init() -> void: caret_blink_interval = 0.6 focus_entered.connect(_on_base_class_focus_entered) focus_exited.connect(_on_base_class_focus_exited) - mouse_exited.connect(_on_base_class_mouse_exited) + mouse_exited.connect(queue_redraw) text_submitted.connect(release_focus.unbind(1)) original_selection_color = get_theme_color("selection_color") Configs.theme_changed.connect(sync_theming) @@ -47,8 +45,7 @@ var popup_level := -1 # Set when focused, as it can't be focused unless it's to func _on_base_class_focus_entered() -> void: # Hack to check if focus entered was from a mouse click. - if get_global_rect().has_point(get_viewport().get_mouse_position()) and\ - Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + if get_global_rect().has_point(get_viewport().get_mouse_position()) and Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): first_click = true else: select_all() @@ -65,13 +62,9 @@ func _on_base_class_focus_exited() -> void: # If ui_accept is pressed, text_submitted gets emitted anyway. text_submitted.emit(text) -func _on_base_class_mouse_exited() -> void: - _hovered = false - queue_redraw() - func _draw() -> void: - if _hovered and editable and has_theme_stylebox("hover"): + if editable and get_viewport().gui_get_hovered_control() == self and has_theme_stylebox("hover"): draw_style_box(get_theme_stylebox("hover"), Rect2(Vector2.ZERO, size)) func _make_custom_tooltip(for_text: String) -> Object: @@ -90,8 +83,7 @@ func _input(event: InputEvent) -> void: if event is InputEventMouseButton and (event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE]): - if event.is_pressed() and not get_global_rect().has_point(event.position) and\ - popup_level == HandlerGUI.popup_stack.size(): + if event.is_pressed() and not get_global_rect().has_point(event.position) and popup_level == HandlerGUI.popup_stack.size(): release_focus() elif event.is_released() and first_click and not has_selection(): first_click = false @@ -114,10 +106,8 @@ func _gui_input(event: InputEvent) -> void: mouse_filter = Utils.mouse_filter_pass_non_drag_events(event) if event is InputEventMouseMotion and event.button_mask == 0: - _hovered = true queue_redraw() - elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and\ - event.is_pressed(): + elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): grab_focus() var btn_arr: Array[Button] = [] var separator_arr: Array[int] = [] diff --git a/src/ui_widgets/BetterTextEdit.gd b/src/ui_widgets/BetterTextEdit.gd index 20d292d..06f69ca 100644 --- a/src/ui_widgets/BetterTextEdit.gd +++ b/src/ui_widgets/BetterTextEdit.gd @@ -10,8 +10,6 @@ var _timer := Timer.new() var _is_caret_queued_for_redraw := false -var _hovered := false - func _init() -> void: # Solves an issue where Ctrl+S would type an "s" and handle the input. # We want anything with Ctrl to not be handled, but other keys to still be handled. @@ -31,7 +29,7 @@ func _ready() -> void: _timer.timeout.connect(blink) get_v_scroll_bar().value_changed.connect(queue_redraw_caret.unbind(1)) get_h_scroll_bar().value_changed.connect(queue_redraw_caret.unbind(1)) - mouse_exited.connect(_on_base_class_mouse_exited) + mouse_exited.connect(queue_redraw) focus_entered.connect(_on_base_class_focus_entered) focus_exited.connect(_on_base_class_focus_exited) caret_changed.connect(queue_redraw_caret) @@ -50,8 +48,7 @@ func recalibrate_line_gutter() -> void: set_gutter_custom_draw(0, _line_number_draw_callback) set_gutter_clickable(0, false) var max_digits := floori(log(get_line_count()) / log(10) + 1.0) - _line_gutter_needed_space = int(max_digits * get_theme_font("font").get_char_size(69, - get_theme_font_size("font_size")).x) + 11 + _line_gutter_needed_space = int(max_digits * get_theme_font("font").get_char_size(69, get_theme_font_size("font_size")).x) + 11 set_gutter_width(0, _line_gutter_needed_space) func _line_number_draw_callback(line: int, _gutter: int, region: Rect2) -> void: @@ -63,11 +60,9 @@ func _line_number_draw_callback(line: int, _gutter: int, region: Rect2) -> void: var font_size := get_theme_font_size("font_size") # Center vertically, align to the left of the gutter. - var text_pos := Vector2(-5, - region.get_center().y + font.get_ascent(font_size) - font.get_string_size( + var text_pos := Vector2(-5, region.get_center().y + font.get_ascent(font_size) - font.get_string_size( line_number_text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).y / 2) - draw_string(font, text_pos, line_number_text, HORIZONTAL_ALIGNMENT_RIGHT, - _line_gutter_needed_space, font_size, ThemeUtils.dimmer_text_color) + draw_string(font, text_pos, line_number_text, HORIZONTAL_ALIGNMENT_RIGHT, _line_gutter_needed_space, font_size, ThemeUtils.dimmer_text_color) func _exit_tree() -> void: @@ -97,7 +92,8 @@ func _redraw_caret() -> void: if not has_focus(): return - var char_size := ThemeUtils.mono_font.get_char_size(69, get_theme_font_size("font_size")) + var font_size := get_theme_font_size("font_size") + var char_size := ThemeUtils.mono_font.get_char_size(69, font_size) for caret in get_caret_count(): var caret_pos := Vector2.ZERO var caret_column := get_caret_column(caret) @@ -110,39 +106,26 @@ func _redraw_caret() -> void: var glyph_end := Vector2(get_rect_at_line_column(caret_line, caret_column).end) caret_pos = Vector2(glyph_end.x + 1, glyph_end.y - 2) var line := get_line(caret_line) - # Workaround for indent_wrapped_lines. - if get_line_wrap_index_at_column(caret_line, caret_column) >= 1: - var i := 0 - while true: - var c := line[i] - if c == ' ': - caret_pos.x += char_size.x - elif c == '\t': - caret_pos.x += char_size.x * get_tab_size() - else: - break - i += 1 # Workaround for ligatures. - if (caret_column >= line.length() or line[caret_column] != '\t') and\ - glyph_end.x > 0 and glyph_end.y > 0: + if (caret_column >= line.length() or line[caret_column] != '\t') and glyph_end.x > 0 and glyph_end.y > 0: var chars_back := 0 - while line.length() > caret_column + chars_back and glyph_end ==\ - Vector2(get_rect_at_line_column(caret_line, caret_column + chars_back + 1).end): + while line.length() > caret_column + chars_back and glyph_end == Vector2(get_rect_at_line_column(caret_line, caret_column + chars_back + 1).end): chars_back += 1 caret_pos.x -= char_size.x # Determine the end of the caret and draw it. var caret_end := caret_pos if is_overtype_mode_enabled(): - var char_width: float if caret_column >= get_line(caret_line).length(): - char_width = char_size.x + caret_end.x += char_size.x else: - char_width = get_rect_at_line_column(caret_line, caret_column + 1).size.x - caret_end.x += char_width + var caret_char := get_line(caret_line)[caret_column] + if caret_char == '\t': + caret_end.x += char_size.x * get_tab_size() + else: + caret_end.x += ThemeUtils.mono_font.get_char_size(ord(caret_char), font_size).x else: caret_end.y -= char_size.y + 1 - RenderingServer.canvas_item_add_line(_surface, caret_pos, caret_end, - ThemeUtils.caret_color, 1) + RenderingServer.canvas_item_add_line(_surface, caret_pos, caret_end, ThemeUtils.caret_color, 1) var _blonk := true func blink() -> void: @@ -156,26 +139,22 @@ func _on_base_class_focus_exited() -> void: _timer.stop() RenderingServer.canvas_item_clear(_surface) -func _on_base_class_mouse_exited() -> void: - _hovered = false - queue_redraw() - func _draw() -> void: - if editable and _hovered and has_theme_stylebox("hover"): + if editable and get_viewport().gui_get_hovered_control() == self and has_theme_stylebox("hover"): draw_style_box(get_theme_stylebox("hover"), Rect2(Vector2.ZERO, size)) if get_gutter_count() == 1: var col := ThemeUtils.subtle_text_color col.a *= 0.4 - draw_line(Vector2(_line_gutter_needed_space, 0), - Vector2(_line_gutter_needed_space, size.y), col) + var normal_stylebox := get_theme_stylebox("normal") + var top_border: float = normal_stylebox.border_width_top if normal_stylebox is StyleBoxFlat else 0.0 + var bottom_border: float = normal_stylebox.border_width_bottom if normal_stylebox is StyleBoxFlat else 0.0 + draw_line(Vector2(_line_gutter_needed_space, top_border), Vector2(_line_gutter_needed_space, size.y - bottom_border), col) func _input(event: InputEvent) -> void: - if (has_focus() and event is InputEventMouseButton and (event.button_index in\ - [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE]) and\ - event.is_pressed() and not get_global_rect().has_point(event.position) and\ - HandlerGUI.popup_stack.is_empty()): + if (has_focus() and event is InputEventMouseButton and (event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE]) and\ + event.is_pressed() and not get_global_rect().has_point(event.position) and HandlerGUI.popup_stack.is_empty()): release_focus() func _gui_input(event: InputEvent) -> void: @@ -191,7 +170,6 @@ func _gui_input(event: InputEvent) -> void: mouse_filter = Utils.mouse_filter_pass_non_drag_events(event) if event is InputEventMouseMotion and event.button_mask == 0: - _hovered = true queue_redraw() elif event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): diff --git a/src/ui_widgets/ContextPopup.gd b/src/ui_widgets/ContextPopup.gd index 702d0d6..6ada555 100644 --- a/src/ui_widgets/ContextPopup.gd +++ b/src/ui_widgets/ContextPopup.gd @@ -65,7 +65,7 @@ static func create_button(text: String, press_callback: Callable, disabled := fa main_button.icon = icon if press_callback.is_valid(): - main_button.pressed.connect(press_callback) + main_button.pressed.connect(press_callback, CONNECT_ONE_SHOT) main_button.pressed.connect(HandlerGUI.remove_popup) if not dim_text.is_empty(): @@ -77,11 +77,13 @@ static func create_button(text: String, press_callback: Callable, disabled := fa if disabled: shortcut_text_color.a *= 0.75 - var CONST_ARR: PackedStringArray = ["normal", "hover", "pressed"] + main_button.begin_bulk_theme_override() + var CONST_ARR: PackedStringArray = ["normal", "hover", "pressed", "disabled"] for theme_style in CONST_ARR: var sb := main_button.get_theme_stylebox(theme_style, "ContextButton").duplicate() sb.content_margin_right += dim_text_width + 8 main_button.add_theme_stylebox_override(theme_style, sb) + main_button.end_bulk_theme_override() var on_main_button_draw := func() -> void: var sb := ThemeDB.get_default_theme().get_stylebox("normal", "ContextButton") @@ -92,21 +94,23 @@ static func create_button(text: String, press_callback: Callable, disabled := fa return main_button -static func create_shortcut_checkbox(action: String, start_pressed: bool) -> CheckBox: +static func create_shortcut_checkbox(action: String, start_pressed: bool, disabled := false) -> CheckBox: if not InputMap.has_action(action): push_error("Non-existent shortcut was passed.") return return create_checkbox(TranslationUtils.get_action_description(action, true), HandlerGUI.throw_action_event.bind(action), - start_pressed, ShortcutUtils.get_action_showcase_text(action)) + start_pressed, disabled, ShortcutUtils.get_action_showcase_text(action)) -static func create_checkbox(text: String, toggle_action: Callable, -start_pressed: bool, dim_text := "") -> CheckBox: +static func create_checkbox(text: String, toggle_action: Callable, start_pressed: bool, disabled := false, dim_text := "") -> CheckBox: # Create main checkbox. var checkbox := CheckBox.new() checkbox.focus_mode = Control.FOCUS_NONE - checkbox.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + if disabled: + checkbox.disabled = true + else: + checkbox.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND checkbox.text = text checkbox.button_pressed = start_pressed @@ -116,13 +120,18 @@ start_pressed: bool, dim_text := "") -> CheckBox: var font := checkbox.get_theme_font("font") var font_size := checkbox.get_theme_font_size("font_size") var dim_text_width := font.get_string_size(dim_text, HORIZONTAL_ALIGNMENT_RIGHT, -1, font_size).x + var shortcut_text_color := ThemeUtils.subtle_text_color + if disabled: + shortcut_text_color.a *= 0.75 - var CONST_ARR: PackedStringArray = ["normal", "hover", "pressed"] + checkbox.begin_bulk_theme_override() + var CONST_ARR: PackedStringArray = ["normal", "hover", "pressed", "disabled"] for theme_style in CONST_ARR: var sb := checkbox.get_theme_stylebox(theme_style, "CheckBox").duplicate() sb.content_margin_right += dim_text_width + 8 checkbox.add_theme_stylebox_override(theme_style, sb) + checkbox.end_bulk_theme_override() var on_shortcut_draw := func() -> void: var sb := ThemeDB.get_default_theme().get_stylebox("normal", "CheckBox") @@ -136,8 +145,6 @@ func _setup_button(btn: Button, align_left: bool) -> Button: if align_left: btn.alignment = HORIZONTAL_ALIGNMENT_LEFT btn.ready.connect(_order_signals.bind(btn)) - if btn.get_child_count() == 1: - btn.get_child(0).resized.connect(_resize_button_around_child.bind(btn)) return btn # A hack to deal with situations where a popup is replaced by another. @@ -148,11 +155,6 @@ func _order_signals(btn: Button) -> void: btn.pressed.connect(connection.callable, CONNECT_DEFERRED) set_block_signals(true) -# A hack for buttons that are wrapped around a control. -func _resize_button_around_child(btn: Button) -> void: - var child: Control = btn.get_child(0) - btn.custom_minimum_size = child.size - func setup(buttons: Array[Button], align_left := false, min_width := -1.0, max_height := -1.0, separator_indices := PackedInt32Array()) -> void: var main_container := _common_initial_setup() diff --git a/src/ui_widgets/DeltaHandle.gd b/src/ui_widgets/DeltaHandle.gd index 7f6bd6c..28cadd9 100644 --- a/src/ui_widgets/DeltaHandle.gd +++ b/src/ui_widgets/DeltaHandle.gd @@ -7,8 +7,7 @@ var y_name: String var d_name: String var horizontal: bool -func _init(new_element: Element, xref: String, yref: String, dref: String, -p_horizontal: bool) -> void: +func _init(new_element: Element, xref: String, yref: String, dref: String, p_horizontal: bool) -> void: element = new_element x_name = xref y_name = yref @@ -26,8 +25,7 @@ func set_pos(new_pos: PackedFloat64Array) -> void: new_pos[0] = element.get_attribute_num(x_name) if precise_pos != new_pos: - element.set_attribute(d_name, absf(new_pos[0] - element.get_attribute_num(x_name)\ - if horizontal else new_pos[1] - element.get_attribute_num(y_name))) + element.set_attribute(d_name, absf(new_pos[0] - element.get_attribute_num(x_name) if horizontal else new_pos[1] - element.get_attribute_num(y_name))) sync() func sync() -> void: diff --git a/src/ui_widgets/LineEditButton.gd b/src/ui_widgets/LineEditButton.gd index 3d537dc..29cf16b 100644 --- a/src/ui_widgets/LineEditButton.gd +++ b/src/ui_widgets/LineEditButton.gd @@ -160,22 +160,18 @@ func _draw() -> void: var horizontal_margin_width := sb.content_margin_left + sb.content_margin_right if not active: sb.draw(ci, Rect2(Vector2.ZERO, size)) - draw_line(Vector2(size.x - BUTTON_WIDTH, 0), - Vector2(size.x - BUTTON_WIDTH, size.y), sb.border_color, 2) + draw_line(Vector2(size.x - BUTTON_WIDTH, 0), Vector2(size.x - BUTTON_WIDTH, size.y), sb.border_color, 2) # The default overrun behavior couldn't be changed for the simplest draw methods. var text_obj := TextLine.new() text_obj.text_overrun_behavior = TextServer.OVERRUN_TRIM_CHAR text_obj.width = size.x - BUTTON_WIDTH - horizontal_margin_width - text_obj.add_string(placeholder_text if text.is_empty() else text, _get_font(), - get_theme_font_size("font_size", "LineEdit")) - text_obj.draw(ci, Vector2(5, 2), get_theme_color("font_placeholder_color", - "LineEdit") if text.is_empty() else _get_font_color()) + text_obj.add_string(placeholder_text if text.is_empty() else text, _get_font(), get_theme_font_size("font_size", "LineEdit")) + text_obj.draw(ci, Vector2(5, 2), get_theme_color("font_placeholder_color", "LineEdit") if text.is_empty() else _get_font_color()) if is_instance_valid(icon): var icon_side := BUTTON_WIDTH - horizontal_margin_width + 2 - icon.draw_rect(ci, Rect2(size.x - (BUTTON_WIDTH + 0.5 + icon_side) / 2, - (size.y - icon_side) / 2, icon_side, icon_side), false, - get_theme_color("icon_normal_color", "LeftConnectedButton")) + icon.draw_rect(ci, Rect2(size.x - (BUTTON_WIDTH + 0.5 + icon_side) / 2, (size.y - icon_side) / 2, + icon_side, icon_side), false, get_theme_color("icon_normal_color", "LeftConnectedButton")) # Helpers @@ -184,11 +180,9 @@ func _get_font() -> Font: return ThemeUtils.mono_font if use_mono_font else ThemeUtils.regular_font func _get_font_color() -> Color: - return get_theme_color("font_color", "LineEdit") if font_color == Color.TRANSPARENT\ - else font_color + return get_theme_color("font_color", "LineEdit") if font_color == Color.TRANSPARENT else font_color func draw_button_border(theme_name: String) -> void: - var button_outline: StyleBoxFlat =\ - get_theme_stylebox(theme_name, "LeftConnectedButton").duplicate() + var button_outline: StyleBoxFlat = get_theme_stylebox(theme_name, "LeftConnectedButton").duplicate() button_outline.draw_center = false button_outline.draw(ci, Rect2(size.x - BUTTON_WIDTH, 0, BUTTON_WIDTH, size.y)) diff --git a/src/ui_widgets/PanelGrid.gd b/src/ui_widgets/PanelGrid.gd index 07824e3..bbde59c 100644 --- a/src/ui_widgets/PanelGrid.gd +++ b/src/ui_widgets/PanelGrid.gd @@ -1,6 +1,8 @@ @icon("res://godot_only/icons/PanelGrid.svg") class_name PanelGrid extends Control +const copy_icon = preload("res://assets/icons/Copy.svg") + # Can be made into vars if necessary. const border_width = 1 const side_spacing = 6 @@ -11,8 +13,15 @@ const bottom_spacing = 2 @export var items: PackedStringArray @export var dim_last_item := false +var boxes: Array[Rect2] = [] +var copy_button: Button + + +func _ready() -> void: + mouse_exited.connect(remove_copy_button) func _draw() -> void: + boxes.clear() var item_count := items.size() if item_count == 0: return @@ -31,28 +40,59 @@ func _draw() -> void: custom_minimum_size.y = box_height * ceili(item_count / float(effective_columns)) + # One big filled rect for everything but the last row. @warning_ignore("integer_division") RenderingServer.canvas_item_add_rect(ci, Rect2(0, 0, size.x, box_height * (item_count / effective_columns)), inner_color) - for item_idx in item_count: - var pos_x := (size.x / effective_columns) * (item_idx % effective_columns) + for idx in item_count: + var pos_x := (size.x / effective_columns) * (idx % effective_columns) @warning_ignore("integer_division") - var pos_y := box_height * (item_idx / effective_columns) + var pos_y := box_height * (idx / effective_columns) - if item_idx == item_count - 1: + # Sigh... + var box_rect := Rect2(pos_x, pos_y, box_width, box_height) + if is_zero_approx(pos_x): + box_rect = Rect2(1, pos_y, box_width - 1, box_height) + boxes.append(box_rect) + + if idx == item_count - 1: if item_count % effective_columns != 0: - RenderingServer.canvas_item_add_rect(ci, - Rect2(pos_x, pos_y, box_width, box_height), inner_color) + RenderingServer.canvas_item_add_rect(ci, box_rect, inner_color) if dim_last_item: text_color = ThemeUtils.dimmer_text_color - # Sigh... - if is_zero_approx(pos_x): - draw_rect(Rect2(1, pos_y, box_width - 1, box_height), border_color, false, 1.0) - else: - draw_rect(Rect2(pos_x, pos_y, box_width, box_height), border_color, false, 1.0) - - text_font.draw_string(ci, Vector2(pos_x + side_spacing, pos_y + top_spacing +\ - text_font_size), items[item_idx], HORIZONTAL_ALIGNMENT_LEFT, -1, - text_font_size, text_color) + draw_rect(box_rect, border_color, false, 1.0) + text_font.draw_string(ci, Vector2(pos_x + side_spacing, pos_y + top_spacing + text_font_size), + items[idx], HORIZONTAL_ALIGNMENT_LEFT, -1, text_font_size, text_color) + + +func _gui_input(event: InputEvent) -> void: + if not (event is InputEventMouseMotion): + return + + for idx in items.size(): + var item := items[idx] + var item_after_angle_bracket := item.get_slice("<", 1) + if not item_after_angle_bracket.is_empty(): + if ">" in item_after_angle_bracket: + var email := item_after_angle_bracket.get_slice(">", 0) + var box := boxes[idx] + if box.has_point(event.position): + if not is_instance_valid(copy_button): + copy_button = Button.new() + copy_button.theme_type_variation = "FlatButton" + copy_button.icon = copy_icon + copy_button.focus_mode = Control.FOCUS_NONE + copy_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + copy_button.mouse_filter = Control.MOUSE_FILTER_PASS + copy_button.tooltip_text = Translator.translate("Copy email") + copy_button.pressed.connect(DisplayServer.clipboard_set.bind(email)) + add_child(copy_button) + copy_button.position = Vector2(box.end.x - copy_button.size.x - 1, box.position.y + 1) + return + remove_copy_button() + +func remove_copy_button() -> void: + if is_instance_valid(copy_button): + copy_button.queue_free() diff --git a/src/ui_widgets/PathHandle.gd b/src/ui_widgets/PathHandle.gd index 83e52f0..4146230 100644 --- a/src/ui_widgets/PathHandle.gd +++ b/src/ui_widgets/PathHandle.gd @@ -20,9 +20,12 @@ func set_pos(new_pos: PackedFloat64Array) -> void: if precise_pos != new_pos: var path_attribute: AttributePathdata = element.get_attribute(pathdata_name) var cmd := path_attribute.get_command(command_index) + if Input.is_key_pressed(KEY_CTRL): + new_pos = LineConstraint.constrain(path_attribute, command_index, new_pos, x_param, y_param) if cmd.relative: new_pos[0] -= cmd.start_x new_pos[1] -= cmd.start_y + path_attribute.set_command_property(command_index, x_param, new_pos[0]) path_attribute.set_command_property(command_index, y_param, new_pos[1]) sync() @@ -32,8 +35,7 @@ func sync() -> void: # Handle might have been removed. return - var command: PathCommand =\ - element.get_attribute(pathdata_name).get_command(command_index) + var command: PathCommand = element.get_attribute(pathdata_name).get_command(command_index) if x_param in command: var command_x: float = command.get(x_param) precise_pos[0] = command.start_x + command_x if command.relative else command_x @@ -50,3 +52,76 @@ func sync() -> void: func _on_attribute_changed(name: String) -> void: if name in [pathdata_name, "transform"]: sync() + +class LineConstraint: + extends RefCounted + + enum Mode {PREVIOUS, NEXT} + + const valid_prev_commands = ["c", "C", "s", "S", "q", "Q", "l", "L", "h", "H", "v", "V"] + const prev_mode_support = ["c", "C", "q", "Q", "l", "L"] + const valid_next_commands = ["c", "C", "q", "Q", "l", "L", "h", "H", "v", "V"] + const next_mode_support = ["c", "C", "s", "S", "q", "Q"] + + static func constrain( path: AttributePathdata, idx: int, pos: PackedFloat64Array, x_param: String, y_param: String) -> PackedFloat64Array: + var cmd := path.get_command(idx) + + # Move everything to a local (translated) coordinate system with the new origin at the + # connection between the two commands. + + # Define a line using the connection between the 2 commands and whichever attribute we + # care about on the other end. Use vector projection to transform the input. + var opposite := PackedFloat64Array([0, 0]) + var mode: Mode + + # Determine if using next or previous command. + if idx != 0 and path.get_command(idx - 1).command_char in valid_prev_commands and\ + cmd.command_char in prev_mode_support and not ((cmd.command_char in ["c", "C", "q", "Q"]) and\ + (x_param != "x1" or y_param != "y1")): + mode = Mode.PREVIOUS + elif idx < path.get_command_count() - 1 and path.get_command(idx + 1).command_char in valid_next_commands and\ + cmd.command_char in next_mode_support and not ((cmd.command_char in ["c", "C", "s", "S"]) and\ + (x_param != "x2" or y_param != "y2") or (cmd.command_char in ["q", "Q"]) and (x_param != "x1" or y_param != "y1")): + mode = Mode.NEXT + else: + return pos + + # Get the other command and determine the translation offset. + var other:= path.get_command(idx - 1) if mode == Mode.PREVIOUS else path.get_command(idx + 1) + var offset: PackedFloat64Array = [cmd.start_x, cmd.start_y] if mode == Mode.PREVIOUS else [other.start_x, other.start_y] + + # Get the global coords of the opposite point. + match other.command_char: + "c", "C", "s", "S" when mode == Mode.PREVIOUS: + opposite = [other.get("x2"), other.get("y2")] + "q", "Q" when mode == Mode.PREVIOUS: + opposite = [other.get("x1"), other.get("y1")] + "l", "h", "v" when mode == Mode.PREVIOUS: + pass + "L", "H", "V" when mode == Mode.PREVIOUS: + opposite = [other.start_x, other.start_y] + "c", "C", "q", "Q" when mode == Mode.NEXT: + opposite = [other.get("x1"), other.get("y1")] + "l", "L" when mode == Mode.NEXT: + opposite = [other.get("x"), other.get("y")] + "h" when mode == Mode.NEXT: + opposite = [other.get("x"), 0.0] + "H" when mode == Mode.NEXT: + opposite = [other.get("x"), other.start_y] + "v" when mode == Mode.NEXT: + opposite = [0.0, other.get("y")] + "V" when mode == Mode.NEXT: + opposite = [other.start_x, other.get("y")] + if other.relative: + opposite = [opposite[0] + other.start_x, opposite[1] + other.start_y] + + # Translate opposite point to local. + opposite = [opposite[0] - offset[0], opposite[1] - offset[1]] + + # Input to local. + pos = [pos[0] - offset[0], pos[1] - offset[1]] + + pos = Utils64Bit.vector_project(pos, opposite) + + # Input back to global. + return [pos[0] + offset[0], pos[1] + offset[1]] diff --git a/src/ui_widgets/TitledPanel.gd b/src/ui_widgets/TitledPanel.gd index ab8dd9e..53e7d58 100644 --- a/src/ui_widgets/TitledPanel.gd +++ b/src/ui_widgets/TitledPanel.gd @@ -23,10 +23,8 @@ func _get_minimum_size_common_logic(vertical: bool) -> Vector2: var other_axis := 0 if vertical else 1 # The border width counts as part of both the title and the panel. var output: Vector2 - output[stack_axis] = title_minimum_size[stack_axis] + panel_minimum_size[stack_axis] +\ - title_margin * 2 + panel_margin * 2 - border_width - output[other_axis] = maxf(title_minimum_size[other_axis] + title_margin * 2, - panel_minimum_size[other_axis] + panel_margin * 2) + output[stack_axis] = title_minimum_size[stack_axis] + panel_minimum_size[stack_axis] + title_margin * 2 + panel_margin * 2 - border_width + output[other_axis] = maxf(title_minimum_size[other_axis] + title_margin * 2, panel_minimum_size[other_axis] + panel_margin * 2) return output @@ -47,17 +45,14 @@ func _notification_common_logic(what: int, vertical: bool) -> void: fit_child_in_rect(title, Rect2(Vector2(title_margin, title_margin), title_size)) var panel_position: Vector2 - panel_position[stack_axis] = title.size[stack_axis] + title_margin * 2 +\ - panel_margin - border_width + panel_position[stack_axis] = title.size[stack_axis] + title_margin * 2 + panel_margin - border_width panel_position[other_axis] = panel_margin var panel_size: Vector2 - panel_size[stack_axis] = size[stack_axis] - title_margin * 2 - panel_margin * 2 -\ - title.size[stack_axis] + border_width + panel_size[stack_axis] = size[stack_axis] - title_margin * 2 - panel_margin * 2 - title.size[stack_axis] + border_width panel_size[other_axis] = size[other_axis] - panel_margin * 2 fit_child_in_rect(panel, Rect2(panel_position, panel_size)) elif what == NOTIFICATION_DRAW: - var separator_pos: float = get_child(0).size[stack_axis] +\ - title_margin * 2 - floor(border_width / 2.0) + var separator_pos: float = get_child(0).size[stack_axis] + title_margin * 2 - floor(border_width / 2.0) if title_color.a > 0: var title_stylebox := StyleBoxFlat.new() title_stylebox.bg_color = title_color diff --git a/src/ui_widgets/basic_xnode_frame.gd b/src/ui_widgets/basic_xnode_frame.gd index 6bf6a35..07c410f 100644 --- a/src/ui_widgets/basic_xnode_frame.gd +++ b/src/ui_widgets/basic_xnode_frame.gd @@ -40,8 +40,7 @@ func _get_drag_data(_at_position: Vector2) -> Variant: return data func _on_xnodes_dragging_state_changed() -> void: - modulate.a = 0.55 if (State.is_xnode_selection_dragged and\ - xnode.xid in State.selected_xids) else 1.0 + modulate.a = 0.55 if (State.is_xnode_selection_dragged and xnode.xid in State.selected_xids) else 1.0 func _on_title_button_pressed() -> void: @@ -50,15 +49,13 @@ func _on_title_button_pressed() -> void: State.normal_select(xnode.xid) var viewport := get_viewport() var rect := title_bar.get_global_rect() - HandlerGUI.popup_under_rect_center(State.get_selection_context( - HandlerGUI.popup_under_rect_center.bind(rect, viewport), + HandlerGUI.popup_under_rect_center(State.get_selection_context(HandlerGUI.popup_under_rect_center.bind(rect, viewport), Utils.LayoutPart.INSPECTOR), rect, viewport) func _gui_input(event: InputEvent) -> void: if event is InputEventMouseMotion and event.button_mask == 0: - if State.semi_hovered_xid != xnode.xid and\ - not XIDUtils.is_parent(xnode.xid, State.hovered_xid): + if State.semi_hovered_xid != xnode.xid and not XIDUtils.is_parent(xnode.xid, State.hovered_xid): State.set_hovered(xnode.xid) elif event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT: @@ -69,8 +66,7 @@ func _gui_input(event: InputEvent) -> void: State.ctrl_select(xnode.xid) elif not xnode.xid in State.selected_xids: State.normal_select(xnode.xid) - elif event.is_released() and not event.shift_pressed and\ - not event.is_command_or_control_pressed() and\ + elif event.is_released() and not event.shift_pressed and not event.is_command_or_control_pressed() and\ State.selected_xids.size() > 1 and xnode.xid in State.selected_xids: State.normal_select(xnode.xid) accept_event() @@ -79,8 +75,7 @@ func _gui_input(event: InputEvent) -> void: State.normal_select(xnode.xid) var viewport := get_viewport() var popup_pos := viewport.get_mouse_position() - HandlerGUI.popup_under_pos(State.get_selection_context( - HandlerGUI.popup_under_pos.bind(popup_pos, viewport), + HandlerGUI.popup_under_pos(State.get_selection_context(HandlerGUI.popup_under_pos.bind(popup_pos, viewport), Utils.LayoutPart.INSPECTOR), popup_pos, viewport) accept_event() @@ -162,8 +157,7 @@ func _draw() -> void: are_all_children_valid = false break - var drop_border_color := Configs.savedata.get_validity_color(false, - not are_all_children_valid) + var drop_border_color := Configs.savedata.get_validity_color(false, not are_all_children_valid) drop_border_color.s = lerpf(drop_border_color.s, 1.0, 0.5) drop_sb.border_color = drop_border_color if drop_xid == parent_xid + PackedInt32Array([xnode.xid[-1]]): diff --git a/src/ui_widgets/choose_name_dialog.gd b/src/ui_widgets/choose_name_dialog.gd index 536821b..56ee534 100644 --- a/src/ui_widgets/choose_name_dialog.gd +++ b/src/ui_widgets/choose_name_dialog.gd @@ -39,17 +39,13 @@ warning_callable := Callable()) -> void: func adapt_to_text(text: String) -> void: var stripped_text := text.strip_edges() # Set up error or warning text. - var error: String = error_callback.call(stripped_text) if\ - error_callback.is_valid() else "" - var warning: String = warning_callback.call(stripped_text) if\ - warning_callback.is_valid() else "" + var error: String = error_callback.call(stripped_text) if error_callback.is_valid() else "" + var warning: String = warning_callback.call(stripped_text) if warning_callback.is_valid() else "" if not error.is_empty(): - rich_text_label.add_theme_color_override("default_color", - Configs.savedata.basic_color_error) + rich_text_label.add_theme_color_override("default_color", Configs.savedata.basic_color_error) rich_text_label.text = error elif not warning.is_empty(): - rich_text_label.add_theme_color_override("default_color", - Configs.savedata.basic_color_warning) + rich_text_label.add_theme_color_override("default_color", Configs.savedata.basic_color_warning) rich_text_label.text = warning else: rich_text_label.text = "" @@ -57,6 +53,5 @@ func adapt_to_text(text: String) -> void: # Disable or enable the action button. var can_do_action := not stripped_text.is_empty() and error.is_empty() action_button.disabled = not can_do_action - action_button.mouse_default_cursor_shape = CURSOR_POINTING_HAND if\ - can_do_action else CURSOR_ARROW + action_button.mouse_default_cursor_shape = CURSOR_POINTING_HAND if can_do_action else CURSOR_ARROW action_button.focus_mode = FOCUS_ALL if can_do_action else FOCUS_NONE diff --git a/src/ui_widgets/configure_color_popup.gd b/src/ui_widgets/color_configuration_popup.gd similarity index 93% rename from src/ui_widgets/configure_color_popup.gd rename to src/ui_widgets/color_configuration_popup.gd index e2a7887..cac7c94 100644 --- a/src/ui_widgets/configure_color_popup.gd +++ b/src/ui_widgets/color_configuration_popup.gd @@ -21,10 +21,8 @@ func _ready() -> void: func sync_localization() -> void: - %LabelContainer/EditButton.tooltip_text =\ - Translator.translate("Edit color name") - $ConfigureContainer/BottomContainer/DeleteButton.tooltip_text =\ - Translator.translate("Delete color") + %LabelContainer/EditButton.tooltip_text = Translator.translate("Edit color name") + $ConfigureContainer/BottomContainer/DeleteButton.tooltip_text = Translator.translate("Delete color") func _on_edit_button_pressed() -> void: color_name_edit.text = palette.get_color_name(idx) diff --git a/src/ui_widgets/configure_color_popup.gd.uid b/src/ui_widgets/color_configuration_popup.gd.uid similarity index 100% rename from src/ui_widgets/configure_color_popup.gd.uid rename to src/ui_widgets/color_configuration_popup.gd.uid diff --git a/src/ui_widgets/configure_color_popup.tscn b/src/ui_widgets/color_configuration_popup.tscn similarity index 76% rename from src/ui_widgets/configure_color_popup.tscn rename to src/ui_widgets/color_configuration_popup.tscn index 7fa1ae4..81775d0 100644 --- a/src/ui_widgets/configure_color_popup.tscn +++ b/src/ui_widgets/color_configuration_popup.tscn @@ -1,33 +1,33 @@ [gd_scene load_steps=7 format=3 uid="uid://b7wobq0ndm35"] -[ext_resource type="Script" uid="uid://1hox6gd5pxku" path="res://src/ui_widgets/BetterLineEdit.gd" id="1_i4wi2"] -[ext_resource type="Script" uid="uid://btl68wj2dmivk" path="res://src/ui_widgets/configure_color_popup.gd" id="1_x6cll"] -[ext_resource type="Texture2D" uid="uid://dr2erka82g6j4" path="res://assets/icons/Edit.svg" id="2_0dind"] -[ext_resource type="FontFile" uid="uid://clpf84p1lfwlp" path="res://assets/fonts/Font.ttf" id="2_j4qfn"] -[ext_resource type="PackedScene" uid="uid://5f8uxavn1or1" path="res://src/ui_widgets/color_edit.tscn" id="3_dq5ly"] -[ext_resource type="Texture2D" uid="uid://cj5x2ti8150ja" path="res://assets/icons/Delete.svg" id="5_5n8tt"] +[ext_resource type="Script" uid="uid://btl68wj2dmivk" path="res://src/ui_widgets/color_configuration_popup.gd" id="1_j0oms"] +[ext_resource type="Texture2D" uid="uid://dr2erka82g6j4" path="res://assets/icons/Edit.svg" id="2_y6afs"] +[ext_resource type="FontFile" uid="uid://clpf84p1lfwlp" path="res://assets/fonts/Font.ttf" id="3_wd5vj"] +[ext_resource type="Script" uid="uid://1hox6gd5pxku" path="res://src/ui_widgets/BetterLineEdit.gd" id="4_u07gm"] +[ext_resource type="PackedScene" uid="uid://5f8uxavn1or1" path="res://src/ui_widgets/color_edit.tscn" id="5_idufj"] +[ext_resource type="Texture2D" uid="uid://cj5x2ti8150ja" path="res://assets/icons/Delete.svg" id="6_50dbg"] -[node name="ConfigurePopup" type="PanelContainer"] +[node name="ColorConfigurationPopup" type="PanelContainer"] custom_minimum_size = Vector2(128, 40) anchors_preset = -1 offset_right = 4.0 offset_bottom = 4.0 theme_type_variation = &"SpaciousPanel" -script = ExtResource("1_x6cll") +script = ExtResource("1_j0oms") [node name="ConfigureContainer" type="VBoxContainer" parent="."] unique_name_in_owner = true layout_mode = 2 theme_override_constants/separation = 8 -[node name="TopContainer" type="HBoxContainer" parent="ConfigureContainer"] +[node name="TopContainer" type="CenterContainer" parent="ConfigureContainer"] +custom_minimum_size = Vector2(0, 24) layout_mode = 2 -theme_override_constants/separation = 6 -alignment = 1 [node name="LabelContainer" type="HBoxContainer" parent="ConfigureContainer/TopContainer"] unique_name_in_owner = true layout_mode = 2 +alignment = 1 [node name="ColorLabel" type="Label" parent="ConfigureContainer/TopContainer/LabelContainer"] layout_mode = 2 @@ -39,7 +39,7 @@ layout_mode = 2 focus_mode = 0 mouse_default_cursor_shape = 2 theme_type_variation = &"FlatButton" -icon = ExtResource("2_0dind") +icon = ExtResource("2_y6afs") [node name="NameEdit" type="LineEdit" parent="ConfigureContainer/TopContainer"] visible = false @@ -47,17 +47,17 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 4 focus_mode = 1 -theme_override_fonts/font = ExtResource("2_j4qfn") +theme_override_fonts/font = ExtResource("3_wd5vj") alignment = 1 max_length = 30 -script = ExtResource("1_i4wi2") +script = ExtResource("4_u07gm") [node name="BottomContainer" type="HBoxContainer" parent="ConfigureContainer"] layout_mode = 2 theme_override_constants/separation = 6 alignment = 1 -[node name="ColorEdit" parent="ConfigureContainer/BottomContainer" instance=ExtResource("3_dq5ly")] +[node name="ColorEdit" parent="ConfigureContainer/BottomContainer" instance=ExtResource("5_idufj")] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 4 @@ -67,7 +67,7 @@ layout_mode = 2 focus_mode = 0 mouse_default_cursor_shape = 2 theme_type_variation = &"IconButton" -icon = ExtResource("5_5n8tt") +icon = ExtResource("6_50dbg") [connection signal="pressed" from="ConfigureContainer/TopContainer/LabelContainer/EditButton" to="." method="_on_edit_button_pressed"] [connection signal="pressed" from="ConfigureContainer/BottomContainer/DeleteButton" to="." method="_on_delete_button_pressed"] diff --git a/src/ui_widgets/color_edit.gd b/src/ui_widgets/color_edit.gd index eabd864..264ea52 100644 --- a/src/ui_widgets/color_edit.gd +++ b/src/ui_widgets/color_edit.gd @@ -20,7 +20,6 @@ var value: String: value_changed.emit(value) sync() - func _ready() -> void: text_submitted.connect(func(x: String) -> void: value = x) pressed.connect(_on_pressed) diff --git a/src/ui_widgets/color_field.gd b/src/ui_widgets/color_field.gd index 366fa0a..59d9fee 100644 --- a/src/ui_widgets/color_field.gd +++ b/src/ui_widgets/color_field.gd @@ -67,8 +67,7 @@ func _on_element_ancestor_attribute_changed(attribute_changed: String) -> void: # Redraw in case the gradient might have changed. func _on_svg_changed() -> void: - if cached_allow_url and\ - ColorParser.is_valid_url(element.get_implied_attribute_value(attribute_name)): + if cached_allow_url and ColorParser.is_valid_url(element.get_implied_attribute_value(attribute_name)): update_gradient_texture() queue_redraw() elif element.get_attribute_value(attribute_name) == "currentColor": @@ -83,8 +82,7 @@ func _on_pressed() -> void: # If it's a color attribute, or there's no color attribute children of this element, # mark the current color keyword as uninteresting (won't be shown in palettes). if not cached_allow_current_color: - color_popup.current_color_availability =\ - color_popup.CurrentColorAvailability.UNAVAILABLE + color_popup.current_color_availability = color_popup.CurrentColorAvailability.UNAVAILABLE else: var has_color_attribute_parent := false for element_depth in range(0, element.xid.size()): @@ -93,10 +91,8 @@ func _on_pressed() -> void: if State.root_element.get_xnode(checked_xid).has_attribute("color"): has_color_attribute_parent = true break - color_popup.current_color_availability =\ - color_popup.CurrentColorAvailability.INTERESTING if\ - has_color_attribute_parent else\ - color_popup.CurrentColorAvailability.UNINTERESTING + color_popup.current_color_availability = color_popup.CurrentColorAvailability.INTERESTING if has_color_attribute_parent\ + else color_popup.CurrentColorAvailability.UNINTERESTING color_popup.current_color = element.get_default("color") color_popup.is_none_keyword_available = cached_allow_none color_popup.color_picked.connect(_on_color_picked) @@ -185,8 +181,7 @@ func update_gradient_texture() -> void: gradient_texture = null func _on_button_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and\ - event.is_pressed(): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): accept_event() HandlerGUI.throw_mouse_motion_event() else: diff --git a/src/ui_widgets/color_field_popup.gd b/src/ui_widgets/color_field_popup.gd index d354b4d..9830454 100644 --- a/src/ui_widgets/color_field_popup.gd +++ b/src/ui_widgets/color_field_popup.gd @@ -45,8 +45,7 @@ var swatches_list: Array[ColorSwatch] = [] # Updated manually. func _ready() -> void: color_picker.is_none_keyword_available = is_none_keyword_available - color_picker.is_current_color_keyword_available =\ - (current_color_availability != CurrentColorAvailability.UNAVAILABLE) + color_picker.is_current_color_keyword_available = (current_color_availability != CurrentColorAvailability.UNAVAILABLE) color_picker.update_keyword_button() # Setup the switch mode button. switch_mode_button.pressed.connect(_on_switch_mode_button_pressed) @@ -101,8 +100,7 @@ func update_palettes(search_text := "") -> void: for palette in displayed_palettes: var indices_to_show := PackedInt32Array() for i in palette.colors.size(): - if search_text.is_empty() or\ - search_text.is_subsequence_ofn(palette.color_names[i]): + if search_text.is_empty() or search_text.is_subsequence_ofn(palette.color_names[i]): indices_to_show.append(i) if indices_to_show.is_empty(): @@ -154,8 +152,7 @@ func _on_switch_mode_button_pressed() -> void: setup_content() func setup_content() -> void: - switch_mode_button.text = Translator.translate("Palettes") if palette_mode\ - else Translator.translate("Color Picker") + switch_mode_button.text = Translator.translate("Palettes") if palette_mode else Translator.translate("Color Picker") color_picker_content.visible = not palette_mode palettes_content.visible = palette_mode if palette_mode and _palettes_pending_update: diff --git a/src/ui_widgets/element_frame.gd b/src/ui_widgets/element_frame.gd index 6a00f07..4ad2bc1 100644 --- a/src/ui_widgets/element_frame.gd +++ b/src/ui_widgets/element_frame.gd @@ -17,8 +17,7 @@ const element_content_types: Dictionary[String, PackedScene] = { "linearGradient": preload("res://src/ui_widgets/element_content_linear_gradient.tscn"), "radialGradient": preload("res://src/ui_widgets/element_content_radial_gradient.tscn"), } -const ElementContentUnrecognizedScene =\ - preload("res://src/ui_widgets/element_content_unrecognized.tscn") +const ElementContentUnrecognizedScene = preload("res://src/ui_widgets/element_content_unrecognized.tscn") @onready var main_container: VBoxContainer = $MainContainer @onready var title_bar: Control = $TitleBar @@ -88,14 +87,12 @@ func _get_drag_data(_at_position: Vector2) -> Variant: return null State.set_selection_dragged(true) - var data: Array[PackedInt32Array] = XIDUtils.filter_descendants( - State.selected_xids.duplicate(true)) + var data: Array[PackedInt32Array] = XIDUtils.filter_descendants(State.selected_xids.duplicate(true)) set_drag_preview(XNodeChildrenBuilder.generate_drag_preview(data)) return data func _on_xnodes_dragging_state_changed() -> void: - modulate.a = 0.55 if (State.is_xnode_selection_dragged and\ - element.xid in State.selected_xids) else 1.0 + modulate.a = 0.55 if (State.is_xnode_selection_dragged and element.xid in State.selected_xids) else 1.0 func _on_title_button_pressed() -> void: @@ -104,15 +101,13 @@ func _on_title_button_pressed() -> void: State.normal_select(element.xid) var viewport := get_viewport() var rect := title_bar.get_global_rect() - HandlerGUI.popup_under_rect_center(State.get_selection_context( - HandlerGUI.popup_under_rect_center.bind(rect, viewport), + HandlerGUI.popup_under_rect_center(State.get_selection_context(HandlerGUI.popup_under_rect_center.bind(rect, viewport), Utils.LayoutPart.INSPECTOR), rect, viewport) func _gui_input(event: InputEvent) -> void: if event is InputEventMouseMotion and event.button_mask == 0: - if State.semi_hovered_xid != element.xid and\ - not XIDUtils.is_parent(element.xid, State.hovered_xid): + if State.semi_hovered_xid != element.xid and not XIDUtils.is_parent(element.xid, State.hovered_xid): State.set_hovered(element.xid) elif event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT: @@ -123,8 +118,7 @@ func _gui_input(event: InputEvent) -> void: State.ctrl_select(element.xid) elif not element.xid in State.selected_xids: State.normal_select(element.xid) - elif event.is_released() and not event.shift_pressed and\ - not event.is_command_or_control_pressed() and\ + elif event.is_released() and not event.shift_pressed and not event.is_command_or_control_pressed() and\ State.selected_xids.size() > 1 and element.xid in State.selected_xids: State.normal_select(element.xid) accept_event() @@ -133,24 +127,21 @@ func _gui_input(event: InputEvent) -> void: State.normal_select(element.xid) var viewport := get_viewport() var popup_pos := viewport.get_mouse_position() - HandlerGUI.popup_under_pos(State.get_selection_context( - HandlerGUI.popup_under_pos.bind(popup_pos, viewport), + HandlerGUI.popup_under_pos(State.get_selection_context(HandlerGUI.popup_under_pos.bind(popup_pos, viewport), Utils.LayoutPart.INSPECTOR), popup_pos, viewport) accept_event() func _on_mouse_entered() -> void: var element_icon_size := DB.get_element_icon(element.name).get_size() var half_bar_width := title_bar.size.x / 2 - var title_width := ThemeUtils.mono_font.get_string_size(element.name, - HORIZONTAL_ALIGNMENT_LEFT, 180, 12).x + var title_width := ThemeUtils.mono_font.get_string_size(element.name, HORIZONTAL_ALIGNMENT_LEFT, 180, 12).x # Add button. var title_button := Button.new() title_button.focus_mode = Control.FOCUS_NONE title_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND title_button.mouse_filter = Control.MOUSE_FILTER_PASS title_button.theme_type_variation = "FlatButton" - title_button.position = Vector2(half_bar_width - title_width / 2 -\ - element_icon_size.x / 2 - 6, 0) + title_button.position = Vector2(half_bar_width - title_width / 2 - element_icon_size.x / 2 - 6, 0) title_button.size = Vector2(title_width + 28, 20) title_bar.add_child(title_button) title_button.gui_input.connect(_on_title_button_gui_input) @@ -271,8 +262,7 @@ func _draw() -> void: are_all_children_valid = false break - var drop_border_color := Configs.savedata.get_validity_color(false, - not are_all_children_valid) + var drop_border_color := Configs.savedata.get_validity_color(false, not are_all_children_valid) drop_border_color.s = lerpf(drop_border_color.s, 1.0, 0.5) drop_sb.border_color = drop_border_color if drop_xid == parent_xid + PackedInt32Array([element.xid[-1]]): @@ -294,18 +284,15 @@ func _on_title_bar_draw() -> void: var element_icon := DB.get_element_icon(element.name) var element_icon_size := element_icon.get_size() var half_bar_width := title_bar.size.x / 2 - var half_title_width := ThemeUtils.mono_font.get_string_size(element.name, - HORIZONTAL_ALIGNMENT_LEFT, 180, 12).x / 2 - ThemeUtils.mono_font.draw_string(title_bar_ci, Vector2(half_bar_width -\ - half_title_width + element_icon_size.x / 2, 15), element.name, - HORIZONTAL_ALIGNMENT_LEFT, 180, 12, ThemeUtils.editable_text_color) - element_icon.draw_rect(title_bar_ci, Rect2(Vector2(half_bar_width - half_title_width -\ - element_icon_size.x + 6, 1).round(), element_icon_size), false, ThemeUtils.tinted_contrast_color) + var half_title_width := ThemeUtils.mono_font.get_string_size(element.name, HORIZONTAL_ALIGNMENT_LEFT, 180, 12).x / 2 + ThemeUtils.mono_font.draw_string(title_bar_ci, Vector2(half_bar_width - half_title_width + element_icon_size.x / 2, 15), + element.name, HORIZONTAL_ALIGNMENT_LEFT, 180, 12, ThemeUtils.editable_text_color) + element_icon.draw_rect(title_bar_ci, Rect2(Vector2(half_bar_width - half_title_width - element_icon_size.x + 6, 1).round(), element_icon_size), + false, ThemeUtils.tinted_contrast_color) var element_warnings := element.get_config_warnings() if not element_warnings.is_empty(): - warning_icon.draw_rect(title_bar_ci, Rect2(Vector2(title_bar.size.x - 23, 2), - warning_icon.get_size()), false, ThemeUtils.warning_icon_color) + warning_icon.draw_rect(title_bar_ci, Rect2(Vector2(title_bar.size.x - 23, 2), warning_icon.get_size()), false, ThemeUtils.warning_icon_color) # Block dragging from starting when pressing the title button. func _on_title_button_gui_input(event: InputEvent) -> void: diff --git a/src/ui_widgets/enum_field.gd b/src/ui_widgets/enum_field.gd index 9584e01..2e0aada 100644 --- a/src/ui_widgets/enum_field.gd +++ b/src/ui_widgets/enum_field.gd @@ -83,8 +83,7 @@ func sync() -> void: func _on_button_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and\ - event.is_pressed(): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): accept_event() HandlerGUI.throw_mouse_motion_event() else: diff --git a/src/ui_widgets/good_color_picker.gd b/src/ui_widgets/good_color_picker.gd index 7e9dd54..257d612 100644 --- a/src/ui_widgets/good_color_picker.gd +++ b/src/ui_widgets/good_color_picker.gd @@ -122,8 +122,7 @@ func sync_color_space_buttons() -> void: btn.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS var on_slider_mode_changed := func() -> void: - btn.mouse_default_cursor_shape = Control.CURSOR_ARROW if\ - slider_mode == color_space else Control.CURSOR_POINTING_HAND + btn.mouse_default_cursor_shape = Control.CURSOR_ARROW if slider_mode == color_space else Control.CURSOR_POINTING_HAND slider_mode_changed.connect(on_slider_mode_changed) btn.tree_exiting.connect(slider_mode_changed.disconnect.bind(on_slider_mode_changed)) @@ -143,6 +142,11 @@ func update_keyword_button() -> void: keyword_button.show() func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("ui_undo", undo_redo.undo) + shortcuts.add_shortcut("ui_redo", undo_redo.redo) + HandlerGUI.register_shortcuts(self, shortcuts) + Configs.theme_changed.connect(sync_color_space_buttons) sync_color_space_buttons() # Set up signals. @@ -187,8 +191,7 @@ func _on_slider_mode_changed() -> void: func register_visual_change(new_color: Color, use_backup := true) -> void: # Return early if the color didn't change. If the color is a keyword, all visual # changes reset it to a normal color. - if not color in ["none", "currentColor"] and\ - new_color == (backup_display_color if use_backup else display_color): + if not color in ["none", "currentColor"] and new_color == (backup_display_color if use_backup else display_color): return undo_redo.create_action() @@ -218,8 +221,7 @@ func set_display_color(new_display_color: Color) -> void: func update() -> void: # Adjust the shaders. tracks_arr[0].material.set_shader_parameter("v", display_color.v) - tracks_arr[0].material.set_shader_parameter("base_color", - Color.from_hsv(display_color.h, display_color.s, 1.0)) + tracks_arr[0].material.set_shader_parameter("base_color", Color.from_hsv(display_color.h, display_color.s, 1.0)) tracks_arr[1].material.set_shader_parameter("base_color", display_color) tracks_arr[2].material.set_shader_parameter("base_color", display_color) tracks_arr[3].material.set_shader_parameter("base_color", display_color) @@ -255,11 +257,9 @@ func _on_color_wheel_gui_input(event: InputEvent) -> void: backup() var new_color := display_color if Utils.is_event_drag(event) or is_event_drag_start: - var event_pos_on_wheel: Vector2 = event.position + color_wheel.position -\ - color_wheel_drawn.position + var event_pos_on_wheel: Vector2 = event.position + color_wheel.position - color_wheel_drawn.position new_color.h = fposmod(center.angle_to_point(event_pos_on_wheel), TAU) / TAU - new_color.s = minf(event_pos_on_wheel.distance_to(center) * 2 /\ - color_wheel_drawn.size.x, 1.0) + new_color.s = minf(event_pos_on_wheel.distance_to(center) * 2 / color_wheel_drawn.size.x, 1.0) set_display_color(new_color) if Utils.is_event_drag_end(event): register_visual_change(display_color) @@ -394,8 +394,7 @@ func _on_keyword_button_pressed() -> void: var context_popup := ContextPopup.new() context_popup.setup(btn_arr, true) - HandlerGUI.popup_under_rect(context_popup, keyword_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect(context_popup, keyword_button.get_global_rect(), get_viewport()) func set_to_keyword(keyword: String) -> void: undo_redo.create_action() @@ -446,27 +445,23 @@ func _on_side_slider_draw() -> void: if not sliders_dragged[0]: arrow_modulate.a = 0.7 widgets_arr[0].draw_texture(side_slider_arrow, Vector2(0, tracks_arr[0].position.y +\ - tracks_arr[0].size.y * (1 - display_color.v) -\ - side_slider_arrow.get_height() / 2.0), arrow_modulate) + tracks_arr[0].size.y * (1 - display_color.v) - side_slider_arrow.get_height() / 2.0), arrow_modulate) func _draw() -> void: RenderingServer.canvas_item_clear(color_wheel_surface) # Draw the color wheel handle. - var point_pos := center + Vector2(center.x * cos(display_color.h * TAU), - center.y * sin(display_color.h * TAU)) * display_color.s - RenderingServer.canvas_item_add_texture_rect(color_wheel_surface, Rect2(point_pos -\ - handle_texture.get_size() / 2, handle_texture.get_size()), handle_texture) + var handle_texture_size := handle_texture.get_size() + var point_pos := center + Vector2(center.x * cos(display_color.h * TAU), center.y * sin(display_color.h * TAU)) * display_color.s + RenderingServer.canvas_item_add_texture_rect(color_wheel_surface, Rect2(point_pos - handle_texture_size / 2, handle_texture_size), handle_texture) # Helper for drawing the horizontal sliders. func draw_hslider(idx: int, offset: float, chr: String) -> void: var arrow_modulate := ThemeUtils.tinted_contrast_color if not sliders_dragged[idx]: arrow_modulate.a = 0.7 - widgets_arr[idx].draw_texture(slider_arrow, Vector2(tracks_arr[idx].position.x +\ - tracks_arr[idx].size.x * offset - slider_arrow.get_width() / 2.0, + widgets_arr[idx].draw_texture(slider_arrow, Vector2(tracks_arr[idx].position.x + tracks_arr[idx].size.x * offset - slider_arrow.get_width() / 2.0, tracks_arr[idx].size.y), arrow_modulate) - widgets_arr[idx].draw_string(get_theme_default_font(), Vector2(-12, 11), chr, - HORIZONTAL_ALIGNMENT_CENTER, 12, 14, ThemeUtils.text_color) + widgets_arr[idx].draw_string(get_theme_default_font(), Vector2(-12, 11), chr, HORIZONTAL_ALIGNMENT_CENTER, 12, 14, ThemeUtils.text_color) # Make sure the arrows are redrawn when the tracks finish resizing. func _on_track_resized() -> void: @@ -530,18 +525,6 @@ func hex(col: Color) -> String: return col.to_html(alpha_enabled and col.a != 1.0) -func _unhandled_input(event: InputEvent) -> void: - if not visible: - return - - if ShortcutUtils.is_action_pressed(event, "ui_undo"): - undo_redo.undo() - accept_event() - elif ShortcutUtils.is_action_pressed(event, "ui_redo"): - undo_redo.redo() - accept_event() - - func _on_eyedropper_pressed() -> void: var eyedropper_popup := EyedropperPopupScene.instantiate() eyedropper_popup.color_picked.connect(register_visual_change.bind(false)) diff --git a/src/ui_widgets/href_field.gd b/src/ui_widgets/href_field.gd index 9ffd918..db97122 100644 --- a/src/ui_widgets/href_field.gd +++ b/src/ui_widgets/href_field.gd @@ -28,16 +28,14 @@ func _on_focus_entered() -> void: remove_theme_color_override("font_color") func _on_text_submitted(new_text: String) -> void: - if new_text.is_empty() or\ - AttributeHref.get_validity(new_text) != Attribute.NameValidityLevel.INVALID: + if new_text.is_empty() or AttributeHref.get_validity(new_text) != Attribute.NameValidityLevel.INVALID: set_value(new_text, true) else: sync() func _on_text_changed(new_text: String) -> void: var validity_level := AttributeHref.get_validity(new_text) - var font_color := Configs.savedata.get_validity_color( - validity_level == Attribute.NameValidityLevel.INVALID, + var font_color := Configs.savedata.get_validity_color(validity_level == Attribute.NameValidityLevel.INVALID, validity_level == Attribute.NameValidityLevel.INVALID_XML_NAMETOKEN) add_theme_color_override("font_color", font_color) diff --git a/src/ui_widgets/id_field.gd b/src/ui_widgets/id_field.gd index 3752afe..8c8febe 100644 --- a/src/ui_widgets/id_field.gd +++ b/src/ui_widgets/id_field.gd @@ -29,8 +29,7 @@ func _on_focus_entered() -> void: remove_theme_color_override("font_color") func _on_text_submitted(new_text: String) -> void: - if new_text.is_empty() or\ - AttributeID.get_validity(new_text) != Attribute.NameValidityLevel.INVALID: + if new_text.is_empty() or AttributeID.get_validity(new_text) != Attribute.NameValidityLevel.INVALID: set_value(new_text, true) else: sync() diff --git a/src/ui_widgets/number_field.gd b/src/ui_widgets/number_field.gd index d146c95..2d48651 100644 --- a/src/ui_widgets/number_field.gd +++ b/src/ui_widgets/number_field.gd @@ -56,8 +56,7 @@ func _on_element_attribute_changed(attribute_changed: String) -> void: set_value(element.get_attribute_value(attribute_name)) func _on_element_other_attribute_changed(attribute_changed: String) -> void: - if (attribute_name == "fx" and attribute_changed == "cx") or\ - (attribute_name == "fy" and attribute_changed == "cy"): + if (attribute_name == "fx" and attribute_changed == "cx") or (attribute_name == "fy" and attribute_changed == "cy"): setup_placeholder() sync() diff --git a/src/ui_widgets/number_field_with_slider.gd b/src/ui_widgets/number_field_with_slider.gd index 48debfa..444f0fa 100644 --- a/src/ui_widgets/number_field_with_slider.gd +++ b/src/ui_widgets/number_field_with_slider.gd @@ -98,8 +98,7 @@ func _draw() -> void: stylebox.corner_radius_bottom_right = 5 stylebox.bg_color = get_theme_stylebox("normal", "LineEdit").bg_color stylebox.draw(ci, Rect2(size.x - BUTTON_WIDTH, 1, BUTTON_WIDTH - 2, size.y - 2)) - var fill_height := (size.y - 4) * (element.get_attribute_num(attribute_name) -\ - MIN_VALUE) / MAX_VALUE + var fill_height := (size.y - 4) * (element.get_attribute_num(attribute_name) - MIN_VALUE) / MAX_VALUE # Create a stylebox that'll occupy the exact amount of space. var fill_stylebox := StyleBoxFlat.new() fill_stylebox.bg_color = ThemeUtils.tinted_contrast_color @@ -107,8 +106,7 @@ func _draw() -> void: fill_stylebox.bg_color.a = 0.65 elif not slider_hovered: fill_stylebox.bg_color.a = 0.5 - fill_stylebox.draw(ci, Rect2(size.x - BUTTON_WIDTH, size.y - 2 - fill_height, - BUTTON_WIDTH - 2, fill_height)) + fill_stylebox.draw(ci, Rect2(size.x - BUTTON_WIDTH, size.y - 2 - fill_height, BUTTON_WIDTH - 2, fill_height)) if slider_dragged: draw_button_border("pressed") elif slider_hovered: @@ -120,8 +118,7 @@ func _on_slider_gui_input(event: InputEvent) -> void: if not temp_button.mouse_exited.is_connected(_on_slider_mouse_exited): temp_button.mouse_exited.connect(_on_slider_mouse_exited) - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and\ - event.is_pressed(): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): accept_event() HandlerGUI.throw_mouse_motion_event() else: @@ -140,8 +137,7 @@ func _on_slider_gui_input(event: InputEvent) -> void: elif Utils.is_event_drag_end(event): slider_dragged = false var final_slider_value := get_slider_value_at_y(event.position.y) - if initial_slider_value !=\ - element.get_attribute(attribute_name).num_to_text(final_slider_value): + if initial_slider_value != element.get_attribute(attribute_name).num_to_text(final_slider_value): set_num(final_slider_value, true) func _unhandled_input(event: InputEvent) -> void: @@ -150,9 +146,9 @@ func _unhandled_input(event: InputEvent) -> void: set_value(initial_slider_value) accept_event() + func get_slider_value_at_y(y_coord: float) -> float: - return snappedf(lerpf(MAX_VALUE, MIN_VALUE, - (y_coord - 4) / (temp_button.size.y - 4)), SLIDER_STEP) + return snappedf(lerpf(MAX_VALUE, MIN_VALUE, (y_coord - 4) / (temp_button.size.y - 4)), SLIDER_STEP) func _on_slider_mouse_exited() -> void: slider_hovered = false diff --git a/src/ui_widgets/palette_config.gd b/src/ui_widgets/palette_config.gd index cdee72a..46c402e 100644 --- a/src/ui_widgets/palette_config.gd +++ b/src/ui_widgets/palette_config.gd @@ -3,7 +3,7 @@ extends PanelContainer const ColorSwatch = preload("res://src/ui_widgets/color_swatch_config.gd") const ColorSwatchScene = preload("res://src/ui_widgets/color_swatch_config.tscn") -const ConfigurePopupScene = preload("res://src/ui_widgets/configure_color_popup.tscn") +const ColorConfigurationPopupScene = preload("res://src/ui_widgets/color_configuration_popup.tscn") const plus_icon = preload("res://assets/icons/Plus.svg") signal layout_changed @@ -96,12 +96,11 @@ func display_warnings() -> void: func popup_configure_color(swatch: Button) -> void: - var configure_popup := ConfigurePopupScene.instantiate() + var configure_popup := ColorConfigurationPopupScene.instantiate() configure_popup.palette = swatch.palette configure_popup.idx = swatch.idx configure_popup.color_deletion_requested.connect(remove_color.bind(swatch.idx)) - HandlerGUI.popup_under_rect_center(configure_popup, swatch.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(configure_popup, swatch.get_global_rect(), get_viewport()) configure_popup.color_edit.value_changed.connect(swatch.change_color) configure_popup.color_edit.value_changed.connect(display_warnings.unbind(1)) configure_popup.color_name_edit.text_submitted.connect(swatch.change_color_name) @@ -127,8 +126,7 @@ func _on_name_edit_text_changed(new_text: String) -> void: # if the palette is currently invalid. If the new text is different, # check if it's unused, i.e., would be a valid title. name_edit.add_theme_color_override(theme_type, - Configs.savedata.get_validity_color(false, (new_text != palette.title and\ - not Configs.savedata.is_palette_title_unused(new_text)) or\ + Configs.savedata.get_validity_color(false, (new_text != palette.title and not Configs.savedata.is_palette_title_unused(new_text)) or\ (new_text == palette.title and Configs.savedata.is_palette_valid(palette)))) name_edit.end_bulk_theme_override() @@ -210,8 +208,7 @@ func open_palette_options() -> void: var context_popup := ContextPopup.new() context_popup.setup(btn_arr, true) - HandlerGUI.popup_under_rect_center(context_popup, palette_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, palette_button.get_global_rect(), get_viewport()) func apply_preset(preset: Palette.Preset) -> void: Configs.savedata.get_palette(find_palette_index()).apply_preset(preset) @@ -248,8 +245,7 @@ func _on_palette_button_pressed() -> void: var context_popup := ContextPopup.new() context_popup.setup(btn_arr, true, -1, -1, PackedInt32Array([separator_idx])) - HandlerGUI.popup_under_rect_center(context_popup, palette_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, palette_button.get_global_rect(), get_viewport()) # Drag and drop logic. @@ -266,8 +262,7 @@ func _can_drop_data(_at_position: Vector2, data: Variant) -> bool: var buffer := 6 var pos := colors_container.get_local_mouse_position() - if not (data is ColorSwatch.DragData and\ - Rect2(Vector2.ZERO, colors_container.size).grow(buffer).has_point(pos)): + if not (data is ColorSwatch.DragData and Rect2(Vector2.ZERO, colors_container.size).grow(buffer).has_point(pos)): clear_proposed_drop() return false else: @@ -288,8 +283,7 @@ func _can_drop_data(_at_position: Vector2, data: Variant) -> bool: for swatch in get_swatches(): swatch.proposed_drop_data = ColorSwatch.DragData.new(palette, new_idx) swatch.queue_redraw() - return data.palette != palette or (data.palette == palette and\ - data.index != new_idx and data.index != new_idx - 1) + return data.palette != palette or (data.palette == palette and data.index != new_idx and data.index != new_idx - 1) func _drop_data(_at_position: Vector2, data: Variant) -> void: if proposed_drop_idx == -1: diff --git a/src/ui_widgets/path_popup.gd b/src/ui_widgets/path_popup.gd index 0b5847e..bd9a853 100644 --- a/src/ui_widgets/path_popup.gd +++ b/src/ui_widgets/path_popup.gd @@ -22,8 +22,7 @@ func emit_picked(cmd_char: String) -> void: func _on_relative_toggle_toggled(toggled_on: bool) -> void: Configs.savedata.path_command_relative = toggled_on for command_button in command_container.get_children(): - command_button.command_char = command_button.command_char.to_lower() if toggled_on\ - else command_button.command_char.to_upper() + command_button.command_char = command_button.command_char.to_lower() if toggled_on else command_button.command_char.to_upper() command_button.queue_redraw() func mark_invalid(warned: PackedStringArray, disabled: PackedStringArray) -> void: diff --git a/src/ui_widgets/pathdata_field.gd b/src/ui_widgets/pathdata_field.gd index 5074069..a1b3041 100644 --- a/src/ui_widgets/pathdata_field.gd +++ b/src/ui_widgets/pathdata_field.gd @@ -202,8 +202,7 @@ func _on_commands_gui_input(event: InputEvent) -> void: if event.button_index == MOUSE_BUTTON_LEFT: if event.is_pressed(): if event.double_click: - var subpath_range: Vector2i =\ - element.get_attribute(attribute_name).get_subpath(cmd_idx) + var subpath_range: Vector2i = element.get_attribute(attribute_name).get_subpath(cmd_idx) State.normal_select(element.xid, subpath_range.x) State.shift_select(element.xid, subpath_range.y) elif event.is_command_or_control_pressed(): @@ -212,19 +211,16 @@ func _on_commands_gui_input(event: InputEvent) -> void: State.shift_select(element.xid, cmd_idx) else: State.normal_select(element.xid, cmd_idx) - elif event.is_released() and not event.shift_pressed and\ - not event.is_command_or_control_pressed() and not event.double_click and\ - State.inner_selections.size() > 1 and cmd_idx in State.inner_selections: + elif event.is_released() and not event.shift_pressed and not event.is_command_or_control_pressed() and\ + not event.double_click and State.inner_selections.size() > 1 and cmd_idx in State.inner_selections: State.normal_select(element.xid, cmd_idx) elif event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): - if State.semi_selected_xid != element.xid or\ - not cmd_idx in State.inner_selections: + if State.semi_selected_xid != element.xid or not cmd_idx in State.inner_selections: State.normal_select(element.xid, cmd_idx) # Popup the actions. var viewport := get_viewport() var popup_pos := viewport.get_mouse_position() - HandlerGUI.popup_under_pos(State.get_selection_context( - HandlerGUI.popup_under_pos.bind(popup_pos, viewport), + HandlerGUI.popup_under_pos(State.get_selection_context(HandlerGUI.popup_under_pos.bind(popup_pos, viewport), Utils.LayoutPart.INSPECTOR), popup_pos, viewport) @@ -254,15 +250,12 @@ func _commands_draw() -> void: var cmd: PathCommand = element.get_attribute(attribute_name).get_command(i) var cmd_char := cmd.command_char # Draw the action button. - more_icon.draw_rect(ci, Rect2(Vector2(commands_container.size.x - 19, 4 + v_offset), - Vector2(14, 14)), false, ThemeUtils.icon_normal_color) + more_icon.draw_rect(ci, Rect2(Vector2(commands_container.size.x - 19, 4 + v_offset), Vector2(14, 14)), false, ThemeUtils.icon_normal_color) # Draw the relative/absolute button. - var relative_stylebox := get_theme_stylebox("normal", "PathCommandAbsoluteButton") if\ - Utils.is_string_upper(cmd_char) else get_theme_stylebox("normal", "PathCommandRelativeButton") - relative_stylebox.draw(ci, Rect2(Vector2(3, 2 + v_offset), - Vector2(18, STRIP_HEIGHT - 4))) - ThemeUtils.mono_font.draw_string(ci, Vector2(6, v_offset + STRIP_HEIGHT - 6), - cmd_char, HORIZONTAL_ALIGNMENT_CENTER, 12, 13, ThemeUtils.text_color) + var relative_stylebox := get_theme_stylebox("normal", "PathCommandAbsoluteButton") if Utils.is_string_upper(cmd_char)\ + else get_theme_stylebox("normal", "PathCommandRelativeButton") + relative_stylebox.draw(ci, Rect2(Vector2(3, 2 + v_offset), Vector2(18, STRIP_HEIGHT - 4))) + ThemeUtils.mono_font.draw_string(ci, Vector2(6, v_offset + STRIP_HEIGHT - 6), cmd_char, HORIZONTAL_ALIGNMENT_CENTER, 12, 13, ThemeUtils.text_color) # Draw the fields. var rect := Rect2(Vector2(25, 2 + v_offset), Vector2(44, 18)) match cmd_char.to_upper(): @@ -278,27 +271,20 @@ func _commands_draw() -> void: var flag_field := FlagFieldScene.instantiate() var is_large_arc: bool = (cmd.large_arc_flag == 0) var is_sweep: bool = (cmd.sweep_flag == 0) - flag_field.get_theme_stylebox("normal" if is_large_arc\ - else "pressed").draw(ci, rect) - ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(5, 14), - String.num_uint64(cmd.large_arc_flag), HORIZONTAL_ALIGNMENT_LEFT, - rect.size.x, 14, flag_field.get_theme_color( - "font_color" if is_large_arc else "font_pressed_color")) + flag_field.get_theme_stylebox("normal" if is_large_arc else "pressed").draw(ci, rect) + ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(5, 14), String.num_uint64(cmd.large_arc_flag), HORIZONTAL_ALIGNMENT_LEFT, + rect.size.x, 14, flag_field.get_theme_color("font_color" if is_large_arc else "font_pressed_color")) rect.position.x = rect.end.x + 4 - flag_field.get_theme_stylebox("normal" if is_sweep - else "pressed").draw(ci, rect) - ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(5, 14), - String.num_uint64(cmd.sweep_flag), HORIZONTAL_ALIGNMENT_LEFT, - rect.size.x, 14, flag_field.get_theme_color("font_color" if is_sweep\ - else "font_pressed_color")) + flag_field.get_theme_stylebox("normal" if is_sweep else "pressed").draw(ci, rect) + ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(5, 14), String.num_uint64(cmd.sweep_flag), HORIZONTAL_ALIGNMENT_LEFT, + rect.size.x, 14, flag_field.get_theme_color("font_color" if is_sweep else "font_pressed_color")) flag_field.free() rect.position.x = rect.end.x + 4 rect.size.x = 44 draw_numfield(rect, "x", cmd) rect.position.x = rect.end.x + 3 draw_numfield(rect, "y", cmd) - "C": draw_numfield_arr(rect, [3, 4, 3, 4, 3], ["x1", "y1", "x2", "y2", "x", "y"], - cmd) + "C": draw_numfield_arr(rect, [3, 4, 3, 4, 3], ["x1", "y1", "x2", "y2", "x", "y"], cmd) "Q": draw_numfield_arr(rect, [3, 4, 3], ["x1", "y1", "x", "y"], cmd) "S": draw_numfield_arr(rect, [3, 4, 3], ["x2", "y2", "x", "y"], cmd) "M", "L", "T": draw_numfield_arr(rect, [3], ["x", "y"], cmd) @@ -309,8 +295,7 @@ func draw_numfield(rect: Rect2, property: String, path_command: PathCommand) -> mini_line_edit_stylebox.draw(ci, rect) ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(3, 13), NumstringParser.basic_num_to_text(path_command.get(property)), - HORIZONTAL_ALIGNMENT_LEFT, rect.size.x - 6, - mini_line_edit_font_size, mini_line_edit_font_color) + HORIZONTAL_ALIGNMENT_LEFT, rect.size.x - 6, mini_line_edit_font_size, mini_line_edit_font_color) func draw_numfield_arr(first_rect: Rect2, spacings: Array, names: PackedStringArray, path_command: PathCommand) -> void: @@ -321,8 +306,7 @@ path_command: PathCommand) -> void: func activate_hovered(idx: int) -> void: - if idx != hovered_idx and\ - idx < element.get_attribute(attribute_name).get_command_count(): + if idx != hovered_idx and idx < element.get_attribute(attribute_name).get_command_count(): activate_hovered_shared_logic(idx) func reactivate_hovered() -> void: diff --git a/src/ui_widgets/points_field.gd b/src/ui_widgets/points_field.gd index 7fe82ec..ef99723 100644 --- a/src/ui_widgets/points_field.gd +++ b/src/ui_widgets/points_field.gd @@ -213,13 +213,11 @@ func _on_points_gui_input(event: InputEvent) -> void: State.shift_select(element.xid, cmd_idx) else: State.normal_select(element.xid, cmd_idx) - elif event.is_released() and not event.shift_pressed and\ - not event.is_command_or_control_pressed() and not event.double_click and\ - State.inner_selections.size() > 1 and cmd_idx in State.inner_selections: + elif event.is_released() and not event.shift_pressed and not event.is_command_or_control_pressed() and\ + not event.double_click and State.inner_selections.size() > 1 and cmd_idx in State.inner_selections: State.normal_select(element.xid, cmd_idx) elif event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): - if State.semi_selected_xid != element.xid or\ - not cmd_idx in State.inner_selections: + if State.semi_selected_xid != element.xid or not cmd_idx in State.inner_selections: State.normal_select(element.xid, cmd_idx) # Popup the actions. var viewport := get_viewport() @@ -263,14 +261,12 @@ func points_draw() -> void: func draw_numfield(rect: Rect2, num: float) -> void: mini_line_edit_stylebox.draw(ci, rect) - ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(3, 13), - NumstringParser.basic_num_to_text(num), HORIZONTAL_ALIGNMENT_LEFT, - rect.size.x - 6, mini_line_edit_font_size, mini_line_edit_font_color) + ThemeUtils.mono_font.draw_string(ci, rect.position + Vector2(3, 13), NumstringParser.basic_num_to_text(num), + HORIZONTAL_ALIGNMENT_LEFT, rect.size.x - 6, mini_line_edit_font_size, mini_line_edit_font_color) func activate_hovered(idx: int) -> void: - if idx != hovered_idx and\ - idx < element.get_attribute(attribute_name).get_list_size() / 2: + if idx != hovered_idx and idx < element.get_attribute(attribute_name).get_list_size() / 2: activate_hovered_shared_logic(idx) func reactivate_hovered() -> void: diff --git a/src/ui_widgets/presented_shortcut.gd b/src/ui_widgets/presented_shortcut.gd index 601e23e..bdee97b 100644 --- a/src/ui_widgets/presented_shortcut.gd +++ b/src/ui_widgets/presented_shortcut.gd @@ -54,8 +54,7 @@ func check_shortcuts_validity() -> void: if conflicts.size() > 8: conflicts.resize(8) conflicts.append("...") - shortcut_btn.tooltip_text = Translator.translate("Also used by") +\ - ":\n" + "\n".join(conflicts) + shortcut_btn.tooltip_text = Translator.translate("Also used by") + ":\n" + "\n".join(conflicts) else: shortcut_btn.remove_theme_color_override("font_disabled_color") shortcut_btn.tooltip_text = "" diff --git a/src/ui_widgets/profile_frame.gd b/src/ui_widgets/profile_frame.gd index b0f38c8..b44a913 100644 --- a/src/ui_widgets/profile_frame.gd +++ b/src/ui_widgets/profile_frame.gd @@ -53,8 +53,7 @@ func sync_theming() -> void: func button_update_disabled() -> void: var should_disable: bool = disabled_check_callback.call() button.disabled = should_disable - button.mouse_default_cursor_shape = Control.CURSOR_ARROW if should_disable else\ - Control.CURSOR_POINTING_HAND + button.mouse_default_cursor_shape = Control.CURSOR_ARROW if should_disable else Control.CURSOR_POINTING_HAND func setup_size() -> void: dropdown.position = Vector2(control.size.x - 102, 1) diff --git a/src/ui_widgets/setting_frame.gd b/src/ui_widgets/setting_frame.gd index a238062..1eeb7ea 100644 --- a/src/ui_widgets/setting_frame.gd +++ b/src/ui_widgets/setting_frame.gd @@ -167,8 +167,7 @@ func update_widgets() -> void: var show_alpha: bool = widget.enable_alpha and setting_value.a != 1.0 var setting_str := setting_value.to_html(show_alpha) widget.value = setting_str - reset_button.visible = (not disabled and\ - getter.call().to_html() != default.to_html()) + reset_button.visible = (not disabled and getter.call().to_html() != default.to_html()) Type.DROPDOWN: widget.set_value(getter.call()) reset_button.visible = (not disabled and getter.call() != default) diff --git a/src/ui_widgets/settings_content_generic.gd b/src/ui_widgets/settings_content_generic.gd index 5237f96..cb7dcdf 100644 --- a/src/ui_widgets/settings_content_generic.gd +++ b/src/ui_widgets/settings_content_generic.gd @@ -68,9 +68,7 @@ func _ready() -> void: btn.pressed.connect(_set_current_setup_resource_index.bind(idx)) btn.pressed.connect(setup_content) var update_category_button_text := func() -> void: - btn.text = Translator.translate("Editor formatter") if\ - current_setup_resource_index == 0 else\ - Translator.translate("Export formatter") + btn.text = Translator.translate("Editor formatter") if current_setup_resource_index == 0 else Translator.translate("Export formatter") Configs.language_changed.connect(update_category_button_text) update_category_button_text.call() btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND @@ -223,10 +221,8 @@ func setup_formatting_content() -> void: current_setup_setting = "xml_indentation_spaces" add_number_dropdown(Translator.translate("Number of indentation spaces"), [2, 3, 4, 6, 8], true, false, Formatter.INDENTS_MIN, Formatter.INDENTS_MAX, - not (current_setup_resource.xml_pretty_formatting and\ - current_setup_resource.xml_indentation_use_spaces)) - if current_setup_resource.xml_pretty_formatting and\ - current_setup_resource.xml_indentation_use_spaces: + not (current_setup_resource.xml_pretty_formatting and current_setup_resource.xml_indentation_use_spaces)) + if current_setup_resource.xml_pretty_formatting and current_setup_resource.xml_indentation_use_spaces: var xml_indentation_spaces_root_element := ElementRoot.new() var xml_indentation_spaces_circle_element := ElementCircle.new() xml_indentation_spaces_circle_element.set_attribute("cx", 6) @@ -581,20 +577,22 @@ func setup_other_content() -> void: Translator.translate("Determines the maximum number of frames per second."))) current_setup_setting = "keep_screen_on" - add_checkbox(Translator.translate("Keep Screen On")) - add_preview(SettingTextPreview.new( - Translator.translate("Keeps the screen on even after inactivity, so the screensaver does not take over."))) + var keep_screen_on := add_checkbox(Translator.translate("Keep Screen On")) + var keep_screen_on_forced_off := OS.has_feature("web") + add_preview(SettingTextPreview.new(Translator.translate( + "Keeps the screen on even after inactivity, so the screensaver does not take over."), + SettingTextPreview.get_platform_availability_warning(keep_screen_on_forced_off))) + if keep_screen_on_forced_off: + keep_screen_on.permanent_disable_checkbox(false) add_section(Translator.translate("Miscellaneous")) current_setup_setting = "use_native_file_dialog" var use_native_file_dialog := add_checkbox(Translator.translate("Use native file dialog")) var use_native_file_dialog_forced_on := OS.has_feature("web") - var use_native_file_dialog_forced_off :=\ - (not DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE)) + var use_native_file_dialog_forced_off := (not DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE)) add_preview(SettingTextPreview.new(Translator.translate( "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one."), - SettingTextPreview.get_platform_availability_warning( - use_native_file_dialog_forced_on or use_native_file_dialog_forced_off))) + SettingTextPreview.get_platform_availability_warning(use_native_file_dialog_forced_on or use_native_file_dialog_forced_off))) # Disable fallback file dialog on web, and native file dialog if not available. if use_native_file_dialog_forced_on: use_native_file_dialog.permanent_disable_checkbox(true) @@ -730,11 +728,9 @@ func emit_preview_changed() -> void: var label := Label.new() label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER var update_label_font_color := func() -> void: - label.add_theme_color_override("font_color", - Configs.savedata.get(preview.setting_bind)) + label.add_theme_color_override("font_color", Configs.savedata.get(preview.setting_bind)) Configs.basic_colors_changed.connect(update_label_font_color) - label.tree_exiting.connect(Configs.basic_colors_changed.disconnect.bind( - update_label_font_color), CONNECT_ONE_SHOT) + label.tree_exiting.connect(Configs.basic_colors_changed.disconnect.bind(update_label_font_color), CONNECT_ONE_SHOT) update_label_font_color.call() label.text = preview.text preview_changed.emit(label) @@ -761,8 +757,7 @@ func emit_preview_changed() -> void: no_effect_warning_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART no_effect_warning_label.size_flags_vertical = Control.SIZE_EXPAND_FILL no_effect_warning_label.add_theme_constant_override("line_spacing", 2) - no_effect_warning_label.add_theme_color_override("font_color", - Configs.savedata.basic_color_warning) + no_effect_warning_label.add_theme_color_override("font_color", Configs.savedata.basic_color_warning) match preview.warning: preview.WarningType.NO_EFFECT_IN_CURRENT_CONFIGURATION: no_effect_warning_label.text = Translator.translate( @@ -774,8 +769,7 @@ func emit_preview_changed() -> void: no_effect_warning_label.text = "" while no_effect_warning_label.get_line_count() >= 2: preview_font_size -= 1 - no_effect_warning_label.add_theme_font_size_override("font_size", - preview_font_size) + no_effect_warning_label.add_theme_font_size_override("font_size", preview_font_size) label.add_theme_font_size_override("font_size", preview_font_size) if not preview.text.is_empty(): vbox.add_child(label) @@ -802,8 +796,7 @@ func emit_preview_changed() -> void: code_preview.add_theme_stylebox_override("read_only", empty_stylebox) code_preview.text = preview.text Configs.highlighting_colors_changed.connect(update_highlighter) - code_preview.tree_exiting.connect(Configs.highlighting_colors_changed.disconnect.bind( - update_highlighter), CONNECT_ONE_SHOT) + code_preview.tree_exiting.connect(Configs.highlighting_colors_changed.disconnect.bind(update_highlighter), CONNECT_ONE_SHOT) update_highlighter.call() preview_changed.emit(code_preview) elif preview is SettingFormatterPreview: @@ -816,11 +809,9 @@ func emit_preview_changed() -> void: var update_text := func() -> void: if preview.show_only_children: - code_preview.text = SVGParser.root_children_to_text( - preview.root_element, preview.resource_bind) + code_preview.text = SVGParser.root_children_to_text(preview.root_element, preview.resource_bind) else: - code_preview.text = SVGParser.root_to_text( - preview.root_element, preview.resource_bind) + code_preview.text = SVGParser.root_to_text(preview.root_element, preview.resource_bind) code_preview.add_theme_color_override("font_readonly_color", Color.WHITE) var text_edit_default_stylebox := code_preview.get_theme_stylebox("normal") diff --git a/src/ui_widgets/settings_content_palettes.gd b/src/ui_widgets/settings_content_palettes.gd index dc921ef..737546a 100644 --- a/src/ui_widgets/settings_content_palettes.gd +++ b/src/ui_widgets/settings_content_palettes.gd @@ -39,8 +39,7 @@ func _popup_xml_palette_options(palette_xml_button: Button) -> void: var context_popup := ContextPopup.new() context_popup.setup(btn_arr, true) - HandlerGUI.popup_under_rect_center(context_popup, palette_xml_button.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, palette_xml_button.get_global_rect(), get_viewport()) func add_empty_palette() -> void: diff --git a/src/ui_widgets/settings_content_shortcuts.gd b/src/ui_widgets/settings_content_shortcuts.gd index f0a5072..e1b3f76 100644 --- a/src/ui_widgets/settings_content_shortcuts.gd +++ b/src/ui_widgets/settings_content_shortcuts.gd @@ -20,6 +20,11 @@ func get_translated_shortcut_tab(tab_idx: String) -> String: return "" func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("ui_undo", undo_redo.undo) + shortcuts.add_shortcut("ui_redo", undo_redo.redo) + HandlerGUI.register_shortcuts(self, shortcuts) + var button_group := ButtonGroup.new() for tab_idx in shortcut_tab_names: var btn := Button.new() @@ -37,12 +42,6 @@ func _ready() -> void: categories_container.get_child(0).button_pressed = true categories_container.get_child(0).pressed.emit() -func _unhandled_input(event: InputEvent) -> void: - if ShortcutUtils.is_action_pressed(event, "ui_undo"): - undo_redo.undo() - elif ShortcutUtils.is_action_pressed(event, "ui_redo"): - undo_redo.redo() - func show_shortcuts(category: String) -> void: undo_redo.clear_history() diff --git a/src/ui_widgets/transform_field.gd b/src/ui_widgets/transform_field.gd index 82f04c5..5eed897 100644 --- a/src/ui_widgets/transform_field.gd +++ b/src/ui_widgets/transform_field.gd @@ -47,8 +47,7 @@ func _on_pressed() -> void: func _on_button_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and\ - event.is_pressed(): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): accept_event() HandlerGUI.throw_mouse_motion_event() else: diff --git a/src/ui_widgets/transform_popup.gd b/src/ui_widgets/transform_popup.gd index dbb57c2..f774100 100644 --- a/src/ui_widgets/transform_popup.gd +++ b/src/ui_widgets/transform_popup.gd @@ -29,6 +29,11 @@ var undo_redo := UndoRedoRef.new() @onready var apply_matrix: Button = %ApplyMatrix func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("ui_undo", undo_redo.undo) + shortcuts.add_shortcut("ui_redo", undo_redo.redo) + HandlerGUI.register_shortcuts(self, shortcuts) + Configs.language_changed.connect(sync_localization) add_button.pressed.connect(popup_new_transform_context.bind(0, add_button)) apply_matrix.pressed.connect(_on_apply_matrix_pressed) @@ -162,13 +167,11 @@ func popup_transform_actions(idx: int, control: Control) -> void: var context_popup := ContextPopup.new() context_popup.setup(btn_array, true) - HandlerGUI.popup_under_rect_center(context_popup, control.get_global_rect(), - get_viewport()) + HandlerGUI.popup_under_rect_center(context_popup, control.get_global_rect(), get_viewport()) func popup_new_transform_context(idx: int, control: Control) -> void: var btn_array: Array[Button] = [] - const CONST_ARR: PackedStringArray = ["matrix", "translate", "rotate", "scale", - "skewX", "skewY"] + const CONST_ARR: PackedStringArray = ["matrix", "translate", "rotate", "scale", "skewX", "skewY"] for transform_type in CONST_ARR: var btn := ContextPopup.create_button(transform_type, insert_transform.bind(idx, transform_type), false, @@ -177,19 +180,8 @@ func popup_new_transform_context(idx: int, control: Control) -> void: btn_array.append(btn) var transform_context := ContextPopup.new() - transform_context.setup_with_title(btn_array, - Translator.translate("New transform"), true) - HandlerGUI.popup_under_rect_center(transform_context, control.get_global_rect(), - get_viewport()) - - -func _unhandled_input(event: InputEvent) -> void: - if ShortcutUtils.is_action_pressed(event, "ui_undo"): - undo_redo.undo() - accept_event() - elif ShortcutUtils.is_action_pressed(event, "ui_redo"): - undo_redo.redo() - accept_event() + transform_context.setup_with_title(btn_array, Translator.translate("New transform"), true) + HandlerGUI.popup_under_rect_center(transform_context, control.get_global_rect(), get_viewport()) # So I have to rebuild this in its entirety to keep the references safe or something... diff --git a/src/ui_widgets/unrecognized_field.gd b/src/ui_widgets/unrecognized_field.gd index d3815a0..ffb99a8 100644 --- a/src/ui_widgets/unrecognized_field.gd +++ b/src/ui_widgets/unrecognized_field.gd @@ -21,5 +21,4 @@ func sync() -> void: text = element.get_attribute_value(attribute_name) func sync_localization() -> void: - tooltip_text = attribute_name + "\n(%s)" %\ - Translator.translate("VectorTouch doesn’t recognize this attribute") + tooltip_text = attribute_name + "\n(%s)" % Translator.translate("VectorTouch doesn’t recognize this attribute") diff --git a/src/ui_widgets/zoom_menu.gd b/src/ui_widgets/zoom_menu.gd index 146da5f..4dfd987 100644 --- a/src/ui_widgets/zoom_menu.gd +++ b/src/ui_widgets/zoom_menu.gd @@ -6,23 +6,22 @@ const MAX_ZOOM = 512.0 signal zoom_changed(zoom_level: float, offset: Vector2) signal zoom_reset_pressed -@onready var zoom_out_button: Button = $ZoomOut -@onready var zoom_in_button: Button = $ZoomIn -@onready var zoom_reset_button: Button = $ZoomReset +@onready var zoom_out_button: BetterButton = $ZoomOut +@onready var zoom_in_button: BetterButton = $ZoomIn +@onready var zoom_reset_button: BetterButton = $ZoomReset var _zoom_level: float -func _unhandled_input(event: InputEvent) -> void: - if ShortcutUtils.is_action_pressed(event, "zoom_in"): - zoom_in() - accept_event() - elif ShortcutUtils.is_action_pressed(event, "zoom_out"): - zoom_out() - accept_event() - elif ShortcutUtils.is_action_pressed(event, "zoom_reset"): - zoom_reset() - accept_event() +func _ready() -> void: + var shortcuts := ShortcutsRegistration.new() + shortcuts.add_shortcut("zoom_in", zoom_in) + shortcuts.add_shortcut("zoom_out", zoom_out) + shortcuts.add_shortcut("zoom_reset", zoom_reset) + HandlerGUI.register_shortcuts(self, shortcuts) + zoom_out_button.shortcuts_bind = shortcuts + zoom_in_button.shortcuts_bind = shortcuts + zoom_reset_button.shortcuts_bind = shortcuts func set_zoom(new_value: float, offset := Vector2(0.5, 0.5)) -> void: @@ -65,12 +64,10 @@ func update_buttons_appearance() -> void: var is_min_zoom := _zoom_level < MIN_ZOOM or is_equal_approx(_zoom_level, MIN_ZOOM) zoom_in_button.disabled = is_max_zoom - zoom_in_button.mouse_default_cursor_shape = Control.CURSOR_ARROW if\ - is_max_zoom else Control.CURSOR_POINTING_HAND + zoom_in_button.mouse_default_cursor_shape = Control.CURSOR_ARROW if is_max_zoom else Control.CURSOR_POINTING_HAND zoom_out_button.disabled = is_min_zoom - zoom_out_button.mouse_default_cursor_shape = Control.CURSOR_ARROW if\ - is_min_zoom else Control.CURSOR_POINTING_HAND + zoom_out_button.mouse_default_cursor_shape = Control.CURSOR_ARROW if is_min_zoom else Control.CURSOR_POINTING_HAND func _on_zoom_out_pressed() -> void: diff --git a/src/ui_widgets/zoom_menu.tscn b/src/ui_widgets/zoom_menu.tscn index 776a197..91ddd5a 100644 --- a/src/ui_widgets/zoom_menu.tscn +++ b/src/ui_widgets/zoom_menu.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://oltvrf01xrxl"] +[gd_scene load_steps=5 format=3 uid="uid://oltvrf01xrxl"] [ext_resource type="Texture2D" uid="uid://c2h5snkvemm4p" path="res://assets/icons/Minus.svg" id="1_8ggy2"] [ext_resource type="Script" uid="uid://dj2q7wnto3uqp" path="res://src/ui_widgets/zoom_menu.gd" id="1_18ab8"] [ext_resource type="Texture2D" uid="uid://eif2ioi0mw17" path="res://assets/icons/Plus.svg" id="2_284x5"] +[ext_resource type="Script" uid="uid://ynx3s1jc6bwq" path="res://src/ui_widgets/BetterButton.gd" id="3_r0sro"] [node name="ZoomMenu" type="HBoxContainer"] anchors_preset = -1 @@ -17,6 +18,8 @@ focus_mode = 0 mouse_default_cursor_shape = 2 icon = ExtResource("1_8ggy2") icon_alignment = 1 +script = ExtResource("3_r0sro") +metadata/_custom_type_script = "uid://ynx3s1jc6bwq" [node name="ZoomReset" type="Button" parent="."] custom_minimum_size = Vector2(58, 0) @@ -24,6 +27,8 @@ layout_mode = 2 focus_mode = 0 mouse_default_cursor_shape = 2 text = "100%" +script = ExtResource("3_r0sro") +metadata/_custom_type_script = "uid://ynx3s1jc6bwq" [node name="ZoomIn" type="Button" parent="."] layout_mode = 2 @@ -31,6 +36,8 @@ focus_mode = 0 mouse_default_cursor_shape = 2 icon = ExtResource("2_284x5") icon_alignment = 1 +script = ExtResource("3_r0sro") +metadata/_custom_type_script = "uid://ynx3s1jc6bwq" [connection signal="pressed" from="ZoomOut" to="." method="_on_zoom_out_pressed"] [connection signal="pressed" from="ZoomReset" to="." method="_on_zoom_reset_pressed"] diff --git a/src/utils/FileUtils.gd b/src/utils/FileUtils.gd index 70823ab..661f7a4 100644 --- a/src/utils/FileUtils.gd +++ b/src/utils/FileUtils.gd @@ -19,8 +19,7 @@ static func reset_svg() -> void: static func apply_svgs_from_paths(paths: PackedStringArray, show_incorrect_extension_errors := true) -> void: - _start_file_import_process(paths, _apply_svg, PackedStringArray(["svg"]), - show_incorrect_extension_errors) + _start_file_import_process(paths, _apply_svg, PackedStringArray(["svg"]), show_incorrect_extension_errors) static func compare_svg_to_disk_contents(idx := -1) -> FileState: var tab := Configs.savedata.get_active_tab() if idx == -1 else Configs.savedata.get_tab(idx) @@ -29,8 +28,7 @@ static func compare_svg_to_disk_contents(idx := -1) -> FileState: return FileState.DOES_NOT_EXIST # Check if importing the file's text into VectorTouch would change the current SVG text. # Avoid the parsing if checking the active tab. - var state_svg_text := State.svg_text if idx == -1 else\ - SVGParser.root_to_editor_text(SVGParser.text_to_root(tab.get_true_svg_text()).svg) + var state_svg_text := State.svg_text if idx == -1 else SVGParser.root_to_editor_text(SVGParser.text_to_root(tab.get_true_svg_text()).svg) if state_svg_text == SVGParser.root_to_editor_text(SVGParser.text_to_root(content).svg): return FileState.SAME else: @@ -68,12 +66,11 @@ static func open_export_dialog(export_data: ImageExportData, final_callback := C final_callback.call() else: if _is_native_preferred(): - var native_callback :=\ - func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: - if has_selected: - _finish_export(files[0], export_data) - if final_callback.is_valid(): - final_callback.call() + var native_callback := func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: + if has_selected: + _finish_export(files[0], export_data) + if final_callback.is_valid(): + final_callback.call() DisplayServer.file_dialog_show( TranslationUtils.get_file_dialog_save_mode_title_text(export_data.format), @@ -82,11 +79,10 @@ static func open_export_dialog(export_data: ImageExportData, final_callback := C DisplayServer.FILE_DIALOG_MODE_SAVE_FILE, PackedStringArray(["*." + export_data.format]), native_callback) else: - var non_native_callback :=\ - func(paths: PackedStringArray) -> void: - _finish_export(paths[0], export_data) - if final_callback.is_valid(): - final_callback.call() + var non_native_callback := func(paths: PackedStringArray) -> void: + _finish_export(paths[0], export_data) + if final_callback.is_valid(): + final_callback.call() var export_dialog := GoodFileDialogScene.instantiate() export_dialog.setup(Configs.savedata.get_active_tab_dir(), _choose_file_name(), @@ -99,10 +95,9 @@ static func open_xml_export_dialog(xml: String, file_name: String) -> void: _web_save(xml.to_utf8_buffer(), "application/xml") else: if _is_native_preferred(): - var native_callback :=\ - func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: - if has_selected: - _finish_xml_export(files[0], xml) + var native_callback := func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: + if has_selected: + _finish_xml_export(files[0], xml) DisplayServer.file_dialog_show( TranslationUtils.get_file_dialog_save_mode_title_text("xml"), @@ -111,11 +106,12 @@ static func open_xml_export_dialog(xml: String, file_name: String) -> void: PackedStringArray(["*.xml"]), native_callback) else: var export_dialog := GoodFileDialogScene.instantiate() - export_dialog.setup(Configs.savedata.get_last_dir(), - file_name, GoodFileDialog.FileMode.SAVE, PackedStringArray(["xml"])) + export_dialog.setup(Configs.savedata.get_last_dir(), file_name, GoodFileDialog.FileMode.SAVE, PackedStringArray(["xml"])) HandlerGUI.add_menu(export_dialog) export_dialog.files_selected.connect( - func(paths: PackedStringArray) -> void: _finish_xml_export(paths[0], xml)) + func(paths: PackedStringArray) -> void: + _finish_xml_export(paths[0], xml) + ) static func _finish_export(file_path: String, export_data: ImageExportData) -> void: if not (file_path.contains("/Documents/") or file_path.contains("/Download/")): @@ -160,8 +156,7 @@ static func load_reference_from_image(img: Image) -> void: static func _is_native_preferred() -> bool: - return DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE) and\ - Configs.savedata.use_native_file_dialog + return DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE) and Configs.savedata.use_native_file_dialog static func _choose_file_name() -> String: return Utils.get_file_name(Configs.savedata.get_active_tab().svg_file_path) @@ -172,16 +167,14 @@ static func open_svg_import_dialog() -> void: _open_import_dialog(PackedStringArray(["svg"]), _apply_svg, true) static func open_image_import_dialog() -> void: - _open_import_dialog(PackedStringArray(["png", "jpg", "jpeg", "webp", "svg"]), - _finish_reference_load) + _open_import_dialog(PackedStringArray(["png", "jpg", "jpeg", "webp", "svg"]), _finish_reference_load) static func open_xml_import_dialog(completion_callback: Callable) -> void: _open_import_dialog(PackedStringArray(["xml"]), completion_callback) # On web, the completion callback can't use the full file path. -static func _open_import_dialog(extensions: PackedStringArray, -completion_callback: Callable, multi_select := false) -> void: +static func _open_import_dialog(extensions: PackedStringArray, completion_callback: Callable, multi_select := false) -> void: var permission := "android.permission.READ_MEDIA_IMAGES" if Configs.current_sdk < 33: permission = "android.permission.READ_EXTERNAL_STORAGE" @@ -201,21 +194,17 @@ completion_callback: Callable, multi_select := false) -> void: for extension in extensions_with_dots: filters.append("*" + extension) - var native_callback :=\ - func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: - if has_selected: - _start_file_import_process(files, completion_callback, extensions) + var native_callback := func(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: + if has_selected: + _start_file_import_process(files, completion_callback, extensions) DisplayServer.file_dialog_show( - TranslationUtils.get_file_dialog_select_mode_title_text(multi_select, - extensions), Configs.savedata.get_last_dir(), "", false, - DisplayServer.FILE_DIALOG_MODE_OPEN_FILES if multi_select else\ - DisplayServer.FILE_DIALOG_MODE_OPEN_FILE, filters, native_callback) + TranslationUtils.get_file_dialog_select_mode_title_text(multi_select, extensions), Configs.savedata.get_last_dir(), "", false, + DisplayServer.FILE_DIALOG_MODE_OPEN_FILES if multi_select else DisplayServer.FILE_DIALOG_MODE_OPEN_FILE, filters, native_callback) else: var import_dialog := GoodFileDialogScene.instantiate() import_dialog.setup(Configs.savedata.get_last_dir(), "", - GoodFileDialog.FileMode.MULTI_SELECT if multi_select else\ - GoodFileDialog.FileMode.SELECT, extensions) + GoodFileDialog.FileMode.MULTI_SELECT if multi_select else GoodFileDialog.FileMode.SELECT, extensions) HandlerGUI.add_menu(import_dialog) import_dialog.files_selected.connect( func(paths: PackedStringArray) -> void: @@ -223,9 +212,8 @@ completion_callback: Callable, multi_select := false) -> void: ) # Preprocessing step where all files with wrong extensions are discarded. -static func _start_file_import_process(file_paths: PackedStringArray, -completion_callback: Callable, allowed_extensions: PackedStringArray, -show_incorrect_extension_errors := true) -> void: +static func _start_file_import_process(file_paths: PackedStringArray, completion_callback: Callable, +allowed_extensions: PackedStringArray, show_incorrect_extension_errors := true) -> void: if not show_incorrect_extension_errors: for i in range(file_paths.size() - 1, -1, -1): if not file_paths[i].get_extension() in allowed_extensions: @@ -267,8 +255,7 @@ show_incorrect_extension_errors := true) -> void: proceed_callback.call() -static func _file_import_proceed(file_paths: PackedStringArray, -completion_callback: Callable, show_file_missing_alert := true) -> void: +static func _file_import_proceed(file_paths: PackedStringArray, completion_callback: Callable, show_file_missing_alert := true) -> void: var file_path := file_paths[0] var preserved_file_paths := file_paths.duplicate() file_paths.remove_at(0) @@ -328,8 +315,7 @@ completion_callback: Callable, show_file_missing_alert := true) -> void: _: completion_callback.call(file.get_buffer(file.get_length()), file_path) -static func _apply_svg(data: Variant, file_path: String, proceed_callback := Callable(), -is_last_file := true) -> void: +static func _apply_svg(data: Variant, file_path: String, proceed_callback := Callable(), is_last_file := true) -> void: var existing_tab_idx := -1 for tab_idx in Configs.savedata.get_tab_count(): if Configs.savedata.get_tab(tab_idx).svg_file_path == file_path: @@ -391,8 +377,7 @@ static func _on_import_panel_accepted_empty_tab_scenario(svg_text: String) -> vo static func _on_import_panel_canceled_transient_scenario() -> void: State.transient_tab_path = "" -static func _on_import_panel_accepted_transient_scenario( -file_path: String, svg_text: String) -> void: +static func _on_import_panel_accepted_transient_scenario(file_path: String, svg_text: String) -> void: Configs.savedata.add_tab_with_path(file_path) State.transient_tab_path = "" Configs.savedata.get_active_tab().setup_svg_text(svg_text) @@ -465,9 +450,8 @@ static func _close_tabs_internal(indices: Array[int]) -> void: else: title = Translator.translate("Save the changes?") message = Translator.translate( - "Do you want to save the changes made to {file_name}?").format( - {"file_name": Configs.savedata.get_active_tab().presented_name}) + "\n\n" +\ - Translator.translate("Your changes will be lost if you don't save them.") + "Do you want to save the changes made to {file_name}?").format({"file_name": Configs.savedata.get_active_tab().presented_name}) +\ + "\n\n" + Translator.translate("Your changes will be lost if you don't save them.") var options_dialog := OptionsDialogScene.instantiate() HandlerGUI.add_menu(options_dialog) diff --git a/src/utils/ImageExportData.gd b/src/utils/ImageExportData.gd index 1a8cf33..24e8083 100644 --- a/src/utils/ImageExportData.gd +++ b/src/utils/ImageExportData.gd @@ -49,8 +49,7 @@ func image_to_buffer(image: Image) -> PackedByteArray: func generate_image() -> Image: var export_svg := State.root_element.duplicate() if export_svg.get_attribute_list("viewBox").is_empty(): - export_svg.set_attribute("viewBox", - PackedFloat64Array([0.0, 0.0, export_svg.width, export_svg.height])) + export_svg.set_attribute("viewBox", PackedFloat64Array([0.0, 0.0, export_svg.width, export_svg.height])) # First ensure there are dimensions. # Otherwise changing one side could influence the other. export_svg.set_attribute("width", export_svg.width) diff --git a/src/utils/ShortcutUtils.gd b/src/utils/ShortcutUtils.gd index 490ae28..8eb7dd3 100644 --- a/src/utils/ShortcutUtils.gd +++ b/src/utils/ShortcutUtils.gd @@ -1,26 +1,5 @@ @abstract class_name ShortcutUtils -# Can be activated in all contexts. -const UNIVERSAL_ACTIONS: PackedStringArray = ["quit", "toggle_fullscreen", "about_info", - "about_donate", "check_updates", "open_settings", "about_repo", "about_website", - "open_externally", "open_in_folder"] - -# Requires there being no dialogs. -const EFFECT_ACTIONS: PackedStringArray = ["view_show_grid", "view_show_handles", - "view_rasterized_svg", "view_show_reference", "view_overlay_reference", - "load_reference", "toggle_snap"] - -# Requires there being no popups either. -const EDITOR_ACTIONS: PackedStringArray = ["import", "export", "save", "save_as", - "close_tab", "close_all_other_tabs", "close_tabs_to_left", "close_tabs_to_right", - "close_empty_tabs", "close_saved_tabs", "new_tab", "select_next_tab", - "select_previous_tab", "copy_svg_text", "optimize", "reset_svg", "debug"] - -# Requires no drag-and-drop actions ongoing. -const PRISTINE_ACTIONS: PackedStringArray = ["ui_undo", "ui_redo", "ui_cancel", "delete", - "move_up", "move_down", "duplicate", "select_all"] - - # The bool after each action is for whether the action can be modified. const _action_categories_dict: Dictionary[String, Dictionary] = { "file": { diff --git a/src/utils/ThemeUtils.gd b/src/utils/ThemeUtils.gd index 413c0eb..b67e899 100644 --- a/src/utils/ThemeUtils.gd +++ b/src/utils/ThemeUtils.gd @@ -74,6 +74,7 @@ static var icon_pressed_color: Color static var translucent_button_color_disabled: Color static var flat_button_color_disabled: Color +static var context_button_color_disabled: Color static var subtle_flat_panel_color: Color static var contrast_flat_panel_color: Color @@ -164,6 +165,7 @@ static func recalculate_colors() -> void: # Panels basic_panel_inner_color = softer_base_color basic_panel_border_color = base_color.lerp(max_contrast_color, 0.24) + basic_panel_border_color.s = minf(basic_panel_border_color.s * 2.0, lerpf(basic_panel_border_color.s, 1.0, 0.2)) subtle_panel_border_color = basic_panel_border_color.lerp(basic_panel_inner_color, 0.4) subtle_panel_border_color.s = minf(subtle_panel_border_color.s * 2.0, lerpf(subtle_panel_border_color.s, 1.0, 0.2)) @@ -708,8 +710,7 @@ static func _setup_button(theme: Theme) -> void: var disabled_context_button_stylebox := context_button_stylebox.duplicate() # Ensure enough contrast. - disabled_context_button_stylebox.bg_color = Color(Color.BLACK, maxf(0.16, - 0.48 - color_difference(Color.BLACK, basic_panel_inner_color) * 2)) + disabled_context_button_stylebox.bg_color = context_button_color_disabled theme.set_stylebox("disabled", "ContextButton", disabled_context_button_stylebox) theme.add_type("PathCommandAbsoluteButton") @@ -721,63 +722,38 @@ static func _setup_button(theme: Theme) -> void: path_command_absolute_button_stylebox_normal.content_margin_right = 5.0 path_command_absolute_button_stylebox_normal.content_margin_top = 0.0 path_command_absolute_button_stylebox_normal.content_margin_bottom = 0.0 - path_command_absolute_button_stylebox_normal.bg_color = Color("cc7a29") if\ - ThemeUtils.is_theme_dark else Color("f2cb91") - path_command_absolute_button_stylebox_normal.border_color = Color("e6ae5c") if\ - ThemeUtils.is_theme_dark else Color("ffaa33") - theme.set_stylebox("normal", "PathCommandAbsoluteButton", - path_command_absolute_button_stylebox_normal) - theme.set_stylebox("disabled", "PathCommandAbsoluteButton", - path_command_absolute_button_stylebox_normal) - - var path_command_absolute_button_stylebox_hover :=\ - path_command_absolute_button_stylebox_normal.duplicate() - path_command_absolute_button_stylebox_hover.bg_color = Color("d9822b") if\ - ThemeUtils.is_theme_dark else Color("f2c279") - path_command_absolute_button_stylebox_hover.border_color = Color("f2cb91") if\ - ThemeUtils.is_theme_dark else Color("f29718") - theme.set_stylebox("hover", "PathCommandAbsoluteButton", - path_command_absolute_button_stylebox_hover) - - var path_command_absolute_button_stylebox_pressed :=\ - path_command_absolute_button_stylebox_normal.duplicate() - path_command_absolute_button_stylebox_pressed.bg_color = Color("ffbf40") if\ - ThemeUtils.is_theme_dark else Color("f2ae49") - path_command_absolute_button_stylebox_pressed.border_color = Color("ffecb3") if\ - ThemeUtils.is_theme_dark else Color("e68600") - theme.set_stylebox("pressed", "PathCommandAbsoluteButton", - path_command_absolute_button_stylebox_pressed) + path_command_absolute_button_stylebox_normal.bg_color = Color("cc7a29") if ThemeUtils.is_theme_dark else Color("f2cb91") + path_command_absolute_button_stylebox_normal.border_color = Color("e6ae5c") if ThemeUtils.is_theme_dark else Color("ffaa33") + theme.set_stylebox("normal", "PathCommandAbsoluteButton", path_command_absolute_button_stylebox_normal) + theme.set_stylebox("disabled", "PathCommandAbsoluteButton", path_command_absolute_button_stylebox_normal) + + var path_command_absolute_button_stylebox_hover := path_command_absolute_button_stylebox_normal.duplicate() + path_command_absolute_button_stylebox_hover.bg_color = Color("d9822b") if ThemeUtils.is_theme_dark else Color("f2c279") + path_command_absolute_button_stylebox_hover.border_color = Color("f2cb91") if ThemeUtils.is_theme_dark else Color("f29718") + theme.set_stylebox("hover", "PathCommandAbsoluteButton", path_command_absolute_button_stylebox_hover) + + var path_command_absolute_button_stylebox_pressed := path_command_absolute_button_stylebox_normal.duplicate() + path_command_absolute_button_stylebox_pressed.bg_color = Color("ffbf40") if ThemeUtils.is_theme_dark else Color("f2ae49") + path_command_absolute_button_stylebox_pressed.border_color = Color("ffecb3") if ThemeUtils.is_theme_dark else Color("e68600") + theme.set_stylebox("pressed", "PathCommandAbsoluteButton", path_command_absolute_button_stylebox_pressed) theme.add_type("PathCommandRelativeButton") theme.set_type_variation("PathCommandRelativeButton", "Button") - var path_command_relative_button_stylebox_normal :=\ - path_command_absolute_button_stylebox_normal.duplicate() - path_command_relative_button_stylebox_normal.bg_color = Color("a329cc") if\ - ThemeUtils.is_theme_dark else Color("d291f2") - path_command_relative_button_stylebox_normal.border_color = Color("bd73e6") if\ - ThemeUtils.is_theme_dark else Color("bb33ff") - theme.set_stylebox("normal", "PathCommandRelativeButton", - path_command_relative_button_stylebox_normal) - theme.set_stylebox("disabled", "PathCommandRelativeButton", - path_command_relative_button_stylebox_normal) - - var path_command_relative_button_stylebox_hover :=\ - path_command_absolute_button_stylebox_normal.duplicate() - path_command_relative_button_stylebox_hover.bg_color = Color("ad2bd9") if\ - ThemeUtils.is_theme_dark else Color("ca79f2") - path_command_relative_button_stylebox_hover.border_color = Color("d291f2") if\ - ThemeUtils.is_theme_dark else Color("aa18f2") - theme.set_stylebox("hover", "PathCommandRelativeButton", - path_command_relative_button_stylebox_hover) - - var path_command_relative_button_stylebox_pressed :=\ - path_command_absolute_button_stylebox_normal.duplicate() - path_command_relative_button_stylebox_pressed.bg_color = Color("bf40ff") if\ - ThemeUtils.is_theme_dark else Color("ba49f2") - path_command_relative_button_stylebox_pressed.border_color = Color("dfb3ff") if\ - ThemeUtils.is_theme_dark else Color("9900e6") - theme.set_stylebox("pressed", "PathCommandRelativeButton", - path_command_relative_button_stylebox_pressed) + var path_command_relative_button_stylebox_normal := path_command_absolute_button_stylebox_normal.duplicate() + path_command_relative_button_stylebox_normal.bg_color = Color("a329cc") if ThemeUtils.is_theme_dark else Color("d291f2") + path_command_relative_button_stylebox_normal.border_color = Color("bd73e6") if ThemeUtils.is_theme_dark else Color("bb33ff") + theme.set_stylebox("normal", "PathCommandRelativeButton", path_command_relative_button_stylebox_normal) + theme.set_stylebox("disabled", "PathCommandRelativeButton", path_command_relative_button_stylebox_normal) + + var path_command_relative_button_stylebox_hover := path_command_absolute_button_stylebox_normal.duplicate() + path_command_relative_button_stylebox_hover.bg_color = Color("ad2bd9") if ThemeUtils.is_theme_dark else Color("ca79f2") + path_command_relative_button_stylebox_hover.border_color = Color("d291f2") if ThemeUtils.is_theme_dark else Color("aa18f2") + theme.set_stylebox("hover", "PathCommandRelativeButton", path_command_relative_button_stylebox_hover) + + var path_command_relative_button_stylebox_pressed := path_command_absolute_button_stylebox_normal.duplicate() + path_command_relative_button_stylebox_pressed.bg_color = Color("bf40ff") if ThemeUtils.is_theme_dark else Color("ba49f2") + path_command_relative_button_stylebox_pressed.border_color = Color("dfb3ff") if ThemeUtils.is_theme_dark else Color("9900e6") + theme.set_stylebox("pressed", "PathCommandRelativeButton", path_command_relative_button_stylebox_pressed) theme.add_type("TextButton") theme.set_type_variation("TextButton", "Button") @@ -843,31 +819,25 @@ static func _setup_checkbox(theme: Theme) -> void: theme.set_color("font_hover_color", "CheckBox", highlighted_text_color) theme.set_color("font_pressed_color", "CheckBox", text_color) theme.set_color("font_hover_pressed_color", "CheckBox", highlighted_text_color) - theme.set_icon("checked", "CheckBox", - SVGTexture.create_from_string(""" - + theme.set_icon("checked", "CheckBox", SVGTexture.create_from_string( + """ - """ %\ - [soft_accent_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) + """ % [soft_accent_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) ) - theme.set_icon("checked_disabled", "CheckBox", - SVGTexture.create_from_string(""" - + theme.set_icon("checked_disabled", "CheckBox", SVGTexture.create_from_string( + """ - """ %\ - [soft_accent_color.lerp(gray_color, 0.2).to_html(false), black_or_white_counter_accent_color.to_html(false)]) + """ % [soft_accent_color.lerp(gray_color, 0.2).to_html(false), black_or_white_counter_accent_color.to_html(false)]) ) - theme.set_icon("unchecked", "CheckBox", - SVGTexture.create_from_string(""" - + theme.set_icon("unchecked", "CheckBox", SVGTexture.create_from_string( + """ """ % gray_color.to_html(false)) ) - theme.set_icon("unchecked_disabled", "CheckBox", - SVGTexture.create_from_string(""" - + theme.set_icon("unchecked_disabled", "CheckBox", SVGTexture.create_from_string( + """ """ % gray_color.to_html(false)) ) @@ -893,7 +863,7 @@ static func _setup_checkbox(theme: Theme) -> void: theme.set_stylebox("hover_pressed", "CheckBox", hover_checkbox_stylebox) var disabled_checkbox_stylebox := checkbox_stylebox.duplicate() - disabled_checkbox_stylebox.bg_color = flat_button_color_disabled + disabled_checkbox_stylebox.bg_color = context_button_color_disabled theme.set_stylebox("disabled", "CheckBox", disabled_checkbox_stylebox) @@ -905,21 +875,17 @@ static func _setup_checkbutton(theme: Theme) -> void: theme.set_color("font_hover_color", "CheckButton", highlighted_text_color) theme.set_color("font_pressed_color", "CheckButton", text_color) theme.set_color("font_hover_pressed_color", "CheckButton", highlighted_text_color) - theme.set_icon("checked", "CheckButton", - SVGTexture.create_from_string(""" - + theme.set_icon("checked", "CheckButton", SVGTexture.create_from_string( + """ - """ %\ - [soft_accent_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) + """ % [soft_accent_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) ) - theme.set_icon("unchecked", "CheckButton", - SVGTexture.create_from_string(""" - + theme.set_icon("unchecked", "CheckButton", SVGTexture.create_from_string( + """ - """ %\ - [gray_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) + """ % [gray_color.to_html(false), black_or_white_counter_accent_color.to_html(false)]) ) @@ -988,8 +954,7 @@ static func _setup_lineedit(theme: Theme) -> void: var hover_stylebox := stylebox.duplicate() hover_stylebox.draw_center = false - hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else\ - stronger_hover_overlay_color + hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else stronger_hover_overlay_color theme.set_stylebox("hover", "LineEdit", hover_stylebox) var focus_stylebox := stylebox.duplicate() @@ -1027,8 +992,7 @@ static func _setup_lineedit(theme: Theme) -> void: var left_connected_hover_stylebox := left_connected_stylebox.duplicate() left_connected_hover_stylebox.draw_center = false - left_connected_hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else\ - stronger_hover_overlay_color + left_connected_hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else stronger_hover_overlay_color theme.set_stylebox("hover", "LeftConnectedLineEdit", left_connected_hover_stylebox) var left_connected_focus_stylebox := left_connected_stylebox.duplicate() @@ -1066,8 +1030,7 @@ static func _setup_lineedit(theme: Theme) -> void: var right_connected_hover_stylebox := right_connected_stylebox.duplicate() right_connected_hover_stylebox.draw_center = false - right_connected_hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else\ - stronger_hover_overlay_color + right_connected_hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else stronger_hover_overlay_color theme.set_stylebox("hover", "RightConnectedLineEdit", right_connected_hover_stylebox) var right_connected_focus_stylebox := right_connected_stylebox.duplicate() @@ -1100,8 +1063,7 @@ static func _setup_lineedit(theme: Theme) -> void: var mini_stylebox_hover := mini_stylebox.duplicate() mini_stylebox_hover.draw_center = false - mini_stylebox_hover.border_color = strong_hover_overlay_color if is_theme_dark else\ - stronger_hover_overlay_color + mini_stylebox_hover.border_color = strong_hover_overlay_color if is_theme_dark else stronger_hover_overlay_color theme.set_stylebox("hover", "MiniLineEdit", mini_stylebox_hover) var mini_stylebox_pressed := mini_stylebox.duplicate() @@ -1305,8 +1267,7 @@ static func _setup_textedit(theme: Theme) -> void: var hover_stylebox := StyleBoxFlat.new() hover_stylebox.draw_center = false - hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else\ - stronger_hover_overlay_color + hover_stylebox.border_color = strong_hover_overlay_color if is_theme_dark else stronger_hover_overlay_color hover_stylebox.set_border_width_all(2) hover_stylebox.set_corner_radius_all(5) theme.set_stylebox("hover", "TextEdit", hover_stylebox) @@ -1333,15 +1294,13 @@ static func _setup_tooltip(theme: Theme) -> void: static func _setup_splitcontainer(theme: Theme) -> void: theme.add_type("SplitContainer") - theme.set_icon("grabber", "VSplitContainer", - SVGTexture.create_from_string(""" - + theme.set_icon("grabber", "VSplitContainer", SVGTexture.create_from_string( + """ """ % desaturated_color.to_html(false)) ) - theme.set_icon("grabber", "HSplitContainer", - SVGTexture.create_from_string(""" - + theme.set_icon("grabber", "HSplitContainer", SVGTexture.create_from_string( + """ """ % desaturated_color.to_html(false)) ) diff --git a/src/utils/TranslationUtils.gd b/src/utils/TranslationUtils.gd index 4215184..f13fbf9 100644 --- a/src/utils/TranslationUtils.gd +++ b/src/utils/TranslationUtils.gd @@ -28,33 +28,24 @@ static func get_action_description(action_name: String, for_button := false) -> "close_all_other_tabs": return Translator.translate("Close all other tabs") "close_empty_tabs": return Translator.translate("Close empty tabs") "close_saved_tabs": return Translator.translate("Close saved tabs") - "new_tab": return Translator.translate("Create tab") if\ - for_button else Translator.translate("Create a new tab") + "new_tab": return Translator.translate("Create tab") if for_button else Translator.translate("Create a new tab") "select_next_tab": return Translator.translate("Select the next tab") "select_previous_tab": return Translator.translate("Select the previous tab") - "optimize": return Translator.translate("Optimize") if\ - for_button else Translator.translate("Optimize SVG") - "copy_svg_text": return Translator.translate("Copy all text") if\ - for_button else Translator.translate("Copy the SVG text") + "optimize": return Translator.translate("Optimize") if for_button else Translator.translate("Optimize SVG") + "copy_svg_text": return Translator.translate("Copy all text") if for_button else Translator.translate("Copy the SVG text") "reset_svg": return Translator.translate("Reset SVG") - "open_externally": return Translator.translate("Open externally") if\ - for_button else Translator.translate("Open SVG externally") - "open_in_folder": return Translator.translate("Show in File Manager") if\ - for_button else Translator.translate("Show SVG in File Manager") + "open_externally": return Translator.translate("Open externally") if for_button else Translator.translate("Open SVG externally") + "open_in_folder": return Translator.translate("Show in File Manager") if for_button else Translator.translate("Show SVG in File Manager") "ui_undo": return Translator.translate("Undo") "ui_redo": return Translator.translate("Redo") "ui_copy": return Translator.translate("Copy") "ui_paste": return Translator.translate("Paste") "ui_cut": return Translator.translate("Cut") "select_all": return Translator.translate("Select all") - "duplicate": return Translator.translate("Duplicate") if\ - for_button else Translator.translate("Duplicate the selection") - "delete": return Translator.translate("Delete") if\ - for_button else Translator.translate("Delete the selection") - "move_up": return Translator.translate("Move up") if\ - for_button else Translator.translate("Move the selection up") - "move_down": return Translator.translate("Move down") if\ - for_button else Translator.translate("Move the selection down") + "duplicate": return Translator.translate("Duplicate") if for_button else Translator.translate("Duplicate the selection") + "delete": return Translator.translate("Delete") if for_button else Translator.translate("Delete the selection") + "move_up": return Translator.translate("Move up") if for_button else Translator.translate("Move the selection up") + "move_down": return Translator.translate("Move down") if for_button else Translator.translate("Move the selection down") "find": return Translator.translate("Find") "zoom_in": return Translator.translate("Zoom in") "zoom_out": return Translator.translate("Zoom out") @@ -87,24 +78,18 @@ static func get_action_description(action_name: String, for_button := false) -> "cubic_bezier_absolute": return get_path_command_description("C") "shorthand_cubic_bezier_relative": return get_path_command_description("s") "shorthand_cubic_bezier_absolute": return get_path_command_description("S") - "open_settings": return Translator.translate("Settings") if\ - for_button else Translator.translate("Open Settings menu") - "about_info": return Translator.translate("About…") if\ - for_button else Translator.translate("Open About menu") - "about_donate": return Translator.translate("Donate…") if\ - for_button else Translator.translate("Open Donate menu") - "about_repo": return Translator.translate("VectorTouch repository") if\ - for_button else Translator.translate("Open VectorTouch repository") - "about_website": return Translator.translate("VectorTouch website") if\ - for_button else Translator.translate("Open VectorTouch website") + "open_settings": return Translator.translate("Settings") if for_button else Translator.translate("Open Settings menu") + "about_info": return Translator.translate("About…") if for_button else Translator.translate("Open About menu") + "about_donate": return Translator.translate("Donate…") if for_button else Translator.translate("Open Donate menu") + "about_repo": return Translator.translate("VectorTouch repository") if for_button else Translator.translate("Open VectorTouch repository") + "about_website": return Translator.translate("VectorTouch website") if for_button else Translator.translate("Open VectorTouch website") "check_updates": return Translator.translate("Check for updates") "quit": return Translator.translate("Quit the application") "toggle_fullscreen": return Translator.translate("Toggle fullscreen") _: return action_name -static func get_path_command_description(command_char: String, -omit_relativity := false) -> String: +static func get_path_command_description(command_char: String, omit_relativity := false) -> String: var description: String match command_char: "M", "m": description = Translator.translate("Move to") @@ -139,27 +124,21 @@ static func get_extension_alert_text(allowed_extensions: PackedStringArray) -> S for i in allowed_extensions.size(): allowed_extensions[i] = get_extension_readable_name(allowed_extensions[i]) var extension_list := ", ".join(allowed_extensions) - return Translator.translate( - "Only {extension_list} files are supported for this operation.").format( - {"extension_list": extension_list}) + return Translator.translate("Only {extension_list} files are supported for this operation.").format({"extension_list": extension_list}) -static func get_file_dialog_select_mode_title_text(multi_select: bool, -extensions: PackedStringArray) -> String: +static func get_file_dialog_select_mode_title_text(multi_select: bool, extensions: PackedStringArray) -> String: if multi_select: - return Translator.translate("Select {format} files").format( - {"format": get_extension_readable_name("svg")}) + return Translator.translate("Select {format} files").format({"format": get_extension_readable_name("svg")}) else: if extensions.size() > 1: # Multiple formats currently only show up for reference images. return Translator.translate("Select an image") else: # "an" because this can currently only show for SVG and XML files. - return Translator.translate("Select an {format} file").format( - {"format": get_extension_readable_name(extensions[0])}) + return Translator.translate("Select an {format} file").format({"format": get_extension_readable_name(extensions[0])}) static func get_file_dialog_save_mode_title_text(extension: String) -> String: - return Translator.translate("Save the {format} file").format( - {"format": get_extension_readable_name(extension)}) + return Translator.translate("Save the {format} file").format({"format": get_extension_readable_name(extension)}) static func get_extension_readable_name(extension: String) -> String: match extension: diff --git a/src/utils/Utils.gd b/src/utils/Utils.gd index 0c82c50..72dd48f 100644 --- a/src/utils/Utils.gd +++ b/src/utils/Utils.gd @@ -46,12 +46,9 @@ static func simplify_file_path(file_path: String) -> String: # Resize the control to be resized automatically to its text width, up to a maximum. # The property name defaults account for most controls that may need to use this. static func set_max_text_width(control: Control, max_width: float, buffer: float, -text_property := "text", font_property := "font", -font_size_property := "font_size") -> void: - control.custom_minimum_size.x = minf(control.get_theme_font( - font_property).get_string_size(control.get(text_property), - HORIZONTAL_ALIGNMENT_FILL, -1, - control.get_theme_font_size(font_size_property)).x + buffer, max_width) +text_property := "text", font_property := "font", font_size_property := "font_size") -> void: + control.custom_minimum_size.x = minf(control.get_theme_font(font_property).get_string_size(control.get(text_property), + HORIZONTAL_ALIGNMENT_FILL, -1, control.get_theme_font_size(font_size_property)).x + buffer, max_width) # TODO This is a necessary workaround for a few situations, # because Godot declines position changes if they are too small. @@ -60,15 +57,13 @@ static func set_control_position_fixed(control: Control, new_position: Vector2) control.position = new_position -static func get_cubic_bezier_points(cp1: Vector2, cp2: Vector2, cp3: Vector2, -cp4: Vector2) -> PackedVector2Array: +static func get_cubic_bezier_points(cp1: Vector2, cp2: Vector2, cp3: Vector2, cp4: Vector2) -> PackedVector2Array: var curve := Curve2D.new() curve.add_point(cp1, Vector2(), cp2) curve.add_point(cp4, cp3) return curve.tessellate(6, 1) -static func get_quadratic_bezier_points(cp1: Vector2, cp2: Vector2, -cp3: Vector2) -> PackedVector2Array: +static func get_quadratic_bezier_points(cp1: Vector2, cp2: Vector2, cp3: Vector2) -> PackedVector2Array: return Utils.get_cubic_bezier_points( cp1, 2/3.0 * (cp2 - cp1), 2/3.0 * (cp2 - cp3), cp3) @@ -99,22 +94,18 @@ static func is_event_drag(event: InputEvent) -> bool: return event is InputEventMouseMotion and event.button_mask == MOUSE_BUTTON_LEFT static func is_event_drag_start(event: InputEvent) -> bool: - return event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and\ - event.is_pressed() + return event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() static func is_event_drag_end(event: InputEvent) -> bool: - return event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and\ - event.is_released() + return event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_released() static func is_event_drag_cancel(event: InputEvent) -> bool: - return event.is_action_pressed("ui_cancel") or\ - event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT + return event.is_action_pressed("ui_cancel") or event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT # Used to somewhat prevent unwanted inputs from triggering XNode drag & drop. static func mouse_filter_pass_non_drag_events(event: InputEvent) -> Control.MouseFilter: - return Control.MOUSE_FILTER_STOP if event is InputEventMouseMotion and\ - event.button_mask == MOUSE_BUTTON_MASK_LEFT else Control.MOUSE_FILTER_PASS + return Control.MOUSE_FILTER_STOP if event is InputEventMouseMotion and event.button_mask == MOUSE_BUTTON_MASK_LEFT else Control.MOUSE_FILTER_PASS static func has_clipboard_web_safe() -> bool: diff --git a/src/utils/Utils64Bit.gd b/src/utils/Utils64Bit.gd index eca5460..da03260 100644 --- a/src/utils/Utils64Bit.gd +++ b/src/utils/Utils64Bit.gd @@ -7,12 +7,10 @@ static func get_vector(vector: PackedFloat64Array) -> Vector2: return Vector2(vector[0], vector[1]) static func get_transform(transform: PackedFloat64Array) -> Transform2D: - return Transform2D(Vector2(transform[0], transform[1]), - Vector2(transform[2], transform[3]), Vector2(transform[4], transform[5])) + return Transform2D(Vector2(transform[0], transform[1]), Vector2(transform[2], transform[3]), Vector2(transform[4], transform[5])) # Vector2 * Transform2D -static func transform_vector_mult(transform: PackedFloat64Array, -vector: PackedFloat64Array) -> PackedFloat64Array: +static func transform_vector_mult(transform: PackedFloat64Array, vector: PackedFloat64Array) -> PackedFloat64Array: var x := vector[0] var y := vector[1] var xx := transform[0] @@ -32,8 +30,7 @@ static func get_transform_determinant(transform: PackedFloat64Array) -> float: return xx * yy - xy * yx # Transform2D.affine_inverse() -static func get_transform_affine_inverse( -transform: PackedFloat64Array) -> PackedFloat64Array: +static func get_transform_affine_inverse(transform: PackedFloat64Array) -> PackedFloat64Array: var det := get_transform_determinant(transform) if det == 0: return PackedFloat64Array([NAN, NAN, NAN, NAN, NAN, NAN]) @@ -55,8 +52,7 @@ transform: PackedFloat64Array) -> PackedFloat64Array: return PackedFloat64Array([new_xx, new_xy, new_yx, new_yy, new_ox, new_oy]) # Transform2D * Transform2D -static func transforms_mult(a: PackedFloat64Array, -b: PackedFloat64Array) -> PackedFloat64Array: +static func transforms_mult(a: PackedFloat64Array, b: PackedFloat64Array) -> PackedFloat64Array: var a_xx := a[0] var a_xy := a[1] var a_yx := a[2] @@ -78,3 +74,12 @@ b: PackedFloat64Array) -> PackedFloat64Array: var ox := a_xx * b_ox + a_yx * b_oy + a_ox var oy := a_xy * b_ox + a_yy * b_oy + a_oy return PackedFloat64Array([xx, xy, yx, yy, ox, oy]) + +# Vector2.project(Vector2) +static func vector_project(a: PackedFloat64Array, b: PackedFloat64Array) -> PackedFloat64Array: + var scalar := dot(a, b) / dot(b, b) + return [b[0] * scalar, b[1] * scalar] + +# Vector2.dot(Vector2) +static func dot(a: PackedFloat64Array, b: PackedFloat64Array) -> float: + return a[0] * b[0] + a[1] * b[1] diff --git a/translations/GodSVG.pot b/translations/GodSVG.pot index f3ef2da..5df76f6 100644 --- a/translations/GodSVG.pot +++ b/translations/GodSVG.pot @@ -11,6 +11,8 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "" @@ -316,7 +318,8 @@ msgstr "" msgid "Preview image size is limited to {dimensions}" msgstr "" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "" @@ -413,11 +416,11 @@ msgid "Add element" msgstr "" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "" @@ -534,28 +537,33 @@ msgstr "" msgid "New versions available!" msgstr "" +#: src/ui_widgets/PanelGrid.gd: +msgid "Copy email" +msgstr "" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" +#: src/ui_widgets/color_configuration_popup.gd: +msgid "Edit color name" msgstr "" -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" +#: src/ui_widgets/color_configuration_popup.gd: +msgid "Delete color" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: -msgid "Edit color name" +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: +msgid "Unnamed" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: -msgid "Delete color" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: -msgid "Unnamed" +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" msgstr "" #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: @@ -945,10 +953,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "" @@ -974,7 +978,11 @@ msgid "Warps the cursor to the opposite side whenever it reaches a viewport boun msgstr "" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + +#: src/ui_widgets/settings_content_generic.gd: +msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one." msgstr "" #: src/ui_widgets/settings_content_generic.gd: diff --git a/translations/bg.po b/translations/bg.po index 7ce4031..270ef37 100644 --- a/translations/bg.po +++ b/translations/bg.po @@ -1,7 +1,7 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: VectorTouch\n" +"Project-Id-Version: GodSVG\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: \n" @@ -12,16 +12,18 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.2\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "MewPurPur " #: src/autoload/HandlerGUI.gd: -msgid "Quit VectorTouch" -msgstr "Затвори VectorTouch" +msgid "Quit GodSVG" +msgstr "Затвори GodSVG" #: src/autoload/HandlerGUI.gd: -msgid "Do you want to quit VectorTouch?" -msgstr "Наистина ли искаш да затвориш VectorTouch?" +msgid "Do you want to quit GodSVG?" +msgstr "Наистина ли искаш да затвориш GodSVG?" #: src/autoload/HandlerGUI.gd: msgid "Quit" @@ -317,7 +319,8 @@ msgstr "Копирай" msgid "Preview image size is limited to {dimensions}" msgstr "Размерът на визуализацията е ограничен до {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Оформление" @@ -414,11 +417,11 @@ msgid "Add element" msgstr "Добави елемент" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Изключени" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Влачи и пусни за да промениш оформлението на интерфейса" @@ -528,37 +531,42 @@ msgid "View all releases" msgstr "Разгледай всички издания" #: src/ui_parts/update_menu.gd: -msgid "VectorTouch is up-to-date." -msgstr "VectorTouch е актуален." +msgid "GodSVG is up-to-date." +msgstr "GodSVG е актуален." #: src/ui_parts/update_menu.gd: msgid "New versions available!" msgstr "Налични са нови версии!" +#: src/ui_widgets/PanelGrid.gd: +msgid "Copy email" +msgstr "Копирай имейла" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Създай" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Търсене на цвят" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Цветно колело" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Промени името на цвета" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Изтрий цвета" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Неименуван" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Търсене на цвят" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Цветно колело" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "Неограничено" @@ -652,7 +660,7 @@ msgstr "Добави бърз клавиш" msgid "Press keys…" msgstr "Натисни клавиши…" -#. Refers to the formatter used for VectorTouch's code editor. +#. Refers to the formatter used for GodSVG's code editor. #: src/ui_widgets/settings_content_generic.gd: msgid "Editor formatter" msgstr "Форматировач за приложението" @@ -946,10 +954,6 @@ msgstr "Определя максималния брой кадри в секу msgid "Keep Screen On" msgstr "Задръж екрана включен" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "Поддържа екрана включен дори при неактивност, така че скрийнсейвърът да не се включва." - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Разни" @@ -963,8 +967,8 @@ msgid "Sync window title to file name" msgstr "Синхронизирай името на прозореца с файла" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, adds the current file name before the \"VectorTouch\" window title." -msgstr "Когато е включено, добавя името на настоящия файл пред заглавието на прозореца \"VectorTouch\"." +msgid "When enabled, adds the current file name before the \"GodSVG\" window title." +msgstr "Когато е включено, добавя името на настоящия файл пред заглавието на прозореца \"GodSVG\"." #: src/ui_widgets/settings_content_generic.gd: msgid "When enabled, uses spaces instead of a single tab for indentation." @@ -975,8 +979,12 @@ msgid "Warps the cursor to the opposite side whenever it reaches a viewport boun msgstr "Превърта курсора когато той достигне краищата на екрана докато влачи гледката." #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." -msgstr "Когато е активирано, ще бъде използван файловият мениджър на твоята операционна система вместо вградения файлов мениджър на VectorTouch." +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "Поддържа екрана включен дори при неактивност, така че скрийнсейвърът да не се включва." + +#: src/ui_widgets/settings_content_generic.gd: +msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one." +msgstr "Когато е активирано, ще бъде използван файловият мениджър на твоята операционна система вместо вградения файлов мениджър на GodSVG." #: src/ui_widgets/settings_content_generic.gd: msgid "The setting has no effect in the current configuration." @@ -1023,8 +1031,8 @@ msgid "New transform" msgstr "Нова трансформация" #: src/ui_widgets/unrecognized_field.gd: -msgid "VectorTouch doesn’t recognize this attribute" -msgstr "VectorTouch не разпознава този атрибут" +msgid "GodSVG doesn’t recognize this attribute" +msgstr "GodSVG не разпознава този атрибут" #: src/utils/FileUtils.gd: msgid "The following files were discarded:" @@ -1079,8 +1087,8 @@ msgid "Don't save" msgstr "Не записвай" #: src/utils/FileUtils.gd: -msgid "{file_path} is already being edited inside VectorTouch." -msgstr "{file_path} вече се редактира в VectorTouch." +msgid "{file_path} is already being edited inside GodSVG." +msgstr "{file_path} вече се редактира в GodSVG." #: src/utils/FileUtils.gd: msgid "If you want to revert your edits since the last save, use {reset_svg}." @@ -1287,20 +1295,20 @@ msgid "Open Donate menu" msgstr "Отвори менюто за дарения" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch repository" -msgstr "Репозиторията на VectorTouch" +msgid "GodSVG repository" +msgstr "Репозиторията на GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch repository" -msgstr "Отвори репозиторията на VectorTouch" +msgid "Open GodSVG repository" +msgstr "Отвори репозиторията на GodSVG" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch website" -msgstr "Уебсайта на VectorTouch" +msgid "GodSVG website" +msgstr "Уебсайта на GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch website" -msgstr "Отвори уебсайта на VectorTouch" +msgid "Open GodSVG website" +msgstr "Отвори уебсайта на GodSVG" #: src/utils/TranslationUtils.gd: msgid "Check for updates" diff --git a/translations/de.po b/translations/de.po index 19c66c5..5a12abd 100644 --- a/translations/de.po +++ b/translations/de.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.6\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Kiisu-Master, Swarkin" @@ -318,7 +320,8 @@ msgstr "Kopieren" msgid "Preview image size is limited to {dimensions}" msgstr "Vorschaubildgröße ist auf {dimensions} limitiert." -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Layout" @@ -415,11 +418,11 @@ msgid "Add element" msgstr "Element hinzufügen" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Ausgeschlossen" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Ziehen und Ablegen zum Ändern des Layouts" @@ -536,30 +539,36 @@ msgstr "VectorTouch ist auf dem neuesten Stand." msgid "New versions available!" msgstr "Neue Versionen verfügbar!" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Pfad kopieren" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Erstellen" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Farbe suchen" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Farbauswahl" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Farbnamen ändern" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Farbe löschen" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Unbenannt" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Farbe suchen" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Farbauswahl" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -959,10 +968,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Verschiedenes" @@ -987,6 +992,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Teleportiert den Mauszeiger zur gegenüberliegenden Seite, soblald eine Bildschirmgrenze während des Verschiebens erreicht wird." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/en.po b/translations/en.po index d5ce00d..5c0202f 100644 --- a/translations/en.po +++ b/translations/en.po @@ -1,7 +1,7 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: VectorTouch\n" +"Project-Id-Version: GodSVG\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: \n" @@ -12,15 +12,17 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.2\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "" #: src/autoload/HandlerGUI.gd: -msgid "Quit VectorTouch" +msgid "Quit GodSVG" msgstr "" #: src/autoload/HandlerGUI.gd: -msgid "Do you want to quit VectorTouch?" +msgid "Do you want to quit GodSVG?" msgstr "" #: src/autoload/HandlerGUI.gd: @@ -317,7 +319,8 @@ msgstr "" msgid "Preview image size is limited to {dimensions}" msgstr "" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "" @@ -414,11 +417,11 @@ msgid "Add element" msgstr "" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "" @@ -528,35 +531,40 @@ msgid "View all releases" msgstr "" #: src/ui_parts/update_menu.gd: -msgid "VectorTouch is up-to-date." +msgid "GodSVG is up-to-date." msgstr "" #: src/ui_parts/update_menu.gd: msgid "New versions available!" msgstr "" +#: src/ui_widgets/PanelGrid.gd: +msgid "Copy email" +msgstr "" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" +#: src/ui_widgets/color_configuration_popup.gd: +msgid "Edit color name" msgstr "" -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" +#: src/ui_widgets/color_configuration_popup.gd: +msgid "Delete color" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: -msgid "Edit color name" +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: +msgid "Unnamed" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: -msgid "Delete color" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" msgstr "" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: -msgid "Unnamed" +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" msgstr "" #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: @@ -652,7 +660,7 @@ msgstr "" msgid "Press keys…" msgstr "" -#. Refers to the formatter used for VectorTouch's code editor. +#. Refers to the formatter used for GodSVG's code editor. #: src/ui_widgets/settings_content_generic.gd: msgid "Editor formatter" msgstr "" @@ -946,10 +954,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "" @@ -963,7 +967,7 @@ msgid "Sync window title to file name" msgstr "" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, adds the current file name before the \"VectorTouch\" window title." +msgid "When enabled, adds the current file name before the \"GodSVG\" window title." msgstr "" #: src/ui_widgets/settings_content_generic.gd: @@ -975,7 +979,11 @@ msgid "Warps the cursor to the opposite side whenever it reaches a viewport boun msgstr "" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + +#: src/ui_widgets/settings_content_generic.gd: +msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one." msgstr "" #: src/ui_widgets/settings_content_generic.gd: @@ -1023,7 +1031,7 @@ msgid "New transform" msgstr "" #: src/ui_widgets/unrecognized_field.gd: -msgid "VectorTouch doesn’t recognize this attribute" +msgid "GodSVG doesn’t recognize this attribute" msgstr "" #: src/utils/FileUtils.gd: @@ -1079,7 +1087,7 @@ msgid "Don't save" msgstr "" #: src/utils/FileUtils.gd: -msgid "{file_path} is already being edited inside VectorTouch." +msgid "{file_path} is already being edited inside GodSVG." msgstr "" #: src/utils/FileUtils.gd: @@ -1287,19 +1295,19 @@ msgid "Open Donate menu" msgstr "" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch repository" +msgid "GodSVG repository" msgstr "" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch repository" +msgid "Open GodSVG repository" msgstr "" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch website" +msgid "GodSVG website" msgstr "" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch website" +msgid "Open GodSVG website" msgstr "" #: src/utils/TranslationUtils.gd: diff --git a/translations/es.po b/translations/es.po index c20ee34..32d7e00 100644 --- a/translations/es.po +++ b/translations/es.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.6\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Alejandro Moctezuma " @@ -318,7 +320,8 @@ msgstr "Copiar" msgid "Preview image size is limited to {dimensions}" msgstr "El tamaño de la imagen de vista previa está limitado a {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Diseño" @@ -415,11 +418,11 @@ msgid "Add element" msgstr "Añadir elemento" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Excluidos" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Arrastra y suelta para cambiar el diseño" @@ -536,30 +539,36 @@ msgstr "VectorTouch está actualizado." msgid "New versions available!" msgstr "¡Nuevas versiones disponibles!" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Copiar ruta" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Crear" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Buscar color" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Cuentagotas" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Editar nombre del color" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Eliminar color" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Sin nombre" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Buscar color" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Cuentagotas" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -959,10 +968,6 @@ msgstr "Si la velocidad de fotogramas está limitada, este valor determina la ca msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Misceláneos" @@ -987,6 +992,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Mueve el cursor hacia el lado opuesto cada vez que alcanza el límite de la ventana gráfica mientras se desplaza." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/et.po b/translations/et.po index b9620dc..ac5f7b0 100644 --- a/translations/et.po +++ b/translations/et.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.2\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Kiisu-Master" @@ -318,7 +320,8 @@ msgstr "Kopeeri" msgid "Preview image size is limited to {dimensions}" msgstr "Eelvaade on piiratud suurusele {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Paigutus" @@ -415,11 +418,11 @@ msgid "Add element" msgstr "Lisa element" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Peidetud" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Lohista, et muuta paigutust" @@ -536,30 +539,36 @@ msgstr "VectorTouch on ajakohane." msgid "New versions available!" msgstr "Uuem versioon on saadaval!" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Kopeeri asukoht" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Loo" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Otsi värvi" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Värvivalija" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Muuda värvi nime" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Kustuta värv" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Nimetu" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Otsi värvi" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Värvivalija" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -958,10 +967,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Mitmesugust" @@ -986,6 +991,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Viib kursori akna vastaspoolele, kui see jõuab vaate liigutamise ajal selle servani, et see liikumist ei takistaks." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/fr.po b/translations/fr.po index e01d65c..0014e1f 100644 --- a/translations/fr.po +++ b/translations/fr.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.2\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "thatoddshade " @@ -318,7 +320,8 @@ msgstr "Copier" msgid "Preview image size is limited to {dimensions}" msgstr "La taille de l'image de prévisualisation est limitée à {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Disposition" @@ -415,11 +418,11 @@ msgid "Add element" msgstr "Ajouter un élément" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Exclu(s)" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Glissez-déposez pour modifier la disposition" @@ -536,30 +539,36 @@ msgstr "VectorTouch est à jour." msgid "New versions available!" msgstr "De nouvelles versions sont disponibles !" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Copier le chemin" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Créer" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Rechercher la couleur" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Pipette" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Modifier le nom de la couleur" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Supprimer la couleur" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Sans nom" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Rechercher la couleur" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Pipette" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -960,10 +969,6 @@ msgstr "Si le taux de rafraîchissement est limité, cette valeur déterminera l msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Divers" @@ -988,6 +993,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Téléporte le curseur de l'autre côté de la vue à chaque fois qu'il en atteind la limite." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/nl.po b/translations/nl.po index 55c3e1b..46d5948 100644 --- a/translations/nl.po +++ b/translations/nl.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.4\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Racer911dash1, jas31415" @@ -320,7 +322,8 @@ msgstr "Kopiëren" msgid "Preview image size is limited to {dimensions}" msgstr "Voorbeeldafbeelding maat is beperkt tot {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Indeling" @@ -417,11 +420,11 @@ msgid "Add element" msgstr "Element toevoegen" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "" @@ -540,30 +543,36 @@ msgstr "VectorTouch is up-to-date." msgid "New versions available!" msgstr "Nieuwe versies" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Pad kopiëren" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Creëren" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Zoekkleur" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Kleurenplukker" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Kleurnaam bewerken" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Kleur verwijderen" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Onbenoemd" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Zoekkleur" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Kleurenplukker" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -963,10 +972,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Overige" @@ -991,6 +996,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Verplaatst de cursur naar de overkant wanneer het buiten de viewport gaat tijdens het rondkijken." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/pt_BR.po b/translations/pt_BR.po index 6a826a2..b2858e0 100644 --- a/translations/pt_BR.po +++ b/translations/pt_BR.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.6\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Felipe Sena Costa " @@ -319,7 +321,8 @@ msgstr "Copiar" msgid "Preview image size is limited to {dimensions}" msgstr "O tamanho da visualização da prévia de imagem é limitado à {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Layout" @@ -416,11 +419,11 @@ msgid "Add element" msgstr "Adicionar elemento" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Excluídos" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Arraste e solte para modificar o layout" @@ -537,30 +540,36 @@ msgstr "VectorTouch está atualizado." msgid "New versions available!" msgstr "Novas versões disponíveis!" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "Copiar caminho" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Criar" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Procurar cor" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Seletor de Cores" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Editar nome da cor" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Remover cor" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Sem nome" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Procurar cor" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Seletor de Cores" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -959,10 +968,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "Variados" @@ -987,6 +992,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Passa o cursor para o lado oposto da tela quando ele atinge uma borda da viewport quando movimentando a visualização." +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." diff --git a/translations/ru.po b/translations/ru.po index 821be27..6a78dc1 100644 --- a/translations/ru.po +++ b/translations/ru.po @@ -1,10 +1,10 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: VectorTouch\n" +"Project-Id-Version: GodSVG\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" -"Last-Translator: \n" +"Last-Translator: freeducks-debug \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" @@ -13,16 +13,18 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.6\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" -msgstr "volkov, Gallifreyan " +msgstr "volkov, Gallifreyan , freeducks-debug" #: src/autoload/HandlerGUI.gd: -msgid "Quit VectorTouch" -msgstr "Выйти из VectorTouch" +msgid "Quit GodSVG" +msgstr "Выйти из GodSVG" #: src/autoload/HandlerGUI.gd: -msgid "Do you want to quit VectorTouch?" -msgstr "Вы хотите выйти из VectorTouch?" +msgid "Do you want to quit GodSVG?" +msgstr "Вы хотите выйти из GodSVG?" #: src/autoload/HandlerGUI.gd: msgid "Quit" @@ -133,26 +135,25 @@ msgstr "6 цифровое шестандцатяричное значение" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: msgid "Dark" -msgstr "" +msgstr "Темная" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: -#, fuzzy msgid "Light" -msgstr "Высота" +msgstr "Светлая" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: msgid "Black (OLED)" -msgstr "" +msgstr "Темная (OLED)" #: src/config_classes/SaveData.gd: msgid "Default Dark" -msgstr "" +msgstr "Стандартная темная" #: src/config_classes/SaveData.gd: msgid "Default Light" -msgstr "" +msgstr "Стандартная светлая" #: src/config_classes/TabData.gd: msgid "Empty" @@ -319,7 +320,8 @@ msgstr "Скопировать" msgid "Preview image size is limited to {dimensions}" msgstr "Размер предварительного просмотра изображения ограничен до {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Макет" @@ -416,11 +418,11 @@ msgid "Add element" msgstr "Добавить элемент" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Исключены" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Перетягивайте, чтобы изменить макет" @@ -530,40 +532,45 @@ msgid "View all releases" msgstr "Показать все сборки" #: src/ui_parts/update_menu.gd: -msgid "VectorTouch is up-to-date." -msgstr "Установлена последняя версия VectorTouch." +msgid "GodSVG is up-to-date." +msgstr "Установлена последняя версия GodSVG." #: src/ui_parts/update_menu.gd: msgid "New versions available!" msgstr "Доступна новая версия!" +#: src/ui_widgets/PanelGrid.gd: +msgid "Copy email" +msgstr "Скопировать электронную почту" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Создать" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Искать цвет" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Цветовая пипетка" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Редактировать название цвета" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Удалить цвет" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Без названия" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Искать цвет" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Цветовая пипетка" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" -msgstr "" +msgstr "Без ограничений" #: src/ui_widgets/good_color_picker.gd: msgid "Color keywords" @@ -632,11 +639,11 @@ msgstr "Так же используется" #: src/ui_widgets/profile_frame.gd: msgid "Apply" -msgstr "" +msgstr "Применить" #: src/ui_widgets/profile_frame.gd: msgid "Apply all of this preset's defaults" -msgstr "" +msgstr "Применить все стандартные значения этого пресета" #: src/ui_widgets/setting_frame.gd: src/ui_widgets/setting_shortcut.gd: msgid "Reset to default" @@ -654,7 +661,7 @@ msgstr "Добавить сочетание клавиш" msgid "Press keys…" msgstr "Нажмите клавиши…" -#. Refers to the formatter used for VectorTouch's code editor. +#. Refers to the formatter used for GodSVG's code editor. #: src/ui_widgets/settings_content_generic.gd: msgid "Editor formatter" msgstr "Форматер редактора" @@ -669,9 +676,8 @@ msgid "Preset" msgstr "Пресет" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Determines the default values of the formatter configs." -msgstr "Изменить масштаб пользовательского интерфейса." +msgstr "Определяет стандартные значения для настроек форматера." #: src/ui_widgets/settings_content_generic.gd: msgid "Keep comments" @@ -758,27 +764,24 @@ msgid "Remove unnecessary parameters" msgstr "Удалить ненужные параметры" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Theme preset" -msgstr "Сбросить масштаб" +msgstr "Пресет темы" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the default values of theming-related settings, including the highlighter preset." -msgstr "" +msgstr "Определяет стандартные значения связанные с настройками темы, включая пресет подсветки." #: src/ui_widgets/settings_content_generic.gd: msgid "Primary theme colors" -msgstr "" +msgstr "Главные цвета темы" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Base color" msgstr "Базовый цвет" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Accent color" -msgstr "Цвет текста" +msgstr "Цвет акцента" #: src/ui_widgets/settings_content_generic.gd: msgid "SVG Text colors" @@ -786,11 +789,11 @@ msgstr "Цвет SVG текста" #: src/ui_widgets/settings_content_generic.gd: msgid "Highlighter preset" -msgstr "" +msgstr "Пресет подсветки" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the default values of SVG highlighter settings." -msgstr "" +msgstr "Определяет стандартные значения настроек SVG подсветки." #: src/ui_widgets/settings_content_generic.gd: msgid "Symbol color" @@ -827,9 +830,8 @@ msgstr "Цвет ошибки" #. Refers to the draggable gizmos. #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Handles" -msgstr "Размер ручек" +msgstr "Ручки" #: src/ui_widgets/settings_content_generic.gd: msgid "Inside color" @@ -852,32 +854,29 @@ msgid "Hovered selected color" msgstr "Цвет выделенного-наведенного" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Selection rectangle" -msgstr "Выбрать изображение" +msgstr "Прямоугольник выбора" #: src/ui_widgets/settings_content_generic.gd: msgid "Speed" -msgstr "" +msgstr "Скорость" #. Refers to the selection rectangle's animated dashed stroke. #: src/ui_widgets/settings_content_generic.gd: msgid "Dash length" -msgstr "" +msgstr "Длина линии" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Color {index}" -msgstr "Цветовая пипетка" +msgstr "Цвет {index}" #: src/ui_widgets/settings_content_generic.gd: msgid "Basic colors" msgstr "Базовый цвет" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Canvas color" -msgstr "Внутренний цвет" +msgstr "Цвет полотна" #: src/ui_widgets/settings_content_generic.gd: msgid "Grid color" @@ -900,9 +899,8 @@ msgid "Close tabs with middle mouse button" msgstr "Закрывать вкладки средней клавишей мыши" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it." -msgstr "Если включено - нажатие на вкладку средней кнопкой мыши закроет ее. Если выключено - вкладка получит фокус." +msgstr "Если включено - нажатие на вкладку средней кнопкой мыши закроет ее вместо переключения фокуса." #: src/ui_widgets/settings_content_generic.gd: msgid "Invert zoom direction" @@ -921,47 +919,41 @@ msgid "Use CTRL for zooming" msgstr "Использовать CTRL для масштабирования" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling." msgstr "Если включено - прокрутка будет перемещать окно просмотра. Чтобы масштабировать зажмите CTRL при прокручивании." #: src/ui_widgets/settings_content_generic.gd: msgid "Display" -msgstr "" +msgstr "Отображение" #: src/ui_widgets/settings_content_generic.gd: msgid "UI scale" msgstr "Масштаб интерфейса" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Determines the scale factor for the interface." -msgstr "Изменить масштаб пользовательского интерфейса." +msgstr "Определяет множитель масштабирования интерфейса." #. Stands for "Vertical Synchronization". #: src/ui_widgets/settings_content_generic.gd: msgid "V-Sync" -msgstr "" +msgstr "Вертикальная синхронизация" #: src/ui_widgets/settings_content_generic.gd: msgid "Synchronizes graphics rendering with display refresh rate to prevent screen tearing artifacts. May increase input lag slightly." -msgstr "" +msgstr "Синхронизирует отображение графики с частотой обновления экрана, чтобы избегать артефактам (вроде \"разрыва\" картинки). Может увеличить задержку нажатий кнопок мыши и клавиатуры." #: src/ui_widgets/settings_content_generic.gd: msgid "Maximum FPS" -msgstr "" +msgstr "Максимальное количество кадров в секунду" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the maximum number of frames per second." -msgstr "" +msgstr "Определяет максимальное количество кадров в секунду." #: src/ui_widgets/settings_content_generic.gd: msgid "Keep Screen On" -msgstr "" - -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" +msgstr "Держать экран включенным" #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" @@ -976,29 +968,32 @@ msgid "Sync window title to file name" msgstr "Синхронизировать заголовок окна с названием файла" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, adds the current file name before the \"VectorTouch\" window title." -msgstr "" +msgid "When enabled, adds the current file name before the \"GodSVG\" window title." +msgstr "Когда активно, добавит текущий открытый файл перед \"GodSVG\" в заголовке окна." #: src/ui_widgets/settings_content_generic.gd: msgid "When enabled, uses spaces instead of a single tab for indentation." -msgstr "" +msgstr "Когда активно, использует пробелы вместо одного tab-а для отступов." #: src/ui_widgets/settings_content_generic.gd: msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Курсор будет телепортироваться от одного до противоположного края на границе окна просмотра." #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy -msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." -msgstr "Если включено, то будет использоваться родной файловый диалог вашей операционной системы для выбора файлов. Если выключено, то будет использоваться встроенный файловый диалог." +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "Будет удерживать экран активным, даже после бездействия, поэтому хранитель экрана не будет запускаться." + +#: src/ui_widgets/settings_content_generic.gd: +msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one." +msgstr "Если включено, то будет использоваться родной файловый диалог вашей операционной системы для выбора файлов вместо встроенного в GodSVG." #: src/ui_widgets/settings_content_generic.gd: msgid "The setting has no effect in the current configuration." -msgstr "" +msgstr "Эта опция не имеет эффекта на текущую конфигурацию." #: src/ui_widgets/settings_content_generic.gd: msgid "The setting can't be changed on this platform." -msgstr "" +msgstr "Эту опцию нельзя изменить на текущей платформе." #: src/ui_widgets/settings_content_palettes.gd: msgid "New palette" @@ -1037,8 +1032,8 @@ msgid "New transform" msgstr "Новая трансформация" #: src/ui_widgets/unrecognized_field.gd: -msgid "VectorTouch doesn’t recognize this attribute" -msgstr "VectorTouch не может распознать этот атрибут" +msgid "GodSVG doesn’t recognize this attribute" +msgstr "GodSVG не может распознать этот атрибут" #: src/utils/FileUtils.gd: msgid "The following files were discarded:" @@ -1093,8 +1088,8 @@ msgid "Don't save" msgstr "Не сохранять" #: src/utils/FileUtils.gd: -msgid "{file_path} is already being edited inside VectorTouch." -msgstr "Файл {file_path} уже редактируется внутри VectorTouch." +msgid "{file_path} is already being edited inside GodSVG." +msgstr "Файл {file_path} уже редактируется внутри GodSVG." #: src/utils/FileUtils.gd: msgid "If you want to revert your edits since the last save, use {reset_svg}." @@ -1301,20 +1296,20 @@ msgid "Open Donate menu" msgstr "Открыть меню благотворителей" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch repository" -msgstr "Репозиторий VectorTouch" +msgid "GodSVG repository" +msgstr "Репозиторий GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch repository" -msgstr "Открыть репозиторий VectorTouch" +msgid "Open GodSVG repository" +msgstr "Открыть репозиторий GodSVG" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch website" -msgstr "Веб-сайт VectorTouch" +msgid "GodSVG website" +msgstr "Веб-сайт GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch website" -msgstr "Открыть веб-сайт VectorTouch" +msgid "Open GodSVG website" +msgstr "Открыть веб-сайт GodSVG" #: src/utils/TranslationUtils.gd: msgid "Check for updates" @@ -1405,8 +1400,8 @@ msgstr "Сохранить {format} файл" msgid "Only {extension_list} files are supported for this operation." msgstr "Только файлы с расширениями {extension_list} поддерживаются для этой операции." -#~ msgid "If turned off, the window title remains as \"VectorTouch\" without including the current file." -#~ msgstr "Если выключено - заголовок окна будет просто \"VectorTouch\", не включая текущий файл." +#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file." +#~ msgstr "Если выключено - заголовок окна будет просто \"GodSVG\", не включая текущий файл." #~ msgid "Keep unrecognized XML structures" #~ msgstr "Сохранять нераспознанные XML" diff --git a/translations/uk.po b/translations/uk.po index 32341c3..c5c84a4 100644 --- a/translations/uk.po +++ b/translations/uk.po @@ -1,10 +1,10 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: VectorTouch\n" +"Project-Id-Version: GodSVG\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" -"Last-Translator: \n" +"Last-Translator: freeducks-debug \n" "Language-Team: \n" "Language: uk\n" "MIME-Version: 1.0\n" @@ -12,16 +12,18 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.6\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" -msgstr "volkov" +msgstr "volkov, freeducks-debug" #: src/autoload/HandlerGUI.gd: -msgid "Quit VectorTouch" -msgstr "Вийти із VectorTouch" +msgid "Quit GodSVG" +msgstr "Вийти із GodSVG" #: src/autoload/HandlerGUI.gd: -msgid "Do you want to quit VectorTouch?" -msgstr "Ви дійсно бажаєте вийти із VectorTouch?" +msgid "Do you want to quit GodSVG?" +msgstr "Ви дійсно бажаєте вийти із GodSVG?" #: src/autoload/HandlerGUI.gd: msgid "Quit" @@ -132,26 +134,25 @@ msgstr "6 значне шістнадцятирічне число" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: msgid "Dark" -msgstr "" +msgstr "Темна" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: -#, fuzzy msgid "Light" -msgstr "Висота" +msgstr "Світла" #. Refers to a theme preset. #: src/config_classes/SaveData.gd: msgid "Black (OLED)" -msgstr "" +msgstr "Темна (OLED)" #: src/config_classes/SaveData.gd: msgid "Default Dark" -msgstr "" +msgstr "Стандартна темна" #: src/config_classes/SaveData.gd: msgid "Default Light" -msgstr "" +msgstr "Стандартна світла" #: src/config_classes/TabData.gd: msgid "Empty" @@ -318,7 +319,8 @@ msgstr "Скопіювати" msgid "Preview image size is limited to {dimensions}" msgstr "Розмір попереднього перегляду зображення обмежено до {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "Макет" @@ -415,11 +417,11 @@ msgid "Add element" msgstr "Додати елемент" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "Виключені" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "Перетягніть і опустіть, щоб змінити макет" @@ -529,40 +531,45 @@ msgid "View all releases" msgstr "Показати усі версії" #: src/ui_parts/update_menu.gd: -msgid "VectorTouch is up-to-date." -msgstr "VectorTouch оновлено до останньої версії." +msgid "GodSVG is up-to-date." +msgstr "GodSVG оновлено до останньої версії." #: src/ui_parts/update_menu.gd: msgid "New versions available!" msgstr "Доступна нова версія!" +#: src/ui_widgets/PanelGrid.gd: +msgid "Copy email" +msgstr "Скопіювати електрону пошту" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "Створити" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "Шукати колір" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "Кольорова піпетка" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "Редагувати назву кольору" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "Видалити колір" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "Без назви" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "Шукати колір" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "Кольорова піпетка" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" -msgstr "" +msgstr "Без обмежень" #: src/ui_widgets/good_color_picker.gd: msgid "Color keywords" @@ -631,11 +638,11 @@ msgstr "Також використовується" #: src/ui_widgets/profile_frame.gd: msgid "Apply" -msgstr "" +msgstr "Застосувати" #: src/ui_widgets/profile_frame.gd: msgid "Apply all of this preset's defaults" -msgstr "" +msgstr "Застосувати стандартні значення цього пресету" #: src/ui_widgets/setting_frame.gd: src/ui_widgets/setting_shortcut.gd: msgid "Reset to default" @@ -653,7 +660,7 @@ msgstr "Додати клавіатурне скорочення" msgid "Press keys…" msgstr "Натисніть кнопки…" -#. Refers to the formatter used for VectorTouch's code editor. +#. Refers to the formatter used for GodSVG's code editor. #: src/ui_widgets/settings_content_generic.gd: msgid "Editor formatter" msgstr "Форматер редактору" @@ -669,9 +676,8 @@ msgid "Preset" msgstr "Пресет" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Determines the default values of the formatter configs." -msgstr "Змінити масштаб інтерфейсу користувача." +msgstr "Визначає стандартні значення конфігурації форматера." #: src/ui_widgets/settings_content_generic.gd: msgid "Keep comments" @@ -761,27 +767,24 @@ msgid "Remove unnecessary parameters" msgstr "Видалити необов'язкові параметри" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Theme preset" -msgstr "Скинути масштаб" +msgstr "Тема додатку" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the default values of theming-related settings, including the highlighter preset." -msgstr "" +msgstr "Визначає стандартні значення для налаштувань теми, включаючи налаштування підсвітки." #: src/ui_widgets/settings_content_generic.gd: msgid "Primary theme colors" -msgstr "" +msgstr "Головні кольори теми" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Base color" msgstr "Базовий колір" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Accent color" -msgstr "Колір тексту" +msgstr "Колір акценту" #: src/ui_widgets/settings_content_generic.gd: msgid "SVG Text colors" @@ -789,11 +792,11 @@ msgstr "Колір SVG тексту" #: src/ui_widgets/settings_content_generic.gd: msgid "Highlighter preset" -msgstr "" +msgstr "Тема підсвітки" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the default values of SVG highlighter settings." -msgstr "" +msgstr "Визначає стандартні значення підсвітки SVG." #: src/ui_widgets/settings_content_generic.gd: msgid "Symbol color" @@ -830,9 +833,8 @@ msgstr "Колір помилки" #. Refers to the draggable gizmos. #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Handles" -msgstr "Розмір ручок редагування" +msgstr "Ручки редагування" #: src/ui_widgets/settings_content_generic.gd: msgid "Inside color" @@ -855,32 +857,29 @@ msgid "Hovered selected color" msgstr "Колір наведено-виділеного" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Selection rectangle" -msgstr "Обрати зображення" +msgstr "Прямокутник вибору" #: src/ui_widgets/settings_content_generic.gd: msgid "Speed" -msgstr "" +msgstr "Швидкість" #. Refers to the selection rectangle's animated dashed stroke. #: src/ui_widgets/settings_content_generic.gd: msgid "Dash length" -msgstr "" +msgstr "Довжина лінії" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Color {index}" -msgstr "Кольорова піпетка" +msgstr "Колір {index}" #: src/ui_widgets/settings_content_generic.gd: msgid "Basic colors" msgstr "Базовий колір" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Canvas color" -msgstr "Внутрішній колір" +msgstr "Колір полотна" #: src/ui_widgets/settings_content_generic.gd: msgid "Grid color" @@ -903,9 +902,8 @@ msgid "Close tabs with middle mouse button" msgstr "Закривати вкладки при натисканні середньої кнопки миші" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it." -msgstr "Якщо увімкнено - клацання на вкладку середньою кнопкою миші закриє її. Якщо вимкнено - фокус буде замінено на неї." +msgstr "Якщо увімкнено - клацання на вкладку середньою кнопкою миші закриє її, замість того, щоб фокусуватися на ній." #: src/ui_widgets/settings_content_generic.gd: msgid "Invert zoom direction" @@ -924,47 +922,41 @@ msgid "Use CTRL for zooming" msgstr "Використовувати CTRL для масштабування" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling." msgstr "Якщо увімкнено - гортання буде рухати вікно перегляду. Щоб масштабувати, затисніть CTRL доки гортаєте." #: src/ui_widgets/settings_content_generic.gd: msgid "Display" -msgstr "" +msgstr "Дисплей" #: src/ui_widgets/settings_content_generic.gd: msgid "UI scale" msgstr "Масштаб інтерфейсу" #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy msgid "Determines the scale factor for the interface." -msgstr "Змінити масштаб інтерфейсу користувача." +msgstr "Визначає множник масштабу інтерфейсу." #. Stands for "Vertical Synchronization". #: src/ui_widgets/settings_content_generic.gd: msgid "V-Sync" -msgstr "" +msgstr "Вертикальна синхроназація" #: src/ui_widgets/settings_content_generic.gd: msgid "Synchronizes graphics rendering with display refresh rate to prevent screen tearing artifacts. May increase input lag slightly." -msgstr "" +msgstr "Синхронізує відображення графіки з частотою відновлення екрану, щоб запобігати артефактам відображення (на кшталт \"розриву\" екрана). Також може збільшити затримку натискань клавіатури або курсору." #: src/ui_widgets/settings_content_generic.gd: msgid "Maximum FPS" -msgstr "" +msgstr "Максимальна кількість кадрів на секунду" #: src/ui_widgets/settings_content_generic.gd: msgid "Determines the maximum number of frames per second." -msgstr "" +msgstr "Визначає максимальну кількість кадрів на секунду." #: src/ui_widgets/settings_content_generic.gd: msgid "Keep Screen On" -msgstr "" - -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" +msgstr "Тримати екран увімкненим" #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" @@ -979,29 +971,32 @@ msgid "Sync window title to file name" msgstr "Синхронізувати заголовок вікна з назвою поточного файлу" #: src/ui_widgets/settings_content_generic.gd: -msgid "When enabled, adds the current file name before the \"VectorTouch\" window title." -msgstr "" +msgid "When enabled, adds the current file name before the \"GodSVG\" window title." +msgstr "Коли активовано, додає назву поточного файлу перед \"GodSVG\" у заголовку вікна." #: src/ui_widgets/settings_content_generic.gd: msgid "When enabled, uses spaces instead of a single tab for indentation." -msgstr "" +msgstr "Коли активно, використовує пробіли замість одного tab-у для відступів." #: src/ui_widgets/settings_content_generic.gd: msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "Курсор буде телепортуватися від одного краю до протилежного при пересуванні вікна перегляду." #: src/ui_widgets/settings_content_generic.gd: -#, fuzzy -msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one." -msgstr "Якщо увімкнено, то буде використовувати рідний файловий діалог вашої операційної системи для обирання файлів. Якщо вимкнено, то замість буде використовуватися вбудований файловий діалог." +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "Відкладати присипляння системи та/або екрану навіть після бездіяльності, завдяки чому зберігач екрану не буде запускатися." + +#: src/ui_widgets/settings_content_generic.gd: +msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one." +msgstr "Якщо увімкнено, то буде використовувати рідний файловий діалог вашої операційної системи для обирання файлів замість вбудованого." #: src/ui_widgets/settings_content_generic.gd: msgid "The setting has no effect in the current configuration." -msgstr "" +msgstr "Це опція не має ефекту на поточну конфігурацію." #: src/ui_widgets/settings_content_generic.gd: msgid "The setting can't be changed on this platform." -msgstr "" +msgstr "Ця опція не може бути змінена на поточній платформі." #: src/ui_widgets/settings_content_palettes.gd: msgid "New palette" @@ -1040,8 +1035,8 @@ msgid "New transform" msgstr "Нова трансформація" #: src/ui_widgets/unrecognized_field.gd: -msgid "VectorTouch doesn’t recognize this attribute" -msgstr "VectorTouch не може розпізнати цей атрибут" +msgid "GodSVG doesn’t recognize this attribute" +msgstr "GodSVG не може розпізнати цей атрибут" #: src/utils/FileUtils.gd: msgid "The following files were discarded:" @@ -1096,8 +1091,8 @@ msgid "Don't save" msgstr "Не зберігати" #: src/utils/FileUtils.gd: -msgid "{file_path} is already being edited inside VectorTouch." -msgstr "Файл {file_path} вже редагується в VectorTouch." +msgid "{file_path} is already being edited inside GodSVG." +msgstr "Файл {file_path} вже редагується в GodSVG." #: src/utils/FileUtils.gd: msgid "If you want to revert your edits since the last save, use {reset_svg}." @@ -1305,20 +1300,20 @@ msgid "Open Donate menu" msgstr "Відкрити меню благодійників" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch repository" -msgstr "Репозиторій VectorTouch" +msgid "GodSVG repository" +msgstr "Репозиторій GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch repository" -msgstr "Відкрити репозиторій VectorTouch" +msgid "Open GodSVG repository" +msgstr "Відкрити репозиторій GodSVG" #: src/utils/TranslationUtils.gd: -msgid "VectorTouch website" -msgstr "Веб-сайт VectorTouch" +msgid "GodSVG website" +msgstr "Веб-сайт GodSVG" #: src/utils/TranslationUtils.gd: -msgid "Open VectorTouch website" -msgstr "Відкрити веб-сайт VectorTouch" +msgid "Open GodSVG website" +msgstr "Відкрити веб-сайт GodSVG" #: src/utils/TranslationUtils.gd: msgid "Check for updates" @@ -1409,8 +1404,8 @@ msgstr "Зберегти {format} файл" msgid "Only {extension_list} files are supported for this operation." msgstr "Тільки файли з розширеннями {extension_list} підтримуються для цієї операції." -#~ msgid "If turned off, the window title remains as \"VectorTouch\" without including the current file." -#~ msgstr "Якщо вимкнено - заголовок вікна залишиться як \"VectorTouch\", не включаючи назву поточного файлу." +#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file." +#~ msgstr "Якщо вимкнено - заголовок вікна залишиться як \"GodSVG\", не включаючи назву поточного файлу." #~ msgid "Keep unrecognized XML structures" #~ msgstr "Зберігати не розпізнані структури XML" diff --git a/translations/zh_CN.po b/translations/zh_CN.po index 08e7645..07a3031 100644 --- a/translations/zh_CN.po +++ b/translations/zh_CN.po @@ -12,6 +12,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.4\n" +#. Translators (comma-separated): Name or alias, optionally followed by an email in angle brackets . +#. Used for credits. Adding yourself is optional. New entries go at the end. Don't remove or rearrange existing entries. msgid "translation-credits" msgstr "Hamster5295 , Mike Lei " @@ -325,7 +327,8 @@ msgstr "复制" msgid "Preview image size is limited to {dimensions}" msgstr "预览图像大小被限制到 {dimensions}" -#: src/ui_parts/global_actions.gd: src/ui_parts/shortcut_panel_config.gd: +#: src/ui_parts/global_actions.gd: src/ui_parts/layout_configuration.gd: +#: src/ui_parts/shortcut_panel_config.gd: msgid "Layout" msgstr "" @@ -422,11 +425,11 @@ msgid "Add element" msgstr "添加元素" #. Refers to the zero, one, or multiple UI parts to not be shown in the final layout. It's of plural cardinality. -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Excluded" msgstr "" -#: src/ui_parts/layout_popup.gd: +#: src/ui_parts/layout_configuration.gd: msgid "Drag and drop to change the layout" msgstr "" @@ -550,30 +553,36 @@ msgstr "VectorTouch 是最新版本。" msgid "New versions available!" msgstr "新版本" +#: src/ui_widgets/PanelGrid.gd: +#, fuzzy +msgid "Copy email" +msgstr "复制路径" + #: src/ui_widgets/choose_name_dialog.gd: msgid "Create" msgstr "创建" -#: src/ui_widgets/color_field_popup.gd: -msgid "Search color" -msgstr "搜索颜色" - -#: src/ui_widgets/color_field_popup.gd: -msgid "Color Picker" -msgstr "取色器" - -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Edit color name" msgstr "编辑颜色名称" -#: src/ui_widgets/configure_color_popup.gd: +#: src/ui_widgets/color_configuration_popup.gd: msgid "Delete color" msgstr "删除颜色" -#: src/ui_widgets/configure_color_popup.gd: src/ui_widgets/palette_config.gd: +#: src/ui_widgets/color_configuration_popup.gd: +#: src/ui_widgets/palette_config.gd: msgid "Unnamed" msgstr "未命名" +#: src/ui_widgets/color_field_popup.gd: +msgid "Search color" +msgstr "搜索颜色" + +#: src/ui_widgets/color_field_popup.gd: +msgid "Color Picker" +msgstr "取色器" + #: src/ui_widgets/fps_limit_dropdown.gd: src/ui_widgets/setting_frame.gd: msgid "Unlimited" msgstr "" @@ -977,10 +986,6 @@ msgstr "" msgid "Keep Screen On" msgstr "" -#: src/ui_widgets/settings_content_generic.gd: -msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." -msgstr "" - #: src/ui_widgets/settings_content_generic.gd: msgid "Miscellaneous" msgstr "杂项" @@ -1005,6 +1010,10 @@ msgstr "" msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning." msgstr "" +#: src/ui_widgets/settings_content_generic.gd: +msgid "Keeps the screen on even after inactivity, so the screensaver does not take over." +msgstr "" + #: src/ui_widgets/settings_content_generic.gd: #, fuzzy msgid "When enabled, uses your operating system's native file dialog instead of VectorTouch's built-in one."