mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
Save backups for all opened projects
current_save_paths and backup_save_paths in OpenSave.gd are arrays now, have paths for every project
This commit is contained in:
parent
2c409ab025
commit
709a401373
|
@ -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.
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
## [v0.8] - Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Project tabs! You can now have multiple projects open at the same time, and access each one with tabs.
|
||||||
|
<br><br>
|
||||||
|
|
||||||
## [v0.7.1] - Unreleased
|
## [v0.7.1] - Unreleased
|
||||||
This update has been brought to you by the contributions of:
|
This update has been brought to you by the contributions of:
|
||||||
Igor Santarek (jegor377), rob-a-bolton, Kinwailo
|
Igor Santarek (jegor377), rob-a-bolton, Kinwailo
|
||||||
|
|
|
@ -723,6 +723,8 @@ func _exit_tree() -> void:
|
||||||
config_cache.set_value("window", "size", OS.window_size)
|
config_cache.set_value("window", "size", OS.window_size)
|
||||||
config_cache.save("user://cache.ini")
|
config_cache.save("user://cache.ini")
|
||||||
|
|
||||||
# Thanks to qarmin from GitHub for pointing this out
|
var i := 0
|
||||||
for project in projects:
|
for project in projects:
|
||||||
project.undo_redo.free()
|
project.undo_redo.free()
|
||||||
|
OpenSave.remove_backup(i)
|
||||||
|
i += 1
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
extends Node
|
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
|
# 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
|
onready var autosave_timer : Timer
|
||||||
|
|
||||||
|
@ -184,11 +184,11 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
|
||||||
|
|
||||||
if not untitled_backup:
|
if not untitled_backup:
|
||||||
# Untitled backup should not change window title and save path
|
# 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
|
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 file := File.new()
|
||||||
var err := file.open_compressed(path, File.WRITE, File.COMPRESSION_ZSTD)
|
var err := file.open_compressed(path, File.WRITE, File.COMPRESSION_ZSTD)
|
||||||
if err == OK:
|
if err == OK:
|
||||||
|
@ -196,7 +196,7 @@ func save_pxo_file(path : String, autosave : bool) -> void:
|
||||||
file.store_line(Global.current_version)
|
file.store_line(Global.current_version)
|
||||||
|
|
||||||
# Store Global layers
|
# Store Global layers
|
||||||
for layer in Global.current_project.layers:
|
for layer in project.layers:
|
||||||
file.store_line(".")
|
file.store_line(".")
|
||||||
file.store_line(layer.name)
|
file.store_line(layer.name)
|
||||||
file.store_8(layer.visible)
|
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)
|
file.store_8(layer.new_cels_linked)
|
||||||
var linked_cels := []
|
var linked_cels := []
|
||||||
for frame in layer.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_var(linked_cels) # Linked cels as cel numbers
|
||||||
|
|
||||||
file.store_line("END_GLOBAL_LAYERS")
|
file.store_line("END_GLOBAL_LAYERS")
|
||||||
|
|
||||||
# Store frames
|
# Store frames
|
||||||
for frame in Global.current_project.frames:
|
for frame in project.frames:
|
||||||
file.store_line("--")
|
file.store_line("--")
|
||||||
file.store_16(Global.current_project.size.x)
|
file.store_16(project.size.x)
|
||||||
file.store_16(Global.current_project.size.y)
|
file.store_16(project.size.y)
|
||||||
for cel in frame.cels: # Store canvas layers
|
for cel in frame.cels: # Store canvas layers
|
||||||
file.store_line("-")
|
file.store_line("-")
|
||||||
file.store_buffer(cel.image.get_data())
|
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)
|
file.store_8(right_brush_size)
|
||||||
|
|
||||||
# Save custom brushes
|
# Save custom brushes
|
||||||
for i in range(Global.current_project.brushes.size()):
|
for i in range(project.brushes.size()):
|
||||||
var brush = Global.current_project.brushes[i]
|
var brush = project.brushes[i]
|
||||||
file.store_line("/")
|
file.store_line("/")
|
||||||
file.store_16(brush.get_size().x)
|
file.store_16(brush.get_size().x)
|
||||||
file.store_16(brush.get_size().y)
|
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")
|
file.store_line("END_BRUSHES")
|
||||||
|
|
||||||
# Store animation tags
|
# Store animation tags
|
||||||
for tag in Global.current_project.animation_tags:
|
for tag in project.animation_tags:
|
||||||
file.store_line(".T/")
|
file.store_line(".T/")
|
||||||
file.store_line(tag.name)
|
file.store_line(tag.name)
|
||||||
file.store_var(tag.color)
|
file.store_var(tag.color)
|
||||||
|
@ -265,19 +265,17 @@ func save_pxo_file(path : String, autosave : bool) -> void:
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
if Global.current_project.has_changed and not autosave:
|
if project.has_changed and not autosave:
|
||||||
Global.current_project.has_changed = false
|
project.has_changed = false
|
||||||
|
|
||||||
if autosave:
|
if autosave:
|
||||||
Global.notification_label("File autosaved")
|
Global.notification_label("File autosaved")
|
||||||
else:
|
else:
|
||||||
# First remove backup then set current save path
|
# First remove backup then set current save path
|
||||||
remove_backup()
|
remove_backup(Global.current_project_index)
|
||||||
current_save_path = path
|
current_save_paths[Global.current_project_index] = path
|
||||||
Global.notification_label("File saved")
|
Global.notification_label("File saved")
|
||||||
|
project.name = path.get_file()
|
||||||
if backup_save_path == "":
|
|
||||||
Global.current_project.name = path.get_file()
|
|
||||||
Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version
|
Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -292,39 +290,40 @@ func update_autosave() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _on_Autosave_timeout() -> void:
|
func _on_Autosave_timeout() -> void:
|
||||||
if backup_save_path == "":
|
for i in range(backup_save_paths.size()):
|
||||||
|
if backup_save_paths[i] == "":
|
||||||
# Create a new backup file if it doesn't exist yet
|
# Create a new backup file if it doesn't exist yet
|
||||||
backup_save_path = "user://backup-" + String(OS.get_unix_time())
|
backup_save_paths[i] = "user://backup-" + String(OS.get_unix_time()) + "-%s" % i
|
||||||
|
|
||||||
store_backup_path()
|
store_backup_path(i)
|
||||||
save_pxo_file(backup_save_path, true)
|
save_pxo_file(backup_save_paths[i], true, Global.projects[i])
|
||||||
|
|
||||||
|
|
||||||
# Backup paths are stored in two ways:
|
# Backup paths are stored in two ways:
|
||||||
# 1) User already manually saved and defined a save path -> {current_save_path, backup_save_path}
|
# 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}
|
# 2) User didn't manually saved, "untitled" backup is stored -> {backup_save_path, backup_save_path}
|
||||||
func store_backup_path() -> void:
|
func store_backup_path(i : int) -> void:
|
||||||
if current_save_path != "":
|
if current_save_paths[i] != "":
|
||||||
# Remove "untitled" backup if it existed on this project instance
|
# Remove "untitled" backup if it existed on this project instance
|
||||||
if Global.config_cache.has_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_path)
|
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:
|
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")
|
Global.config_cache.save("user://cache.ini")
|
||||||
|
|
||||||
|
|
||||||
func remove_backup() -> void:
|
func remove_backup(i : int) -> void:
|
||||||
# Remove backup file
|
# Remove backup file
|
||||||
if backup_save_path != "":
|
if backup_save_paths[i] != "":
|
||||||
if current_save_path != "":
|
if current_save_paths[i] != "":
|
||||||
remove_backup_by_path(current_save_path, backup_save_path)
|
remove_backup_by_path(current_save_paths[i], backup_save_paths[i])
|
||||||
else:
|
else:
|
||||||
# If manual save was not yet done - remove "untitled" backup
|
# If manual save was not yet done - remove "untitled" backup
|
||||||
remove_backup_by_path(backup_save_path, backup_save_path)
|
remove_backup_by_path(backup_save_paths[i], backup_save_paths[i])
|
||||||
backup_save_path = ""
|
backup_save_paths[i] = ""
|
||||||
|
|
||||||
|
|
||||||
func remove_backup_by_path(project_path : String, backup_path : String) -> void:
|
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")
|
Global.config_cache.save("user://cache.ini")
|
||||||
|
|
||||||
|
|
||||||
func reload_backup_file(project_path : String, backup_path : String) -> void:
|
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
|
# If project path is the same as backup save path -> the backup was untitled
|
||||||
open_pxo_file(backup_path, project_path == backup_path)
|
open_pxo_file(backup_paths[i], project_paths[i] == backup_paths[i])
|
||||||
backup_save_path = backup_path
|
backup_save_paths[i] = backup_paths[i]
|
||||||
|
|
||||||
if project_path != backup_path:
|
if project_paths[i] != backup_paths[i]:
|
||||||
current_save_path = project_path
|
current_save_paths[i] = project_paths[i]
|
||||||
Global.window_title = project_path.get_file() + " - Pixelorama(*) " + Global.current_version
|
Global.window_title = project_paths[i].get_file() + " - Pixelorama(*) " + Global.current_version
|
||||||
Global.current_project.has_changed = true
|
Global.current_project.has_changed = true
|
||||||
|
|
||||||
Global.notification_label("Backup reloaded")
|
Global.notification_label("Backup reloaded")
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ class_name Project extends Reference
|
||||||
|
|
||||||
|
|
||||||
var name := "" setget name_changed
|
var name := "" setget name_changed
|
||||||
var size : Vector2
|
var size := Vector2(64, 64)
|
||||||
var undo_redo : UndoRedo
|
var undo_redo : UndoRedo
|
||||||
var undos := 0 # The number of times we added undo properties
|
var undos := 0 # The number of times we added undo properties
|
||||||
var has_changed := false setget has_changed_changed
|
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
|
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
|
frames = _frames
|
||||||
name = _name
|
name = _name
|
||||||
size = _size
|
|
||||||
x_max = size.x
|
x_max = size.x
|
||||||
y_max = size.y
|
y_max = size.y
|
||||||
undo_redo = UndoRedo.new()
|
undo_redo = UndoRedo.new()
|
||||||
|
|
||||||
Global.tabs.add_tab(name)
|
Global.tabs.add_tab(name)
|
||||||
|
OpenSave.current_save_paths.append("")
|
||||||
|
OpenSave.backup_save_paths.append("")
|
||||||
|
|
||||||
|
|
||||||
func change_project() -> void:
|
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.zoom_level_label.text = str(round(100 / Global.camera.zoom.x)) + " %"
|
||||||
Global.canvas.update()
|
Global.canvas.update()
|
||||||
Global.transparent_checker._ready()
|
Global.transparent_checker._ready()
|
||||||
|
Global.horizontal_ruler.update()
|
||||||
|
Global.vertical_ruler.update()
|
||||||
Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version]
|
Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version]
|
||||||
if has_changed:
|
if has_changed:
|
||||||
Global.window_title = Global.window_title + "(*)"
|
Global.window_title = Global.window_title + "(*)"
|
||||||
|
|
30
src/Main.gd
30
src/Main.gd
|
@ -201,14 +201,16 @@ func handle_backup() -> void:
|
||||||
if Global.config_cache.has_section("backups"):
|
if Global.config_cache.has_section("backups"):
|
||||||
var project_paths = Global.config_cache.get_section_keys("backups")
|
var project_paths = Global.config_cache.get_section_keys("backups")
|
||||||
if project_paths.size() > 0:
|
if project_paths.size() > 0:
|
||||||
# Get backup path
|
# Get backup paths
|
||||||
var backup_path = Global.config_cache.get_value("backups", project_paths[0])
|
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
|
# Temporatily stop autosave until user confirms backup
|
||||||
OpenSave.autosave_timer.stop()
|
OpenSave.autosave_timer.stop()
|
||||||
# For it's only possible to reload the first found backup
|
# For it's only possible to reload the first found backup
|
||||||
$BackupConfirmation.dialog_text = tr($BackupConfirmation.dialog_text) % project_paths[0]
|
$BackupConfirmation.dialog_text = tr($BackupConfirmation.dialog_text) % project_paths
|
||||||
$BackupConfirmation.connect("confirmed", self, "_on_BackupConfirmation_confirmed", [project_paths[0], backup_path])
|
$BackupConfirmation.connect("confirmed", self, "_on_BackupConfirmation_confirmed", [project_paths, backup_paths])
|
||||||
$BackupConfirmation.get_cancel().connect("pressed", self, "_on_BackupConfirmation_delete", [project_paths[0], backup_path])
|
$BackupConfirmation.get_cancel().connect("pressed", self, "_on_BackupConfirmation_delete", [project_paths, backup_paths])
|
||||||
$BackupConfirmation.popup_centered()
|
$BackupConfirmation.popup_centered()
|
||||||
Global.can_draw = false
|
Global.can_draw = false
|
||||||
modulate = Color(0.5, 0.5, 0.5)
|
modulate = Color(0.5, 0.5, 0.5)
|
||||||
|
@ -595,29 +597,29 @@ func _on_QuitAndSaveDialog_custom_action(action : String) -> void:
|
||||||
$SaveSprite.popup_centered()
|
$SaveSprite.popup_centered()
|
||||||
$QuitDialog.hide()
|
$QuitDialog.hide()
|
||||||
Global.dialog_open(true)
|
Global.dialog_open(true)
|
||||||
OpenSave.remove_backup()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_QuitDialog_confirmed() -> void:
|
func _on_QuitDialog_confirmed() -> void:
|
||||||
# Darken the UI to denote that the application is currently exiting
|
# Darken the UI to denote that the application is currently exiting
|
||||||
# (it won't respond to user input in this state).
|
# (it won't respond to user input in this state).
|
||||||
modulate = Color(0.5, 0.5, 0.5)
|
modulate = Color(0.5, 0.5, 0.5)
|
||||||
OpenSave.remove_backup()
|
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
|
|
||||||
func _on_BackupConfirmation_confirmed(project_path : String, backup_path : String) -> void:
|
func _on_BackupConfirmation_confirmed(project_paths : Array, backup_paths : Array) -> void:
|
||||||
OpenSave.reload_backup_file(project_path, backup_path)
|
OpenSave.reload_backup_file(project_paths, backup_paths)
|
||||||
|
# Global.tabs.delete_tab(0)
|
||||||
OpenSave.autosave_timer.start()
|
OpenSave.autosave_timer.start()
|
||||||
$ExportDialog.file_name = OpenSave.current_save_path.get_file().trim_suffix(".pxo")
|
$ExportDialog.file_name = OpenSave.current_save_paths[0].get_file().trim_suffix(".pxo")
|
||||||
$ExportDialog.directory_path = OpenSave.current_save_path.get_base_dir()
|
$ExportDialog.directory_path = OpenSave.current_save_paths[0].get_base_dir()
|
||||||
$ExportDialog.was_exported = false
|
$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"))
|
file_menu.set_item_text(6, tr("Export"))
|
||||||
|
|
||||||
|
|
||||||
func _on_BackupConfirmation_delete(project_path : String, backup_path : String) -> void:
|
func _on_BackupConfirmation_delete(project_paths : Array, backup_paths : Array) -> void:
|
||||||
OpenSave.remove_backup_by_path(project_path, backup_path)
|
for i in range(project_paths.size()):
|
||||||
|
OpenSave.remove_backup_by_path(project_paths[i], backup_paths[i])
|
||||||
OpenSave.autosave_timer.start()
|
OpenSave.autosave_timer.start()
|
||||||
# Reopen last project
|
# Reopen last project
|
||||||
if Global.open_last_project:
|
if Global.open_last_project:
|
||||||
|
|
|
@ -112,6 +112,6 @@ func _on_PreferencesDialog_popup_hide() -> void:
|
||||||
list.clear()
|
list.clear()
|
||||||
|
|
||||||
|
|
||||||
func _on_List_item_selected(index):
|
func _on_List_item_selected(index) -> void:
|
||||||
for child in right_side.get_children():
|
for child in right_side.get_children():
|
||||||
child.visible = child.name == ["General", "Languages", "Themes", "Canvas", "Image", "Shortcuts"][index]
|
child.visible = child.name == ["General", "Languages", "Themes", "Canvas", "Image", "Shortcuts"][index]
|
||||||
|
|
|
@ -185,9 +185,9 @@ margin_right = 506.0
|
||||||
margin_bottom = 24.0
|
margin_bottom = 24.0
|
||||||
mouse_default_cursor_shape = 2
|
mouse_default_cursor_shape = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
min_value = 0.5
|
min_value = 0.1
|
||||||
max_value = 30.0
|
max_value = 30.0
|
||||||
step = 0.5
|
step = 0.25
|
||||||
value = 1.0
|
value = 1.0
|
||||||
align = 2
|
align = 2
|
||||||
suffix = "minute(s)"
|
suffix = "minute(s)"
|
||||||
|
|
|
@ -27,6 +27,9 @@ func _on_Tabs_reposition_active_tab_request(idx_to : int) -> void:
|
||||||
func delete_tab(tab : int) -> void:
|
func delete_tab(tab : int) -> void:
|
||||||
remove_tab(tab)
|
remove_tab(tab)
|
||||||
Global.projects[tab].undo_redo.free()
|
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)
|
Global.projects.remove(tab)
|
||||||
if tab > 0:
|
if tab > 0:
|
||||||
Global.current_project_index -= 1
|
Global.current_project_index -= 1
|
||||||
|
|
Loading…
Reference in a new issue