Initial Dansori character workspace

This commit is contained in:
eKeerar
2026-07-04 10:34:46 +09:00
commit 5a419816ff
2480 changed files with 38692 additions and 0 deletions
@@ -0,0 +1,78 @@
from __future__ import annotations
import json
from collections import OrderedDict
from pathlib import Path
from PIL import Image
from psd_tools import PSDImage
from psd_tools.api.layers import PixelLayer
ROOT = Path(__file__).resolve().parents[1]
LIVE2D = ROOT / "03_Assets" / "Live2D"
LAYER_BASE = LIVE2D / "LayerPNGs"
MANIFEST = LIVE2D / "layer_manifest.json"
MATERIAL_PSD = LIVE2D / "sori_live2d_material_separation.psd"
IMPORT_PSD = LIVE2D / "sori_live2d_import.psd"
def load_manifest() -> dict:
return json.loads(MANIFEST.read_text(encoding="utf-8"))
def make_psd(name: str, size: tuple[int, int]) -> PSDImage:
psd = PSDImage.new("RGB", size, color=(0, 0, 0), depth=8)
return psd
def add_grouped_layer(psd: PSDImage, groups: OrderedDict[str, object], layer: dict, visible: bool) -> None:
group_name = layer["group"]
group = groups.get(group_name)
if group is None:
group = psd.create_group(name=group_name)
groups[group_name] = group
path = LAYER_BASE / layer["file"]
if not path.exists():
raise FileNotFoundError(path)
image = Image.open(path).convert("RGBA")
pixel_layer = PixelLayer.frompil(image, parent=group, name=layer["id"], top=0, left=0)
pixel_layer.visible = visible
group.append(pixel_layer)
def save_psd(path: Path, layers: list[dict], size: tuple[int, int], material: bool) -> None:
psd = make_psd(path.stem, size)
groups: OrderedDict[str, object] = OrderedDict()
for layer in layers:
if not material and not layer.get("import", False):
continue
visible = layer.get("group") not in ("Guide", "SwapParts")
add_grouped_layer(psd, groups, layer, visible)
psd.save(path)
reopened = PSDImage.open(path)
if reopened.size != size:
raise RuntimeError(f"Unexpected PSD size for {path}: {reopened.size}")
if not list(reopened.descendants()):
raise RuntimeError(f"No layers saved in {path}")
def main() -> None:
manifest = load_manifest()
canvas = manifest["canvas"]
size = (int(canvas["width"]), int(canvas["height"]))
layers = manifest["layers"]
save_psd(MATERIAL_PSD, layers, size, material=True)
save_psd(IMPORT_PSD, layers, size, material=False)
print(MATERIAL_PSD)
print(IMPORT_PSD)
if __name__ == "__main__":
main()