crabs-game/addons/aseprite_importer/classes/AsepriteImporter.gd

154 lines
4.4 KiB
GDScript

tool
extends Node
class_name AsepriteImporter
enum Error{
OK,
INVALID_JSON_DATA,
MISSING_JSON_DATA,
MISSING_ANIMATION_PLAYER,
MISSING_SPRITE,
NO_TAGS_SELECTED,
DUPLICATE_TAG_NAME,
MISSING_TEXTURE,
}
static func generate_animations(import_data : AsepriteImportData, selected_tags : Array,
animation_player : AnimationPlayer, sprite : Node, texture : Texture) -> int:
if not(import_data and import_data.json_data):
return Error.MISSING_JSON_DATA
var frame_tags : Array = import_data.get_tags()
if not selected_tags:
return Error.NO_TAGS_SELECTED
else:
var tag_names := []
for tag_idx in selected_tags:
var tag_name : String = frame_tags[tag_idx].name
if tag_names.has(tag_name):
return Error.DUPLICATE_TAG_NAME
else:
tag_names.append(tag_name)
if not animation_player:
return Error.MISSING_ANIMATION_PLAYER
if not(sprite is Sprite or sprite is Sprite3D):
return Error.MISSING_SPRITE
if texture == null:
return Error.MISSING_TEXTURE
var animation_root_path := animation_player.root_node
var animation_root_node := animation_player.get_node(animation_root_path)
var sprite_relative_path := str(animation_root_node.get_path_to(sprite))
# These are tracks that will be used
var tracks := {
"region" : {
path = (sprite_relative_path + ":region_rect"),
},
"offset" : {
path = (sprite_relative_path + ":offset")
}
}
var frames := import_data.get_frame_array()
var is_sprite3d := sprite is Sprite3D
# Iterate over each tag (animation)
for tag_idx in selected_tags:
var tag : Dictionary = frame_tags[tag_idx]
var animation : Animation
# Check if the animation already exists
if animation_player.has_animation(tag.name):
animation = animation_player.get_animation(tag.name)
else:
# If it doesn't, adds a new one
animation = Animation.new()
# warning-ignore:return_value_discarded
animation_player.add_animation(tag.name, animation)
# Setup the animation tracks
for track_name in tracks:
var track : Dictionary = tracks[track_name]
track.idx = animation.find_track(track.path)
# Checks if the track doesn't exist
if track.idx == -1:
# Create a new_track
track.idx = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track.idx, track.path)
else:
# Remove all existing keys from the track
for key_idx in range(animation.track_get_key_count(track.idx)):
animation.track_remove_key(track.idx, 0)
# Set the track Interpolation Mode to Nearest
animation.track_set_interpolation_type(track.idx, Animation.INTERPOLATION_NEAREST)
#Enable the track
animation.track_set_enabled(track.idx, true)
var time := 0.0
var frame_idxs := range(tag.from, tag.to + 1)
# Modify the frame order based on the tag's direction
match tag.direction:
"reverse":
frame_idxs.invert()
"pingpong":
var pong_frame_idxs := range(tag.from + 1, tag.to)
pong_frame_idxs.invert()
frame_idxs += pong_frame_idxs
# Insert the new keys
for i in frame_idxs:
var frame : Dictionary = frames[i]
# Get the region of the spritesheet that has the frame
var rect = frame.frame
var region = Rect2(rect.x, rect.y, rect.w, rect.h)
# Insert the new key for the region track
animation.track_insert_key(tracks.region.idx, time, region)
# Get the center of the frame in the original size
var source_size : Dictionary = frame.sourceSize
var source_center_x : float = source_size.w / 2
var source_center_y : float = source_size.h / 2
# Get the center of the trimmed frame in the spritesheet
var trim_rect : Dictionary = frame.spriteSourceSize
var trim_rect_center_x : float = trim_rect.x + (trim_rect.w / 2)
var trim_rect_center_y : float = trim_rect.y + (trim_rect.h / 2)
# Calculate the offset between the trimmed frame center and original frame center
var offset_x := trim_rect_center_x - source_center_x
var offset_y := trim_rect_center_y - source_center_y
# Invert the vertical offset when the selected sprite is a Sprite3D
if is_sprite3d:
offset_y *= -1
# Insert the new key for the offset track
animation.track_insert_key(tracks.offset.idx, time, Vector2(offset_x, offset_y))
# Add up the current frame's duration for the next key position
time += frame.duration / 1000
# Set the animation length equal to the sum of all frame's durations
animation.length = time
sprite.texture = texture
sprite.region_enabled = true
sprite.centered = true
return OK