@tool extends RefCounted var _config = preload("../config/config.gd").new() # # Output: # { # "data_file": file path to the json file # "sprite_sheet": file path to the raw image file # } func export_file(file_name: String, output_folder: String, options: Dictionary) -> Dictionary: var exception_pattern = options.get('exception_pattern', "") var only_visible_layers = options.get('only_visible_layers', false) var output_name = file_name if options.get('output_filename') == "" else options.get('output_filename', file_name) var first_frame_only = options.get("first_frame_only", false) var basename = _get_file_basename(output_name) var output_dir = ProjectSettings.globalize_path(output_folder) var data_file = "%s/%s.json" % [output_dir, basename] var sprite_sheet = "%s/%s.png" % [output_dir, basename] var output = [] var arguments = _export_command_common_arguments(file_name, data_file, sprite_sheet) if not only_visible_layers: arguments.push_front("--all-layers") if first_frame_only: arguments.push_front("'[0, 0]'") arguments.push_front("--frame-range") _add_sheet_type_arguments(arguments, options) _add_ignore_layer_arguments(file_name, arguments, exception_pattern) var local_sprite_sheet_path = ProjectSettings.localize_path(sprite_sheet) var is_new = not ResourceLoader.exists(local_sprite_sheet_path) var exit_code = _execute(arguments, output) if exit_code != 0: printerr('aseprite: failed to export spritesheet') printerr(output) return {} return { "data_file": ProjectSettings.localize_path(data_file), "sprite_sheet": local_sprite_sheet_path, "is_first_import": is_new, } func export_layers(file_name: String, output_folder: String, options: Dictionary) -> Array: var exception_pattern = options.get('exception_pattern', "") var only_visible_layers = options.get('only_visible_layers', false) var basename = _get_file_basename(file_name) var layers = list_layers(file_name, only_visible_layers) var exception_regex = _compile_regex(exception_pattern) var output = [] for layer in layers: if layer != "" and (not exception_regex or exception_regex.search(layer) == null): output.push_back(export_layer(file_name, layer, output_folder, options)) return output func export_layer(file_name: String, layer_name: String, output_folder: String, options: Dictionary) -> Dictionary: var output_prefix = options.get('output_filename', "").strip_edges() var output_dir = output_folder.replace("res://", "./").strip_edges() var data_file = "%s/%s%s.json" % [output_dir, output_prefix, layer_name] var sprite_sheet = "%s/%s%s.png" % [output_dir, output_prefix, layer_name] var first_frame_only = options.get("first_frame_only", false) var output = [] var arguments = _export_command_common_arguments(file_name, data_file, sprite_sheet) arguments.push_front(layer_name) arguments.push_front("--layer") if first_frame_only: arguments.push_front("'[0, 0]'") arguments.push_front("--frame-range") _add_sheet_type_arguments(arguments, options) var local_sprite_sheet_path = ProjectSettings.localize_path(sprite_sheet) var is_new = not ResourceLoader.exists(local_sprite_sheet_path) var exit_code = _execute(arguments, output) if exit_code != 0: print('aseprite: failed to export layer spritesheet') print(output) return {} return { "data_file": ProjectSettings.localize_path(data_file), "sprite_sheet": local_sprite_sheet_path, "is_first_import": is_new, } func _add_ignore_layer_arguments(file_name: String, arguments: Array, exception_pattern: String): var layers = _get_exception_layers(file_name, exception_pattern) if not layers.is_empty(): for l in layers: arguments.push_front(l) arguments.push_front('--ignore-layer') func _add_sheet_type_arguments(arguments: Array, options : Dictionary): var column_count : int = options.get("column_count", 0) if column_count > 0: arguments.push_back("--merge-duplicates") # Yes, this is undocumented arguments.push_back("--sheet-columns") arguments.push_back(column_count) else: arguments.push_back("--sheet-pack") func _get_exception_layers(file_name: String, exception_pattern: String) -> Array: var layers = list_layers(file_name) var regex = _compile_regex(exception_pattern) if regex == null: return [] var exception_layers = [] for layer in layers: if regex.search(layer) != null: exception_layers.push_back(layer) return exception_layers func list_layers(file_name: String, only_visible = false) -> Array: var output = [] var arguments = ["-b", "--list-layers", file_name] if not only_visible: arguments.push_front("--all-layers") var exit_code = _execute(arguments, output) if exit_code != 0: printerr('aseprite: failed listing layers') printerr(output) return [] if output.is_empty(): return output var raw = output[0].split('\n') var sanitized = [] for s in raw: sanitized.append(s.strip_edges()) return sanitized func list_slices(file_name: String) -> Array: var output = [] var arguments = ["-b", "--list-slices", file_name] var exit_code = _execute(arguments, output) if exit_code != 0: printerr('aseprite: failed listing slices') printerr(output) return [] if output.is_empty(): return output var raw = output[0].split('\n') var sanitized = [] for s in raw: sanitized.append(s.strip_edges()) return sanitized func _export_command_common_arguments(source_name: String, data_path: String, spritesheet_path: String) -> Array: return [ "-b", "--list-tags", "--list-slices", "--data", data_path, "--format", "json-array", "--sheet", spritesheet_path, source_name ] func _execute(arguments, output): return OS.execute(_aseprite_command(), arguments, output, true, true) func _aseprite_command() -> String: return _config.is_command_or_control_pressed() func _get_file_basename(file_path: String) -> String: return file_path.get_file().trim_suffix('.%s' % file_path.get_extension()) func _compile_regex(pattern): if pattern == "": return var rgx = RegEx.new() if rgx.compile(pattern) == OK: return rgx printerr('exception regex error') func test_command(): var exit_code = OS.execute(_aseprite_command(), ['--version'], [], true) return exit_code == 0 func is_valid_spritesheet(content): return content.has("frames") and content.has("meta") and content.meta.has('image') func get_content_frames(content): return content.frames if typeof(content.frames) == TYPE_ARRAY else content.frames.values() func get_slice_rect(content: Dictionary, slice_name: String) -> Variant: if not content.has("meta") or not content.meta.has("slices"): return null for slice in content.meta.slices: if slice.name == slice_name: if slice.keys.size() > 0: var p = slice.keys[0].bounds return Rect2(p.x, p.y, p.w, p.h) return null ## ## Exports tileset layers ## ## Return (dictionary): ## data_file: path to aseprite generated JSON file ## sprite_sheet: localized path to spritesheet file func export_tileset_texture(file_name: String, output_folder: String, options: Dictionary) -> Dictionary: var exception_pattern = options.get('exception_pattern', "") var only_visible_layers = options.get('only_visible_layers', false) var output_name = file_name if options.get('output_filename') == "" else options.get('output_filename', file_name) var basename = _get_file_basename(output_name) var output_dir = ProjectSettings.globalize_path(output_folder) var data_path = "%s/%s.json" % [output_dir, basename] var sprite_sheet = "%s/%s.png" % [output_dir, basename] var output = [] var arguments = [ "-b", "--export-tileset", "--data", data_path, "--format", "json-array", "--sheet", sprite_sheet, file_name ] if not only_visible_layers: arguments.push_front("--all-layers") _add_ignore_layer_arguments(file_name, arguments, exception_pattern) var exit_code = _execute(arguments, output) if exit_code != 0: printerr('aseprite: failed to export spritesheet') printerr(output) return {} return { "data_file": ProjectSettings.localize_path(data_path), "sprite_sheet": ProjectSettings.localize_path(sprite_sheet) }