mirror of
https://github.com/mr0xb/spritetagger.git
synced 2026-08-27 20:44:56 -04:00
55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
"""Persistence for sprite frame label assignments.
|
|
|
|
Assignments are stored in a JSON sidecar keyed by filename (not frame index),
|
|
so resuming a session survives frames being added, removed, or reordered.
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
SIDECAR_NAME = '.sprite_tags.json'
|
|
SCHEMA_VERSION = 1
|
|
|
|
|
|
def sidecar_path(frames_dir: Path) -> Path:
|
|
return frames_dir / SIDECAR_NAME
|
|
|
|
|
|
def save_labels(path: Path, assignments_by_name: dict, labels: list) -> None:
|
|
data = {
|
|
'version': SCHEMA_VERSION,
|
|
'labels': list(labels),
|
|
'assignments': dict(assignments_by_name),
|
|
}
|
|
Path(path).write_text(json.dumps(data, indent=2))
|
|
|
|
|
|
def load_labels(path: Path):
|
|
"""Return (assignments_by_name, labels). Missing or invalid file → ({}, [])."""
|
|
path = Path(path)
|
|
if not path.exists():
|
|
return {}, []
|
|
try:
|
|
data = json.loads(path.read_text())
|
|
except (json.JSONDecodeError, OSError, ValueError):
|
|
return {}, []
|
|
assignments = data.get('assignments', {})
|
|
labels = data.get('labels', [])
|
|
if not isinstance(assignments, dict) or not isinstance(labels, list):
|
|
return {}, []
|
|
return assignments, labels
|
|
|
|
|
|
def to_name_keyed(assignments_by_index: dict, frames: list) -> dict:
|
|
"""{index: label} → {filename: label}."""
|
|
return {frames[i].name: label for i, label in assignments_by_index.items()}
|
|
|
|
|
|
def to_index_keyed(assignments_by_name: dict, frames: list) -> dict:
|
|
"""{filename: label} → {index: label}, dropping files not in `frames`."""
|
|
name_to_index = {p.name: i for i, p in enumerate(frames)}
|
|
return {
|
|
name_to_index[name]: label
|
|
for name, label in assignments_by_name.items()
|
|
if name in name_to_index
|
|
}
|