Regenerate the base, keep the hand work, and say when you cannot
The loop the layer design exists for, tested for the first time: correct a generated channel by hand, turn the generator's knob, and get the new base with the correction still on it. `replace-feature` already carried `:over` across — somebody anticipated this — so the feature path needed a test and not a fix. The head path needed a fix, and there was a second fault of my own making. `regenerate-head` leaves the head's authored channels alone once somebody has placed it by hand, and decided that by `(= (:channels old) (:measured old))`. Sound, until a correction exists: an `:over` layer makes those unequal, so the FIRST correction anyone made would have stopped the head following re-measurement for good — the exact opposite of what a layer is for. It compares the channels without their layers now. The test fails against the old guard, which is how I know the bug was real and not a story about one. The other fault was mine, from the commit before this one. An `:offset` whose shape does not match its base threw, which is right for authored data — the validator catches it — but WRONG for the case the model actually names: turn the mouth's `:verts` knob and the re-freeze gives it a different number of points, so a correction that was correct when it was made stops fitting through nobody's error, and a throw in the read path takes the stage down. So a base that has outgrown a correction is a CONFLICT, and a conflict is the third thing beside applied and discarded. The regeneration records `:conflict` on the layer; the layer stays exactly where it is; `over-at` skips it, so the picture is the base meanwhile; and `clip/conflicts` lists them for a view to offer. A later regeneration that restores the shape clears the mark, so resolving one can be as simple as putting the knob back. Deliberately NOT `problems`. A document with a conflict loads, evaluates and saves — it contains a decision nobody has made yet, and refusing to open it would be the persistence layer taking a side in an editing question. The distinction in the validator is one line: a shape mismatch nobody has recorded is an authoring bug, and one a regeneration recorded is a conflict. `channel/conflict-with` is the single rule for "can this layer apply to this base", used by the validator, by `conflicts`, and by the regeneration that marks them. Only `:offset` can conflict, since `:replace` states a whole value and has nothing to agree with; a shape that cannot be read yet — an empty key map — is not a disagreement. `value-shape` answers it without sampling anything. 414 tests, 5,696 assertions, and `:verts` in the test is a real topology change rather than a synthetic one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
94c0a21de1
commit
72b57e3786
7 changed files with 297 additions and 11 deletions
|
|
@ -268,6 +268,22 @@ This is what `docs/design.md` means by an override layer, and it is why
|
|||
re-freezing is safe: the base is regenerated, the layers are untouched. It is
|
||||
Blender's NLA blending and AE's effect stack at one property.
|
||||
|
||||
WHEN THE BASE OUTGROWS A CORRECTION it is a CONFLICT, which is neither a dropped
|
||||
layer nor an applied one. Turning `:verts` gives the mouth a different number of
|
||||
points, and an `:offset` is a row of components that has to match: so the
|
||||
regeneration records `:conflict` on the layer, the layer stays in the document,
|
||||
the picture is the base meanwhile, and `clip/conflicts` is the list a view
|
||||
offers to resolve. Deliberately not `problems` — the document loads and saves
|
||||
fine, it just contains a decision nobody has made yet. A later regeneration
|
||||
that restores the shape clears the mark. Only `:offset` can conflict; `:replace`
|
||||
states a whole value and has nothing to agree with.
|
||||
|
||||
A correction is NOT a hand placement. `regenerate-head` leaves the head's
|
||||
authored channels alone once somebody has placed it by hand, and it compares the
|
||||
channels WITHOUT their layers to decide: otherwise the first correction anyone
|
||||
made would stop the head following re-measurement forever, which is the opposite
|
||||
of what a layer is for.
|
||||
|
||||
Layers are what "set it by hand" means for anything measured, and the measured
|
||||
channel does not need to know. A hand-set gaze is an `:over` on
|
||||
`[:xform :pos]` of the iris; a hand-set mouth shape is an `:over` on
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue