1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-30 23:19:49 +00:00

Made pxo saving a bit safer

It now first attempts to serialize the project data and turn them to JSON, and then opens the file. This is a lto safer because, if a crash happens in the serialization, the file is not already open, and therefore it does not get corrupt. Earlier, if a crash happened, the file would be empty. This meant that if that file existed previously, all of the data would be lost.
This commit is contained in:
OverloadedOrama 2020-10-20 03:27:38 +03:00
parent 852365c38f
commit e94bcf50e0
5 changed files with 58 additions and 50 deletions

View file

@ -113,7 +113,7 @@ boot_splash/bg_color=Color( 0.145098, 0.145098, 0.164706, 1 )
config/icon="res://assets/graphics/icons/icon.png" config/icon="res://assets/graphics/icons/icon.png"
config/macos_native_icon="res://assets/graphics/icons/icon.icns" config/macos_native_icon="res://assets/graphics/icons/icon.icns"
config/windows_native_icon="res://assets/graphics/icons/icon.ico" config/windows_native_icon="res://assets/graphics/icons/icon.ico"
config/Version="v0.8.1-stable" config/Version="v0.8.2-dev"
[audio] [audio]

View file

@ -222,7 +222,7 @@ func _ready() -> void:
patterns_popup = find_node_by_name(root, "PatternsPopup") patterns_popup = find_node_by_name(root, "PatternsPopup")
animation_timeline = find_node_by_name(root, "AnimationTimeline") animation_timeline = find_node_by_name(root, "AnimationTimeline")
frame_properties = find_node_by_name(root, "FrameProperties") frame_properties = find_node_by_name(root, "FrameProperties")
layers_container = find_node_by_name(animation_timeline, "LayersContainer") layers_container = find_node_by_name(animation_timeline, "LayersContainer")
frames_container = find_node_by_name(animation_timeline, "FramesContainer") frames_container = find_node_by_name(animation_timeline, "FramesContainer")

View file

@ -265,6 +265,15 @@ func open_old_pxo_file(file : File, new_project : Project, first_line : String)
func save_pxo_file(path : String, autosave : bool, use_zstd_compression := true, project : Project = Global.current_project) -> void: func save_pxo_file(path : String, autosave : bool, use_zstd_compression := true, project : Project = Global.current_project) -> void:
var serialized_data = project.serialize()
if !serialized_data:
Global.notification_label(tr("File failed to save. Serialization to dictionary failed."))
return
var to_save = JSON.print(serialized_data)
if !to_save:
Global.notification_label(tr("File failed to save. Dictionary to JSON failed."))
return
var file : File = File.new() var file : File = File.new()
var err var err
if use_zstd_compression: if use_zstd_compression:
@ -272,53 +281,52 @@ func save_pxo_file(path : String, autosave : bool, use_zstd_compression := true,
else: else:
err = file.open(path, File.WRITE) err = file.open(path, File.WRITE)
if err == OK: if err != OK:
if !autosave:
project.name = path.get_file()
current_save_paths[Global.current_project_index] = path
var to_save = JSON.print(project.serialize())
file.store_line(to_save)
for frame in project.frames:
for cel in frame.cels:
file.store_buffer(cel.image.get_data())
for brush in project.brushes:
file.store_buffer(brush.get_data())
file.close()
if OS.get_name() == "HTML5" and !autosave:
err = file.open(path, File.READ)
if !err:
var file_data = Array(file.get_buffer(file.get_len()))
JavaScript.eval("download('%s', %s, '');" % [path.get_file(), str(file_data)], true)
file.close()
# Remove the .pxo file from memory, as we don't need it anymore
var dir = Directory.new()
dir.remove(path)
if autosave:
Global.notification_label("File autosaved")
else:
# First remove backup then set current save path
if project.has_changed:
project.has_changed = false
remove_backup(Global.current_project_index)
Global.notification_label("File saved")
Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version
# Set last opened project path and save
Global.config_cache.set_value("preferences", "last_project_path", path)
Global.config_cache.save("user://cache.ini")
Export.file_name = path.get_file().trim_suffix(".pxo")
Export.directory_path = path.get_base_dir()
Export.was_exported = false
Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % path.get_file())
else:
Global.notification_label(tr("File failed to save. Error code %s") % err) Global.notification_label(tr("File failed to save. Error code %s") % err)
file.close() file.close()
return
if !autosave:
project.name = path.get_file()
current_save_paths[Global.current_project_index] = path
file.store_line(to_save)
for frame in project.frames:
for cel in frame.cels:
file.store_buffer(cel.image.get_data())
for brush in project.brushes:
file.store_buffer(brush.get_data())
file.close()
if OS.get_name() == "HTML5" and !autosave:
err = file.open(path, File.READ)
if !err:
var file_data = Array(file.get_buffer(file.get_len()))
JavaScript.eval("download('%s', %s, '');" % [path.get_file(), str(file_data)], true)
file.close()
# Remove the .pxo file from memory, as we don't need it anymore
var dir = Directory.new()
dir.remove(path)
if autosave:
Global.notification_label("File autosaved")
else:
# First remove backup then set current save path
if project.has_changed:
project.has_changed = false
remove_backup(Global.current_project_index)
Global.notification_label("File saved")
Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version
# Set last opened project path and save
Global.config_cache.set_value("preferences", "last_project_path", path)
Global.config_cache.save("user://cache.ini")
Export.file_name = path.get_file().trim_suffix(".pxo")
Export.directory_path = path.get_base_dir()
Export.was_exported = false
Global.file_menu.get_popup().set_item_text(3, tr("Save") + " %s" % path.get_file())
func open_image_as_new_tab(path : String, image : Image) -> void: func open_image_as_new_tab(path : String, image : Image) -> void:

View file

@ -8,7 +8,7 @@ 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
var frames := [] setget frames_changed # Array of Frames (that contain Cels) var frames := [] setget frames_changed # Array of Frames (that contain Cels)
var frame_duration := [] var frame_duration := []
var layers := [] setget layers_changed # Array of Layers var layers := [] setget layers_changed # Array of Layers
var current_frame := 0 setget frame_changed var current_frame := 0 setget frame_changed
var current_layer := 0 setget layer_changed var current_layer := 0 setget layer_changed

View file

@ -65,7 +65,7 @@ func _on_DeleteFrame_pressed(frame := -1) -> void:
return return
if frame == -1: if frame == -1:
frame = Global.current_project.current_frame frame = Global.current_project.current_frame
var frame_duration : Array = Global.current_project.frame_duration.duplicate() var frame_duration : Array = Global.current_project.frame_duration.duplicate()
frame_duration.remove(frame) frame_duration.remove(frame)
var frame_to_delete : Frame = Global.current_project.frames[frame] var frame_to_delete : Frame = Global.current_project.frames[frame]
@ -311,7 +311,7 @@ func play_animation(play : bool, forward_dir : bool) -> void:
if play: if play:
Global.animation_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing Global.animation_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing
Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1 / fps) Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1 / fps)
Global.animation_timer.start() Global.animation_timer.start()
animation_forward = forward_dir animation_forward = forward_dir
else: else: