From 709a401373b6dbf540f856026fee6d508017c068 Mon Sep 17 00:00:00 2001 From: OverloadedOrama <35376950+OverloadedOrama@users.noreply.github.com> Date: Sat, 6 Jun 2020 02:16:53 +0300 Subject: [PATCH] Save backups for all opened projects current_save_paths and backup_save_paths in OpenSave.gd are arrays now, have paths for every project --- CHANGELOG.md | 6 ++ src/Autoload/Global.gd | 4 +- src/Autoload/OpenSave.gd | 89 +++++++++++++------------- src/Classes/Project.gd | 9 ++- src/Main.gd | 30 +++++---- src/Preferences/PreferencesDialog.gd | 2 +- src/Preferences/PreferencesDialog.tscn | 4 +- src/UI/Tabs.gd | 3 + 8 files changed, 81 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b50a030..d033b914e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.

+## [v0.8] - Unreleased + +### Added +- Project tabs! You can now have multiple projects open at the same time, and access each one with tabs. +

+ ## [v0.7.1] - Unreleased This update has been brought to you by the contributions of: Igor Santarek (jegor377), rob-a-bolton, Kinwailo diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index b26b55f0e..f8fe9e6bb 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -723,6 +723,8 @@ func _exit_tree() -> void: config_cache.set_value("window", "size", OS.window_size) config_cache.save("user://cache.ini") - # Thanks to qarmin from GitHub for pointing this out + var i := 0 for project in projects: project.undo_redo.free() + OpenSave.remove_backup(i) + i += 1 diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index aa3cf886e..29e7fa703 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -1,8 +1,8 @@ extends Node -var current_save_path := "" +var current_save_paths := [] # Array of strings # Stores a filename of a backup file in user:// until user saves manually -var backup_save_path = "" +var backup_save_paths := [] # Array of strings onready var autosave_timer : Timer @@ -184,11 +184,11 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void: if not untitled_backup: # Untitled backup should not change window title and save path - current_save_path = path + current_save_paths[Global.current_project_index] = path Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version -func save_pxo_file(path : String, autosave : bool) -> void: +func save_pxo_file(path : String, autosave : bool, project : Project = Global.current_project) -> void: var file := File.new() var err := file.open_compressed(path, File.WRITE, File.COMPRESSION_ZSTD) if err == OK: @@ -196,7 +196,7 @@ func save_pxo_file(path : String, autosave : bool) -> void: file.store_line(Global.current_version) # Store Global layers - for layer in Global.current_project.layers: + for layer in project.layers: file.store_line(".") file.store_line(layer.name) file.store_8(layer.visible) @@ -204,16 +204,16 @@ func save_pxo_file(path : String, autosave : bool) -> void: file.store_8(layer.new_cels_linked) var linked_cels := [] for frame in layer.linked_cels: - linked_cels.append(Global.current_project.frames.find(frame)) + linked_cels.append(project.frames.find(frame)) file.store_var(linked_cels) # Linked cels as cel numbers file.store_line("END_GLOBAL_LAYERS") # Store frames - for frame in Global.current_project.frames: + for frame in project.frames: file.store_line("--") - file.store_16(Global.current_project.size.x) - file.store_16(Global.current_project.size.y) + file.store_16(project.size.x) + file.store_16(project.size.y) for cel in frame.cels: # Store canvas layers file.store_line("-") file.store_buffer(cel.image.get_data()) @@ -246,8 +246,8 @@ func save_pxo_file(path : String, autosave : bool) -> void: file.store_8(right_brush_size) # Save custom brushes - for i in range(Global.current_project.brushes.size()): - var brush = Global.current_project.brushes[i] + for i in range(project.brushes.size()): + var brush = project.brushes[i] file.store_line("/") file.store_16(brush.get_size().x) file.store_16(brush.get_size().y) @@ -255,7 +255,7 @@ func save_pxo_file(path : String, autosave : bool) -> void: file.store_line("END_BRUSHES") # Store animation tags - for tag in Global.current_project.animation_tags: + for tag in project.animation_tags: file.store_line(".T/") file.store_line(tag.name) file.store_var(tag.color) @@ -265,19 +265,17 @@ func save_pxo_file(path : String, autosave : bool) -> void: file.close() - if Global.current_project.has_changed and not autosave: - Global.current_project.has_changed = false + if project.has_changed and not autosave: + project.has_changed = false if autosave: Global.notification_label("File autosaved") else: # First remove backup then set current save path - remove_backup() - current_save_path = path + remove_backup(Global.current_project_index) + current_save_paths[Global.current_project_index] = path Global.notification_label("File saved") - - if backup_save_path == "": - Global.current_project.name = path.get_file() + project.name = path.get_file() Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version else: @@ -292,39 +290,40 @@ func update_autosave() -> void: func _on_Autosave_timeout() -> void: - if backup_save_path == "": - # Create a new backup file if it doesn't exist yet - backup_save_path = "user://backup-" + String(OS.get_unix_time()) + for i in range(backup_save_paths.size()): + if backup_save_paths[i] == "": + # Create a new backup file if it doesn't exist yet + backup_save_paths[i] = "user://backup-" + String(OS.get_unix_time()) + "-%s" % i - store_backup_path() - save_pxo_file(backup_save_path, true) + store_backup_path(i) + save_pxo_file(backup_save_paths[i], true, Global.projects[i]) # Backup paths are stored in two ways: # 1) User already manually saved and defined a save path -> {current_save_path, backup_save_path} # 2) User didn't manually saved, "untitled" backup is stored -> {backup_save_path, backup_save_path} -func store_backup_path() -> void: - if current_save_path != "": +func store_backup_path(i : int) -> void: + if current_save_paths[i] != "": # Remove "untitled" backup if it existed on this project instance - if Global.config_cache.has_section_key("backups", backup_save_path): - Global.config_cache.erase_section_key("backups", backup_save_path) + if Global.config_cache.has_section_key("backups", backup_save_paths[i]): + Global.config_cache.erase_section_key("backups", backup_save_paths[i]) - Global.config_cache.set_value("backups", current_save_path, backup_save_path) + Global.config_cache.set_value("backups", current_save_paths[i], backup_save_paths[i]) else: - Global.config_cache.set_value("backups", backup_save_path, backup_save_path) + Global.config_cache.set_value("backups", backup_save_paths[i], backup_save_paths[i]) Global.config_cache.save("user://cache.ini") -func remove_backup() -> void: +func remove_backup(i : int) -> void: # Remove backup file - if backup_save_path != "": - if current_save_path != "": - remove_backup_by_path(current_save_path, backup_save_path) + if backup_save_paths[i] != "": + if current_save_paths[i] != "": + remove_backup_by_path(current_save_paths[i], backup_save_paths[i]) else: # If manual save was not yet done - remove "untitled" backup - remove_backup_by_path(backup_save_path, backup_save_path) - backup_save_path = "" + remove_backup_by_path(backup_save_paths[i], backup_save_paths[i]) + backup_save_paths[i] = "" func remove_backup_by_path(project_path : String, backup_path : String) -> void: @@ -333,15 +332,15 @@ func remove_backup_by_path(project_path : String, backup_path : String) -> void: Global.config_cache.save("user://cache.ini") -func reload_backup_file(project_path : String, backup_path : String) -> void: - # If project path is the same as backup save path -> the backup was untitled - open_pxo_file(backup_path, project_path == backup_path) - backup_save_path = backup_path +func reload_backup_file(project_paths : Array, backup_paths : Array) -> void: + for i in range(project_paths.size()): + # If project path is the same as backup save path -> the backup was untitled + open_pxo_file(backup_paths[i], project_paths[i] == backup_paths[i]) + backup_save_paths[i] = backup_paths[i] - if project_path != backup_path: - current_save_path = project_path - Global.window_title = project_path.get_file() + " - Pixelorama(*) " + Global.current_version - Global.current_project.has_changed = true + if project_paths[i] != backup_paths[i]: + current_save_paths[i] = project_paths[i] + Global.window_title = project_paths[i].get_file() + " - Pixelorama(*) " + Global.current_version + Global.current_project.has_changed = true Global.notification_label("Backup reloaded") - diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index e40d29fce..679ad2336 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -3,7 +3,7 @@ class_name Project extends Reference var name := "" setget name_changed -var size : Vector2 +var size := Vector2(64, 64) var undo_redo : UndoRedo var undos := 0 # The number of times we added undo properties var has_changed := false setget has_changed_changed @@ -27,15 +27,16 @@ var cameras_zoom := [Vector2(0.15, 0.15), Vector2(0.15, 0.15), Vector2(0.15, 0.1 var cameras_offset := [Vector2.ZERO, Vector2.ZERO, Vector2.ZERO] # Array of Vector2 -func _init(_frames := [], _name := tr("untitled"), _size := Vector2(64, 64)) -> void: +func _init(_frames := [], _name := tr("untitled")) -> void: frames = _frames name = _name - size = _size x_max = size.x y_max = size.y undo_redo = UndoRedo.new() Global.tabs.add_tab(name) + OpenSave.current_save_paths.append("") + OpenSave.backup_save_paths.append("") func change_project() -> void: @@ -128,6 +129,8 @@ func change_project() -> void: Global.zoom_level_label.text = str(round(100 / Global.camera.zoom.x)) + " %" Global.canvas.update() Global.transparent_checker._ready() + Global.horizontal_ruler.update() + Global.vertical_ruler.update() Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version] if has_changed: Global.window_title = Global.window_title + "(*)" diff --git a/src/Main.gd b/src/Main.gd index 050fe4a89..31051d72f 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -201,14 +201,16 @@ func handle_backup() -> void: if Global.config_cache.has_section("backups"): var project_paths = Global.config_cache.get_section_keys("backups") if project_paths.size() > 0: - # Get backup path - var backup_path = Global.config_cache.get_value("backups", project_paths[0]) + # Get backup paths + var backup_paths := [] + for p_path in project_paths: + backup_paths.append(Global.config_cache.get_value("backups", p_path)) # Temporatily stop autosave until user confirms backup OpenSave.autosave_timer.stop() # For it's only possible to reload the first found backup - $BackupConfirmation.dialog_text = tr($BackupConfirmation.dialog_text) % project_paths[0] - $BackupConfirmation.connect("confirmed", self, "_on_BackupConfirmation_confirmed", [project_paths[0], backup_path]) - $BackupConfirmation.get_cancel().connect("pressed", self, "_on_BackupConfirmation_delete", [project_paths[0], backup_path]) + $BackupConfirmation.dialog_text = tr($BackupConfirmation.dialog_text) % project_paths + $BackupConfirmation.connect("confirmed", self, "_on_BackupConfirmation_confirmed", [project_paths, backup_paths]) + $BackupConfirmation.get_cancel().connect("pressed", self, "_on_BackupConfirmation_delete", [project_paths, backup_paths]) $BackupConfirmation.popup_centered() Global.can_draw = false modulate = Color(0.5, 0.5, 0.5) @@ -595,29 +597,29 @@ func _on_QuitAndSaveDialog_custom_action(action : String) -> void: $SaveSprite.popup_centered() $QuitDialog.hide() Global.dialog_open(true) - OpenSave.remove_backup() func _on_QuitDialog_confirmed() -> void: # Darken the UI to denote that the application is currently exiting # (it won't respond to user input in this state). modulate = Color(0.5, 0.5, 0.5) - OpenSave.remove_backup() get_tree().quit() -func _on_BackupConfirmation_confirmed(project_path : String, backup_path : String) -> void: - OpenSave.reload_backup_file(project_path, backup_path) +func _on_BackupConfirmation_confirmed(project_paths : Array, backup_paths : Array) -> void: + OpenSave.reload_backup_file(project_paths, backup_paths) +# Global.tabs.delete_tab(0) OpenSave.autosave_timer.start() - $ExportDialog.file_name = OpenSave.current_save_path.get_file().trim_suffix(".pxo") - $ExportDialog.directory_path = OpenSave.current_save_path.get_base_dir() + $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_path.get_file()) + file_menu.set_item_text(3, tr("Save") + " %s" % OpenSave.current_save_paths[0].get_file()) file_menu.set_item_text(6, tr("Export")) -func _on_BackupConfirmation_delete(project_path : String, backup_path : String) -> void: - OpenSave.remove_backup_by_path(project_path, backup_path) +func _on_BackupConfirmation_delete(project_paths : Array, backup_paths : Array) -> void: + for i in range(project_paths.size()): + OpenSave.remove_backup_by_path(project_paths[i], backup_paths[i]) OpenSave.autosave_timer.start() # Reopen last project if Global.open_last_project: diff --git a/src/Preferences/PreferencesDialog.gd b/src/Preferences/PreferencesDialog.gd index 357b3a35b..f032f2576 100644 --- a/src/Preferences/PreferencesDialog.gd +++ b/src/Preferences/PreferencesDialog.gd @@ -112,6 +112,6 @@ func _on_PreferencesDialog_popup_hide() -> void: list.clear() -func _on_List_item_selected(index): +func _on_List_item_selected(index) -> void: for child in right_side.get_children(): child.visible = child.name == ["General", "Languages", "Themes", "Canvas", "Image", "Shortcuts"][index] diff --git a/src/Preferences/PreferencesDialog.tscn b/src/Preferences/PreferencesDialog.tscn index 5ac758ea9..15239d70b 100644 --- a/src/Preferences/PreferencesDialog.tscn +++ b/src/Preferences/PreferencesDialog.tscn @@ -185,9 +185,9 @@ margin_right = 506.0 margin_bottom = 24.0 mouse_default_cursor_shape = 2 size_flags_horizontal = 3 -min_value = 0.5 +min_value = 0.1 max_value = 30.0 -step = 0.5 +step = 0.25 value = 1.0 align = 2 suffix = "minute(s)" diff --git a/src/UI/Tabs.gd b/src/UI/Tabs.gd index 7bdb13092..799f12483 100644 --- a/src/UI/Tabs.gd +++ b/src/UI/Tabs.gd @@ -27,6 +27,9 @@ func _on_Tabs_reposition_active_tab_request(idx_to : int) -> void: func delete_tab(tab : int) -> void: remove_tab(tab) Global.projects[tab].undo_redo.free() + OpenSave.remove_backup(tab) + OpenSave.current_save_paths.remove(tab) + OpenSave.backup_save_paths.remove(tab) Global.projects.remove(tab) if tab > 0: Global.current_project_index -= 1