From a3f64fe1cfc418d3fe106eba571eee1a7f4338c2 Mon Sep 17 00:00:00 2001 From: Kebrerross Date: Sun, 18 Dec 2022 14:55:49 +0100 Subject: [PATCH 1/6] Migrate addon to godot 4.0 --- .github/workflows/static-checks.yml | 4 +- addons/godot_pixelorama_importer/plugin.gd | 23 ++--- .../single_image_import.gd | 41 +++++--- .../spriteframes_import.gd | 58 ++++++----- .../util/read_pxo_file.gd | 99 ++++++++++--------- 5 files changed, 129 insertions(+), 96 deletions(-) diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index ef49961..5e8486c 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -5,11 +5,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: pip3 install gdtoolkit + - run: pip3 install git+https://github.com/Scony/godot-gdscript-toolkit.git - run: gdformat --diff . lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: pip3 install gdtoolkit + - run: pip3 install git+https://github.com/Scony/godot-gdscript-toolkit.git - run: gdlint . diff --git a/addons/godot_pixelorama_importer/plugin.gd b/addons/godot_pixelorama_importer/plugin.gd index ed48df5..de6c8f6 100644 --- a/addons/godot_pixelorama_importer/plugin.gd +++ b/addons/godot_pixelorama_importer/plugin.gd @@ -1,4 +1,4 @@ -tool +@tool extends EditorPlugin var editor_settings := get_editor_interface().get_editor_settings() @@ -6,7 +6,7 @@ var editor_settings := get_editor_interface().get_editor_settings() var import_plugins -func handles(object: Object) -> bool: +func _handles(object) -> bool: # object is Variant # Find .pxo files if object is Resource && (object as Resource).resource_path.ends_with(".pxo"): return true @@ -14,34 +14,35 @@ func handles(object: Object) -> bool: return false -func edit(object: Object) -> void: +func _edit(object) -> void: # object is Variant # Safeguard if object is Resource && (object as Resource).resource_path.ends_with(".pxo"): if editor_settings.get_setting("pixelorama/path") == "": var popup = AcceptDialog.new() - popup.window_title = "No Pixelorama Binary found!" + popup.title = "No Pixelorama Binary found!" # gdlint: ignore=max-line-length popup.dialog_text = "Specify the path to the binary in the Editor Settings (Editor > Editor Settings...) under Pixelorama > Path" - popup.popup_exclusive = true - popup.set_as_minsize() + popup.exclusive = true + popup.wrap_controls = true get_editor_interface().get_base_control().add_child(popup) - popup.popup_centered_minsize() + popup.popup_centered_clamped() - yield(popup, "confirmed") + var confirmed = await popup.confirmed popup.queue_free() return - var file = File.new() var path = editor_settings.get_setting("pixelorama/path") if OS.get_name() == "OSX": path += "/Contents/MacOS/Pixelorama" - if file.open(path, File.READ): + FileAccess.open(path, FileAccess.READ) + if FileAccess.get_open_error(): push_error("Pixelorama binary could not be found") return - OS.execute(path, [ProjectSettings.globalize_path(object.resource_path)], false) + var output = [] + OS.execute(path, [ProjectSettings.globalize_path(object.resource_path)], output, false) func _enter_tree() -> void: diff --git a/addons/godot_pixelorama_importer/single_image_import.gd b/addons/godot_pixelorama_importer/single_image_import.gd index cb44341..7e7e823 100644 --- a/addons/godot_pixelorama_importer/single_image_import.gd +++ b/addons/godot_pixelorama_importer/single_image_import.gd @@ -1,45 +1,60 @@ -tool +@tool extends EditorImportPlugin -func get_importer_name(): +func _get_importer_name() -> String: return "com.technohacker.pixelorama" -func get_visible_name(): +func _get_visible_name() -> String: return "Single Image" -func get_recognized_extensions(): - return ["pxo"] +func _get_recognized_extensions() -> PackedStringArray: + return PackedStringArray(["pxo"]) # We save directly to stex because ImageTexture doesn't work for some reason -func get_save_extension(): - return "stex" +func _get_save_extension() -> String: + return "ctex" -func get_resource_type(): - return "StreamTexture" +func _get_resource_type() -> String: + return "CompressedTexture2D" -func get_import_options(_preset): +func _get_priority() -> float: + return 1.0 + + +func _get_import_order() -> int: + return 1 + + +func _get_import_options(_path: String, _preset_index: int) -> Array[Dictionary]: return [] -func get_option_visibility(_option, _options): +func _get_option_visibility(_path: String, _option_name: StringName, _options: Dictionary) -> bool: return true -func get_preset_count(): +func _get_preset_count() -> int: return 0 -func import(source_file, save_path, _options, _r_platform_variants, _r_gen_files): +func _import( + source_file: String, + save_path: String, + _options: Dictionary, + _platform_variants: Array[String], + _gen_files: Array[String] +) -> int: """ Main import function. Reads the Pixelorama project and extracts the PNG image from it """ # Open the project var load_res = preload("./util/read_pxo_file.gd").read_pxo_file(source_file, save_path) + return load_res.error diff --git a/addons/godot_pixelorama_importer/spriteframes_import.gd b/addons/godot_pixelorama_importer/spriteframes_import.gd index 50b2cbe..cd60547 100644 --- a/addons/godot_pixelorama_importer/spriteframes_import.gd +++ b/addons/godot_pixelorama_importer/spriteframes_import.gd @@ -1,47 +1,61 @@ -tool +@tool extends EditorImportPlugin var editor: EditorInterface -func _init(editor_interface): +func _init(editor_interface: EditorInterface): editor = editor_interface -func get_importer_name(): +func _get_importer_name() -> String: return "com.technohacker.pixelorama.spriteframe" -func get_visible_name(): +func _get_visible_name() -> String: return "SpriteFrames" -func get_recognized_extensions(): - return ["pxo"] +func _get_recognized_extensions() -> PackedStringArray: + return PackedStringArray(["pxo"]) -# We save directly to stex because ImageTexture doesn't work for some reason -func get_save_extension(): +# We save directly to ctex because ImageTexture doesn't work for some reason +func _get_save_extension() -> String: return "tres" -func get_resource_type(): +func _get_resource_type() -> String: return "SpriteFrames" -func get_import_options(_preset): +func _get_priority() -> float: + return 1.0 + + +func _get_import_order() -> int: + return 1 + + +func _get_import_options(_path: String, _preset_index: int) -> Array[Dictionary]: return [{"name": "animation_fps", "default_value": 6}] -func get_option_visibility(_option, _options): +func _get_option_visibility(_path: String, _option_name: StringName, _options: Dictionary) -> bool: return true -func get_preset_count(): +func _get_preset_count() -> int: return 0 -func import(source_file, save_path, options, _r_platform_variants, r_gen_files): +func _import( + source_file: String, + save_path: String, + options: Dictionary, + _platform_variants: Array[String], + gen_files: Array[String] +) -> int: """ Main import function. Reads the Pixelorama project and creates the SpriteFrames resource """ @@ -58,11 +72,11 @@ func import(source_file, save_path, options, _r_platform_variants, r_gen_files): var project = load_res.value # Note the spritesheet - spritesheet_path = "%s.stex" % spritesheet_path - r_gen_files.push_back(spritesheet_path) + spritesheet_path = "%s.ctex" % spritesheet_path + gen_files.push_back(spritesheet_path) - # Load the spritesheet as a .stex - var spritesheet_tex = StreamTexture.new() + # Load the spritesheet as a .ctex + var spritesheet_tex = CompressedTexture2D.new() spritesheet_tex.load(spritesheet_path) # Create the frames @@ -81,18 +95,16 @@ func import(source_file, save_path, options, _r_platform_variants, r_gen_files): frames.set_animation_speed(tag.name, options.animation_fps) for frame in range(tag.from, tag.to + 1): - var image_rect := Rect2(Vector2((frame - 1) * frame_size.x, 0), frame_size) + var image_rect := Rect2i(Vector2((frame - 1) * frame_size.x, 0), frame_size) var image := Image.new() - image = spritesheet_tex.get_data().get_rect(image_rect) - var image_texture := ImageTexture.new() - image_texture.create_from_image(image, 0) + image = spritesheet_tex.get_image().get_region(image_rect) + var image_texture := ImageTexture.create_from_image(image) #,0 frames.add_frame(tag.name, image_texture) - var err = ResourceSaver.save("%s.%s" % [save_path, get_save_extension()], frames) + var err = ResourceSaver.save(frames, "%s.%s" % [save_path, _get_save_extension()]) if err != OK: printerr("Error saving SpriteFrames") return err - editor.get_inspector().refresh() return OK diff --git a/addons/godot_pixelorama_importer/util/read_pxo_file.gd b/addons/godot_pixelorama_importer/util/read_pxo_file.gd index bab17dc..52e15c4 100644 --- a/addons/godot_pixelorama_importer/util/read_pxo_file.gd +++ b/addons/godot_pixelorama_importer/util/read_pxo_file.gd @@ -7,21 +7,21 @@ static func read_pxo_file(source_file: String, image_save_path: String): var result = Result.new() # Open the Pixelorama project file - var file = File.new() - var err = file.open_compressed(source_file, File.READ, File.COMPRESSION_ZSTD) - if err != OK: - file.open(source_file, File.READ) + var file = FileAccess.open_compressed(source_file, FileAccess.READ, FileAccess.COMPRESSION_ZSTD) + if FileAccess.get_open_error() != OK: + file = FileAccess.open(source_file, FileAccess.READ) # Parse it as JSON var text = file.get_line() - var json = JSON.parse(text) + var test_json_conv = JSON.new() + var json_error = test_json_conv.parse(text) - if json.error != OK: + if json_error != OK: printerr("JSON Parse Error") - result.error = json.error + result.error = json_error return result - var project = json.result + var project = test_json_conv.get_data() # Make sure it's a JSON Object if typeof(project) != TYPE_DICTIONARY: @@ -34,8 +34,7 @@ static func read_pxo_file(source_file: String, image_save_path: String): var frame_count = project.frames.size() # Prepare the spritesheet image - var spritesheet = Image.new() - spritesheet.create(size.x * frame_count, size.y, false, Image.FORMAT_RGBA8) + var spritesheet = Image.create(size.x * frame_count, size.y, false, Image.FORMAT_RGBA8) var cel_data_size: int = size.x * size.y * 4 @@ -50,19 +49,19 @@ static func read_pxo_file(source_file: String, image_save_path: String): if project.layers[layer].visible and opacity > 0.0: # Load the cel image - var cel_img := Image.new() - cel_img.create_from_data( - size.x, size.y, false, Image.FORMAT_RGBA8, file.get_buffer(cel_data_size) + var cel_img = ( + Image + . create_from_data( + size.x, size.y, false, Image.FORMAT_RGBA8, file.get_buffer(cel_data_size) + ) ) if opacity < 1.0: - cel_img.lock() for x in range(size.x): for y in range(size.y): var color := cel_img.get_pixel(x, y) color.a *= opacity cel_img.set_pixel(x, y, color) - cel_img.unlock() if frame_img == null: frame_img = cel_img @@ -79,43 +78,49 @@ static func read_pxo_file(source_file: String, image_save_path: String): # Add to the spritesheet spritesheet.blit_rect(frame_img, Rect2(Vector2.ZERO, size), Vector2(size.x * i, 0)) - save_stex(spritesheet, image_save_path) + save_ctex(spritesheet, image_save_path) result.value = project result.error = OK return result -# Taken from https://github.com/lifelike/godot-animator-import -static func save_stex(image, save_path): - var tmppng = "%s-tmp.png" % [save_path] - image.save_png(tmppng) - var pngf = File.new() - pngf.open(tmppng, File.READ) - var pnglen = pngf.get_len() - var pngdata = pngf.get_buffer(pnglen) - pngf.close() - Directory.new().remove(tmppng) - - var stexf = File.new() - stexf.open("%s.stex" % [save_path], File.WRITE) - stexf.store_8(0x47) # G - stexf.store_8(0x44) # D - stexf.store_8(0x53) # S - stexf.store_8(0x54) # T - stexf.store_32(image.get_width()) - stexf.store_32(image.get_height()) - stexf.store_32(0) # flags: Disable all of it as we're dealing with pixel-perfect images - stexf.store_32(0x07100000) # data format - stexf.store_32(1) # nr mipmaps - stexf.store_32(pnglen + 6) - stexf.store_8(0x50) # P - stexf.store_8(0x4e) # N - stexf.store_8(0x47) # G - stexf.store_8(0x20) # space - stexf.store_buffer(pngdata) - stexf.close() - - print("stex saved") +# Based on CompressedTexture2D::_load_data from +# https://github.com/godotengine/godot/blob/master/scene/resources/texture.cpp +static func save_ctex(image, save_path: String): + var tmpwebp = "%s-tmp.webp" % [save_path] + image.save_webp(tmpwebp) # not quite sure, but the png import that I tested was in webp + + var webpf = FileAccess.open(tmpwebp, FileAccess.READ) + var webplen = webpf.get_length() + var webpdata = webpf.get_buffer(webplen) + webpf = null # setting null will close the file + + var dir := DirAccess.open(tmpwebp.get_base_dir()) + dir.remove(tmpwebp.get_file()) + + var ctexf = FileAccess.open("%s.ctex" % [save_path], FileAccess.WRITE) + ctexf.store_8(0x47) # G + ctexf.store_8(0x53) # S + ctexf.store_8(0x54) # T + ctexf.store_8(0x32) # 2 + ctexf.store_32(0x01) # FORMAT_VERSION + ctexf.store_32(image.get_width()) + ctexf.store_32(image.get_height()) + ctexf.store_32(0xD000000) # data format (?) + ctexf.store_32(0xFFFFFFFF) # mipmap_limit + ctexf.store_32(0x0) # reserved + ctexf.store_32(0x0) # reserved + ctexf.store_32(0x0) # reserved + ctexf.store_32(0x02) # data format (WEBP, it's DataFormat enum but not available in gdscript) + ctexf.store_16(image.get_width()) # w + ctexf.store_16(image.get_height()) # h + ctexf.store_32(0x00) # mipmaps + ctexf.store_32(Image.FORMAT_RGBA8) # format + ctexf.store_32(webplen) # webp length + ctexf.store_buffer(webpdata) + ctexf = null # setting null will close the file + + print("ctex saved") return OK From 930a2cb44272a0bf5616a626944d0c30cb0e1801 Mon Sep 17 00:00:00 2001 From: Kebrerross Date: Sat, 7 Jan 2023 20:12:07 +0100 Subject: [PATCH 2/6] [refs #8] Add the Sprite and AnimationPlayer import --- README.md | 4 +- .../animation_player_import.gd | 188 ++++++++++++++++++ addons/godot_pixelorama_importer/plugin.gd | 35 +++- 3 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 addons/godot_pixelorama_importer/animation_player_import.gd diff --git a/README.md b/README.md index 58341f7..19aae41 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,14 @@ Imports `.pxo` files from [Pixelorama](https://orama-interactive.itch.io/pixelor ## Status -The plugin provides two import types: +The plugin provides three import types: **Single Image**: All Cels are overlaid into one image per frame as a `1xN` StreamTexture PNG with the 2D Pixel Texture preset. **SpriteFrames**: Animation tags are used to create a SpriteFrames resource from the pxo file, which can be used with AnimatedSprite. However, due to a resource reload bug in Godot, any changes to the pxo file are not visible in the editor but by either launching the game or restarting the editor, the edited textures are visible. +**Sprite & AnimationPlayer**: Animation tags are used to create a Sprite and AnimationPlayer scene from the pxo file. + There is also an Inspector plugin which lets you open Pixelorama from within the Godot editor. When you have a .pxo file open in the Inspector, click on "Open in Pixelorama" to launch Pixelorama. It requires a one-time configuration of the location of the Pixelorama binary. Linux/BSD and Windows are supported as of now ## Usage diff --git a/addons/godot_pixelorama_importer/animation_player_import.gd b/addons/godot_pixelorama_importer/animation_player_import.gd new file mode 100644 index 0000000..2a0684b --- /dev/null +++ b/addons/godot_pixelorama_importer/animation_player_import.gd @@ -0,0 +1,188 @@ +tool +extends EditorImportPlugin + +var editor: EditorInterface + + +func _init(editor_interface): + editor = editor_interface + + +func get_importer_name(): + return "com.technohacker.pixelorama.animationplayer" + + +func get_visible_name(): + return "Sprite & AnimationPlayer" + + +func get_recognized_extensions(): + return ["pxo"] + + +# We save directly to stex because ImageTexture doesn't work for some reason +func get_save_extension(): + return "tscn" + + +func get_resource_type(): + return "PackedScene" + + +func get_import_options(_preset): + var default_scale: Vector2 = ProjectSettings.get_setting("pixelorama/default_scale") + var default_external_save: bool = ProjectSettings.get_setting( + "pixelorama/default_external_save" + ) + var default_external_save_path: String = ProjectSettings.get_setting( + "pixelorama/default_external_save_path" + ) + + return [ + {"name": "Sprite2D", "default_value": false, "usage": PROPERTY_USAGE_GROUP}, + {"name": "scale", "default_value": default_scale}, + {"name": "Animation", "default_value": false, "usage": PROPERTY_USAGE_GROUP}, + # 65536 = PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, but not exported in GDscript. + { + "name": "external_save", + "default_value": default_external_save, + "usage": PROPERTY_USAGE_DEFAULT | 65536 + }, + { + "name": "external_save_path", + "default_value": default_external_save_path, + "property_hint": PROPERTY_HINT_DIR + }, + ] + + +func get_option_visibility(option, options): + if option == "external_save_path" and options.has("external_save"): + return options["external_save"] + return true + + +func get_preset_count(): + return 0 + + +func import(source_file, save_path, options, _r_platform_variants, gen_files): + """ + Main import function. Reads the Pixelorama project and creates the animation player resource + """ + + var spritesheet_path = "%s.spritesheet" % [save_path] + + # Open the project + var load_res = preload("./util/read_pxo_file.gd").read_pxo_file(source_file, spritesheet_path) + + if load_res.error != OK: + printerr("Project Load Error") + return load_res.error + + var project = load_res.value + + var base_animation_path: String = options.external_save_path + if base_animation_path == "" and options.external_save: + base_animation_path = source_file.get_base_dir() + source_file.get_file().get_basename() + var directory = Directory.new() + if not directory.dir_exists(base_animation_path): + var tmp = directory.make_dir(base_animation_path) + base_animation_path = base_animation_path + "/" + + # Note the spritesheet + spritesheet_path = "%s.stex" % spritesheet_path + gen_files.push_back(spritesheet_path) + + # Load the spritesheet as a .stex + var spritesheet_tex = StreamTexture.new() + spritesheet_tex.load(spritesheet_path) + + # create the Sprite + var sprite := Sprite.new() + sprite.texture = spritesheet_tex + sprite.name = source_file.get_file().get_basename() + sprite.apply_scale(options.scale) + sprite.hframes = project.frames.size() + + # create the AnimationPlayer + var animation_player := AnimationPlayer.new() + sprite.add_child(animation_player) + animation_player.name = "AnimationPlayer" + animation_player.owner = sprite # for PackedScene + + # add some default animations + if project.tags.size() == 0: + # No tags, put all in default + project.tags.append({"name": "default", "from": 1, "to": project.frames.size()}) + # puts a RESET track + project.tags.append({"name": "RESET", "from": 1, "to": 1}) + + var err: int # Error enum + # import all animations + for tag in project.tags: + var animation: Animation + var animation_path: String + if options.external_save: + # in case the animation is already save, try to load it + animation_path = "%s/%s.tres" % [base_animation_path, tag.name] + var file = File.new() + if file.file_exists(animation_path): + animation = load(animation_path) + else: + animation = Animation.new() + animation.resource_path = animation_path + else: + animation = Animation.new() + animation_player.add_animation(tag.name, animation) + + var track_index := animation.find_track(".:frame") + if track_index != -1: + # track exist, remove it to add a fresh one + animation.remove_track(track_index) + + # add the track for the frame + track_index = animation.add_track(Animation.TYPE_VALUE) + animation.track_set_path(track_index, ".:frame") + animation.track_set_interpolation_loop_wrap(track_index, false) + + # insert the new animation keys + var time := 0.0 + for frame in range(tag.from - 1, tag.to): + animation.track_insert_key(track_index, time, frame) + time += 1.0 / (project.fps / project.frames[frame].duration) + + # loop handling + if ( + tag.name.begins_with("loop") + or tag.name.begins_with("cycle") + or tag.name.ends_with("loop") + or tag.name.ends_with("cycle") + ): + animation.loop = true + + # update/set the length + animation.length = time + + if options.external_save: + err = ResourceSaver.save(animation_path, animation) + if err != OK: + printerr("Error saving Animation %s: error %s" % [tag.name, err]) + return err + gen_files.push_back(animation_path) + + var scene = PackedScene.new() + err = scene.pack(sprite) + if err != OK: + printerr("Error creating PackedScene") + return err + + var packed_scene_path = "%s.%s" % [save_path, get_save_extension()] + err = ResourceSaver.save(packed_scene_path, scene) + if err != OK: + printerr("Error saving PackedScene") + return err + gen_files.push_back(packed_scene_path) + + editor.get_inspector().refresh() + return OK diff --git a/addons/godot_pixelorama_importer/plugin.gd b/addons/godot_pixelorama_importer/plugin.gd index ed48df5..ab20f49 100644 --- a/addons/godot_pixelorama_importer/plugin.gd +++ b/addons/godot_pixelorama_importer/plugin.gd @@ -68,9 +68,42 @@ func _enter_tree() -> void: editor_settings.add_property_info(property_info) + var property_infos = [ + { + "default": Vector2.ONE, + "property_info": + { + "name": "pixelorama/default_scale", + "type": TYPE_VECTOR2, + } + }, + { + "default": false, + "property_info": + { + "name": "pixelorama/default_external_save", + "type": TYPE_BOOL, + } + }, + { + "default": "", + "property_info": + { + "name": "pixelorama/default_external_save_path", + "type": TYPE_STRING, + "hint": PROPERTY_HINT_DIR + } + } + ] + for pi in property_infos: + if !ProjectSettings.has_setting(pi.property_info.name): + ProjectSettings.set_setting(pi.property_info.name, pi.default) + ProjectSettings.add_property_info(pi.property_info) + import_plugins = [ preload("single_image_import.gd").new(), - preload("spriteframes_import.gd").new(get_editor_interface()) + preload("spriteframes_import.gd").new(get_editor_interface()), + preload("animation_player_import.gd").new(get_editor_interface()) ] for plugin in import_plugins: add_import_plugin(plugin) From daa61ed073b4127dda4b40414dda7a4b8875fcdc Mon Sep 17 00:00:00 2001 From: Kebrerross Date: Sun, 8 Jan 2023 17:55:04 +0100 Subject: [PATCH 3/6] Add a parameter to define the default import type and use the pfs in the pxo file instead of a parameter --- .../animation_player_import.gd | 15 ++++++++-- addons/godot_pixelorama_importer/plugin.gd | 30 ++++++++++++++----- .../single_image_import.gd | 11 ++++++- .../spriteframes_import.gd | 17 ++++++++--- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/addons/godot_pixelorama_importer/animation_player_import.gd b/addons/godot_pixelorama_importer/animation_player_import.gd index 2a0684b..867ea56 100644 --- a/addons/godot_pixelorama_importer/animation_player_import.gd +++ b/addons/godot_pixelorama_importer/animation_player_import.gd @@ -1,6 +1,8 @@ tool extends EditorImportPlugin +const VISIBLE_NAME := "Sprite & AnimationPlayer" + var editor: EditorInterface @@ -13,7 +15,7 @@ func get_importer_name(): func get_visible_name(): - return "Sprite & AnimationPlayer" + return VISIBLE_NAME func get_recognized_extensions(): @@ -32,10 +34,10 @@ func get_resource_type(): func get_import_options(_preset): var default_scale: Vector2 = ProjectSettings.get_setting("pixelorama/default_scale") var default_external_save: bool = ProjectSettings.get_setting( - "pixelorama/default_external_save" + "pixelorama/default_animation_external_save" ) var default_external_save_path: String = ProjectSettings.get_setting( - "pixelorama/default_external_save_path" + "pixelorama/default_animation_external_save_path" ) return [ @@ -66,6 +68,13 @@ func get_preset_count(): return 0 +func get_priority() -> float: + var default_import_type: String = ProjectSettings.get_setting("pixelorama/default_import_type") + if default_import_type == get_visible_name(): + return 2.0 + return 1.0 + + func import(source_file, save_path, options, _r_platform_variants, gen_files): """ Main import function. Reads the Pixelorama project and creates the animation player resource diff --git a/addons/godot_pixelorama_importer/plugin.gd b/addons/godot_pixelorama_importer/plugin.gd index ab20f49..ec55438 100644 --- a/addons/godot_pixelorama_importer/plugin.gd +++ b/addons/godot_pixelorama_importer/plugin.gd @@ -68,7 +68,27 @@ func _enter_tree() -> void: editor_settings.add_property_info(property_info) + import_plugins = [ + preload("single_image_import.gd").new(), + preload("spriteframes_import.gd").new(get_editor_interface()), + preload("animation_player_import.gd").new(get_editor_interface()) + ] + + var hint_string := [] + for plugin in import_plugins: + hint_string.append(plugin.VISIBLE_NAME) + var property_infos = [ + { + "default": "Single Image", + "property_info": + { + "name": "pixelorama/default_import_type", + "type": TYPE_STRING, + "hint": PROPERTY_HINT_ENUM, + "hint_string": ",".join(hint_string) # "Single Image,SpriteFrames,Sprite & AnimationPlayer" + } + }, { "default": Vector2.ONE, "property_info": @@ -81,7 +101,7 @@ func _enter_tree() -> void: "default": false, "property_info": { - "name": "pixelorama/default_external_save", + "name": "pixelorama/default_animation_external_save", "type": TYPE_BOOL, } }, @@ -89,22 +109,18 @@ func _enter_tree() -> void: "default": "", "property_info": { - "name": "pixelorama/default_external_save_path", + "name": "pixelorama/default_animation_external_save_path", "type": TYPE_STRING, "hint": PROPERTY_HINT_DIR } } ] + for pi in property_infos: if !ProjectSettings.has_setting(pi.property_info.name): ProjectSettings.set_setting(pi.property_info.name, pi.default) ProjectSettings.add_property_info(pi.property_info) - import_plugins = [ - preload("single_image_import.gd").new(), - preload("spriteframes_import.gd").new(get_editor_interface()), - preload("animation_player_import.gd").new(get_editor_interface()) - ] for plugin in import_plugins: add_import_plugin(plugin) diff --git a/addons/godot_pixelorama_importer/single_image_import.gd b/addons/godot_pixelorama_importer/single_image_import.gd index cb44341..f103cfd 100644 --- a/addons/godot_pixelorama_importer/single_image_import.gd +++ b/addons/godot_pixelorama_importer/single_image_import.gd @@ -1,13 +1,15 @@ tool extends EditorImportPlugin +const VISIBLE_NAME := "Single Image" + func get_importer_name(): return "com.technohacker.pixelorama" func get_visible_name(): - return "Single Image" + return VISIBLE_NAME func get_recognized_extensions(): @@ -35,6 +37,13 @@ func get_preset_count(): return 0 +func get_priority() -> float: + var default_import_type: String = ProjectSettings.get_setting("pixelorama/default_import_type") + if default_import_type == get_visible_name(): + return 2.0 + return 1.0 + + func import(source_file, save_path, _options, _r_platform_variants, _r_gen_files): """ Main import function. Reads the Pixelorama project and extracts the PNG image from it diff --git a/addons/godot_pixelorama_importer/spriteframes_import.gd b/addons/godot_pixelorama_importer/spriteframes_import.gd index 50b2cbe..45502f6 100644 --- a/addons/godot_pixelorama_importer/spriteframes_import.gd +++ b/addons/godot_pixelorama_importer/spriteframes_import.gd @@ -1,6 +1,8 @@ tool extends EditorImportPlugin +const VISIBLE_NAME := "SpriteFrames" + var editor: EditorInterface @@ -13,7 +15,7 @@ func get_importer_name(): func get_visible_name(): - return "SpriteFrames" + return VISIBLE_NAME func get_recognized_extensions(): @@ -30,7 +32,7 @@ func get_resource_type(): func get_import_options(_preset): - return [{"name": "animation_fps", "default_value": 6}] + return [] func get_option_visibility(_option, _options): @@ -41,7 +43,14 @@ func get_preset_count(): return 0 -func import(source_file, save_path, options, _r_platform_variants, r_gen_files): +func get_priority() -> float: + var default_import_type: String = ProjectSettings.get_setting("pixelorama/default_import_type") + if default_import_type == get_visible_name(): + return 2.0 + return 1.0 + + +func import(source_file, save_path, _options, _r_platform_variants, r_gen_files): """ Main import function. Reads the Pixelorama project and creates the SpriteFrames resource """ @@ -78,7 +87,7 @@ func import(source_file, save_path, options, _r_platform_variants, r_gen_files): for tag in project.tags: frames.add_animation(tag.name) - frames.set_animation_speed(tag.name, options.animation_fps) + frames.set_animation_speed(tag.name, project.fps) for frame in range(tag.from, tag.to + 1): var image_rect := Rect2(Vector2((frame - 1) * frame_size.x, 0), frame_size) From 31a9edd95550797421327c035d17ff64a74136ad Mon Sep 17 00:00:00 2001 From: Kebrerross Date: Wed, 11 Jan 2023 19:58:18 +0100 Subject: [PATCH 4/6] Remove useless comment and change 65536 to 1 << 16 --- addons/godot_pixelorama_importer/animation_player_import.gd | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/godot_pixelorama_importer/animation_player_import.gd b/addons/godot_pixelorama_importer/animation_player_import.gd index 867ea56..8a52646 100644 --- a/addons/godot_pixelorama_importer/animation_player_import.gd +++ b/addons/godot_pixelorama_importer/animation_player_import.gd @@ -22,7 +22,6 @@ func get_recognized_extensions(): return ["pxo"] -# We save directly to stex because ImageTexture doesn't work for some reason func get_save_extension(): return "tscn" @@ -44,11 +43,11 @@ func get_import_options(_preset): {"name": "Sprite2D", "default_value": false, "usage": PROPERTY_USAGE_GROUP}, {"name": "scale", "default_value": default_scale}, {"name": "Animation", "default_value": false, "usage": PROPERTY_USAGE_GROUP}, - # 65536 = PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, but not exported in GDscript. + # (1 << 16) = PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, but not exported in GDscript. { "name": "external_save", "default_value": default_external_save, - "usage": PROPERTY_USAGE_DEFAULT | 65536 + "usage": PROPERTY_USAGE_DEFAULT | (1 << 16) }, { "name": "external_save_path", From e1710ab5bdbd7eb98a054c54248a3167149eb1cd Mon Sep 17 00:00:00 2001 From: Kebrerross Date: Sat, 4 Mar 2023 21:10:57 +0100 Subject: [PATCH 5/6] Fix signature (int -> Error), reuse the gdtoolkit from pypi, and apply gdformat/gdlint --- .github/workflows/static-checks.yml | 4 ++-- .../animation_player_import.gd | 21 +++++++++++++------ .../single_image_import.gd | 2 +- .../spriteframes_import.gd | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 5e8486c..ef49961 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -5,11 +5,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: pip3 install git+https://github.com/Scony/godot-gdscript-toolkit.git + - run: pip3 install gdtoolkit - run: gdformat --diff . lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: pip3 install git+https://github.com/Scony/godot-gdscript-toolkit.git + - run: pip3 install gdtoolkit - run: gdlint . diff --git a/addons/godot_pixelorama_importer/animation_player_import.gd b/addons/godot_pixelorama_importer/animation_player_import.gd index cec2ea4..845e98a 100644 --- a/addons/godot_pixelorama_importer/animation_player_import.gd +++ b/addons/godot_pixelorama_importer/animation_player_import.gd @@ -34,7 +34,7 @@ func _get_import_order() -> int: return 1 -func _get_import_options(path: String, preset_index: int) -> Array: #TODO path +func _get_import_options(path: String, _preset_index: int) -> Array: var default_scale: Vector2 = ProjectSettings.get_setting("pixelorama/default_scale") var default_external_save: bool = ProjectSettings.get_setting( "pixelorama/default_animation_external_save" @@ -53,7 +53,7 @@ func _get_import_options(path: String, preset_index: int) -> Array: #TODO path { "name": "external_save", "default_value": default_external_save, - "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED + "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED }, { "name": "external_save_path", @@ -63,7 +63,7 @@ func _get_import_options(path: String, preset_index: int) -> Array: #TODO path ] -func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool: +func _get_option_visibility(_path: String, option_name: StringName, options: Dictionary) -> bool: if option_name == "external_save_path" and options.has("external_save"): return options["external_save"] return true @@ -80,7 +80,13 @@ func _get_priority() -> float: return 1.0 -func _import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array, gen_files: Array) -> int: +func _import( + source_file: String, + save_path: String, + options: Dictionary, + _platform_variants: Array[String], + gen_files: Array[String] +) -> Error: """ Main import function. Reads the Pixelorama project and creates the animation player resource """ @@ -131,7 +137,10 @@ func _import(source_file: String, save_path: String, options: Dictionary, platfo var base_dir = options.external_save_path if base_dir == "": base_dir = source_file.get_file().get_base_dir() - animation_library_path = "%s%s-animations.tres" % [options.external_save_path, source_file.get_file().get_basename()] + animation_library_path = ( + "%s%s-animations.tres" + % [options.external_save_path, source_file.get_file().get_basename()] + ) if FileAccess.file_exists(animation_library_path): # in case the AnimationLibrary is already save, try to load it animation_library = load(animation_library_path) @@ -141,7 +150,7 @@ func _import(source_file: String, save_path: String, options: Dictionary, platfo else: animation_library = AnimationLibrary.new() animation_player.add_animation_library("", animation_library) - + # import all animations for tag in project.tags: var animation: Animation diff --git a/addons/godot_pixelorama_importer/single_image_import.gd b/addons/godot_pixelorama_importer/single_image_import.gd index e179c48..f24b6e6 100644 --- a/addons/godot_pixelorama_importer/single_image_import.gd +++ b/addons/godot_pixelorama_importer/single_image_import.gd @@ -54,7 +54,7 @@ func _import( _options: Dictionary, _platform_variants: Array[String], _gen_files: Array[String] -) -> int: +) -> Error: """ Main import function. Reads the Pixelorama project and extracts the PNG image from it """ diff --git a/addons/godot_pixelorama_importer/spriteframes_import.gd b/addons/godot_pixelorama_importer/spriteframes_import.gd index 650c2ea..ba2a6b0 100644 --- a/addons/godot_pixelorama_importer/spriteframes_import.gd +++ b/addons/godot_pixelorama_importer/spriteframes_import.gd @@ -57,10 +57,10 @@ func _get_priority() -> float: func _import( source_file: String, save_path: String, - options: Dictionary, + _options: Dictionary, _platform_variants: Array[String], gen_files: Array[String] -) -> int: +) -> Error: """ Main import function. Reads the Pixelorama project and creates the SpriteFrames resource """ From 63013bb3480a708d7e7464c8caf6d8a5e75264b6 Mon Sep 17 00:00:00 2001 From: Kevin Kuriakose Date: Sun, 5 Mar 2023 08:56:34 +0530 Subject: [PATCH 6/6] Formatting --- addons/godot_pixelorama_importer/util/read_pxo_file.gd | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/addons/godot_pixelorama_importer/util/read_pxo_file.gd b/addons/godot_pixelorama_importer/util/read_pxo_file.gd index 52e15c4..9525074 100644 --- a/addons/godot_pixelorama_importer/util/read_pxo_file.gd +++ b/addons/godot_pixelorama_importer/util/read_pxo_file.gd @@ -49,11 +49,8 @@ static func read_pxo_file(source_file: String, image_save_path: String): if project.layers[layer].visible and opacity > 0.0: # Load the cel image - var cel_img = ( - Image - . create_from_data( - size.x, size.y, false, Image.FORMAT_RGBA8, file.get_buffer(cel_data_size) - ) + var cel_img = Image.create_from_data( + size.x, size.y, false, Image.FORMAT_RGBA8, file.get_buffer(cel_data_size) ) if opacity < 1.0: