init commit
This commit is contained in:
149
addons/nklbdev.importality/export/piskel.gd
Normal file
149
addons/nklbdev.importality/export/piskel.gd
Normal file
@@ -0,0 +1,149 @@
|
||||
@tool
|
||||
extends "_.gd"
|
||||
|
||||
const __ANIMATIONS_PARAMETERS_OPTION: StringName = "piskel/animations_parameters"
|
||||
|
||||
func _init(editor_file_system: EditorFileSystem) -> void:
|
||||
var recognized_extensions: PackedStringArray = ["piskel"]
|
||||
super("Piskel", recognized_extensions, [
|
||||
_Options.create_option(__ANIMATIONS_PARAMETERS_OPTION, PackedStringArray(),
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT)],
|
||||
[],
|
||||
CustomImageFormatLoaderExtension.new(recognized_extensions))
|
||||
|
||||
func _export(res_source_file_path: String, options: Dictionary) -> ExportResult:
|
||||
var result: ExportResult = ExportResult.new()
|
||||
|
||||
var raw_animations_params_list: PackedStringArray = options[__ANIMATIONS_PARAMETERS_OPTION]
|
||||
var animations_params_parsing_results: Array[AnimationParamsParsingResult]
|
||||
animations_params_parsing_results.resize(raw_animations_params_list.size())
|
||||
var unique_animations_names: PackedStringArray
|
||||
var frame_indices_to_export
|
||||
var unique_frames_count: int = 0
|
||||
var animation_first_frame_index: int = 0
|
||||
for animation_index in raw_animations_params_list.size():
|
||||
var raw_animation_params: String = raw_animations_params_list[animation_index]
|
||||
var animation_params_parsing_result: AnimationParamsParsingResult = _parse_animation_params(
|
||||
raw_animation_params,
|
||||
AnimationOptions.FramesCount | AnimationOptions.Direction | AnimationOptions.RepeatCount,
|
||||
animation_first_frame_index)
|
||||
if animation_params_parsing_result.error:
|
||||
result.fail(ERR_CANT_RESOLVE, "Failed to parse animation parameters", animation_params_parsing_result)
|
||||
return result
|
||||
if unique_animations_names.has(animation_params_parsing_result.name):
|
||||
result.fail(ERR_INVALID_DATA, "Duplicated animation name \"%s\" at index: %s" %
|
||||
[animation_params_parsing_result.name, animation_index])
|
||||
return result
|
||||
unique_animations_names.push_back(animation_params_parsing_result.name)
|
||||
unique_frames_count += animation_params_parsing_result.frames_count
|
||||
animation_first_frame_index += animation_params_parsing_result.frames_count
|
||||
animations_params_parsing_results[animation_index] = animation_params_parsing_result
|
||||
|
||||
var document: Dictionary = JSON.parse_string(FileAccess.get_file_as_string(res_source_file_path))
|
||||
document.modelVersion #int 2
|
||||
var piskel: Dictionary = document.piskel
|
||||
piskel.name #string New Piskel
|
||||
piskel.description #string asdfasdfasdf
|
||||
piskel.fps #int 12,
|
||||
var image_size: Vector2i = Vector2i(piskel.width, piskel.height)
|
||||
# piskel.hiddenFrames#Array may absend
|
||||
var blended_layers: Image
|
||||
var layer_image: Image = Image.new()
|
||||
var frames_count: int
|
||||
var layer_image_size: Vector2i = image_size
|
||||
for layer_string in piskel.layers: #Array
|
||||
var layer: Dictionary = JSON.parse_string(layer_string)
|
||||
layer.name #string layer 1
|
||||
layer.opacity #float 1
|
||||
if frames_count == 0:
|
||||
frames_count = layer.frameCount
|
||||
layer_image_size.x = image_size.x * frames_count
|
||||
else:
|
||||
assert(frames_count == layer.frameCount)
|
||||
for chunk in layer.chunks:
|
||||
# chunk.layout # array [ [ 0 ], [ 1 ], [ 2 ] ]
|
||||
layer_image.load_png_from_buffer(Marshalls.base64_to_raw(chunk.base64PNG.trim_prefix("data:image/png;base64,")))
|
||||
assert(layer_image.get_size() == layer_image_size)
|
||||
if blended_layers == null:
|
||||
blended_layers = layer_image
|
||||
layer_image = Image.new()
|
||||
else:
|
||||
blended_layers.blend_rect(layer_image, Rect2i(Vector2i.ZERO, layer_image.get_size()), Vector2i.ZERO)
|
||||
|
||||
var frames_images: Array[Image]
|
||||
frames_images.resize(frames_count)
|
||||
for frame_index in frames_count:
|
||||
frames_images[frame_index] = blended_layers.get_region(
|
||||
Rect2i(Vector2i(frame_index * image_size.x, 0), image_size))
|
||||
|
||||
var sprite_sheet_builder: _SpriteSheetBuilderBase = _create_sprite_sheet_builder(options)
|
||||
|
||||
var sprite_sheet_building_result: _SpriteSheetBuilderBase.SpriteSheetBuildingResult = \
|
||||
sprite_sheet_builder.build_sprite_sheet(frames_images)
|
||||
if sprite_sheet_building_result.error:
|
||||
result.fail(ERR_BUG, "Sprite sheet building failed", sprite_sheet_building_result)
|
||||
return result
|
||||
var sprite_sheet: _Common.SpriteSheetInfo = sprite_sheet_building_result.sprite_sheet
|
||||
|
||||
var animation_library: _Common.AnimationLibraryInfo = _Common.AnimationLibraryInfo.new()
|
||||
var autoplay_animation_name: String = options[_Options.AUTOPLAY_ANIMATION_NAME].strip_edges()
|
||||
|
||||
var frames_duration: float = 1.0 / piskel.fps
|
||||
var all_frames: Array[_Common.FrameInfo]
|
||||
all_frames.resize(unique_frames_count)
|
||||
for animation_index in animations_params_parsing_results.size():
|
||||
var animation_params_parsing_result: AnimationParamsParsingResult = animations_params_parsing_results[animation_index]
|
||||
var animation = _Common.AnimationInfo.new()
|
||||
animation.name = animation_params_parsing_result.name
|
||||
if animation.name == autoplay_animation_name:
|
||||
animation_library.autoplay_index = animation_index
|
||||
animation.direction = animation_params_parsing_result.direction
|
||||
if animation.direction < 0:
|
||||
animation.direction = _Common.AnimationDirection.FORWARD
|
||||
animation.repeat_count = animation_params_parsing_result.repeat_count
|
||||
if animation.repeat_count < 0:
|
||||
animation.repeat_count = 1
|
||||
for animation_frame_index in animation_params_parsing_result.frames_count:
|
||||
var global_frame_index: int = animation_params_parsing_result.first_frame_index + animation_frame_index
|
||||
var frame: _Common.FrameInfo = all_frames[global_frame_index]
|
||||
if frame == null:
|
||||
frame = _Common.FrameInfo.new()
|
||||
frame.sprite = sprite_sheet.sprites[global_frame_index]
|
||||
frame.duration = frames_duration
|
||||
all_frames[global_frame_index] = frame
|
||||
animation.frames.push_back(frame)
|
||||
animation_library.animations.push_back(animation)
|
||||
if not autoplay_animation_name.is_empty() and animation_library.autoplay_index < 0:
|
||||
push_warning("Autoplay animation name not found: \"%s\". Continuing..." % [autoplay_animation_name])
|
||||
|
||||
result.success(sprite_sheet_building_result.atlas_image, sprite_sheet, animation_library)
|
||||
return result
|
||||
|
||||
class CustomImageFormatLoaderExtension:
|
||||
extends ImageFormatLoaderExtension
|
||||
|
||||
var __recognized_extensions: PackedStringArray
|
||||
|
||||
func _init(recognized_extensions: PackedStringArray) -> void:
|
||||
__recognized_extensions = recognized_extensions
|
||||
|
||||
func _get_recognized_extensions() -> PackedStringArray:
|
||||
return __recognized_extensions
|
||||
|
||||
func _load_image(image: Image, file_access: FileAccess, flags: int, scale: float) -> Error:
|
||||
|
||||
var document: Dictionary = JSON.parse_string(file_access.get_as_text())
|
||||
var piskel: Dictionary = document.piskel
|
||||
var image_size: Vector2i = Vector2i(piskel.width, piskel.height)
|
||||
var image_rect: Rect2i = Rect2i(Vector2i.ZERO, image_size)
|
||||
image.set_data(1, 1, false, Image.FORMAT_RGBA8, [0, 0, 0, 0])
|
||||
image.resize(image_size.x, image_size.y)
|
||||
var layer_image: Image = Image.new()
|
||||
for layer_string in piskel.layers: #Array
|
||||
var layer: Dictionary = JSON.parse_string(layer_string)
|
||||
layer.opacity #float 1
|
||||
for chunk in layer.chunks:
|
||||
# chunk.layout # array [ [ 0 ], [ 1 ], [ 2 ] ]
|
||||
layer_image.load_png_from_buffer(Marshalls.base64_to_raw(chunk.base64PNG.trim_prefix("data:image/png;base64,")))
|
||||
image.blend_rect(layer_image, image_rect, Vector2i.ZERO)
|
||||
return OK
|
||||
Reference in New Issue
Block a user