155 lines
6.7 KiB
Python
155 lines
6.7 KiB
Python
"""Copies approved sprites from the variants directory to the game assets directory."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
from engine.registry import SpriteRegistry
|
|
|
|
|
|
class SpriteInstaller:
|
|
def __init__(self, assets_dir: Path, registry: SpriteRegistry) -> None:
|
|
self.assets_dir = assets_dir
|
|
self.registry = registry
|
|
|
|
def install_approved(self, category: str | None = None, dry_run: bool = False) -> int:
|
|
"""Install all approved, uninstalled sprites. Returns count installed."""
|
|
entries = self.registry.get_approved_uninstalled(category)
|
|
count = 0
|
|
|
|
for sprite in entries:
|
|
sprite_id = sprite["id"]
|
|
install_path = sprite.get("install_path")
|
|
if not install_path:
|
|
continue
|
|
|
|
# Check if sprite-level has an approved variant (no dimension)
|
|
if sprite["status"] == "approved":
|
|
variants = self.registry.get_variants(sprite_id)
|
|
approved = [v for v in variants if v["is_approved"] and v["dimension_id"] is None]
|
|
if approved:
|
|
source = approved[0].get("processed_path")
|
|
if source and Path(source).exists():
|
|
dest = self.assets_dir / install_path
|
|
if dry_run:
|
|
print(f"[DRY RUN] Would install {install_path}")
|
|
else:
|
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source, dest)
|
|
self.registry.mark_installed(sprite_id)
|
|
print(f"Installed {install_path}")
|
|
count += 1
|
|
|
|
# Handle approved dimensions
|
|
for dim in sprite.get("approved_dimensions", []):
|
|
dim_install = dim.get("install_path")
|
|
if not dim_install:
|
|
continue
|
|
if dim["status"] != "approved":
|
|
continue
|
|
dim_id = dim["id"]
|
|
approved_vid = dim.get("approved_variant_id")
|
|
if not approved_vid:
|
|
continue
|
|
dim_variants = self.registry.get_variants(sprite_id, dim_id)
|
|
approved = [v for v in dim_variants if v["id"] == approved_vid]
|
|
if not approved:
|
|
continue
|
|
source = approved[0].get("processed_path")
|
|
if not source or not Path(source).exists():
|
|
continue
|
|
dest = self.assets_dir / dim_install
|
|
if dry_run:
|
|
print(f"[DRY RUN] Would install {dim_install}")
|
|
else:
|
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source, dest)
|
|
self.registry.mark_installed(sprite_id, dim_id)
|
|
print(f"Installed {dim_install}")
|
|
count += 1
|
|
|
|
return count
|
|
|
|
def install_one(self, sprite_id: str, dimension_id: int | None = None) -> Path | None:
|
|
"""Install a single sprite/dimension. Returns install path or None."""
|
|
sprite = self.registry.get_sprite(sprite_id)
|
|
if not sprite:
|
|
print(f"Sprite '{sprite_id}' not found")
|
|
return None
|
|
|
|
if dimension_id is not None:
|
|
dim = next((d for d in sprite["dimensions_list"] if d["id"] == dimension_id), None)
|
|
if not dim:
|
|
print(f"Dimension {dimension_id} not found for '{sprite_id}'")
|
|
return None
|
|
if dim["status"] not in ("approved", "installed"):
|
|
print(f"Dimension {dimension_id} is not approved (status: {dim['status']})")
|
|
return None
|
|
install_path = dim.get("install_path")
|
|
approved_vid = dim.get("approved_variant_id")
|
|
if not install_path or not approved_vid:
|
|
print(f"Dimension {dimension_id} has no install_path or approved variant")
|
|
return None
|
|
approved = [v for v in dim.get("variants", []) if v["id"] == approved_vid]
|
|
if not approved:
|
|
print(f"Approved variant {approved_vid} not found")
|
|
return None
|
|
source = approved[0].get("processed_path")
|
|
else:
|
|
if sprite["status"] not in ("approved", "installed"):
|
|
print(f"Sprite '{sprite_id}' is not approved (status: {sprite['status']})")
|
|
return None
|
|
install_path = sprite.get("install_path")
|
|
if not install_path:
|
|
print(f"Sprite '{sprite_id}' has no install_path")
|
|
return None
|
|
approved = [v for v in sprite.get("variants", []) if v["is_approved"]]
|
|
if not approved:
|
|
print(f"No approved variant for '{sprite_id}'")
|
|
return None
|
|
source = approved[0].get("processed_path")
|
|
|
|
if not source or not Path(source).exists():
|
|
print(f"Source file not found: {source}")
|
|
return None
|
|
|
|
dest = self.assets_dir / install_path
|
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source, dest)
|
|
self.registry.mark_installed(sprite_id, dimension_id)
|
|
print(f"Installed {install_path}")
|
|
return dest
|
|
|
|
def uninstall(self, sprite_id: str, dimension_id: int | None = None) -> bool:
|
|
"""Remove an installed sprite, revert status to approved."""
|
|
sprite = self.registry.get_sprite(sprite_id)
|
|
if not sprite:
|
|
print(f"Sprite '{sprite_id}' not found")
|
|
return False
|
|
|
|
if dimension_id is not None:
|
|
dim = next((d for d in sprite["dimensions_list"] if d["id"] == dimension_id), None)
|
|
if not dim or dim["status"] != "installed":
|
|
print(f"Dimension {dimension_id} is not installed")
|
|
return False
|
|
install_path = dim.get("install_path")
|
|
if install_path:
|
|
dest = self.assets_dir / install_path
|
|
if dest.exists():
|
|
dest.unlink()
|
|
self.registry.update_dimension_status(dimension_id, "approved")
|
|
print(f"Uninstalled dimension {dimension_id} of '{sprite_id}'")
|
|
return True
|
|
|
|
if sprite["status"] != "installed":
|
|
print(f"Sprite '{sprite_id}' is not installed (status: {sprite['status']})")
|
|
return False
|
|
install_path = sprite.get("install_path")
|
|
if install_path:
|
|
dest = self.assets_dir / install_path
|
|
if dest.exists():
|
|
dest.unlink()
|
|
self.registry.update_sprite_status(sprite_id, "approved")
|
|
print(f"Uninstalled '{sprite_id}'")
|
|
return True
|