diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0251051 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changelog + +## 0.2.0 (unreleased, tag is the maintainer's step) + +### Package +- JSON schemas ship as package data (`spritemotion.schemas`) with `version()`, `path()` and `load_file()`. The package + has no required dependencies; numpy and Pillow are the `imaging` extra (#23). +- Fit rules live in the package: `spritemotion.fit_rules` (Python) and `spritemotion/web/fit-rules.mjs` (JavaScript), + one source each, with a parity test. `tools/fit-lab/fit_rules.py` is a shim that also works inside Blender (#28). + +### Transfer artifact +- New schema `spritemotion.transfer-artifact` v1 and a stdlib-only reader, `spritemotion.transfer` (#24). It rejects + absolute and `..` paths, missing files, sha256 mismatches and a wrong mirror map; it resolves mirrored facings 5-7 and + gives `centre = (128 - left, 192 - bottom)`. A synthetic fixture is committed under `tests/fixtures/transfer/`. +- `tools/transfer-export/run.py` turns a finished `tools/uo-content` job into a transfer artifact and fails unless the + reader accepts the result (#25). + +### Fit Lab +- The poke metric models the 1 cm holdout margin, the push-out upper bound and the occlusion modes; push-out is decided + from the mapping part's `studio_part`, as the renderer does (#21, SM-16a). +- DirectorDeck restyle, a facing ring that matches the screen, and a 2x2 3D view (#19). +- Whole-outfit view: Keep visible holds a slot's selected item in the 3D view while another slot is fitted; Show + outfit, Wear set and Clear outfit manage the kept slots, and Measure outfit makes body hiding and Measure slot count + the kept items. It is view state only (no history step, no autosave, no change to saved fits), remembered per + browser and pack; its document is the schema `spritemotion.fit-lab-view` v1 in the package (#20). +- Robustness fixes for issues #5-#11 (#18): VD offsets are bounded in `vdtool`/`uo_vd_writer`, outfit-lab `vd.py` clips + runs, `vdtool` prints usage on bad arguments, `jsonio` writes are atomic, `restore()` compares sha256, annotation + errors are narrowed and warn, and the studio skips an unreadable job status. +- Issue #12 (portability) fixed (#18, #30): the `region_fonts` font fallback, one `find_blender` discovery shared by + the tools, and no hardcoded Windows paths (the hardcoded-path test matches backslash and slash). + +### Local servers (security) +- Content Studio, Fit Lab and the live pose editor bind to the loopback interface only and check `Host` and `Origin` + on every GET, HEAD and POST (blocks DNS rebinding and cross-site requests). Studio and the pose editor share one + guard, `common/local_guard.py`; Fit Lab has the same rule. +- A POST needs a local `Origin` (pose editor) and a JSON body; the pose editor caps the body size. No server lists a + directory, and static files are served only from the tool's own folders. Studio gained `HEAD` with the same check. +- `SECURITY.md` lists every local server, how to report a vulnerability, and the two features that take a path from the + request on purpose (Fit Lab `/api/assets`, Studio `/api/stage`; trusted local user) (#4). +- Failed client staging and failed rebuilds now remove their half-written output folder, so a retry works; the Fit Lab + render index ignores patch-only jobs. +- The franchise-named outfit-lab examples are now generic: `mario-lab`/`spartan-lab` became `overalls-lab` and + `plate-armor-lab` (launchers, `build_overalls.py`, `build_plate_armor.py`, tests), and the `lightsaber` item is + `energy blade`. Rerun the renamed launchers and scripts; the old names are gone. + +### Canonical body +- Vendors Levy's UO_Model3D at upstream e9544f6 (was 3eaae69): 54-bone symmetric rig (no twist, toe, skirt or cloak + chains), action 17 arm fix, narrower shoulders. `blender_build.py` checks the bones it needs by name instead of a bone + count. Mappings use `foot.L/R` where they used `toe.L/R` (#27). Client data is not vendored. + +### Launchers +- Every `.bat` has a one-sentence description, calls `_shared/common.bat` and has a `.sh` twin; new `dev/` launchers + for the gates (#26). + +### Upgrading from 0.1.0 +- A saved fit or mapping that targets `toe.*`, `upper_arm_twist.*` or `forearm_twist.*` must point at `foot.*` and the + main arm bones. Rebuild items on the new body. +- Schemas moved from the repo-root `schemas/` to `common/schemas/`; load them with `spritemotion.schemas`. diff --git a/common/__init__.py b/common/__init__.py index a9c0138..e20ac51 100644 --- a/common/__init__.py +++ b/common/__init__.py @@ -7,7 +7,7 @@ """ from pathlib import Path -__version__ = "0.1.0" +__version__ = "0.2.0" PACKAGE_ROOT = Path(__file__).resolve().parent REPO_ROOT = PACKAGE_ROOT.parent diff --git a/pyproject.toml b/pyproject.toml index a436141..7c8cb5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "spritemotion" -version = "0.1.0" +version = "0.2.0" description = "Reconstruct editable 3D characters and animations from existing 2D sprites." readme = "README.md" requires-python = ">=3.10" diff --git a/uv.lock b/uv.lock index a9ab1b7..a513017 100644 --- a/uv.lock +++ b/uv.lock @@ -912,7 +912,7 @@ wheels = [ [[package]] name = "spritemotion" -version = "0.1.0" +version = "0.2.0" source = { editable = "." } [package.optional-dependencies]