Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading