diff --git a/src/FileUtils.gd b/src/FileUtils.gd index 918dc47c..447b5b19 100644 --- a/src/FileUtils.gd +++ b/src/FileUtils.gd @@ -8,7 +8,6 @@ const ImportWarningDialog = preload("res://src/ui_parts/import_warning_dialog.ts const GoodFileDialog = preload("res://src/ui_parts/good_file_dialog.tscn") const ExportDialog = preload("res://src/ui_parts/export_dialog.tscn") - static func save_svg_to_file(path: String) -> void: var FA := FileAccess.open(path, FileAccess.WRITE) FA.store_string(SVG.text) @@ -107,10 +106,32 @@ static func open_import_dialog() -> void: HandlerGUI.add_overlay(svg_import_dialog) svg_import_dialog.file_selected.connect(apply_svg_from_path) +static func open_reference_import_dialog() -> void: + if FileUtils._is_native_preferred(): + DisplayServer.file_dialog_show(TranslationServer.translate("Import a .png file"), + Utils.get_last_dir(), "", false, DisplayServer.FILE_DIALOG_MODE_OPEN_FILE, + ["*.png"], native_file_import) + # TODO : Add Web Support + #elif OS.has_feature("web"): + #HandlerGUI.web_load_svg() + else: + var png_import_dialog := GoodFileDialog.instantiate() + png_import_dialog.setup(Utils.get_last_dir(), "", + GoodFileDialogType.FileMode.SELECT, "png") + HandlerGUI.add_overlay(png_import_dialog) + png_import_dialog.file_selected.connect(reference_image_import) + static func native_file_import(has_selected: bool, files: PackedStringArray, _filter_idx: int) -> void: if has_selected: - apply_svg_from_path(files[0]) + if files[0].ends_with(".svg"): + apply_svg_from_path(files[0]) + else: + reference_image_import(files[0]) + +static func reference_image_import(path : String) -> void: + GlobalSettings.modify_save_data("reference_path", path) + Indications.imported_reference.emit() static func apply_svg_from_path(path: String) -> int: var svg_file := FileAccess.open(path, FileAccess.READ) @@ -144,7 +165,6 @@ static func apply_svg_from_path(path: String) -> int: HandlerGUI.add_overlay(warning_panel) return OK - # Web stuff. The loading logic had to remain in HandlerGUI. static func web_import(svg_text: String, file_name: String) -> void: diff --git a/src/Indications.gd b/src/Indications.gd index 963d0001..25ca7f91 100644 --- a/src/Indications.gd +++ b/src/Indications.gd @@ -25,6 +25,8 @@ signal requested_scroll_to_tag_editor(tid: PackedInt32Array) # The viewport listens for this signal to put you in handle-placing mode. signal handle_added +signal imported_reference + # The PackedInt32Array holds the hierarchical orders. TID means Tag ID. # For example, the 5th child of the 2nd child of the root tag would be (1, 4). # PackedInt32Array() means it's invalid. diff --git a/src/data_classes/SaveData.gd b/src/data_classes/SaveData.gd index 0e48e602..386c86c5 100644 --- a/src/data_classes/SaveData.gd +++ b/src/data_classes/SaveData.gd @@ -4,6 +4,7 @@ class_name SaveData extends Resource const GoodColorPicker = preload("res://src/ui_elements/good_color_picker.gd") @export var svg_text := "" +@export var reference_path := "" @export var viewbox_coupling := true @export var snap := -0.5 # Negative when disabled. @export var color_picker_slider_mode := GoodColorPicker.SliderMode.RGB diff --git a/src/ui_parts/display.gd b/src/ui_parts/display.gd index 750d824e..c11570aa 100644 --- a/src/ui_parts/display.gd +++ b/src/ui_parts/display.gd @@ -17,6 +17,7 @@ const NumberField = preload("res://src/ui_elements/number_field.tscn") @onready var viewport: SubViewport = %Viewport @onready var controls: Control = %Viewport/Checkerboard/Controls @onready var grid_visuals: Control = %Viewport/Camera +@onready var reference_button = %LeftMenu/Reference @onready var visuals_button: Button = %LeftMenu/Visuals @onready var more_button: Button = %LeftMenu/MoreOptions @onready var snapper: NumberEditType = %LeftMenu/Snapping/SnapNumberEdit @@ -27,6 +28,9 @@ const NumberField = preload("res://src/ui_elements/number_field.tscn") @onready var debug_label: Label = $ViewportPanel/DebugContainer/VBoxContainer/DebugLabel @onready var input_debug_label: Label = $ViewportPanel/DebugContainer/VBoxContainer/InputDebugLabel +@onready var reference_texture = %ReferenceTexture + +var reference_overlay := false func _notification(what: int) -> void: if what == Utils.CustomNotification.LANGUAGE_CHANGED: @@ -46,6 +50,8 @@ func _ready() -> void: view_settings_updated.emit(grid_visuals.visible, controls.visible, viewport.display_texture.rasterized) + if OS.has_feature("web"): + reference_button.hide() func _unhandled_input(input_event: InputEvent) -> void: if Input.is_action_pressed("debug"): @@ -111,6 +117,21 @@ func _on_settings_pressed() -> void: HandlerGUI.add_overlay(settings_menu_instance) +func _on_reference_pressed() -> void: + var btn_arr: Array[Button] = [ + Utils.create_btn(TranslationServer.translate("Import Reference Image"), + import_reference_image, false, load("res://visual/icons/Reference.svg")), + Utils.create_checkbox(TranslationServer.translate("Show Reference Image"), + toggle_reference_image, reference_texture.visible), + Utils.create_checkbox(TranslationServer.translate("Overlay Reference Image"), + toggle_reference_overlay, reference_overlay) + ] + + var reference_popup := ContextPopup.new() + reference_popup.setup(btn_arr, false) + HandlerGUI.popup_under_rect_center(reference_popup, reference_button.get_global_rect(), + get_viewport()) + func _on_visuals_button_pressed() -> void: var btn_arr: Array[Button] = [ ContextPopup.create_checkbox(TranslationServer.translate("Show Grid"), @@ -182,6 +203,24 @@ func toggle_rasterization() -> void: viewport.display_texture.rasterized = not viewport.display_texture.rasterized view_settings_updated.emit(grid_visuals.visible, controls.visible, viewport.display_texture.rasterized) +func toggle_reference_image() -> void: + reference_texture.visible = not reference_texture.visible + +func toggle_reference_overlay() -> void: + reference_overlay = not reference_overlay + + if reference_overlay: + viewport.move_child(reference_texture, 2) + else: + viewport.move_child(reference_texture, 0) + +func import_reference_image() -> void: + FileUtils.open_reference_import_dialog() + await Indications.imported_reference + var ref_path = GlobalSettings.save_data.get("reference_path") + var img = Image.load_from_file(ref_path) + reference_texture.texture = ImageTexture.create_from_image(img) + reference_texture.show() func toggle_snap() -> void: snap_button.button_pressed = not snap_button.button_pressed diff --git a/src/ui_parts/display.tscn b/src/ui_parts/display.tscn index d2d0a723..e45203ea 100644 --- a/src/ui_parts/display.tscn +++ b/src/ui_parts/display.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=17 format=3 uid="uid://bvrncl7e6yn5b"] +[gd_scene load_steps=18 format=3 uid="uid://bvrncl7e6yn5b"] [ext_resource type="Script" path="res://src/ui_parts/display.gd" id="1_oib5g"] [ext_resource type="Texture2D" uid="uid://ccbta5q43jobk" path="res://visual/icons/More.svg" id="2_3wliq"] [ext_resource type="Texture2D" uid="uid://ckkkgof1hcbld" path="res://visual/icons/Gear.svg" id="3_0w618"] +[ext_resource type="Texture2D" uid="uid://iglrqrqyg4kn" path="res://visual/icons/Reference.svg" id="4_2hiq7"] [ext_resource type="Texture2D" uid="uid://kkxyv1gyrjgj" path="res://visual/icons/Visuals.svg" id="4_n3qjt"] [ext_resource type="Texture2D" uid="uid://buire51l0mifg" path="res://visual/icons/Snap.svg" id="5_1k2cq"] [ext_resource type="Script" path="res://src/ui_elements/BetterToggleButton.gd" id="6_3v3ve"] @@ -65,6 +66,15 @@ theme_type_variation = &"IconButton" icon = ExtResource("3_0w618") icon_alignment = 1 +[node name="Reference" type="Button" parent="PanelContainer/HBoxContainer/LeftMenu"] +layout_mode = 2 +size_flags_horizontal = 2 +focus_mode = 0 +mouse_default_cursor_shape = 2 +theme_type_variation = &"IconButton" +icon = ExtResource("4_2hiq7") +icon_alignment = 1 + [node name="Visuals" type="Button" parent="PanelContainer/HBoxContainer/LeftMenu"] layout_mode = 2 size_flags_horizontal = 2 @@ -122,6 +132,14 @@ size_2d_override_stretch = true render_target_update_mode = 4 script = ExtResource("9_4xrk7") +[node name="ReferenceTexture" type="TextureRect" parent="ViewportPanel/ViewportContainer/Viewport"] +unique_name_in_owner = true +visible = false +offset_right = 128.0 +offset_bottom = 128.0 +expand_mode = 1 +stretch_mode = 5 + [node name="Checkerboard" type="TextureRect" parent="ViewportPanel/ViewportContainer/Viewport"] texture_filter = 1 material = SubResource("ShaderMaterial_kqplg") @@ -189,6 +207,7 @@ horizontal_alignment = 2 [connection signal="pressed" from="PanelContainer/HBoxContainer/LeftMenu/MoreOptions" to="." method="_on_more_options_pressed"] [connection signal="pressed" from="PanelContainer/HBoxContainer/LeftMenu/Settings" to="." method="_on_settings_pressed"] +[connection signal="pressed" from="PanelContainer/HBoxContainer/LeftMenu/Reference" to="." method="_on_reference_pressed"] [connection signal="pressed" from="PanelContainer/HBoxContainer/LeftMenu/Visuals" to="." method="_on_visuals_button_pressed"] [connection signal="toggled" from="PanelContainer/HBoxContainer/LeftMenu/Snapping/SnapButton" to="." method="_on_snap_button_toggled"] [connection signal="value_changed" from="PanelContainer/HBoxContainer/LeftMenu/Snapping/SnapNumberEdit" to="." method="_on_snap_number_edit_value_changed"] diff --git a/src/ui_parts/viewport.gd b/src/ui_parts/viewport.gd index c5b01469..f7de60d0 100644 --- a/src/ui_parts/viewport.gd +++ b/src/ui_parts/viewport.gd @@ -12,6 +12,7 @@ var _zoom_to: Vector2 @onready var view: Control = $Camera @onready var controls: Control = $Checkerboard/Controls @onready var display_texture: TextureRect = $Checkerboard/DisplayTexture +@onready var reference_texture = %ReferenceTexture @onready var zoom_menu: ZoomMenuType = %ZoomMenu @@ -42,6 +43,7 @@ func set_view(new_position: Vector2) -> void: func resize() -> void: if SVG.root_tag.get_size().is_finite(): display.size = SVG.root_tag.get_size() + reference_texture.size = SVG.root_tag.get_size() zoom_menu.zoom_reset() func center_frame() -> void: diff --git a/visual/icons/Reference.svg b/visual/icons/Reference.svg new file mode 100644 index 00000000..1cc8169d --- /dev/null +++ b/visual/icons/Reference.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/visual/icons/Reference.svg.import b/visual/icons/Reference.svg.import new file mode 100644 index 00000000..328ccc1b --- /dev/null +++ b/visual/icons/Reference.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://iglrqrqyg4kn" +path="res://.godot/imported/Reference.svg-28e3f2638dc2f67db7899c414706e462.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visual/icons/Reference.svg" +dest_files=["res://.godot/imported/Reference.svg-28e3f2638dc2f67db7899c414706e462.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false