Compare commits
2 commits
e369ad9462
...
a4ce750be2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ce750be2 | ||
|
|
e6d0ededb1 |
7 changed files with 63 additions and 40 deletions
|
|
@ -434,7 +434,7 @@ selected head placement, so it aligns with the vectors drawn over it.
|
||||||
:mouth :mouth-in :teeth :lid-r :lid-l :brow-r :brow-l …
|
:mouth :mouth-in :teeth :lid-r :lid-l :brow-r :brow-l …
|
||||||
```
|
```
|
||||||
|
|
||||||
Changing anchor keys edits `:head` and never touches `:face`, so it cannot move
|
Changing anchor keys edits `:head` and never touches `:place`, so it cannot move
|
||||||
something that was placed by hand. A group node is free, and keeping the authored
|
something that was placed by hand. A group node is free, and keeping the authored
|
||||||
and the measured transform apart is the whole reason the transform is decomposed
|
and the measured transform apart is the whole reason the transform is decomposed
|
||||||
in the first place.
|
in the first place.
|
||||||
|
|
@ -679,7 +679,7 @@ Proof that it covers what exists, not just what is wanted:
|
||||||
| square pupil | node `:pupil-r`, `:kind :rect`, parent `:iris-r`, stencil `:iris-r` |
|
| square pupil | node `:pupil-r`, `:kind :rect`, parent `:iris-r`, stencil `:iris-r` |
|
||||||
| brow ring + quantised raise | node `:brow-r`, `[:geom :pts]` dense (the traced ring with height removed), `[:xform :pos]` dense (the quantised raise). **The decomposition design.md insists on is two channels.** |
|
| brow ring + quantised raise | node `:brow-r`, `[:geom :pts]` dense (the traced ring with height removed), `[:xform :pos]` dense (the quantised raise). **The decomposition design.md insists on is two channels.** |
|
||||||
| head plate, kept frames | node `:head`, `:symbol` per instance, keys on `[:symbol]` at kept frames |
|
| head plate, kept frames | node `:head`, `:symbol` per instance, keys on `[:symbol]` at kept frames |
|
||||||
| `makeXform` face-oval crop | **gone.** Placement is `[:xform :*]` on `:face`; the stage clips |
|
| `makeXform` face-oval crop | **gone.** Placement is `[:xform :*]` on the face's own `:place`; the stage clips |
|
||||||
| `stabilize` transforms | dense `[:xform :*]` on `:head`, read through its optional `:anchors` map |
|
| `stabilize` transforms | dense `[:xform :*]` on `:head`, read through its optional `:anchors` map |
|
||||||
| registered underlay | not data — a UI layer riding `(world-of resolver :head)` |
|
| registered underlay | not data — a UI layer riding `(world-of resolver :head)` |
|
||||||
| painted background cel | node per layer, `[:geom :pts]` **framed**, `[:style :color]` framed |
|
| painted background cel | node per layer, `[:geom :pts]` **framed**, `[:style :color]` framed |
|
||||||
|
|
|
||||||
|
|
@ -333,11 +333,12 @@ per-frame header.
|
||||||
numbers: it centres on the face oval's bbox and zooms until the face is 80% of
|
numbers: it centres on the face oval's bbox and zooms until the face is 80% of
|
||||||
the raster height, so every vertex carries a cropping decision made once from one
|
the raster height, so every vertex carries a cropping decision made once from one
|
||||||
frame's landmarks. Dropping it is a deletion. Placement becomes `[:xform :*]` on
|
frame's landmarks. Dropping it is a deletion. Placement becomes `[:xform :*]` on
|
||||||
an authored `:face` node, the stage clips whatever hangs off, and project
|
an authored `:place` node inside the face, the stage clips whatever hangs off,
|
||||||
|
and project
|
||||||
dimensions stop being tied to the footage. See "What space geometry is in" in
|
dimensions stop being tied to the footage. See "What space geometry is in" in
|
||||||
`docs/animation-model.md`.
|
`docs/animation-model.md`.
|
||||||
|
|
||||||
The anchor transform freezes onto `:head`, one level under `:face`, and the
|
The anchor transform freezes onto `:head`, one level under `:place`, and the
|
||||||
normalise on/off/per-plate toggle is which of the three channel shapes that node
|
normalise on/off/per-plate toggle is which of the three channel shapes that node
|
||||||
carries. Always measure and always store factored, whatever the toggle says:
|
carries. Always measure and always store factored, whatever the toggle says:
|
||||||
smoothing and velocity-minimum key selection both require the split to exist in
|
smoothing and velocity-minimum key selection both require the split to exist in
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ measurements without losing the anchor choices.
|
||||||
|
|
||||||
A source image used for tracing should be registered with that image's measured
|
A source image used for tracing should be registered with that image's measured
|
||||||
stabilizing transform, then the selected head transform, then the authored
|
stabilizing transform, then the selected head transform, then the authored
|
||||||
`:face` placement. This makes the photo and head-local vectors share the same
|
`:place` placement the face carries. This makes the photo and head-local vectors share the same
|
||||||
orientation and position. Tracing-photo selection is a separate editor address;
|
orientation and position. Tracing-photo selection is a separate editor address;
|
||||||
it does not choose the head anchor.
|
it does not choose the head anchor.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
[arthur.domain.clip :as clip]
|
[arthur.domain.clip :as clip]
|
||||||
[arthur.domain.leaf :as leaf]
|
[arthur.domain.leaf :as leaf]
|
||||||
[arthur.domain.nest :as nest]
|
[arthur.domain.nest :as nest]
|
||||||
|
[arthur.domain.node :as node]
|
||||||
[arthur.domain.palette :as pal]
|
[arthur.domain.palette :as pal]
|
||||||
[arthur.domain.symbol :as symbol]
|
[arthur.domain.symbol :as symbol]
|
||||||
[arthur.domain.trace :as trace]
|
[arthur.domain.trace :as trace]
|
||||||
|
|
@ -58,15 +59,30 @@
|
||||||
(vec (array-seq (trace/photo-matrix (symbol/world-of r :head) h @store
|
(vec (array-seq (trace/photo-matrix (symbol/world-of r :head) h @store
|
||||||
(trace/photo-frame (trace/of h) f) 1000)))))
|
(trace/photo-frame (trace/of h) f) 1000)))))
|
||||||
|
|
||||||
|
(defn- filmed
|
||||||
|
"Where a photo sitting exactly where it was filmed must land: the face's OWN
|
||||||
|
placement, over image height, and nothing else.
|
||||||
|
|
||||||
|
`:place` carries the source-to-stage mapping now, above `:head` — so a face
|
||||||
|
opened in its own tab draws at the size it is on the stage, and its photo has
|
||||||
|
to come with it. That is the whole reason the mapping belongs to the face: the
|
||||||
|
head still cancels out, which is what these assertions are about, but it
|
||||||
|
cancels against a placement rather than against nothing."
|
||||||
|
[c f]
|
||||||
|
(let [r (symbol/resolver (clip/symbol c :face-1) @store pal/index-of nil)]
|
||||||
|
(r f)
|
||||||
|
(vec (array-seq (node/mul! (node/mat) (symbol/world-of r :place)
|
||||||
|
(js/Float64Array. #js [0.001 0 0 0.001 0 0]))))))
|
||||||
|
|
||||||
(deftest the-photo-registers-to-the-face-it-was-filmed-with
|
(deftest the-photo-registers-to-the-face-it-was-filmed-with
|
||||||
;; Face-1 is its own symbol and its head is its root, so a photo sitting where
|
(let [a (traced {:frames [] :origin :continuous})
|
||||||
;; it was filmed is image pixels over image height and nothing else.
|
b (traced {:frames [12] :origin :keys})
|
||||||
(let [filmed [0.001 0 0 0.001 0 0]]
|
d (traced {:frames [12] :origin :continuous})]
|
||||||
(is (near? filmed (photo-at (traced {:frames [] :origin :continuous}) 30))
|
(is (near? (filmed a 30) (photo-at a 30))
|
||||||
"a head showing the photo's own frame cancels out")
|
"a head showing the photo's own frame cancels out")
|
||||||
(is (near? filmed (photo-at (traced {:frames [12] :origin :keys}) 30))
|
(is (near? (filmed b 30) (photo-at b 30))
|
||||||
"held at the trace frame, face and photo both stand still")
|
"held at the trace frame, face and photo both stand still")
|
||||||
(is (not (near? filmed (photo-at (traced {:frames [12] :origin :continuous}) 30)))
|
(is (not (near? (filmed d 30) (photo-at d 30)))
|
||||||
"a continuous head carries the held photo along with it")))
|
"a continuous head carries the held photo along with it")))
|
||||||
|
|
||||||
(defn- wrapped
|
(defn- wrapped
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,19 @@
|
||||||
(is (empty? (clip/problems c)) (str spec ": " (pr-str (clip/problems c)))))))
|
(is (empty? (clip/problems c)) (str spec ": " (pr-str (clip/problems c)))))))
|
||||||
|
|
||||||
(deftest the-tree-is-the-one-the-model-specifies
|
(deftest the-tree-is-the-one-the-model-specifies
|
||||||
(is (= [:face :root] (symbol/lineage (:nodes (clip/symbol @clip* :main)) :face)))
|
;; :main HOLDS INSTANCES AND NOTHING ELSE. The source-to-stage placement used
|
||||||
|
;; to be a `:face` group here, above them all; it is each face's own `:place`
|
||||||
|
;; now, so the take is a container that knows nothing and a face is the right
|
||||||
|
;; size wherever it is put. Same transform, same subtree, one level lower.
|
||||||
|
(is (= [:face-1 :root] (symbol/lineage (:nodes (clip/symbol @clip* :main)) :face-1)))
|
||||||
|
(is (nil? (get-in @clip* [:symbols :main :nodes :face])))
|
||||||
(is (= #{:face-1} (node/sources (get-in @clip* [:symbols :main :nodes :face-1]))))
|
(is (= #{:face-1} (node/sources (get-in @clip* [:symbols :main :nodes :face-1]))))
|
||||||
(is (= [:head] (symbol/lineage (:nodes @sym*) :head)))
|
(is (= [:place] (symbol/lineage (:nodes @sym*) :place)))
|
||||||
(is (= [:mouth :head] (symbol/lineage (:nodes @sym*) :mouth)))
|
(is (= [:head :place] (symbol/lineage (:nodes @sym*) :head)))
|
||||||
(is (= [:mouth-in :mouth :head] (symbol/lineage (:nodes @sym*) :mouth-in)))
|
(is (= [:mouth :head :place] (symbol/lineage (:nodes @sym*) :mouth)))
|
||||||
|
(is (= [:mouth-in :mouth :head :place] (symbol/lineage (:nodes @sym*) :mouth-in)))
|
||||||
(is (= {:mode :map :expose 2} (:time (node :root))))
|
(is (= {:mode :map :expose 2} (:time (node :root))))
|
||||||
(is (every? #(nil? (:time (node %))) [:face :head :mouth :mouth-in])))
|
(is (every? #(nil? (:time (node %))) [:place :head :mouth :mouth-in])))
|
||||||
|
|
||||||
(deftest geometry-is-flat-and-dense-and-the-interior-shares-the-outline-s-block
|
(deftest geometry-is-flat-and-dense-and-the-interior-shares-the-outline-s-block
|
||||||
(doseq [id [:mouth :mouth-in]]
|
(doseq [id [:mouth :mouth-in]]
|
||||||
|
|
@ -121,11 +127,11 @@
|
||||||
(abs (- a b))))]
|
(abs (- a b))))]
|
||||||
(is (<= gap (/ q 2))
|
(is (<= gap (/ q 2))
|
||||||
(str "worst quantisation error " gap " against a quantum of " q))
|
(str "worst quantisation error " gap " against a quantum of " q))
|
||||||
;; And in stage pixels, which is the unit anyone can judge. `:face`'s scale is
|
;; And in stage pixels, which is the unit anyone can judge. `:place`'s scale is
|
||||||
;; stage px per image height, so the whole quantum is q·k — a twentieth of a
|
;; stage px per image height, so the whole quantum is q·k — a twentieth of a
|
||||||
;; pixel at this placement, two orders below anything the rasteriser can
|
;; pixel at this placement, two orders below anything the rasteriser can
|
||||||
;; express, which is the argument for Int16 geometry stated as a measurement.
|
;; express, which is the argument for Int16 geometry stated as a measurement.
|
||||||
(let [k (first (:value (chan :face [:xform :scale])))]
|
(let [k (first (:value (chan :place [:xform :scale])))]
|
||||||
(is (< (* q k) 0.1)
|
(is (< (* q k) 0.1)
|
||||||
(str "the quantum is " (* q k) " stage pixels at " k " px per image height"))
|
(str "the quantum is " (* q k) " stage pixels at " k " px per image height"))
|
||||||
(is (< (* gap k) (* q k))))))
|
(is (< (* gap k) (* q k))))))
|
||||||
|
|
@ -190,15 +196,15 @@
|
||||||
(deftest head-local-geometry-composed-through-head-and-face-lands-on-the-stage
|
(deftest head-local-geometry-composed-through-head-and-face-lands-on-the-stage
|
||||||
;; The end-to-end claim of the split, asserted against the OPS the resolver
|
;; The end-to-end claim of the split, asserted against the OPS the resolver
|
||||||
;; actually emits rather than against an intermediate: stored head-local, put
|
;; actually emits rather than against an intermediate: stored head-local, put
|
||||||
;; back through `:head`, placed by `:face`, the mouth is where the composition
|
;; back through `:head`, placed by `:place`, the mouth is where the composition
|
||||||
;; of the two says it is. A test that recomputed the chain would only be
|
;; of the two says it is. A test that recomputed the chain would only be
|
||||||
;; checking arithmetic against itself; this checks `node/local!`, `node/world!`
|
;; checking arithmetic against itself; this checks `node/local!`, `node/world!`
|
||||||
;; and `emit` as well.
|
;; and `emit` as well.
|
||||||
(let [c (freeze/head-mode {} @frozen)
|
(let [c (freeze/head-mode {} @frozen)
|
||||||
res (clip/resolver c :main @store pal/index-of nil)
|
res (clip/resolver c :main @store pal/index-of nil)
|
||||||
k (first (:value (chan :face [:xform :scale])))
|
k (first (:value (chan :place [:xform :scale])))
|
||||||
anc (:value (chan :face [:xform :anchor]))
|
anc (:value (chan :place [:xform :anchor]))
|
||||||
pos (:value (chan :face [:xform :pos]))
|
pos (:value (chan :place [:xform :pos]))
|
||||||
tfs (:transforms @take/measured)]
|
tfs (:transforms @take/measured)]
|
||||||
(doseq [f (range 0 take/frames 13)]
|
(doseq [f (range 0 take/frames 13)]
|
||||||
(let [ops (res f)
|
(let [ops (res f)
|
||||||
|
|
@ -217,7 +223,7 @@
|
||||||
;; the fit removed the head's motion, so putting it back is the fit's
|
;; the fit removed the head's motion, so putting it back is the fit's
|
||||||
;; inverse. Node :head carries exactly this.
|
;; inverse. Node :head carries exactly this.
|
||||||
im (geom/apply-sim (freeze/invert (nth tfs ef)) g)
|
im (geom/apply-sim (freeze/invert (nth tfs ef)) g)
|
||||||
;; And where :face puts it: scaled about the anchor, then translated,
|
;; And where :place puts it: scaled about the anchor, then translated,
|
||||||
;; which is p ↦ k(p - anchor) + anchor + pos.
|
;; which is p ↦ k(p - anchor) + anchor + pos.
|
||||||
wx (+ (* k (- (:x im) (nth anc 0))) (nth anc 0) (nth pos 0))
|
wx (+ (* k (- (:x im) (nth anc 0))) (nth anc 0) (nth pos 0))
|
||||||
wy (+ (* k (- (:y im) (nth anc 1))) (nth anc 1) (nth pos 1))]
|
wy (+ (* k (- (:y im) (nth anc 1))) (nth anc 1) (nth pos 1))]
|
||||||
|
|
@ -272,8 +278,8 @@
|
||||||
b (freeze/head-mode {:trace {:origin :start}} @frozen)
|
b (freeze/head-mode {:trace {:origin :start}} @frozen)
|
||||||
c (freeze/head-mode {:trace {:origin :keys :frames [0 40]}} @frozen)]
|
c (freeze/head-mode {:trace {:origin :keys :frames [0 40]}} @frozen)]
|
||||||
(doseq [x [b c]]
|
(doseq [x [b c]]
|
||||||
(is (= (get (nodes a) :face) (get (nodes x) :face))
|
(is (= (get (nodes a) :place) (get (nodes x) :place))
|
||||||
":face moved")
|
":place moved")
|
||||||
(is (= (dissoc (nodes a) :head) (dissoc (nodes x) :head))
|
(is (= (dissoc (nodes a) :head) (dissoc (nodes x) :head))
|
||||||
"a node other than :head changed")
|
"a node other than :head changed")
|
||||||
;; The measurement does not go away when the head is locked: always measure,
|
;; The measurement does not go away when the head is locked: always measure,
|
||||||
|
|
@ -304,7 +310,7 @@
|
||||||
;; transform on a node, which a hand can revise, and it claims no generator that
|
;; transform on a node, which a hand can revise, and it claims no generator that
|
||||||
;; would offer to overwrite it.
|
;; would offer to overwrite it.
|
||||||
(doseq [path [[:xform :pos] [:xform :rot] [:xform :scale] [:xform :anchor]]]
|
(doseq [path [[:xform :pos] [:xform :rot] [:xform :scale] [:xform :anchor]]]
|
||||||
(let [c (get (node/channels (node :face)) path)]
|
(let [c (get (node/channels (node :place)) path)]
|
||||||
(is (= :framed (ch/describe c)) (str path " is not framed"))
|
(is (= :framed (ch/describe c)) (str path " is not framed"))
|
||||||
(is (nil? (:generated c)) (str path " claims provenance")))))
|
(is (nil? (:generated c)) (str path " claims provenance")))))
|
||||||
|
|
||||||
|
|
@ -324,8 +330,8 @@
|
||||||
(let [c @clip*]
|
(let [c @clip*]
|
||||||
(doseq [sid [:main :face-1]
|
(doseq [sid [:main :face-1]
|
||||||
id (keys (get-in c [:symbols sid :nodes]))
|
id (keys (get-in c [:symbols sid :nodes]))
|
||||||
;; `:face` authors its own in `face-placement`, upstream of this.
|
;; `:place` authors its own in `face-placement`, upstream of this.
|
||||||
:when (not= [:main :face] [sid id])]
|
:when (not= [:face-1 :place] [sid id])]
|
||||||
(let [n (get-in c [:symbols sid :nodes id])
|
(let [n (get-in c [:symbols sid :nodes id])
|
||||||
frames (range (get-in c [:symbols sid :frames]))
|
frames (range (get-in c [:symbols sid :frames]))
|
||||||
anchor (:value (get-in n [:channels [:xform :anchor]]))
|
anchor (:value (get-in n [:channels [:xform :anchor]]))
|
||||||
|
|
@ -364,11 +370,11 @@
|
||||||
;; differently, it has been applied to a node whose transform is not the
|
;; differently, it has been applied to a node whose transform is not the
|
||||||
;; identity, which is the one way it could go wrong.
|
;; identity, which is the one way it could go wrong.
|
||||||
(let [c @clip*
|
(let [c @clip*
|
||||||
;; Every node the freeze makes EXCEPT `:face`, whose anchor
|
;; Every node the freeze makes EXCEPT `:place`, whose anchor
|
||||||
;; `face-placement` authors — which is the set `pivoted` writes.
|
;; `face-placement` authors — which is the set `pivoted` writes.
|
||||||
every (for [sid [:main :face-1]
|
every (for [sid [:main :face-1]
|
||||||
id (keys (get-in c [:symbols sid :nodes]))
|
id (keys (get-in c [:symbols sid :nodes]))
|
||||||
:when (and (not= [:main :face] [sid id])
|
:when (and (not= [:face-1 :place] [sid id])
|
||||||
(seq (get-in c [:symbols sid :nodes id :channels])))]
|
(seq (get-in c [:symbols sid :nodes id :channels])))]
|
||||||
[sid id])
|
[sid id])
|
||||||
anchors #(into {} (for [[sid id] every]
|
anchors #(into {} (for [[sid id] every]
|
||||||
|
|
@ -385,13 +391,13 @@
|
||||||
(is (= (render bare f) (render again f))
|
(is (= (render bare f) (render again f))
|
||||||
(str "frame " f " draws differently once every part has a pivot")))))
|
(str "frame " f " draws differently once every part has a pivot")))))
|
||||||
|
|
||||||
(deftest the-face-puts-the-head-s-centre-where-it-says-it-does
|
(deftest the-place-puts-the-head-s-centre-where-it-says-it-does
|
||||||
;; anchor + pos is where the anchor lands in the parent, which is what makes
|
;; anchor + pos is where the anchor lands in the parent, which is what makes
|
||||||
;; `:anchor` the registration point: scale and rotation happen about the head's
|
;; `:anchor` the registration point: scale and rotation happen about the head's
|
||||||
;; centre rather than about the corner of the footage, where MediaPipe's
|
;; centre rather than about the corner of the footage, where MediaPipe's
|
||||||
;; normalised space has its origin.
|
;; normalised space has its origin.
|
||||||
(let [anc (:value (chan :face [:xform :anchor]))
|
(let [anc (:value (chan :place [:xform :anchor]))
|
||||||
pos (:value (chan :face [:xform :pos]))
|
pos (:value (chan :place [:xform :pos]))
|
||||||
c (geom/centroid (:ref @take/measured))]
|
c (geom/centroid (:ref @take/measured))]
|
||||||
(is (< (abs (- (nth anc 0) (:x c))) 1e-12))
|
(is (< (abs (- (nth anc 0) (:x c))) 1e-12))
|
||||||
(is (< (abs (- (nth anc 1) (:y c))) 1e-12))
|
(is (< (abs (- (nth anc 1) (:y c))) 1e-12))
|
||||||
|
|
@ -418,8 +424,8 @@
|
||||||
(vec (array-seq (:data (get (:store big) (key-of (:clip big)))))))
|
(vec (array-seq (:data (get (:store big) (key-of (:clip big)))))))
|
||||||
"the geometry is the same numbers at either stage size")
|
"the geometry is the same numbers at either stage size")
|
||||||
(is (not= (:value (get-in (nodes (:clip big))
|
(is (not= (:value (get-in (nodes (:clip big))
|
||||||
[:face :channels [:xform :scale]]))
|
[:place :channels [:xform :scale]]))
|
||||||
(:value (chan :face [:xform :scale]))))))
|
(:value (chan :place [:xform :scale]))))))
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------
|
||||||
;; the aperture, as [:vis]
|
;; the aperture, as [:vis]
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@
|
||||||
flat (assoc-in clip [:symbols :main :nodes]
|
flat (assoc-in clip [:symbols :main :nodes]
|
||||||
(merge (dissoc (:nodes (clip/symbol clip :main)) :face-1)
|
(merge (dissoc (:nodes (clip/symbol clip :main)) :face-1)
|
||||||
(assoc-in (get-in clip [:symbols :face-1 :nodes])
|
(assoc-in (get-in clip [:symbols :face-1 :nodes])
|
||||||
[:head :parent] :face)))
|
[:head :parent] :place)))
|
||||||
nested (clip/resolver clip :main store pal/index-of nil)
|
nested (clip/resolver clip :main store pal/index-of nil)
|
||||||
reference (clip/resolver flat :main store pal/index-of nil)]
|
reference (clip/resolver flat :main store pal/index-of nil)]
|
||||||
(doseq [f [0 1 7 20 39]]
|
(doseq [f [0 1 7 20 39]]
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@
|
||||||
(channel after :iris-l [:xform :pos])))
|
(channel after :iris-l [:xform :pos])))
|
||||||
(is (= (channel before :mouth [:geom :pts])
|
(is (= (channel before :mouth [:geom :pts])
|
||||||
(channel after :mouth [:geom :pts])))
|
(channel after :mouth [:geom :pts])))
|
||||||
(is (= (get-in before [:clip :symbols :main :nodes :face])
|
(is (= (get-in before [:clip :symbols :face-1 :nodes :place])
|
||||||
(get-in after [:clip :symbols :main :nodes :face])))
|
(get-in after [:clip :symbols :face-1 :nodes :place])))
|
||||||
(is (= (channel (full-at {:gaze-gain 2}) :iris-r [:xform :pos])
|
(is (= (channel (full-at {:gaze-gain 2}) :iris-r [:xform :pos])
|
||||||
(channel after :iris-r [:xform :pos])))))
|
(channel after :iris-r [:xform :pos])))))
|
||||||
|
|
||||||
|
|
@ -85,8 +85,8 @@
|
||||||
(get-in after [:clip :symbols :face-1 :nodes :head :measured])))
|
(get-in after [:clip :symbols :face-1 :nodes :head :measured])))
|
||||||
(is (= (get-in full [:clip :symbols :face-1 :nodes :head :measured])
|
(is (= (get-in full [:clip :symbols :face-1 :nodes :head :measured])
|
||||||
(get-in after [:clip :symbols :face-1 :nodes :head :measured])))
|
(get-in after [:clip :symbols :face-1 :nodes :head :measured])))
|
||||||
(is (= (get-in before [:clip :symbols :main :nodes :face])
|
(is (= (get-in before [:clip :symbols :face-1 :nodes :place])
|
||||||
(get-in after [:clip :symbols :main :nodes :face])))))
|
(get-in after [:clip :symbols :face-1 :nodes :place])))))
|
||||||
|
|
||||||
(deftest contour-edit-does-not-rebuild-head-or-teeth
|
(deftest contour-edit-does-not-rebuild-head-or-teeth
|
||||||
(let [before @initial
|
(let [before @initial
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue