@tool extends RefCounted const _Result = preload("../result.gd").Class const _Common = preload("../common.gd") const _Options = preload("../options.gd") const _Setting = preload("../setting.gd") const _DirAccessExtensions = preload("../dir_access_ext.gd") const _SpriteSheetBuilderBase = preload("../sprite_sheet_builder/_.gd") const _GridBasedSpriteSheetBuilder = preload("../sprite_sheet_builder/grid_based.gd") const _PackedSpriteSheetBuilder = preload("../sprite_sheet_builder/packed.gd") const ATLAS_TEXTURE_RESOURCE_TYPE_NAMES: PackedStringArray = [ "Embedded PortableCompressedTexture2D (compact)", "Embedded ImageTexture (large)", "Separated image (custom)", ] enum AtlasResourceType { EMBEDDED_PORTABLE_COMPRESSED_TEXTURE_2D = 0, EMBEDDED_IMAGE_TEXTURE = 1, SEPARATED_IMAGE = 2, } class ExportResult: extends _Result var atlas_image: Image var sprite_sheet: _Common.SpriteSheetInfo var animation_library: _Common.AnimationLibraryInfo func _get_result_type_description() -> String: return "Export" func success( atlas_image: Image, sprite_sheet: _Common.SpriteSheetInfo, animation_library: _Common.AnimationLibraryInfo ) -> void: _success() self.atlas_image = atlas_image self.sprite_sheet = sprite_sheet self.animation_library = animation_library var __name: String var __recognized_extensions: PackedStringArray var __settings: Array[_Setting] = [_Common.common_temporary_files_directory_path_setting] var __options: Array[Dictionary] = [ _Options.create_option(_Options.EDGES_ARTIFACTS_AVOIDANCE_METHOD, _Common.EdgesArtifactsAvoidanceMethod.NONE, PROPERTY_HINT_ENUM, ",".join(_Common.EDGES_ARTIFACTS_AVOIDANCE_METHODS_NAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), _Options.create_option(_Options.SPRITES_SURROUNDING_COLOR, Color.TRANSPARENT, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, func(o): return o[_Options.EDGES_ARTIFACTS_AVOIDANCE_METHOD] == \ _Common.EdgesArtifactsAvoidanceMethod.SOLID_COLOR_SURROUNDING), _Options.create_option(_Options.SPRITE_SHEET_LAYOUT, _Common.SpriteSheetLayout.PACKED, PROPERTY_HINT_ENUM, ",".join(_Common.SPRITE_SHEET_LAYOUTS_NAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), _Options.create_option(_Options.MAX_CELLS_IN_STRIP, 0, PROPERTY_HINT_RANGE, "0,,1,or_greater", PROPERTY_USAGE_DEFAULT, func(o): return o[_Options.SPRITE_SHEET_LAYOUT] != \ _Common.SpriteSheetLayout.PACKED), _Options.create_option(_Options.TRIM_SPRITES_TO_OVERALL_MIN_SIZE, true, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, func(o): return o[_Options.SPRITE_SHEET_LAYOUT] != \ _Common.SpriteSheetLayout.PACKED), _Options.create_option(_Options.COLLAPSE_TRANSPARENT_SPRITES, true, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, func(o): return o[_Options.SPRITE_SHEET_LAYOUT] != \ _Common.SpriteSheetLayout.PACKED), _Options.create_option(_Options.MERGE_DUPLICATED_SPRITES, true, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, func(o): return o[_Options.SPRITE_SHEET_LAYOUT] != \ _Common.SpriteSheetLayout.PACKED), ] var __image_format_loader_extension: ImageFormatLoaderExtension func _init( name: String, recognized_extensions: PackedStringArray, options: Array[Dictionary], settings: Array[_Setting], image_format_loader_extension: ImageFormatLoaderExtension = null ) -> void: __name = name __recognized_extensions = recognized_extensions __options.append_array(options) __settings.append_array(settings) __image_format_loader_extension = image_format_loader_extension func get_recognized_extensions() -> PackedStringArray: return __recognized_extensions func get_options() -> Array[Dictionary]: return __options func get_name() -> String: return __name func get_settings() -> Array[_Setting]: return __settings func get_image_format_loader_extension() -> ImageFormatLoaderExtension: return __image_format_loader_extension func export( res_source_file_path: String, options: Dictionary, editor_import_plugin: EditorImportPlugin ) -> ExportResult: return _export( res_source_file_path, options) func _export(source_file: String, options: Dictionary) -> ExportResult: assert(false, "This method is abstract and must be overriden.") var result: ExportResult = ExportResult.new() result.fail(ERR_UNCONFIGURED) return result enum AnimationOptions { FramesCount = 1, Direction = 2, RepeatCount = 4, } static var __option_regex: RegEx = RegEx.create_from_string("\\s-\\p{L}:\\s*\\S+") static var __natural_number_regex: RegEx = RegEx.create_from_string("\\A\\d+\\z") class AnimationParamsParsingResult: extends _Result var name: String var first_frame_index: int var frames_count: int var direction: _Common.AnimationDirection var repeat_count: int func _get_result_type_description() -> String: return "Animation parameters parsing" static func _parse_animation_params( raw_animation_params: String, animation_options: AnimationOptions, first_frame_index: int, frames_count: int = 0 ) -> AnimationParamsParsingResult: var result = AnimationParamsParsingResult.new() if first_frame_index < 0: result.fail(ERR_INVALID_DATA, "Wrong value for animation first frame index. Expected natural number, got: %s" % [first_frame_index]) return result result.first_frame_index = first_frame_index result.frames_count = frames_count result.direction = -1 result.repeat_count = -1 raw_animation_params = raw_animation_params.strip_edges() var options_matches: Array[RegExMatch] = __option_regex.search_all(raw_animation_params) var first_match_position: int = raw_animation_params.length() for option_match in options_matches: var match_position: int = option_match.get_start() assert(match_position >= 0) if match_position < first_match_position: first_match_position = match_position var raw_option: String = option_match.get_string().strip_edges() var raw_value = raw_option.substr(3).strip_edges() match raw_option.substr(0, 3): "-f:": if animation_options & AnimationOptions.FramesCount: if result.frames_count == 0: if __natural_number_regex.search(raw_value): result.frames_count = raw_value.to_int() if result.frames_count <= 0: result.fail(ERR_INVALID_DATA, "Wrong value format for frames count. Expected positive integer number, got: \"%s\"" % [raw_value]) return result "-d:": if animation_options & AnimationOptions.Direction: if result.direction < 0: match raw_value: "f": result.direction = _Common.AnimationDirection.FORWARD "r": result.direction = _Common.AnimationDirection.REVERSE "pp": result.direction = _Common.AnimationDirection.PING_PONG "ppr": result.direction = _Common.AnimationDirection.PING_PONG_REVERSE _: result.fail(ERR_INVALID_DATA, "Wrong value format for animation direction. Expected one of: [\"f\", \"r\", \"pp\", \"ppr\"], got: \"%s\"" % [raw_value]) return result "-r:": if animation_options & AnimationOptions.RepeatCount: if result.repeat_count < 0: if __natural_number_regex.search(raw_value): result.repeat_count = raw_value.to_int() else: result.fail(ERR_INVALID_DATA, "Wrong value format for repeat count. Expected positive integer number or zero, got: \"%s\"" % [raw_value]) return result _: pass # Ignore unknown parameter result.name = raw_animation_params.left(first_match_position).strip_edges() if result.frames_count <= 0: result.fail(ERR_UNCONFIGURED, "Animation frames count is required but not specified") return result return result func _create_sprite_sheet_builder(options: Dictionary) -> _SpriteSheetBuilderBase: var sprite_sheet_layout: _Common.SpriteSheetLayout = options[_Options.SPRITE_SHEET_LAYOUT] return \ _PackedSpriteSheetBuilder.new( options[_Options.EDGES_ARTIFACTS_AVOIDANCE_METHOD], options[_Options.SPRITES_SURROUNDING_COLOR]) \ if sprite_sheet_layout == _Common.SpriteSheetLayout.PACKED else \ _GridBasedSpriteSheetBuilder.new( options[_Options.EDGES_ARTIFACTS_AVOIDANCE_METHOD], _GridBasedSpriteSheetBuilder.StripDirection.HORIZONTAL if sprite_sheet_layout == _Common.SpriteSheetLayout.HORIZONTAL_STRIPS else _GridBasedSpriteSheetBuilder.StripDirection.HORIZONTAL, options[_Options.MAX_CELLS_IN_STRIP], options[_Options.TRIM_SPRITES_TO_OVERALL_MIN_SIZE], options[_Options.COLLAPSE_TRANSPARENT_SPRITES], options[_Options.MERGE_DUPLICATED_SPRITES], options[_Options.SPRITES_SURROUNDING_COLOR])