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