Repaint the stage after edits that move the selection; onion any symbol
The player's tracker derefed its inputs one by one inside `ratom/run!`. An edit that also changed the selection ran it from the selection's change: it read `::render/shown` while still stale, then pulled the dirty `::render/clip`, which re-ran it nested with the new resolver — and the outer run, finishing last, wrote the old one back. A deleted layer stayed on the stage until something else ran the tracker. The snapshot is now one sub, so the tracker derefs a single clean input and is never re-entered. Onion skinning only ghosted cels in `:display :lane` symbols, so a drawing made of keyed shapes showed nothing. A ghost is now just the picture the resolver draws n frames back and ahead, limited to the selection when there is one. The scope setting is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
78fb120edd
commit
8d20097e61
5 changed files with 80 additions and 141 deletions
|
|
@ -2,37 +2,8 @@
|
|||
(:require [cljs.test :refer [deftest is]]
|
||||
[arthur.domain.onion :as onion]))
|
||||
|
||||
(def events [{:start 0 :end 12 :drawing :a}
|
||||
{:start 15 :end 17 :drawing :a}
|
||||
{:start 17 :end 19 :drawing :b}
|
||||
{:start 25 :end 30 :drawing :c}])
|
||||
|
||||
(deftest neighbors-count-events-and-skip-gaps
|
||||
(is (= [[0 :before] [17 :after]]
|
||||
(mapv (juxt :start :direction) (onion/neighbors events 16 1 1))))
|
||||
(is (= [0 15] (mapv :start (onion/neighbors events 13 1 1))))
|
||||
(is (= [15 0 25] (mapv :start (onion/neighbors events 18 2 1))))
|
||||
(is (empty? (onion/neighbors events 18 0 0))))
|
||||
|
||||
(def document
|
||||
{:fps 24 :stage [32 32]
|
||||
:symbols {:main {:frames 40 :fps 24 :nodes
|
||||
{:lane {:id :lane :kind :instance :source {:symbol :drawings}
|
||||
:span [0 40]}}}
|
||||
:drawings {:frames 40 :fps 24 :display :lane :nodes
|
||||
{:a {:id :a :kind :instance :source {:symbol :ink}
|
||||
:span [0 12]}
|
||||
:b {:id :b :kind :instance :source {:symbol :ink}
|
||||
:span [0 2] :time {:at 15 :rate 1}}
|
||||
:c {:id :c :kind :instance :source {:symbol :ink}
|
||||
:span [0 2] :time {:at 17 :rate 1}}}}
|
||||
:ink {:frames 1 :nodes {}}}})
|
||||
|
||||
(deftest selected-lane-and-symbol-scopes
|
||||
(let [settings (assoc onion/defaults :on? true)]
|
||||
(is (= [[0 [:lane :a]] [17 [:lane :c]]]
|
||||
(mapv (juxt :frame :path)
|
||||
(onion/samples document {} :main [:node :drawings :b [:lane :b]] 16 settings))))
|
||||
(is (empty? (onion/samples document {} :main nil 16 settings)))
|
||||
(is (= [0 17]
|
||||
(mapv :frame (onion/samples document {} :main nil 16 (assoc settings :scope :symbol)))))))
|
||||
(deftest frames-either-side-within-the-transport
|
||||
(is (= [[4 :before] [3 :before] [6 :after]]
|
||||
(mapv (juxt :frame :direction) (onion/frames 5 10 {:before 2 :after 1}))))
|
||||
(is (= [[1 :after]] (mapv (juxt :frame :direction) (onion/frames 0 2 {:before 3 :after 3}))))
|
||||
(is (empty? (onion/frames 5 10 {:before 0 :after 0}))))
|
||||
|
|
|
|||
|
|
@ -117,9 +117,9 @@ try {
|
|||
const ctx = document.querySelector('canvas.onion-skin').getContext('2d');
|
||||
return [10,20,30].map(x => Array.from(ctx.getImageData(x,10,1,1).data));
|
||||
})()`);
|
||||
assert(pixels[0][0] > pixels[0][2] && pixels[0][3] > 0, 'previous cel is red');
|
||||
assert.equal(pixels[1][3], 0, 'current cel is excluded');
|
||||
assert(pixels[2][2] > pixels[2][0] && pixels[2][3] > 0, 'next cel is blue');
|
||||
assert(pixels[0][0] > pixels[0][2] && pixels[0][3] > 0, 'the previous frame is red');
|
||||
assert(pixels[1][2] > pixels[1][0] && pixels[1][3] > 0, 'the next frame is blue');
|
||||
assert.equal(pixels[2][3], 0, 'two frames ahead is not ghosted at after=1');
|
||||
const playbackAlpha = await evaluate(`(() => {
|
||||
const c=cljs.core, k=c.keyword;
|
||||
c.swap_BANG_(re_frame.db.app_db, db => c.assoc_in(db,c.vector(k('playback'),k('playing?')),true));
|
||||
|
|
@ -137,7 +137,7 @@ try {
|
|||
})()`);
|
||||
assert.deepEqual(preferences, [false,true], 'preferences are remembered per symbol');
|
||||
assert.equal(errors.length, 0, JSON.stringify(errors));
|
||||
console.log('PASS: onion controls, ghost colors, current-cel exclusion, playback hiding, per-symbol preferences');
|
||||
console.log('PASS: onion controls, ghost colors, frames either side, playback hiding, per-symbol preferences');
|
||||
} finally {
|
||||
if (ws?.readyState === WebSocket.OPEN) ws.close();
|
||||
chrome.kill('SIGTERM');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue