extends SceneTree # Нарезает отдельные спрайты из упакованных Unity SpriteAtlas по разметке # tools/sprite_layout.json (сгенерирована из AssetRipper Sprite/*.json). # Unity-координаты снизу-вверх => при вырезании нужен flip по Y. # Запуск: # godot-4.2-4.6.1-stable-mono.exe --headless --path <проект> --script res://tools/slice_atlas.gd const LAYOUT := "res://tools/sprite_layout.json" const ATLAS_DIR := "res://assets/atlas/" const OUT_DIR := "res://assets/" func _initialize(): var f := FileAccess.open(LAYOUT, FileAccess.READ) if f == null: push_error("нет %s" % LAYOUT); quit(); return var data: Dictionary = JSON.parse_string(f.get_as_text()) f.close() var sprites: Array = data.get("sprites", []) var atlas_cache := {} var ok := 0 var fail := 0 var groups := {} for s in sprites: var atlas_file: String = s["atlas"] if not atlas_cache.has(atlas_file): var img := Image.new() var err := img.load(ATLAS_DIR + atlas_file) atlas_cache[atlas_file] = img if err == OK else null if err != OK: push_error("не открылся атлас: " + atlas_file) var atlas: Image = atlas_cache[atlas_file] if atlas == null: fail += 1; continue var w: int = s["w"] var h: int = s["h"] if w <= 0 or h <= 0: fail += 1; continue var x: int = s["x"] var top: int = atlas.get_height() - (int(s["y"]) + h) # flip Y x = clampi(x, 0, atlas.get_width() - w) top = clampi(top, 0, atlas.get_height() - h) var sub := atlas.get_region(Rect2i(x, top, w, h)) var group: String = s["group"] var out_path := "%s%s/%s.png" % [OUT_DIR, group, _safe(s["name"])] DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path("%s%s" % [OUT_DIR, group])) if sub.save_png(out_path) == OK: ok += 1 groups[group] = groups.get(group, 0) + 1 else: fail += 1 print("НАРЕЗКА: сохранено %d, ошибок %d, по группам %s" % [ok, fail, groups]) quit() func _safe(name: String) -> String: var out := "" for c in name: if (c >= "a" and c <= "z") or (c >= "A" and c <= "Z") or (c >= "0" and c <= "9") or c in ["_", "-", "(", ")", "."]: out += c else: out += "_" return out