From 237b8c1507e79fc1319fe96c901738fc8de87cf5 Mon Sep 17 00:00:00 2001 From: novhack <42614907+novhack@users.noreply.github.com> Date: Thu, 9 Apr 2020 22:54:05 +0200 Subject: [PATCH 1/3] Move open/save related code to a separate file. --- Scripts/Main.gd | 220 +----------------------------------------- Scripts/OpenSave.gd | 226 ++++++++++++++++++++++++++++++++++++++++++++ project.godot | 1 + 3 files changed, 232 insertions(+), 215 deletions(-) create mode 100644 Scripts/OpenSave.gd diff --git a/Scripts/Main.gd b/Scripts/Main.gd index 2944d7769..0dac7e7a7 100644 --- a/Scripts/Main.gd +++ b/Scripts/Main.gd @@ -1,6 +1,5 @@ extends Control -var current_save_path := "" var opensprite_file_selected := false var file_menu : PopupMenu var view_menu : PopupMenu @@ -227,11 +226,11 @@ func file_menu_id_pressed(id : int) -> void: opensprite_file_selected = false 2: # Save is_quitting_on_save = false - if current_save_path == "": + if OpenSave.current_save_path == "": $SaveSprite.popup_centered() Global.can_draw = false else: - _on_SaveSprite_file_selected(current_save_path) + _on_SaveSprite_file_selected(OpenSave.current_save_path) 3: # Save as is_quitting_on_save = false $SaveSprite.popup_centered() @@ -403,133 +402,8 @@ func _on_UnsavedCanvasDialog_confirmed() -> void: func _on_OpenSprite_file_selected(path : String) -> void: - var file := File.new() - var err := file.open(path, File.READ) - if err != OK: # An error occured - file.close() - OS.alert("Can't load file") - return + OpenSave.open_pxo_file(path) - var current_version : String = ProjectSettings.get_setting("application/config/Version") - var current_version_number = float(current_version.substr(1, 3)) # Example, "0.6" - var version := file.get_line() - var version_number = float(version.substr(1, 3)) # Example, "0.6" - if current_version_number < 0.5: - OS.alert("File is from an older version of Pixelorama, as such it might not work properly") - - var frame := 0 - Global.layers.clear() - if (version_number - 0.01) > 0.6: - var global_layer_line := file.get_line() - while global_layer_line == ".": - var layer_name := file.get_line() - var layer_visibility := file.get_8() - var layer_lock := file.get_8() - var layer_new_frames_linked := file.get_8() - var linked_frames = file.get_var() - - # Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3), - # will new frames be linked boolean (4), Array of linked frames (5)] - Global.layers.append([layer_name, layer_visibility, layer_lock, HBoxContainer.new(), layer_new_frames_linked, linked_frames]) - global_layer_line = file.get_line() - - var frame_line := file.get_line() - clear_canvases() - while frame_line == "--": # Load frames - var canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance() - Global.canvas = canvas - var width := file.get_16() - var height := file.get_16() - - var layer_line := file.get_line() - while layer_line == "-": # Load layers - var buffer := file.get_buffer(width * height * 4) - if version_number < (0.7 - 0.01): - var layer_name_old_version = file.get_line() - if frame == 0: - # Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3), - # will new frames be linked boolean (4), Array of linked frames (5)] - Global.layers.append([layer_name_old_version, true, false, HBoxContainer.new(), false, []]) - var layer_transparency := 1.0 - if version_number > 0.5: - layer_transparency = file.get_float() - var image := Image.new() - image.create_from_data(width, height, false, Image.FORMAT_RGBA8, buffer) - image.lock() - var tex := ImageTexture.new() - tex.create_from_image(image, 0) - canvas.layers.append([image, tex, layer_transparency]) - layer_line = file.get_line() - - var guide_line := file.get_line() # "guideline" no pun intended - while guide_line == "|": # Load guides - var guide := Guide.new() - guide.default_color = Color.purple - guide.type = file.get_8() - if guide.type == guide.Types.HORIZONTAL: - guide.add_point(Vector2(-99999, file.get_16())) - guide.add_point(Vector2(99999, file.get_16())) - else: - guide.add_point(Vector2(file.get_16(), -99999)) - guide.add_point(Vector2(file.get_16(), 99999)) - guide.has_focus = false - canvas.add_child(guide) - guide_line = file.get_line() - - canvas.size = Vector2(width, height) - Global.canvases.append(canvas) - canvas.frame = frame - Global.canvas_parent.add_child(canvas) - frame_line = file.get_line() - frame += 1 - - Global.canvases = Global.canvases # Just to call Global.canvases_changed - Global.current_frame = frame - 1 - Global.layers = Global.layers # Just to call Global.layers_changed - # Load tool options - Global.left_color_picker.color = file.get_var() - Global.right_color_picker.color = file.get_var() - Global.left_brush_size = file.get_8() - Global.left_brush_size_edit.value = Global.left_brush_size - Global.right_brush_size = file.get_8() - Global.right_brush_size_edit.value = Global.right_brush_size - if version_number < (0.7 - 0.01): - var left_palette = file.get_var() - var right_palette = file.get_var() - for color in left_palette: - Global.left_color_picker.get_picker().add_preset(color) - for color in right_palette: - Global.right_color_picker.get_picker().add_preset(color) - - # Load custom brushes - Global.custom_brushes.resize(Global.brushes_from_files) - Global.remove_brush_buttons() - - var brush_line := file.get_line() - while brush_line == "/": - var b_width := file.get_16() - var b_height := file.get_16() - var buffer := file.get_buffer(b_width * b_height * 4) - var image := Image.new() - image.create_from_data(b_width, b_height, false, Image.FORMAT_RGBA8, buffer) - Global.custom_brushes.append(image) - Global.create_brush_button(image) - brush_line = file.get_line() - - if (version_number - 0.01) > 0.6: - var tag_line := file.get_line() - while tag_line == ".T/": - var tag_name := file.get_line() - var tag_color : Color = file.get_var() - var tag_from := file.get_8() - var tag_to := file.get_8() - Global.animation_tags.append([tag_name, tag_color, tag_from, tag_to]) - Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() - tag_line = file.get_line() - - file.close() - - current_save_path = path $SaveSprite.current_path = path $ExportDialog.file_name = path.get_file().trim_suffix(".pxo") $ExportDialog.directory_path = path.get_base_dir() @@ -537,102 +411,18 @@ func _on_OpenSprite_file_selected(path : String) -> void: file_menu.set_item_text(2, tr("Save") + " %s" % path.get_file()) file_menu.set_item_text(5, tr("Export")) - Global.window_title = path.get_file() + " - Pixelorama" - func _on_SaveSprite_file_selected(path : String) -> void: - current_save_path = path + OpenSave.save_pxo_file(path) + $ExportDialog.file_name = path.get_file().trim_suffix(".pxo") $ExportDialog.directory_path = path.get_base_dir() $ExportDialog.was_exported = false file_menu.set_item_text(2, tr("Save") + " %s" % path.get_file()) - var file := File.new() - var err := file.open(path, File.WRITE) - if err == OK: - file.store_line(ProjectSettings.get_setting("application/config/Version")) - for layer in Global.layers: # Store Global layers - file.store_line(".") - file.store_line(layer[0]) # Layer name - file.store_8(layer[1]) # Layer visibility - file.store_8(layer[2]) # Layer lock - file.store_8(layer[4]) # Future frames linked - file.store_var(layer[5]) # Linked frames - file.store_line("END_GLOBAL_LAYERS") - - for canvas in Global.canvases: # Store frames - file.store_line("--") - file.store_16(canvas.size.x) - file.store_16(canvas.size.y) - for layer in canvas.layers: # Store canvas layers - file.store_line("-") - file.store_buffer(layer[0].get_data()) - file.store_float(layer[2]) # Layer transparency - file.store_line("END_LAYERS") - - for child in canvas.get_children(): # Store guides - if child is Guide: - file.store_line("|") - file.store_8(child.type) - if child.type == child.Types.HORIZONTAL: - file.store_16(child.points[0].y) - file.store_16(child.points[1].y) - else: - file.store_16(child.points[1].x) - file.store_16(child.points[0].x) - file.store_line("END_GUIDES") - file.store_line("END_FRAMES") - - # Save tool options - var left_color : Color = Global.left_color_picker.color - var right_color : Color = Global.right_color_picker.color - var left_brush_size : int = Global.left_brush_size - var right_brush_size : int = Global.right_brush_size - file.store_var(left_color) - file.store_var(right_color) - file.store_8(left_brush_size) - file.store_8(right_brush_size) - # Save custom brushes - for i in range(Global.brushes_from_files, Global.custom_brushes.size()): - var brush = Global.custom_brushes[i] - file.store_line("/") - file.store_16(brush.get_size().x) - file.store_16(brush.get_size().y) - file.store_buffer(brush.get_data()) - file.store_line("END_BRUSHES") - - for tag in Global.animation_tags: # Store Global layers - file.store_line(".T/") - file.store_line(tag[0]) # Tag name - file.store_var(tag[1]) # Tag color - file.store_8(tag[2]) # Tag "from", the first frame - file.store_8(tag[3]) # Tag "to", the last frame - - file.store_line("END_FRAME_TAGS") - - file.close() - - if !Global.saved: - Global.saved = true - Global.window_title = Global.window_title.rstrip("(*)") - - Global.notification_label("File saved") if is_quitting_on_save: _on_QuitDialog_confirmed() -func clear_canvases() -> void: - for child in Global.canvas_parent.get_children(): - if child is Canvas: - child.queue_free() - Global.canvases.clear() - Global.animation_tags.clear() - Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() - - current_save_path = "" - file_menu.set_item_text(2, "Save") - file_menu.set_item_text(5, "Export...") - Global.window_title = "(" + tr("untitled") + ") - Pixelorama" - Global.undo_redo.clear_history(false) func _on_ImportSprites_popup_hide() -> void: if !opensprite_file_selected: diff --git a/Scripts/OpenSave.gd b/Scripts/OpenSave.gd new file mode 100644 index 000000000..9ee852094 --- /dev/null +++ b/Scripts/OpenSave.gd @@ -0,0 +1,226 @@ +extends Node + +var current_save_path := "" + +func open_pxo_file(path : String) -> void: + var file := File.new() + var err := file.open(path, File.READ) + if err != OK: # An error occured + file.close() + OS.alert("Can't load file") + return + + var file_version := file.get_line() # Example, "v0.6" + var file_major_version = int(file_version.substr(1, 1)) + var file_minor_version = int(file_version.substr(3, 1)) + + if file_major_version == 0 and file_minor_version < 5: + OS.alert("File is from an older version of Pixelorama, as such it might not work properly") + + var frame := 0 + Global.layers.clear() + if file_major_version >= 0 and file_minor_version > 6: + var global_layer_line := file.get_line() + while global_layer_line == ".": + var layer_name := file.get_line() + var layer_visibility := file.get_8() + var layer_lock := file.get_8() + var layer_new_frames_linked := file.get_8() + var linked_frames = file.get_var() + + # Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3), + # will new frames be linked boolean (4), Array of linked frames (5)] + Global.layers.append([layer_name, layer_visibility, layer_lock, HBoxContainer.new(), layer_new_frames_linked, linked_frames]) + global_layer_line = file.get_line() + + var frame_line := file.get_line() + clear_canvases() + while frame_line == "--": # Load frames + var canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance() + Global.canvas = canvas + var width := file.get_16() + var height := file.get_16() + + var layer_line := file.get_line() + while layer_line == "-": # Load layers + var buffer := file.get_buffer(width * height * 4) + if file_major_version == 0 and file_minor_version < 7: + var layer_name_old_version = file.get_line() + if frame == 0: + # Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3), + # will new frames be linked boolean (4), Array of linked frames (5)] + Global.layers.append([layer_name_old_version, true, false, HBoxContainer.new(), false, []]) + var layer_transparency := 1.0 + if file_major_version >= 0 and file_minor_version > 5: + layer_transparency = file.get_float() + var image := Image.new() + image.create_from_data(width, height, false, Image.FORMAT_RGBA8, buffer) + image.lock() + var tex := ImageTexture.new() + tex.create_from_image(image, 0) + canvas.layers.append([image, tex, layer_transparency]) + layer_line = file.get_line() + + var guide_line := file.get_line() # "guideline" no pun intended + while guide_line == "|": # Load guides + var guide := Guide.new() + guide.default_color = Color.purple + guide.type = file.get_8() + if guide.type == guide.Types.HORIZONTAL: + guide.add_point(Vector2(-99999, file.get_16())) + guide.add_point(Vector2(99999, file.get_16())) + else: + guide.add_point(Vector2(file.get_16(), -99999)) + guide.add_point(Vector2(file.get_16(), 99999)) + guide.has_focus = false + canvas.add_child(guide) + guide_line = file.get_line() + + canvas.size = Vector2(width, height) + Global.canvases.append(canvas) + canvas.frame = frame + Global.canvas_parent.add_child(canvas) + frame_line = file.get_line() + frame += 1 + + Global.canvases = Global.canvases # Just to call Global.canvases_changed + Global.current_frame = frame - 1 + Global.layers = Global.layers # Just to call Global.layers_changed + # Load tool options + Global.left_color_picker.color = file.get_var() + Global.right_color_picker.color = file.get_var() + Global.left_brush_size = file.get_8() + Global.left_brush_size_edit.value = Global.left_brush_size + Global.right_brush_size = file.get_8() + Global.right_brush_size_edit.value = Global.right_brush_size + if file_major_version == 0 and file_minor_version < 7: + var left_palette = file.get_var() + var right_palette = file.get_var() + for color in left_palette: + Global.left_color_picker.get_picker().add_preset(color) + for color in right_palette: + Global.right_color_picker.get_picker().add_preset(color) + + # Load custom brushes + Global.custom_brushes.resize(Global.brushes_from_files) + Global.remove_brush_buttons() + + var brush_line := file.get_line() + while brush_line == "/": + var b_width := file.get_16() + var b_height := file.get_16() + var buffer := file.get_buffer(b_width * b_height * 4) + var image := Image.new() + image.create_from_data(b_width, b_height, false, Image.FORMAT_RGBA8, buffer) + Global.custom_brushes.append(image) + Global.create_brush_button(image) + brush_line = file.get_line() + + if file_major_version >= 0 and file_minor_version > 6: + var tag_line := file.get_line() + while tag_line == ".T/": + var tag_name := file.get_line() + var tag_color : Color = file.get_var() + var tag_from := file.get_8() + var tag_to := file.get_8() + Global.animation_tags.append([tag_name, tag_color, tag_from, tag_to]) + Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() + tag_line = file.get_line() + + file.close() + + current_save_path = path + Global.window_title = path.get_file() + " - Pixelorama" + + +func save_pxo_file(path : String) -> void: + current_save_path = path + + var file := File.new() + var err := file.open(path, File.WRITE) + if err == OK: + # Store Pixelorama version + file.store_line(ProjectSettings.get_setting("application/config/Version")) + + # Store Global layers + for layer in Global.layers: + file.store_line(".") + file.store_line(layer[0]) # Layer name + file.store_8(layer[1]) # Layer visibility + file.store_8(layer[2]) # Layer lock + file.store_8(layer[4]) # Future frames linked + file.store_var(layer[5]) # Linked frames + file.store_line("END_GLOBAL_LAYERS") + + # Store frames + for canvas in Global.canvases: + file.store_line("--") + file.store_16(canvas.size.x) + file.store_16(canvas.size.y) + for layer in canvas.layers: # Store canvas layers + file.store_line("-") + file.store_buffer(layer[0].get_data()) + file.store_float(layer[2]) # Layer transparency + file.store_line("END_LAYERS") + + # Store guides + for child in canvas.get_children(): + if child is Guide: + file.store_line("|") + file.store_8(child.type) + if child.type == child.Types.HORIZONTAL: + file.store_16(child.points[0].y) + file.store_16(child.points[1].y) + else: + file.store_16(child.points[1].x) + file.store_16(child.points[0].x) + file.store_line("END_GUIDES") + file.store_line("END_FRAMES") + + # Save tool options + var left_color : Color = Global.left_color_picker.color + var right_color : Color = Global.right_color_picker.color + var left_brush_size : int = Global.left_brush_size + var right_brush_size : int = Global.right_brush_size + file.store_var(left_color) + file.store_var(right_color) + file.store_8(left_brush_size) + file.store_8(right_brush_size) + + # Save custom brushes + for i in range(Global.brushes_from_files, Global.custom_brushes.size()): + var brush = Global.custom_brushes[i] + file.store_line("/") + file.store_16(brush.get_size().x) + file.store_16(brush.get_size().y) + file.store_buffer(brush.get_data()) + file.store_line("END_BRUSHES") + + # Store animation tags + for tag in Global.animation_tags: + file.store_line(".T/") + file.store_line(tag[0]) # Tag name + file.store_var(tag[1]) # Tag color + file.store_8(tag[2]) # Tag "from", the first frame + file.store_8(tag[3]) # Tag "to", the last frame + file.store_line("END_FRAME_TAGS") + + file.close() + + if !Global.saved: + Global.saved = true + + Global.window_title = current_save_path.get_file() + " - Pixelorama" + Global.notification_label("File saved") + + +func clear_canvases() -> void: + for child in Global.canvas_parent.get_children(): + if child is Canvas: + child.queue_free() + Global.canvases.clear() + Global.animation_tags.clear() + Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() + + Global.window_title = "(" + tr("untitled") + ") - Pixelorama" + Global.undo_redo.clear_history(false) diff --git a/project.godot b/project.godot index 57275494a..dde3b05ff 100644 --- a/project.godot +++ b/project.godot @@ -59,6 +59,7 @@ config/Version="v0.7" Global="*res://Scripts/Global.gd" Import="*res://Scripts/Import.gd" +OpenSave="*res://Scripts/OpenSave.gd" [debug] From 99f847e73238df9c0b5c0b54680f44fb18a0e355 Mon Sep 17 00:00:00 2001 From: novhack <42614907+novhack@users.noreply.github.com> Date: Fri, 10 Apr 2020 00:06:24 +0200 Subject: [PATCH 2/3] Add ZSTD compression to save files. Move clear_canvases() to Global.gd --- Scripts/Dialogs/CreateNewImage.gd | 2 +- Scripts/Global.gd | 11 +++++++++++ Scripts/OpenSave.gd | 25 ++++++++----------------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Scripts/Dialogs/CreateNewImage.gd b/Scripts/Dialogs/CreateNewImage.gd index 083496a3a..dcb756eeb 100644 --- a/Scripts/Dialogs/CreateNewImage.gd +++ b/Scripts/Dialogs/CreateNewImage.gd @@ -30,7 +30,7 @@ func _on_CreateNewImage_confirmed() -> void: var width : int = width_value.value var height : int = height_value.value var fill_color : Color = fill_color_node.color - Global.control.clear_canvases() + Global.clear_canvases() Global.layers.clear() # Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3), # will new frames be linked boolean (4), Array of linked frames (5)] diff --git a/Scripts/Global.gd b/Scripts/Global.gd index 19674c266..800c45d43 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -499,6 +499,17 @@ func canvases_changed(value : Array) -> void: layers[i][3].add_child(frame_button) +func clear_canvases() -> void: + for child in Global.canvas_parent.get_children(): + if child is Canvas: + child.queue_free() + Global.canvases.clear() + Global.animation_tags.clear() + Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() + + Global.window_title = "(" + tr("untitled") + ") - Pixelorama" + Global.undo_redo.clear_history(false) + func layers_changed(value : Array) -> void: layers = value if layers_changed_skip: diff --git a/Scripts/OpenSave.gd b/Scripts/OpenSave.gd index 9ee852094..745fee96d 100644 --- a/Scripts/OpenSave.gd +++ b/Scripts/OpenSave.gd @@ -4,8 +4,11 @@ var current_save_path := "" func open_pxo_file(path : String) -> void: var file := File.new() - var err := file.open(path, File.READ) - if err != OK: # An error occured + var err := file.open_compressed(path, File.READ, File.COMPRESSION_ZSTD) + if err == ERR_FILE_UNRECOGNIZED: + err = file.open(path, File.READ) # If the file is not compressed open it raw (pre-v0.7) + + if err != OK: file.close() OS.alert("Can't load file") return @@ -15,7 +18,7 @@ func open_pxo_file(path : String) -> void: var file_minor_version = int(file_version.substr(3, 1)) if file_major_version == 0 and file_minor_version < 5: - OS.alert("File is from an older version of Pixelorama, as such it might not work properly") + Global.notification_label("File is from an older version of Pixelorama, as such it might not work properly") var frame := 0 Global.layers.clear() @@ -34,7 +37,7 @@ func open_pxo_file(path : String) -> void: global_layer_line = file.get_line() var frame_line := file.get_line() - clear_canvases() + Global.clear_canvases() while frame_line == "--": # Load frames var canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance() Global.canvas = canvas @@ -137,7 +140,7 @@ func save_pxo_file(path : String) -> void: current_save_path = path var file := File.new() - var err := file.open(path, File.WRITE) + var err := file.open_compressed(path, File.WRITE, File.COMPRESSION_ZSTD) if err == OK: # Store Pixelorama version file.store_line(ProjectSettings.get_setting("application/config/Version")) @@ -212,15 +215,3 @@ func save_pxo_file(path : String) -> void: Global.window_title = current_save_path.get_file() + " - Pixelorama" Global.notification_label("File saved") - - -func clear_canvases() -> void: - for child in Global.canvas_parent.get_children(): - if child is Canvas: - child.queue_free() - Global.canvases.clear() - Global.animation_tags.clear() - Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() - - Global.window_title = "(" + tr("untitled") + ") - Pixelorama" - Global.undo_redo.clear_history(false) From 4b7c0ca713579f531e88f232f00df2e66e4977e5 Mon Sep 17 00:00:00 2001 From: novhack <42614907+novhack@users.noreply.github.com> Date: Fri, 10 Apr 2020 20:37:24 +0200 Subject: [PATCH 3/3] Fix clear_canvases() call in ImportSprites. --- Scripts/Dialogs/ImportSprites.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Dialogs/ImportSprites.gd b/Scripts/Dialogs/ImportSprites.gd index 32a966edd..f71214308 100644 --- a/Scripts/Dialogs/ImportSprites.gd +++ b/Scripts/Dialogs/ImportSprites.gd @@ -32,7 +32,7 @@ func _on_VerticalFrames_value_changed(value) -> void: func _on_ImportSprites_files_selected(paths : PoolStringArray) -> void: Global.control.opensprite_file_selected = true if !new_frame: # If we're not adding a new frame, delete the previous - Global.control.clear_canvases() + Global.clear_canvases() var first_path : String = paths[0] var i : int = Global.canvases.size()