init commit
This commit is contained in:
70
addons/nklbdev.importality/import/_.gd
Normal file
70
addons/nklbdev.importality/import/_.gd
Normal file
@@ -0,0 +1,70 @@
|
||||
@tool
|
||||
extends RefCounted
|
||||
|
||||
const _Result = preload("../result.gd").Class
|
||||
const _Common = preload("../common.gd")
|
||||
const _Options = preload("../options.gd")
|
||||
|
||||
class ImportResult:
|
||||
extends _Result
|
||||
var resource: Resource
|
||||
var resource_saver_flags: ResourceSaver.SaverFlags
|
||||
func _get_result_type_description() -> String:
|
||||
return "Import"
|
||||
func success(
|
||||
resource: Resource,
|
||||
resource_saver_flags: ResourceSaver.SaverFlags = ResourceSaver.FLAG_NONE
|
||||
) -> void:
|
||||
_success()
|
||||
self.resource = resource
|
||||
self.resource_saver_flags = resource_saver_flags
|
||||
|
||||
var __options: Array[Dictionary] = [
|
||||
_Options.create_option(_Options.DEFAULT_ANIMATION_NAME, "default",
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(_Options.DEFAULT_ANIMATION_DIRECTION, _Common.AnimationDirection.FORWARD,
|
||||
PROPERTY_HINT_ENUM, ",".join(_Common.ANIMATION_DIRECTIONS_NAMES), PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(_Options.DEFAULT_ANIMATION_REPEAT_COUNT, 0,
|
||||
PROPERTY_HINT_RANGE, "0,,1,or_greater", PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(_Options.AUTOPLAY_ANIMATION_NAME, "",
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(_Options.ATLAS_TEXTURES_REGION_FILTER_CLIP_ENABLED, false,
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
]
|
||||
var __name: String
|
||||
var __resource_type: StringName
|
||||
var __save_extension: String
|
||||
|
||||
func _init(
|
||||
name: String,
|
||||
resource_type: String,
|
||||
save_extension: String,
|
||||
options: Array[Dictionary] = []) -> void:
|
||||
__name = name
|
||||
__resource_type = resource_type
|
||||
__save_extension = save_extension
|
||||
__options.append_array(options)
|
||||
|
||||
func get_name() -> String:
|
||||
return __name
|
||||
|
||||
func get_resource_type() -> StringName:
|
||||
return __resource_type
|
||||
|
||||
func get_save_extension() -> String:
|
||||
return __save_extension
|
||||
|
||||
func get_options() -> Array[Dictionary]:
|
||||
return __options
|
||||
|
||||
func import(
|
||||
source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String) -> ImportResult:
|
||||
assert(false, "This method is abstract and must be overriden.")
|
||||
var result: ImportResult = ImportResult.new()
|
||||
result.fail(ERR_UNCONFIGURED, "This method is abstract and must be overriden.")
|
||||
return result
|
||||
1
addons/nklbdev.importality/import/_.gd.uid
Normal file
1
addons/nklbdev.importality/import/_.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cnw6e1ikxkc4j
|
||||
14
addons/nklbdev.importality/import/_node.gd
Normal file
14
addons/nklbdev.importality/import/_node.gd
Normal file
@@ -0,0 +1,14 @@
|
||||
@tool
|
||||
extends "_.gd"
|
||||
|
||||
func _init(
|
||||
name: String,
|
||||
resource_type: String,
|
||||
save_extension: String,
|
||||
options: Array[Dictionary] = []
|
||||
) -> void:
|
||||
options.append_array([
|
||||
_Options.create_option(_Options.ROOT_NODE_NAME, "",
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
])
|
||||
super(name, resource_type, save_extension, options)
|
||||
1
addons/nklbdev.importality/import/_node.gd.uid
Normal file
1
addons/nklbdev.importality/import/_node.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bsmnxi7wqyckj
|
||||
@@ -0,0 +1,64 @@
|
||||
@tool
|
||||
extends "_node.gd"
|
||||
|
||||
class TrackFrame:
|
||||
extends RefCounted
|
||||
var duration: float
|
||||
var value: Variant
|
||||
func _init(duration: float, value: Variant) -> void:
|
||||
self.duration = duration
|
||||
self.value = value
|
||||
|
||||
static func _create_animation_player(
|
||||
animation_library_info: _Common.AnimationLibraryInfo,
|
||||
track_value_getters_by_property_path: Dictionary
|
||||
) -> AnimationPlayer:
|
||||
var animation_player: AnimationPlayer = AnimationPlayer.new()
|
||||
animation_player.name = "AnimationPlayer"
|
||||
var animation_library: AnimationLibrary = AnimationLibrary.new()
|
||||
|
||||
for animation_info in animation_library_info.animations:
|
||||
var animation: Animation = Animation.new()
|
||||
var frames: Array[_Common.FrameInfo] = animation_info.get_flatten_frames()
|
||||
for property_path in track_value_getters_by_property_path.keys():
|
||||
__create_track(animation, property_path,
|
||||
frames, track_value_getters_by_property_path[property_path])
|
||||
|
||||
animation.length = 0
|
||||
for frame in frames:
|
||||
animation.length += frame.duration
|
||||
|
||||
animation.loop_mode = Animation.LOOP_LINEAR if animation_info.repeat_count == 0 else Animation.LOOP_NONE
|
||||
animation_library.add_animation(animation_info.name, animation)
|
||||
animation_player.add_animation_library("", animation_library)
|
||||
|
||||
if animation_library_info.autoplay_index >= 0:
|
||||
animation_player.autoplay = animation_library_info \
|
||||
.animations[animation_library_info.autoplay_index].name
|
||||
|
||||
return animation_player
|
||||
|
||||
static func __create_track(
|
||||
animation: Animation,
|
||||
property_path: NodePath,
|
||||
frames: Array[_Common.FrameInfo],
|
||||
track_value_getter: Callable # func(f: FrameModel) -> Variant for each f in frames
|
||||
) -> int:
|
||||
var track_index = animation.add_track(Animation.TYPE_VALUE)
|
||||
animation.track_set_path(track_index, property_path)
|
||||
animation.value_track_set_update_mode(track_index, Animation.UPDATE_DISCRETE)
|
||||
animation.track_set_interpolation_loop_wrap(track_index, false)
|
||||
animation.track_set_interpolation_type(track_index, Animation.INTERPOLATION_NEAREST)
|
||||
var track_frames = frames.map(func (frame: _Common.FrameInfo):
|
||||
return TrackFrame.new(frame.duration, track_value_getter.call(frame)))
|
||||
|
||||
var transition: float = 1
|
||||
var track_length: float = 0
|
||||
var previous_track_frame: TrackFrame = null
|
||||
for track_frame in track_frames:
|
||||
if previous_track_frame == null or track_frame.value != previous_track_frame.value:
|
||||
animation.track_insert_key(track_index, track_length, track_frame.value, transition)
|
||||
previous_track_frame = track_frame
|
||||
track_length += track_frame.duration
|
||||
|
||||
return track_index
|
||||
@@ -0,0 +1 @@
|
||||
uid://c5tklyam00r8k
|
||||
@@ -0,0 +1,27 @@
|
||||
@tool
|
||||
extends "_node_with_animation_player.gd"
|
||||
|
||||
const ANIMATION_STRATEGIES_NAMES: PackedStringArray = [
|
||||
"Animate sprite's region and offset",
|
||||
"Animate single atlas texture's region and margin",
|
||||
"Animate multiple atlas textures instances",
|
||||
]
|
||||
enum AnimationStrategy {
|
||||
SPRITE_REGION_AND_OFFSET = 0,
|
||||
SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN = 1,
|
||||
MULTIPLE_ATLAS_TEXTURES_INSTANCES = 2,
|
||||
}
|
||||
|
||||
func _init(
|
||||
name: String,
|
||||
resource_type: String,
|
||||
save_extension: String,
|
||||
options: Array[Dictionary] = []
|
||||
) -> void:
|
||||
options.append_array([
|
||||
_Options.create_option(_Options.ANIMATION_STRATEGY, AnimationStrategy.SPRITE_REGION_AND_OFFSET,
|
||||
PROPERTY_HINT_ENUM, ",".join(ANIMATION_STRATEGIES_NAMES), PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(_Options.SPRITE_CENTERED, false,
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
])
|
||||
super(name, resource_type, save_extension, options)
|
||||
@@ -0,0 +1 @@
|
||||
uid://jpcaxy1f6srb
|
||||
45
addons/nklbdev.importality/import/animated_sprite_2d.gd
Normal file
45
addons/nklbdev.importality/import/animated_sprite_2d.gd
Normal file
@@ -0,0 +1,45 @@
|
||||
@tool
|
||||
extends "_node.gd"
|
||||
|
||||
const _SpriteFramesImporter = preload("sprite_frames.gd")
|
||||
|
||||
var __sprite_frames_importer: _SpriteFramesImporter
|
||||
|
||||
func _init() -> void:
|
||||
super("AnimatedSprite2D", "PackedScene", "scn")
|
||||
__sprite_frames_importer = _SpriteFramesImporter.new()
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var sprite_frames_import_result: ImportResult = __sprite_frames_importer \
|
||||
.import(res_source_file_path, atlas, sprite_sheet, animation_library, options, save_path)
|
||||
if sprite_frames_import_result.error:
|
||||
return sprite_frames_import_result
|
||||
var sprite_frames: SpriteFrames = sprite_frames_import_result.resource
|
||||
|
||||
var animated_sprite: AnimatedSprite2D = AnimatedSprite2D.new()
|
||||
var node_name: String = options[_Options.ROOT_NODE_NAME].strip_edges()
|
||||
animated_sprite.name = res_source_file_path.get_file().get_basename() \
|
||||
if node_name.is_empty() else node_name
|
||||
animated_sprite.sprite_frames = sprite_frames
|
||||
|
||||
if animation_library.autoplay_index >= 0:
|
||||
if animation_library.autoplay_index >= animation_library.animations.size():
|
||||
result.fail(ERR_INVALID_DATA, "Autoplay animation index overflow")
|
||||
return result
|
||||
animated_sprite.autoplay = animation_library \
|
||||
.animations[animation_library.autoplay_index].name
|
||||
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(animated_sprite)
|
||||
result.success(packed_scene,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://byeghoxxqevfp
|
||||
42
addons/nklbdev.importality/import/animated_sprite_3d.gd
Normal file
42
addons/nklbdev.importality/import/animated_sprite_3d.gd
Normal file
@@ -0,0 +1,42 @@
|
||||
@tool
|
||||
extends "_node.gd"
|
||||
|
||||
const _SpriteFramesImporter = preload("sprite_frames.gd")
|
||||
|
||||
var __sprite_frames_importer: _SpriteFramesImporter
|
||||
|
||||
func _init() -> void:
|
||||
super("AnimatedSprite3D", "PackedScene", "scn")
|
||||
__sprite_frames_importer = _SpriteFramesImporter.new()
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var sprite_frames_import_result: ImportResult = __sprite_frames_importer \
|
||||
.import(res_source_file_path, atlas, sprite_sheet, animation_library, options, save_path)
|
||||
if sprite_frames_import_result.error:
|
||||
return sprite_frames_import_result
|
||||
var sprite_frames: SpriteFrames = sprite_frames_import_result.resource
|
||||
|
||||
var animated_sprite: AnimatedSprite3D = AnimatedSprite3D.new()
|
||||
var node_name: String = options[_Options.ROOT_NODE_NAME].strip_edges()
|
||||
animated_sprite.name = res_source_file_path.get_file().get_basename() \
|
||||
if node_name.is_empty() else node_name
|
||||
animated_sprite.sprite_frames = sprite_frames
|
||||
|
||||
if animation_library.autoplay_index >= 0:
|
||||
animated_sprite.autoplay = animation_library \
|
||||
.animations[animation_library.autoplay_index].name
|
||||
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(animated_sprite)
|
||||
result.success(packed_scene,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://bg331u3nm4w8o
|
||||
@@ -0,0 +1,94 @@
|
||||
@tool
|
||||
extends "_sprite_with_animation_player.gd"
|
||||
|
||||
func _init() -> void:
|
||||
super("Sprite2D with AnimationPlayer", "PackedScene", "scn")
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var sprite_size: Vector2i = sprite_sheet.source_image_size
|
||||
|
||||
var sprite: Sprite2D = Sprite2D.new()
|
||||
var node_name: String = options[_Options.ROOT_NODE_NAME].strip_edges()
|
||||
sprite.name = res_source_file_path.get_file().get_basename() \
|
||||
if node_name.is_empty() else node_name
|
||||
sprite.centered = options[_Options.SPRITE_CENTERED]
|
||||
|
||||
var filter_clip_enabled: bool = options[_Options.ATLAS_TEXTURES_REGION_FILTER_CLIP_ENABLED]
|
||||
|
||||
var animation_player: AnimationPlayer
|
||||
match options[_Options.ANIMATION_STRATEGY]:
|
||||
|
||||
AnimationStrategy.SPRITE_REGION_AND_OFFSET:
|
||||
sprite.texture = atlas
|
||||
sprite.region_enabled = true
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:offset": func(frame: _Common.FrameInfo) -> Vector2:
|
||||
return \
|
||||
Vector2(frame.sprite.offset) - 0.5 * (frame.sprite.region.size - sprite_size) \
|
||||
if sprite.centered else \
|
||||
frame.sprite.offset,
|
||||
".:region_rect": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return Rect2(frame.sprite.region) })
|
||||
|
||||
AnimationStrategy.SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN:
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.resource_local_to_scene = true
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
sprite.texture = atlas_texture
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture:margin": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return \
|
||||
Rect2(frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size) \
|
||||
if frame.sprite.region.has_area() else \
|
||||
Rect2(2, 2, 0, 0),
|
||||
".:texture:region": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return Rect2(frame.sprite.region) if frame.sprite.region.has_area() else Rect2(0, 0, 1, 1) })
|
||||
|
||||
AnimationStrategy.MULTIPLE_ATLAS_TEXTURES_INSTANCES:
|
||||
var atlas_textures: Array[AtlasTexture]
|
||||
var empty_atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
empty_atlas_texture.filter_clip = filter_clip_enabled
|
||||
empty_atlas_texture.atlas = atlas
|
||||
empty_atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
empty_atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture": func(frame: _Common.FrameInfo) -> Texture2D:
|
||||
if not frame.sprite.region.has_area():
|
||||
return empty_atlas_texture
|
||||
var region: Rect2 = frame.sprite.region
|
||||
var margin: Rect2 = Rect2(
|
||||
frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size)
|
||||
var equivalent_atlas_textures: Array = atlas_textures.filter(
|
||||
func(t: AtlasTexture) -> bool: return t.margin == margin and t.region == region)
|
||||
if not equivalent_atlas_textures.is_empty():
|
||||
return equivalent_atlas_textures.front()
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.region = region
|
||||
atlas_texture.margin = margin
|
||||
atlas_textures.append(atlas_texture)
|
||||
return atlas_texture})
|
||||
|
||||
sprite.add_child(animation_player)
|
||||
animation_player.owner = sprite
|
||||
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(sprite)
|
||||
result.success(packed_scene,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://dbik163y6wqp
|
||||
@@ -0,0 +1,97 @@
|
||||
@tool
|
||||
extends "_sprite_with_animation_player.gd"
|
||||
|
||||
func _init() -> void:
|
||||
super("Sprite3D with AnimationPlayer", "PackedScene", "scn")
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var sprite_size: Vector2i = sprite_sheet.source_image_size
|
||||
|
||||
var sprite: Sprite3D = Sprite3D.new()
|
||||
var node_name: String = options[_Options.ROOT_NODE_NAME].strip_edges()
|
||||
sprite.name = res_source_file_path.get_file().get_basename() \
|
||||
if node_name.is_empty() else node_name
|
||||
sprite.centered = options[_Options.SPRITE_CENTERED]
|
||||
|
||||
var filter_clip_enabled: bool = options[_Options.ATLAS_TEXTURES_REGION_FILTER_CLIP_ENABLED]
|
||||
|
||||
var animation_player: AnimationPlayer
|
||||
match options[_Options.ANIMATION_STRATEGY]:
|
||||
|
||||
AnimationStrategy.SPRITE_REGION_AND_OFFSET:
|
||||
sprite.texture = atlas
|
||||
sprite.region_enabled = true
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:offset": func(frame: _Common.FrameInfo) -> Vector2:
|
||||
return Vector2( # spatial sprite offset (the Y-axis is Up-directed)
|
||||
frame.sprite.offset.x,
|
||||
sprite_size.y - frame.sptite.offset.y -
|
||||
frame.sprite.region.size.y) + \
|
||||
# add center correction
|
||||
((Vector2(frame.sprite.region.size - sprite_size) * 0.5)
|
||||
if sprite.centered else Vector2.ZERO),
|
||||
".:region_rect": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return Rect2(frame.sprite.region) })
|
||||
|
||||
AnimationStrategy.SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN:
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.resource_local_to_scene = true
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
sprite.texture = atlas_texture
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture:margin": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return \
|
||||
Rect2(frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size) \
|
||||
if frame.sprite.region.has_area() else \
|
||||
Rect2(2, 2, 0, 0),
|
||||
".:texture:region": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return Rect2(frame.sprite.region) if frame.sprite.region.has_area() else Rect2(0, 0, 1, 1) })
|
||||
|
||||
AnimationStrategy.MULTIPLE_ATLAS_TEXTURES_INSTANCES:
|
||||
var atlas_textures: Array[AtlasTexture]
|
||||
var empty_atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
empty_atlas_texture.filter_clip = filter_clip_enabled
|
||||
empty_atlas_texture.atlas = atlas
|
||||
empty_atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
empty_atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture": func(frame: _Common.FrameInfo) -> Texture2D:
|
||||
if not frame.sprite.region.has_area():
|
||||
return empty_atlas_texture
|
||||
var region: Rect2 = frame.sprite.region
|
||||
var margin: Rect2 = Rect2(
|
||||
frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size)
|
||||
var equivalent_atlas_textures: Array = atlas_textures.filter(
|
||||
func(t: AtlasTexture) -> bool: return t.margin == margin and t.region == region)
|
||||
if not equivalent_atlas_textures.is_empty():
|
||||
return equivalent_atlas_textures.front()
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.region = region
|
||||
atlas_texture.margin = margin
|
||||
atlas_textures.append(atlas_texture)
|
||||
return atlas_texture})
|
||||
|
||||
sprite.add_child(animation_player)
|
||||
animation_player.owner = sprite
|
||||
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(sprite)
|
||||
result.success(packed_scene,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://c3vtlehm0qj6s
|
||||
64
addons/nklbdev.importality/import/sprite_frames.gd
Normal file
64
addons/nklbdev.importality/import/sprite_frames.gd
Normal file
@@ -0,0 +1,64 @@
|
||||
@tool
|
||||
extends "_.gd"
|
||||
|
||||
func _init() -> void: super("SpriteFrames", "SpriteFrames", "res")
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var sprite_frames: SpriteFrames = SpriteFrames.new()
|
||||
for animation_name in sprite_frames.get_animation_names():
|
||||
sprite_frames.remove_animation(animation_name)
|
||||
|
||||
var filter_clip_enabled: bool = options[_Options.ATLAS_TEXTURES_REGION_FILTER_CLIP_ENABLED]
|
||||
var atlas_textures: Array[AtlasTexture]
|
||||
var empty_atlas_texture: AtlasTexture
|
||||
for animation in animation_library.animations:
|
||||
sprite_frames.add_animation(animation.name)
|
||||
sprite_frames.set_animation_loop(animation.name, animation.repeat_count == 0)
|
||||
sprite_frames.set_animation_speed(animation.name, 1)
|
||||
var previous_texture: Texture2D
|
||||
for frame in animation.get_flatten_frames():
|
||||
var atlas_texture: AtlasTexture
|
||||
if frame.sprite.region.has_area():
|
||||
var region: Rect2 = frame.sprite.region
|
||||
var margin: Rect2 = Rect2(
|
||||
frame.sprite.offset,
|
||||
sprite_sheet.source_image_size - frame.sprite.region.size)
|
||||
var equivalent_atlas_textures: Array = atlas_textures.filter(
|
||||
func(t: AtlasTexture) -> bool: return t.margin == margin and t.region == region)
|
||||
if not equivalent_atlas_textures.is_empty():
|
||||
atlas_texture = equivalent_atlas_textures.front()
|
||||
if atlas_texture == null:
|
||||
atlas_texture = AtlasTexture.new()
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.region = region
|
||||
atlas_texture.margin = margin
|
||||
atlas_textures.push_back(atlas_texture)
|
||||
else:
|
||||
if empty_atlas_texture == null:
|
||||
empty_atlas_texture = AtlasTexture.new()
|
||||
empty_atlas_texture.filter_clip = filter_clip_enabled
|
||||
empty_atlas_texture.atlas = atlas
|
||||
empty_atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
empty_atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
atlas_texture = empty_atlas_texture
|
||||
if atlas_texture == previous_texture:
|
||||
var last_frame_index: int = sprite_frames.get_frame_count(animation.name) - 1
|
||||
sprite_frames.set_frame(animation.name, last_frame_index, atlas_texture,
|
||||
sprite_frames.get_frame_duration(animation.name, last_frame_index) + frame.duration)
|
||||
continue
|
||||
sprite_frames.add_frame(animation.name, atlas_texture, frame.duration)
|
||||
previous_texture = atlas_texture
|
||||
|
||||
result.success(sprite_frames,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
1
addons/nklbdev.importality/import/sprite_frames.gd.uid
Normal file
1
addons/nklbdev.importality/import/sprite_frames.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://7divemm1kjo6
|
||||
83
addons/nklbdev.importality/import/sprite_sheet.gd
Normal file
83
addons/nklbdev.importality/import/sprite_sheet.gd
Normal file
@@ -0,0 +1,83 @@
|
||||
@tool
|
||||
extends "_.gd"
|
||||
|
||||
const __ANIMATION_MERGE_EQUAL_CONSEQUENT_FRAMES_OPTION: StringName = "animation/merge_equal_sonsequent_frames"
|
||||
const __ANIMATION_FLATTEN_REPETITION_OPTION: StringName = "animation/flatten_repetition"
|
||||
|
||||
func _init() -> void: super("Sprite sheet (JSON)", "JSON", "res", [
|
||||
_Options.create_option(__ANIMATION_MERGE_EQUAL_CONSEQUENT_FRAMES_OPTION, true,
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
_Options.create_option(__ANIMATION_FLATTEN_REPETITION_OPTION, true,
|
||||
PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT),
|
||||
])
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var unique_indixes_by_sprites: Dictionary
|
||||
var unique_sprite_index: int = 0
|
||||
var sprites: Array[Dictionary]
|
||||
for sprite in sprite_sheet.sprites:
|
||||
if not unique_indixes_by_sprites.has(sprite):
|
||||
unique_indixes_by_sprites[sprite] = unique_sprite_index
|
||||
sprites.push_back({
|
||||
region = sprite.region,
|
||||
offset = sprite.offset
|
||||
})
|
||||
unique_sprite_index += 1
|
||||
|
||||
var flatten_animation_repetition: bool = options[__ANIMATION_FLATTEN_REPETITION_OPTION]
|
||||
var merge_equal_consequent_frames: bool = options[__ANIMATION_MERGE_EQUAL_CONSEQUENT_FRAMES_OPTION]
|
||||
var animations: Array[Dictionary]
|
||||
for animation in animation_library.animations:
|
||||
var frames_data: Array[Dictionary]
|
||||
var frames: Array[_Common.FrameInfo] = \
|
||||
animation.get_flatten_frames() \
|
||||
if flatten_animation_repetition else \
|
||||
animation.frames
|
||||
var previous_sprite_index: int = -1
|
||||
for frame in frames:
|
||||
var sprite_index: int = unique_indixes_by_sprites[frame.sprite]
|
||||
if merge_equal_consequent_frames and sprite_index == previous_sprite_index:
|
||||
frames_data.back().duration += frame.duration
|
||||
else:
|
||||
frames_data.push_back({
|
||||
sprite_index = sprite_index,
|
||||
duration = frame.duration,
|
||||
})
|
||||
previous_sprite_index = sprite_index
|
||||
animations.push_back({
|
||||
name = animation.name,
|
||||
direction =
|
||||
_Common.AnimationDirection.FORWARD
|
||||
if flatten_animation_repetition else
|
||||
animation.direction,
|
||||
repeat_count =
|
||||
mini(1, animation.repeat_count)
|
||||
if flatten_animation_repetition else
|
||||
animation.repeat_count,
|
||||
frames = frames_data,
|
||||
})
|
||||
|
||||
var json: JSON = JSON.new()
|
||||
json.data = {
|
||||
sprite_sheet = {
|
||||
atlas = atlas,
|
||||
source_image_size = sprite_sheet.source_image_size,
|
||||
sprites = sprites,
|
||||
},
|
||||
animation_library = {
|
||||
animations = animations,
|
||||
autoplay_index = animation_library.autoplay_index,
|
||||
},
|
||||
}
|
||||
json.get_parsed_text()
|
||||
result.success(json, ResourceSaver.FLAG_COMPRESS)
|
||||
return result
|
||||
1
addons/nklbdev.importality/import/sprite_sheet.gd.uid
Normal file
1
addons/nklbdev.importality/import/sprite_sheet.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cpbdxtrpuluxc
|
||||
@@ -0,0 +1,98 @@
|
||||
@tool
|
||||
extends "_node_with_animation_player.gd"
|
||||
|
||||
const ANIMATION_STRATEGIES_NAMES: PackedStringArray = [
|
||||
"Animate single atlas texture's region and margin",
|
||||
"Animate multiple atlas textures instances",
|
||||
]
|
||||
enum AnimationStrategy {
|
||||
SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN = 1,
|
||||
MULTIPLE_ATLAS_TEXTURES_INSTANCES = 2
|
||||
}
|
||||
|
||||
func _init() -> void:
|
||||
super("TextureRect with AnimationPlayer", "PackedScene", "scn", [
|
||||
_Options.create_option(_Options.ANIMATION_STRATEGY, AnimationStrategy.SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN,
|
||||
PROPERTY_HINT_ENUM, ",".join(ANIMATION_STRATEGIES_NAMES), PROPERTY_USAGE_DEFAULT),
|
||||
])
|
||||
|
||||
func import(
|
||||
res_source_file_path: String,
|
||||
atlas: Texture2D,
|
||||
sprite_sheet: _Common.SpriteSheetInfo,
|
||||
animation_library: _Common.AnimationLibraryInfo,
|
||||
options: Dictionary,
|
||||
save_path: String
|
||||
) -> ImportResult:
|
||||
var result: ImportResult = ImportResult.new()
|
||||
|
||||
var texture_rect: TextureRect = TextureRect.new()
|
||||
var node_name: String = options[_Options.ROOT_NODE_NAME].strip_edges()
|
||||
texture_rect.name = res_source_file_path.get_file().get_basename() \
|
||||
if node_name.is_empty() else node_name
|
||||
texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
var sprite_size: Vector2i = sprite_sheet.source_image_size
|
||||
texture_rect.size = sprite_size
|
||||
|
||||
var filter_clip_enabled: bool = options[_Options.ATLAS_TEXTURES_REGION_FILTER_CLIP_ENABLED]
|
||||
|
||||
var animation_player: AnimationPlayer
|
||||
match options[_Options.ANIMATION_STRATEGY]:
|
||||
|
||||
AnimationStrategy.SINGLE_ATLAS_TEXTURE_REGION_AND_MARGIN:
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.resource_local_to_scene = true
|
||||
atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
texture_rect.texture = atlas_texture
|
||||
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture:margin": func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return \
|
||||
Rect2(frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size) \
|
||||
if frame.sprite.region.has_area() else \
|
||||
Rect2(2, 2, 0, 0),
|
||||
".:texture:region" : func(frame: _Common.FrameInfo) -> Rect2:
|
||||
return \
|
||||
Rect2(frame.sprite.region) \
|
||||
if frame.sprite.region.has_area() else \
|
||||
Rect2(0, 0, 1, 1) })
|
||||
|
||||
AnimationStrategy.MULTIPLE_ATLAS_TEXTURES_INSTANCES:
|
||||
var atlas_textures: Array[AtlasTexture]
|
||||
var empty_atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
empty_atlas_texture.filter_clip = filter_clip_enabled
|
||||
empty_atlas_texture.atlas = atlas
|
||||
empty_atlas_texture.region = Rect2(0, 0, 1, 1)
|
||||
empty_atlas_texture.margin = Rect2(2, 2, 0, 0)
|
||||
animation_player = _create_animation_player(animation_library, {
|
||||
".:texture": func(frame: _Common.FrameInfo) -> Texture2D:
|
||||
if not frame.sprite.region.has_area():
|
||||
return empty_atlas_texture
|
||||
var region: Rect2 = frame.sprite.region
|
||||
var margin: Rect2 = Rect2(
|
||||
frame.sprite.offset,
|
||||
sprite_size - frame.sprite.region.size)
|
||||
var equivalent_atlas_textures: Array = atlas_textures.filter(
|
||||
func(t: AtlasTexture) -> bool: return t.margin == margin and t.region == region)
|
||||
if not equivalent_atlas_textures.is_empty():
|
||||
return equivalent_atlas_textures.front()
|
||||
var atlas_texture: AtlasTexture = AtlasTexture.new()
|
||||
atlas_texture.atlas = atlas
|
||||
atlas_texture.filter_clip = filter_clip_enabled
|
||||
atlas_texture.region = region
|
||||
atlas_texture.margin = margin
|
||||
atlas_textures.append(atlas_texture)
|
||||
return atlas_texture})
|
||||
|
||||
texture_rect.add_child(animation_player)
|
||||
animation_player.owner = texture_rect
|
||||
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(texture_rect)
|
||||
result.success(packed_scene,
|
||||
ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_BUNDLE_RESOURCES)
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://dqo2tgxc28q6l
|
||||
Reference in New Issue
Block a user