ProjectRR — нативный прототип на ассетах ProjectR
- Все 189 скелетов Spine сконвертированы в нативные Godot Skeleton2D (.tscn), без Spine в рантайме - Меню + сцены: подземелье (карта комнат), просмотр спрайтов, нативные анимации - Кастомизация цвета (кожа/волосы/глаза) через шейдер - Вытащенные текстуры/UI/шрифты + нарезка спрайтов из атласа - Датасет комнат для LoRA, офлайн-инструменты конвертации в tools/ Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
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
|
||||
Reference in New Issue
Block a user