From 2e587e36344b29cd1fb086f8b6792196f1b7f49f Mon Sep 17 00:00:00 2001 From: OverloadedOrama <35376950+OverloadedOrama@users.noreply.github.com> Date: Sat, 13 Jun 2020 17:59:57 +0300 Subject: [PATCH] Made TopMenuContainer.gd and moved all the menu code there from Main.gd Main.gd is now easier to read --- src/Autoload/Global.gd | 6 + src/Autoload/OpenSave.gd | 6 +- src/Classes/Project.gd | 4 +- src/Main.gd | 418 +---------------------------------- src/UI/TopMenuContainer.gd | 412 ++++++++++++++++++++++++++++++++++ src/UI/TopMenuContainer.tscn | 4 +- 6 files changed, 431 insertions(+), 419 deletions(-) create mode 100644 src/UI/TopMenuContainer.gd diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 0559aa6f7..750ad23ff 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -150,6 +150,7 @@ var help_menu : MenuButton var cursor_position_label : Label var zoom_level_label : Label +var new_image_dialog : ConfirmationDialog var open_sprites_dialog : FileDialog var save_sprites_dialog : FileDialog var export_dialog : AcceptDialog @@ -223,6 +224,8 @@ var new_palette_dialog : ConfirmationDialog var new_palette_name_line_edit : LineEdit var palette_import_file_dialog : FileDialog var error_dialog : AcceptDialog +var quit_dialog : ConfirmationDialog +var quit_and_save_dialog : ConfirmationDialog onready var current_version : String = ProjectSettings.get_setting("application/config/Version") @@ -269,6 +272,7 @@ func _ready() -> void: cursor_position_label = find_node_by_name(root, "CursorPosition") zoom_level_label = find_node_by_name(root, "ZoomLevel") + new_image_dialog = find_node_by_name(root, "CreateNewImage") open_sprites_dialog = find_node_by_name(root, "OpenSprite") save_sprites_dialog = find_node_by_name(root, "SaveSprite") export_dialog = find_node_by_name(root, "ExportDialog") @@ -361,6 +365,8 @@ func _ready() -> void: palette_import_file_dialog = find_node_by_name(root, "PaletteImportFileDialog") error_dialog = find_node_by_name(root, "ErrorDialog") + quit_dialog = find_node_by_name(root, "QuitDialog") + quit_and_save_dialog = find_node_by_name(root, "QuitAndSaveDialog") projects.append(Project.new()) projects[0].layers.append(Layer.new()) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 7df6c4d82..034396980 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -93,8 +93,8 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void: Global.export_dialog.file_name = path.get_file().trim_suffix(".pxo") Global.export_dialog.directory_path = path.get_base_dir() Global.export_dialog.was_exported = false - Global.control.file_menu.set_item_text(3, tr("Save") + " %s" % path.get_file()) - Global.control.file_menu.set_item_text(5, tr("Export")) + Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % path.get_file()) + Global.file_menu.get_popup().set_item_text(5, tr("Export")) # For pxo files older than v0.8 @@ -283,7 +283,7 @@ func save_pxo_file(path : String, autosave : bool, project : Project = Global.cu Global.export_dialog.file_name = path.get_file().trim_suffix(".pxo") Global.export_dialog.directory_path = path.get_base_dir() Global.export_dialog.was_exported = false - Global.control.file_menu.set_item_text(3, tr("Save") + " %s" % path.get_file()) + Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % path.get_file()) else: Global.notification_label("File failed to save") diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 82eacc9d3..f0db88baf 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -139,9 +139,9 @@ func change_project() -> void: if save_path != "": Global.open_sprites_dialog.current_path = save_path Global.save_sprites_dialog.current_path = save_path - Global.control.file_menu.set_item_text(3, tr("Save") + " %s" % save_path.get_file()) + Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % save_path.get_file()) else: - Global.control.file_menu.set_item_text(3, tr("Save")) + Global.file_menu.get_popup().set_item_text(3, tr("Save")) func serialize() -> Dictionary: diff --git a/src/Main.gd b/src/Main.gd index 0581927be..bf56dff81 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -1,11 +1,8 @@ extends Control var opensprite_file_selected := false -var file_menu : PopupMenu -var view_menu : PopupMenu var redone := false var is_quitting_on_save := false -var zen_mode := false # Called when the node enters the scene tree for the first time. @@ -13,12 +10,6 @@ func _ready() -> void: get_tree().set_auto_accept_quit(false) setup_application_window_size() - setup_file_menu() - setup_edit_menu() - setup_view_menu() - setup_image_menu() - setup_help_menu() - Global.window_title = tr("untitled") + " - Pixelorama " + Global.current_version Global.current_project.layers[0].name = tr("Layer") + " 0" @@ -83,109 +74,6 @@ func setup_application_window_size() -> void: OS.window_size = Global.config_cache.get_value("window", "size") -func setup_file_menu() -> void: - var file_menu_items := { - "New..." : InputMap.get_action_list("new_file")[0].get_scancode_with_modifiers(), - "Open..." : InputMap.get_action_list("open_file")[0].get_scancode_with_modifiers(), - 'Open last project...' : 0, - "Save..." : InputMap.get_action_list("save_file")[0].get_scancode_with_modifiers(), - "Save as..." : InputMap.get_action_list("save_file_as")[0].get_scancode_with_modifiers(), - "Export..." : InputMap.get_action_list("export_file")[0].get_scancode_with_modifiers(), - "Export as..." : InputMap.get_action_list("export_file_as")[0].get_scancode_with_modifiers(), - "Quit" : InputMap.get_action_list("quit")[0].get_scancode_with_modifiers(), - } - file_menu = Global.file_menu.get_popup() - var i := 0 - - for item in file_menu_items.keys(): - file_menu.add_item(item, i, file_menu_items[item]) - i += 1 - - file_menu.connect("id_pressed", self, "file_menu_id_pressed") - - -func setup_edit_menu() -> void: - var edit_menu_items := { - "Undo" : InputMap.get_action_list("undo")[0].get_scancode_with_modifiers(), - "Redo" : InputMap.get_action_list("redo")[0].get_scancode_with_modifiers(), - "Clear Selection" : 0, - "Preferences" : 0 - } - var edit_menu : PopupMenu = Global.edit_menu.get_popup() - var i := 0 - - for item in edit_menu_items.keys(): - edit_menu.add_item(item, i, edit_menu_items[item]) - i += 1 - - edit_menu.connect("id_pressed", self, "edit_menu_id_pressed") - - -func setup_view_menu() -> void: - var view_menu_items := { - "Tile Mode" : InputMap.get_action_list("tile_mode")[0].get_scancode_with_modifiers(), - "Show Grid" : InputMap.get_action_list("show_grid")[0].get_scancode_with_modifiers(), - "Show Rulers" : InputMap.get_action_list("show_rulers")[0].get_scancode_with_modifiers(), - "Show Guides" : InputMap.get_action_list("show_guides")[0].get_scancode_with_modifiers(), - "Show Animation Timeline" : 0, - "Zen Mode" : InputMap.get_action_list("zen_mode")[0].get_scancode_with_modifiers() - } - view_menu = Global.view_menu.get_popup() - - var i := 0 - for item in view_menu_items.keys(): - view_menu.add_check_item(item, i, view_menu_items[item]) - i += 1 - - view_menu.set_item_checked(2, true) # Show Rulers - view_menu.set_item_checked(3, true) # Show Guides - view_menu.set_item_checked(4, true) # Show Animation Timeline - view_menu.hide_on_checkable_item_selection = false - view_menu.connect("id_pressed", self, "view_menu_id_pressed") - - -func setup_image_menu() -> void: - var image_menu_items := { - "Scale Image" : 0, - "Crop Image" : 0, - "Flip Horizontal" : InputMap.get_action_list("image_flip_horizontal")[0].get_scancode_with_modifiers(), - "Flip Vertical" : InputMap.get_action_list("image_flip_vertical")[0].get_scancode_with_modifiers(), - "Rotate Image" : 0, - "Invert colors" : 0, - "Desaturation" : 0, - "Outline" : 0, - "Adjust Hue/Saturation/Value" : 0 - } - var image_menu : PopupMenu = Global.image_menu.get_popup() - - var i := 0 - for item in image_menu_items.keys(): - image_menu.add_item(item, i, image_menu_items[item]) - if i == 4: - image_menu.add_separator() - i += 1 - - image_menu.connect("id_pressed", self, "image_menu_id_pressed") - - -func setup_help_menu() -> void: - var help_menu_items := { - "View Splash Screen" : 0, - "Online Docs" : InputMap.get_action_list("open_docs")[0].get_scancode_with_modifiers(), - "Issue Tracker" : 0, - "Changelog" : 0, - "About Pixelorama" : 0 - } - var help_menu : PopupMenu = Global.help_menu.get_popup() - - var i := 0 - for item in help_menu_items.keys(): - help_menu.add_item(item, i, help_menu_items[item]) - i += 1 - - help_menu.connect("id_pressed", self, "help_menu_id_pressed") - - func show_splash_screen() -> void: # Wait for the window to adjust itself, so the popup is correctly centered yield(get_tree().create_timer(0.01), "timeout") @@ -231,301 +119,6 @@ func _on_files_dropped(_files : PoolStringArray, _screen : int) -> void: OpenSave.handle_loading_files(_files) -func on_new_project_file_menu_option_pressed() -> void: - $CreateNewImage.popup_centered() - Global.dialog_open(true) - - -func open_project_file() -> void: - $OpenSprite.popup_centered() - Global.dialog_open(true) - opensprite_file_selected = false - - -func on_open_last_project_file_menu_option_pressed() -> void: - # Check if last project path is set and if yes then open - if Global.config_cache.has_section_key("preferences", "last_project_path"): - load_last_project() - else: # if not then warn user that he didn't edit any project yet - Global.error_dialog.set_text("You haven't saved or opened any project in Pixelorama yet!") - Global.error_dialog.popup_centered() - Global.dialog_open(true) - - -func save_project_file() -> void: - is_quitting_on_save = false - if OpenSave.current_save_paths[Global.current_project_index] == "": - $SaveSprite.popup_centered() - Global.dialog_open(true) - else: - _on_SaveSprite_file_selected(OpenSave.current_save_paths[Global.current_project_index]) - - -func save_project_file_as() -> void: - is_quitting_on_save = false - $SaveSprite.popup_centered() - Global.dialog_open(true) - - -func export_file() -> void: - if $ExportDialog.was_exported == false: - $ExportDialog.popup_centered() - Global.dialog_open(true) - else: - $ExportDialog.external_export() - - -func file_menu_id_pressed(id : int) -> void: - match id: - 0: # New - on_new_project_file_menu_option_pressed() - 1: # Open - open_project_file() - 2: # Open last project - on_open_last_project_file_menu_option_pressed() - 3: # Save - save_project_file() - 4: # Save as - save_project_file_as() - 5: # Export - export_file() - 6: # Export as - $ExportDialog.popup_centered() - Global.dialog_open(true) - 7: # Quit - show_quit_dialog() - - -func edit_menu_id_pressed(id : int) -> void: - match id: - 0: # Undo - Global.current_project.undo_redo.undo() - 1: # Redo - redone = true - Global.current_project.undo_redo.redo() - redone = false - 2: # Clear selection - Global.canvas.handle_undo("Rectangle Select") - Global.selection_rectangle.polygon[0] = Vector2.ZERO - Global.selection_rectangle.polygon[1] = Vector2.ZERO - Global.selection_rectangle.polygon[2] = Vector2.ZERO - Global.selection_rectangle.polygon[3] = Vector2.ZERO - Global.current_project.selected_pixels.clear() - Global.canvas.handle_redo("Rectangle Select") - 3: # Preferences - $PreferencesDialog.popup_centered(Vector2(400, 280)) - Global.dialog_open(true) - - -func toggle_tile_mode() -> void: - Global.tile_mode = !Global.tile_mode - view_menu.set_item_checked(0, Global.tile_mode) - - -func toggle_show_grid() -> void: - Global.draw_grid = !Global.draw_grid - view_menu.set_item_checked(1, Global.draw_grid) - - -func toggle_show_rulers() -> void: - Global.show_rulers = !Global.show_rulers - view_menu.set_item_checked(2, Global.show_rulers) - Global.horizontal_ruler.visible = Global.show_rulers - Global.vertical_ruler.visible = Global.show_rulers - - -func toggle_show_guides() -> void: - Global.show_guides = !Global.show_guides - view_menu.set_item_checked(3, Global.show_guides) - for guide in Global.canvas.get_children(): - if guide is Guide: - guide.visible = Global.show_guides - - -func toggle_show_anim_timeline() -> void: - if zen_mode: - return - Global.show_animation_timeline = !Global.show_animation_timeline - view_menu.set_item_checked(4, Global.show_animation_timeline) - Global.animation_timeline.visible = Global.show_animation_timeline - - -func toggle_zen_mode() -> void: - if Global.show_animation_timeline: - Global.animation_timeline.visible = zen_mode - $MenuAndUI/UI/ToolPanel.visible = zen_mode - $MenuAndUI/UI/RightPanel.visible = zen_mode - $MenuAndUI/UI/CanvasAndTimeline/ViewportAndRulers/TabsContainer.visible = zen_mode - zen_mode = !zen_mode - view_menu.set_item_checked(5, zen_mode) - - -func view_menu_id_pressed(id : int) -> void: - match id: - 0: # Tile mode - toggle_tile_mode() - 1: # Show grid - toggle_show_grid() - 2: # Show rulers - toggle_show_rulers() - 3: # Show guides - toggle_show_guides() - 4: # Show animation timeline - toggle_show_anim_timeline() - 5: # Fullscreen mode - toggle_zen_mode() - - Global.canvas.update() - - -func show_scale_image_popup() -> void: - $ScaleImage.popup_centered() - Global.dialog_open(true) - - -func crop_image() -> void: - # Use first cel as a starting rectangle - var used_rect : Rect2 = Global.current_project.frames[0].cels[0].image.get_used_rect() - - for f in Global.current_project.frames: - # However, if first cel is empty, loop through all cels until we find one that isn't - for cel in f.cels: - if used_rect != Rect2(0, 0, 0, 0): - break - else: - if cel.image.get_used_rect() != Rect2(0, 0, 0, 0): - used_rect = cel.image.get_used_rect() - - # Merge all layers with content - for cel in f.cels: - if cel.image.get_used_rect() != Rect2(0, 0, 0, 0): - used_rect = used_rect.merge(cel.image.get_used_rect()) - - # If no layer has any content, just return - if used_rect == Rect2(0, 0, 0, 0): - return - - var width := used_rect.size.x - var height := used_rect.size.y - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Scale") - Global.current_project.undo_redo.add_do_property(Global.current_project, "size", Vector2(width, height).floor()) - for f in Global.current_project.frames: - # Loop through all the layers to crop them - for j in range(Global.current_project.layers.size() - 1, -1, -1): - var sprite : Image = f.cels[j].image.get_rect(used_rect) - Global.current_project.undo_redo.add_do_property(f.cels[j].image, "data", sprite.data) - Global.current_project.undo_redo.add_undo_property(f.cels[j].image, "data", f.cels[j].image.data) - - Global.current_project.undo_redo.add_undo_property(Global.current_project, "size", Global.current_project.size) - Global.current_project.undo_redo.add_undo_method(Global, "undo") - Global.current_project.undo_redo.add_do_method(Global, "redo") - Global.current_project.undo_redo.commit_action() - - -func flip_image(horizontal : bool) -> void: - var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image - Global.canvas.handle_undo("Draw") - image.unlock() - if horizontal: - image.flip_x() - else: - image.flip_y() - image.lock() - Global.canvas.handle_redo("Draw") - - -func show_rotate_image_popup() -> void: - var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image - $RotateImage.set_sprite(image) - $RotateImage.popup_centered() - Global.dialog_open(true) - - -func invert_image_colors() -> void: - var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image - Global.canvas.handle_undo("Draw") - for xx in image.get_size().x: - for yy in image.get_size().y: - var px_color = image.get_pixel(xx, yy).inverted() - if px_color.a == 0: - continue - image.set_pixel(xx, yy, px_color) - Global.canvas.handle_redo("Draw") - - -func desaturate_image() -> void: - var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image - Global.canvas.handle_undo("Draw") - for xx in image.get_size().x: - for yy in image.get_size().y: - var px_color = image.get_pixel(xx, yy) - if px_color.a == 0: - continue - var gray = image.get_pixel(xx, yy).v - px_color = Color(gray, gray, gray, px_color.a) - image.set_pixel(xx, yy, px_color) - Global.canvas.handle_redo("Draw") - - -func show_add_outline_popup() -> void: - $OutlineDialog.popup_centered() - Global.dialog_open(true) - - -func show_hsv_configuration_popup() -> void: - $HSVDialog.popup_centered() - Global.dialog_open(true) - - -func image_menu_id_pressed(id : int) -> void: - if Global.current_project.layers[Global.current_project.current_layer].locked: # No changes if the layer is locked - return - match id: - 0: # Scale Image - show_scale_image_popup() - - 1: # Crop Image - crop_image() - - 2: # Flip Horizontal - flip_image(true) - - 3: # Flip Vertical - flip_image(false) - - 4: # Rotate - show_rotate_image_popup() - - 5: # Invert Colors - invert_image_colors() - - 6: # Desaturation - desaturate_image() - - 7: # Outline - show_add_outline_popup() - - 8: # HSV - show_hsv_configuration_popup() - - -func help_menu_id_pressed(id : int) -> void: - match id: - 0: # Splash Screen - $SplashDialog.popup_centered() - Global.dialog_open(true) - 1: # Online Docs - OS.shell_open("https://orama-interactive.github.io/Pixelorama-Docs/") - 2: # Issue Tracker - OS.shell_open("https://github.com/Orama-Interactive/Pixelorama/issues") - 3: # Changelog - OS.shell_open("https://github.com/Orama-Interactive/Pixelorama/blob/master/CHANGELOG.md#v07---2020-05-16") - 4: # About Pixelorama - $AboutDialog.popup_centered() - Global.dialog_open(true) - - func load_last_project() -> void: # Check if any project was saved or opened last time if Global.config_cache.has_section_key("preferences", "last_project_path"): @@ -562,11 +155,11 @@ func _can_draw_true() -> void: func show_quit_dialog() -> void: - if !$QuitDialog.visible: + if !Global.quit_dialog.visible: if !Global.current_project.has_changed: - $QuitDialog.call_deferred("popup_centered") + Global.quit_dialog.call_deferred("popup_centered") else: - $QuitAndSaveDialog.call_deferred("popup_centered") + Global.quit_and_save_dialog.call_deferred("popup_centered") Global.dialog_open(true) @@ -593,8 +186,8 @@ func _on_BackupConfirmation_confirmed(project_paths : Array, backup_paths : Arra $ExportDialog.file_name = OpenSave.current_save_paths[0].get_file().trim_suffix(".pxo") $ExportDialog.directory_path = OpenSave.current_save_paths[0].get_base_dir() $ExportDialog.was_exported = false - file_menu.set_item_text(3, tr("Save") + " %s" % OpenSave.current_save_paths[0].get_file()) - file_menu.set_item_text(6, tr("Export")) + Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % OpenSave.current_save_paths[0].get_file()) + Global.file_menu.get_popup().set_item_text(6, tr("Export")) func _on_BackupConfirmation_delete(project_paths : Array, backup_paths : Array) -> void: @@ -604,4 +197,3 @@ func _on_BackupConfirmation_delete(project_paths : Array, backup_paths : Array) # Reopen last project if Global.open_last_project: load_last_project() - diff --git a/src/UI/TopMenuContainer.gd b/src/UI/TopMenuContainer.gd new file mode 100644 index 000000000..66f2001f8 --- /dev/null +++ b/src/UI/TopMenuContainer.gd @@ -0,0 +1,412 @@ +extends Panel + + +var file_menu : PopupMenu +var view_menu : PopupMenu +var zen_mode := false + + +func _ready() -> void: + setup_file_menu() + setup_edit_menu() + setup_view_menu() + setup_image_menu() + setup_help_menu() + + +func setup_file_menu() -> void: + var file_menu_items := { + "New..." : InputMap.get_action_list("new_file")[0].get_scancode_with_modifiers(), + "Open..." : InputMap.get_action_list("open_file")[0].get_scancode_with_modifiers(), + 'Open last project...' : 0, + "Save..." : InputMap.get_action_list("save_file")[0].get_scancode_with_modifiers(), + "Save as..." : InputMap.get_action_list("save_file_as")[0].get_scancode_with_modifiers(), + "Export..." : InputMap.get_action_list("export_file")[0].get_scancode_with_modifiers(), + "Export as..." : InputMap.get_action_list("export_file_as")[0].get_scancode_with_modifiers(), + "Quit" : InputMap.get_action_list("quit")[0].get_scancode_with_modifiers(), + } + file_menu = Global.file_menu.get_popup() + var i := 0 + + for item in file_menu_items.keys(): + file_menu.add_item(item, i, file_menu_items[item]) + i += 1 + + file_menu.connect("id_pressed", self, "file_menu_id_pressed") + + +func setup_edit_menu() -> void: + var edit_menu_items := { + "Undo" : InputMap.get_action_list("undo")[0].get_scancode_with_modifiers(), + "Redo" : InputMap.get_action_list("redo")[0].get_scancode_with_modifiers(), + "Clear Selection" : 0, + "Preferences" : 0 + } + var edit_menu : PopupMenu = Global.edit_menu.get_popup() + var i := 0 + + for item in edit_menu_items.keys(): + edit_menu.add_item(item, i, edit_menu_items[item]) + i += 1 + + edit_menu.connect("id_pressed", self, "edit_menu_id_pressed") + + +func setup_view_menu() -> void: + var view_menu_items := { + "Tile Mode" : InputMap.get_action_list("tile_mode")[0].get_scancode_with_modifiers(), + "Show Grid" : InputMap.get_action_list("show_grid")[0].get_scancode_with_modifiers(), + "Show Rulers" : InputMap.get_action_list("show_rulers")[0].get_scancode_with_modifiers(), + "Show Guides" : InputMap.get_action_list("show_guides")[0].get_scancode_with_modifiers(), + "Show Animation Timeline" : 0, + "Zen Mode" : InputMap.get_action_list("zen_mode")[0].get_scancode_with_modifiers() + } + view_menu = Global.view_menu.get_popup() + + var i := 0 + for item in view_menu_items.keys(): + view_menu.add_check_item(item, i, view_menu_items[item]) + i += 1 + + view_menu.set_item_checked(2, true) # Show Rulers + view_menu.set_item_checked(3, true) # Show Guides + view_menu.set_item_checked(4, true) # Show Animation Timeline + view_menu.hide_on_checkable_item_selection = false + view_menu.connect("id_pressed", self, "view_menu_id_pressed") + + +func setup_image_menu() -> void: + var image_menu_items := { + "Scale Image" : 0, + "Crop Image" : 0, + "Flip Horizontal" : InputMap.get_action_list("image_flip_horizontal")[0].get_scancode_with_modifiers(), + "Flip Vertical" : InputMap.get_action_list("image_flip_vertical")[0].get_scancode_with_modifiers(), + "Rotate Image" : 0, + "Invert colors" : 0, + "Desaturation" : 0, + "Outline" : 0, + "Adjust Hue/Saturation/Value" : 0 + } + var image_menu : PopupMenu = Global.image_menu.get_popup() + + var i := 0 + for item in image_menu_items.keys(): + image_menu.add_item(item, i, image_menu_items[item]) + if i == 4: + image_menu.add_separator() + i += 1 + + image_menu.connect("id_pressed", self, "image_menu_id_pressed") + + +func setup_help_menu() -> void: + var help_menu_items := { + "View Splash Screen" : 0, + "Online Docs" : InputMap.get_action_list("open_docs")[0].get_scancode_with_modifiers(), + "Issue Tracker" : 0, + "Changelog" : 0, + "About Pixelorama" : 0 + } + var help_menu : PopupMenu = Global.help_menu.get_popup() + + var i := 0 + for item in help_menu_items.keys(): + help_menu.add_item(item, i, help_menu_items[item]) + i += 1 + + help_menu.connect("id_pressed", self, "help_menu_id_pressed") + + +func file_menu_id_pressed(id : int) -> void: + match id: + 0: # New + on_new_project_file_menu_option_pressed() + 1: # Open + open_project_file() + 2: # Open last project + on_open_last_project_file_menu_option_pressed() + 3: # Save + save_project_file() + 4: # Save as + save_project_file_as() + 5: # Export + export_file() + 6: # Export as + Global.export_dialog.popup_centered() + Global.dialog_open(true) + 7: # Quit + Global.control.show_quit_dialog() + + +func on_new_project_file_menu_option_pressed() -> void: + Global.new_image_dialog.popup_centered() + Global.dialog_open(true) + + +func open_project_file() -> void: + Global.open_sprites_dialog.popup_centered() + Global.dialog_open(true) + Global.control.opensprite_file_selected = false + + +func on_open_last_project_file_menu_option_pressed() -> void: + # Check if last project path is set and if yes then open + if Global.config_cache.has_section_key("preferences", "last_project_path"): + Global.control.load_last_project() + else: # if not then warn user that he didn't edit any project yet + Global.error_dialog.set_text("You haven't saved or opened any project in Pixelorama yet!") + Global.error_dialog.popup_centered() + Global.dialog_open(true) + + +func save_project_file() -> void: + Global.control.is_quitting_on_save = false + if OpenSave.current_save_paths[Global.current_project_index] == "": + Global.save_sprites_dialog.popup_centered() + Global.dialog_open(true) + else: + Global.control._on_SaveSprite_file_selected(OpenSave.current_save_paths[Global.current_project_index]) + + +func save_project_file_as() -> void: + Global.control.is_quitting_on_save = false + Global.save_sprites_dialog.popup_centered() + Global.dialog_open(true) + + +func export_file() -> void: + if Global.export_dialog.was_exported == false: + Global.export_dialog.popup_centered() + Global.dialog_open(true) + else: + Global.export_dialog.external_export() + + +func edit_menu_id_pressed(id : int) -> void: + match id: + 0: # Undo + Global.current_project.undo_redo.undo() + 1: # Redo + Global.control.redone = true + Global.current_project.undo_redo.redo() + Global.control.redone = false + 2: # Clear selection + Global.canvas.handle_undo("Rectangle Select") + Global.selection_rectangle.polygon[0] = Vector2.ZERO + Global.selection_rectangle.polygon[1] = Vector2.ZERO + Global.selection_rectangle.polygon[2] = Vector2.ZERO + Global.selection_rectangle.polygon[3] = Vector2.ZERO + Global.current_project.selected_pixels.clear() + Global.canvas.handle_redo("Rectangle Select") + 3: # Preferences + Global.preferences_dialog.popup_centered(Vector2(400, 280)) + Global.dialog_open(true) + + +func view_menu_id_pressed(id : int) -> void: + match id: + 0: # Tile mode + toggle_tile_mode() + 1: # Show grid + toggle_show_grid() + 2: # Show rulers + toggle_show_rulers() + 3: # Show guides + toggle_show_guides() + 4: # Show animation timeline + toggle_show_anim_timeline() + 5: # Fullscreen mode + toggle_zen_mode() + + Global.canvas.update() + + +func toggle_tile_mode() -> void: + Global.tile_mode = !Global.tile_mode + view_menu.set_item_checked(0, Global.tile_mode) + + +func toggle_show_grid() -> void: + Global.draw_grid = !Global.draw_grid + view_menu.set_item_checked(1, Global.draw_grid) + + +func toggle_show_rulers() -> void: + Global.show_rulers = !Global.show_rulers + view_menu.set_item_checked(2, Global.show_rulers) + Global.horizontal_ruler.visible = Global.show_rulers + Global.vertical_ruler.visible = Global.show_rulers + + +func toggle_show_guides() -> void: + Global.show_guides = !Global.show_guides + view_menu.set_item_checked(3, Global.show_guides) + for guide in Global.canvas.get_children(): + if guide is Guide: + guide.visible = Global.show_guides + + +func toggle_show_anim_timeline() -> void: + if zen_mode: + return + Global.show_animation_timeline = !Global.show_animation_timeline + view_menu.set_item_checked(4, Global.show_animation_timeline) + Global.animation_timeline.visible = Global.show_animation_timeline + + +func toggle_zen_mode() -> void: + if Global.show_animation_timeline: + Global.animation_timeline.visible = zen_mode + Global.control.get_node("MenuAndUI/UI/ToolPanel").visible = zen_mode + Global.control.get_node("MenuAndUI/UI/RightPanel").visible = zen_mode + Global.control.get_node("MenuAndUI/UI/CanvasAndTimeline/ViewportAndRulers/TabsContainer").visible = zen_mode + zen_mode = !zen_mode + view_menu.set_item_checked(5, zen_mode) + + +func image_menu_id_pressed(id : int) -> void: + if Global.current_project.layers[Global.current_project.current_layer].locked: # No changes if the layer is locked + return + match id: + 0: # Scale Image + show_scale_image_popup() + + 1: # Crop Image + crop_image() + + 2: # Flip Horizontal + flip_image(true) + + 3: # Flip Vertical + flip_image(false) + + 4: # Rotate + show_rotate_image_popup() + + 5: # Invert Colors + invert_image_colors() + + 6: # Desaturation + desaturate_image() + + 7: # Outline + show_add_outline_popup() + + 8: # HSV + show_hsv_configuration_popup() + + +func show_scale_image_popup() -> void: + Global.control.get_node("ScaleImage").popup_centered() + Global.dialog_open(true) + + +func crop_image() -> void: + # Use first cel as a starting rectangle + var used_rect : Rect2 = Global.current_project.frames[0].cels[0].image.get_used_rect() + + for f in Global.current_project.frames: + # However, if first cel is empty, loop through all cels until we find one that isn't + for cel in f.cels: + if used_rect != Rect2(0, 0, 0, 0): + break + else: + if cel.image.get_used_rect() != Rect2(0, 0, 0, 0): + used_rect = cel.image.get_used_rect() + + # Merge all layers with content + for cel in f.cels: + if cel.image.get_used_rect() != Rect2(0, 0, 0, 0): + used_rect = used_rect.merge(cel.image.get_used_rect()) + + # If no layer has any content, just return + if used_rect == Rect2(0, 0, 0, 0): + return + + var width := used_rect.size.x + var height := used_rect.size.y + Global.current_project.undos += 1 + Global.current_project.undo_redo.create_action("Scale") + Global.current_project.undo_redo.add_do_property(Global.current_project, "size", Vector2(width, height).floor()) + for f in Global.current_project.frames: + # Loop through all the layers to crop them + for j in range(Global.current_project.layers.size() - 1, -1, -1): + var sprite : Image = f.cels[j].image.get_rect(used_rect) + Global.current_project.undo_redo.add_do_property(f.cels[j].image, "data", sprite.data) + Global.current_project.undo_redo.add_undo_property(f.cels[j].image, "data", f.cels[j].image.data) + + Global.current_project.undo_redo.add_undo_property(Global.current_project, "size", Global.current_project.size) + Global.current_project.undo_redo.add_undo_method(Global, "undo") + Global.current_project.undo_redo.add_do_method(Global, "redo") + Global.current_project.undo_redo.commit_action() + + +func flip_image(horizontal : bool) -> void: + var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + Global.canvas.handle_undo("Draw") + image.unlock() + if horizontal: + image.flip_x() + else: + image.flip_y() + image.lock() + Global.canvas.handle_redo("Draw") + + +func show_rotate_image_popup() -> void: + var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + Global.control.get_node("RotateImage").set_sprite(image) + Global.control.get_node("RotateImage").popup_centered() + Global.dialog_open(true) + + +func invert_image_colors() -> void: + var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + Global.canvas.handle_undo("Draw") + for xx in image.get_size().x: + for yy in image.get_size().y: + var px_color = image.get_pixel(xx, yy).inverted() + if px_color.a == 0: + continue + image.set_pixel(xx, yy, px_color) + Global.canvas.handle_redo("Draw") + + +func desaturate_image() -> void: + var image : Image = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + Global.canvas.handle_undo("Draw") + for xx in image.get_size().x: + for yy in image.get_size().y: + var px_color = image.get_pixel(xx, yy) + if px_color.a == 0: + continue + var gray = image.get_pixel(xx, yy).v + px_color = Color(gray, gray, gray, px_color.a) + image.set_pixel(xx, yy, px_color) + Global.canvas.handle_redo("Draw") + + +func show_add_outline_popup() -> void: + Global.control.get_node("OutlineDialog").popup_centered() + Global.dialog_open(true) + + +func show_hsv_configuration_popup() -> void: + Global.control.get_node("HSVDialog").popup_centered() + Global.dialog_open(true) + + +func help_menu_id_pressed(id : int) -> void: + match id: + 0: # Splash Screen + Global.control.get_node("SplashDialog").popup_centered() + Global.dialog_open(true) + 1: # Online Docs + OS.shell_open("https://orama-interactive.github.io/Pixelorama-Docs/") + 2: # Issue Tracker + OS.shell_open("https://github.com/Orama-Interactive/Pixelorama/issues") + 3: # Changelog + OS.shell_open("https://github.com/Orama-Interactive/Pixelorama/blob/master/CHANGELOG.md#v07---2020-05-16") + 4: # About Pixelorama + Global.control.get_node("AboutDialog").popup_centered() + Global.dialog_open(true) diff --git a/src/UI/TopMenuContainer.tscn b/src/UI/TopMenuContainer.tscn index 7fbb29702..5c5c4b76d 100644 --- a/src/UI/TopMenuContainer.tscn +++ b/src/UI/TopMenuContainer.tscn @@ -1,12 +1,14 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://assets/themes/dark/top_menu_style.tres" type="StyleBox" id=1] +[ext_resource path="res://src/UI/TopMenuContainer.gd" type="Script" id=2] [node name="TopMenuContainer" type="Panel"] margin_right = 1280.0 margin_bottom = 28.0 rect_min_size = Vector2( 0, 28 ) custom_styles/panel = ExtResource( 1 ) +script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false }