Files
project-rr/tools/slice_atlas.gd
T
Leonid PershinandClaude Opus 4.8 04cf5f90b0 ProjectRR — нативный прототип на ассетах ProjectR
- Все 189 скелетов Spine сконвертированы в нативные Godot Skeleton2D (.tscn), без Spine в рантайме
- Меню + сцены: подземелье (карта комнат), просмотр спрайтов, нативные анимации
- Кастомизация цвета (кожа/волосы/глаза) через шейдер
- Вытащенные текстуры/UI/шрифты + нарезка спрайтов из атласа
- Датасет комнат для LoRA, офлайн-инструменты конвертации в tools/

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 16:29:21 +03:00

69 lines
2.2 KiB
GDScript

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