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 := """ 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."