Hold or tween any keyed channel's gaps, as a drawing's
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
da7e293814
commit
2a0426707a
7 changed files with 46 additions and 24 deletions
|
|
@ -94,6 +94,16 @@
|
|||
(:segments c) (update :segments dissoc f))
|
||||
:else (ch/framed v)))))
|
||||
|
||||
(defn set-segment-interp
|
||||
"Choose how channel `path`'s key at `left` leads to the next one: `:hold` cuts
|
||||
there, `:linear` tweens. The same for a drawing's points as for a transform —
|
||||
only a gap that exists, between a key and a later one, can be chosen."
|
||||
[n path left interp]
|
||||
(let [ks (:keys (get (channels n) path))]
|
||||
(if (and (contains? ks left) (some #(< left %) (keys ks)) (#{:hold :linear} interp))
|
||||
(assoc-in n [:channels path :segments left] interp)
|
||||
n)))
|
||||
|
||||
;; ---------------------------------------------------------------------------
|
||||
;; time maps
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -46,13 +46,3 @@
|
|||
(if (and points (< (inc i) (count points)))
|
||||
(assoc-in clip path (-> points (assoc i x) (assoc (inc i) y)))
|
||||
clip)))
|
||||
|
||||
(defn set-segment-interp [clip sid id key-frame interp]
|
||||
(let [node (get-in clip [:symbols sid :nodes id])
|
||||
keys (get-in node [:channels geometry :keys])]
|
||||
(if (and (:paint? node) (contains? keys key-frame)
|
||||
(some #(< key-frame %) (clojure.core/keys keys))
|
||||
(#{:hold :linear} interp))
|
||||
(assoc-in clip [:symbols sid :nodes id :channels geometry
|
||||
:segments key-frame] interp)
|
||||
clip)))
|
||||
|
|
|
|||
|
|
@ -23,8 +23,3 @@
|
|||
::set-vertex
|
||||
(fn [db [_ sid id key-frame vertex point]]
|
||||
(edit/edit db #(paint/set-vertex % sid id key-frame vertex point))))
|
||||
|
||||
(rf/reg-event-db
|
||||
::set-segment-interp
|
||||
(fn [db [_ sid id key-frame interp]]
|
||||
(edit/edit db #(paint/set-segment-interp % sid id key-frame interp))))
|
||||
|
|
|
|||
|
|
@ -624,6 +624,11 @@
|
|||
(fn [db [_ sid id path frame]]
|
||||
(edit/edit db #(update-in % [:symbols sid :nodes id] node/toggle-key path frame))))
|
||||
|
||||
(rf/reg-event-db
|
||||
::set-segment-interp
|
||||
(fn [db [_ sid id path left interp]]
|
||||
(edit/edit db #(update-in % [:symbols sid :nodes id] node/set-segment-interp path left interp))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
::list
|
||||
(fn [{:keys [db]} _]
|
||||
|
|
|
|||
|
|
@ -123,6 +123,16 @@
|
|||
:else (let [v (:value ch)]
|
||||
(str "framed · " (if (channel/nothing? v) "absent" (pr-str v))))))
|
||||
|
||||
(defn- segment-select
|
||||
"Hold or tween, for the gap after the key at `left` — the same choice on a
|
||||
drawing as on a transform."
|
||||
[sid id path ch left]
|
||||
[:select.interp {:value (name (or (channel/segment-interp ch left) :hold))
|
||||
:on-change #(rf/dispatch [::project/set-segment-interp
|
||||
sid id path left (keyword (.. % -target -value))])}
|
||||
[:option {:value "hold"} "hold"]
|
||||
[:option {:value "linear"} "tween"]])
|
||||
|
||||
(defn- drawing-keys
|
||||
"The polygon controls: jump to a drawing key, add one here, and choose what the
|
||||
gap after the current one does. Lifted out of the old stage toolbar unchanged —
|
||||
|
|
@ -158,23 +168,23 @@
|
|||
(when next-k
|
||||
[:div.row {:style {:margin-top "5px"}}
|
||||
[:label.dim (str "key " active " → " next-k " ")
|
||||
[:select {:value (name (or (channel/segment-interp geom active) :hold))
|
||||
:on-change #(rf/dispatch [::paint-events/set-segment-interp
|
||||
sid id active (keyword (.. % -target -value))])}
|
||||
[:option {:value "hold"} "hold"]
|
||||
[:option {:value "linear"} "tween"]]]])]))
|
||||
[segment-select sid id paint/geometry geom active]]])]))
|
||||
|
||||
;; The transform and visibility, which every node has, as one row each: ◆ keys
|
||||
;; the channel here or takes the key here off, and an edit writes a key on a
|
||||
;; keyed channel or the one value on one that is not. `frame` is the node's own,
|
||||
;; nil when it is not on screen, where a keyed channel has no here to write to.
|
||||
;; Rotation is shown in degrees.
|
||||
;; Rotation is shown in degrees. Between two keys, the gap after the one here
|
||||
;; holds or tweens, as a drawing's does.
|
||||
|
||||
(defn- channel-control [sid id path ch frame]
|
||||
(let [keyed? (some? (:keys ch))
|
||||
v (channel/value-at ch (or frame 0))
|
||||
off? (and keyed? (nil? frame))
|
||||
deg? (= path [:xform :rot])
|
||||
;; A boolean has nothing between true and false to tween through.
|
||||
left (when (and keyed? frame (not (boolean? v))) (paint/active-frame ch frame))
|
||||
gap? (and left (some #(< left %) (keys (:keys ch))))
|
||||
put #(rf/dispatch [::project/set-channel sid id path frame %])
|
||||
field (fn [i x on-number]
|
||||
^{:key i}
|
||||
|
|
@ -193,7 +203,8 @@
|
|||
:on-change #(put (.. % -target -checked))}]
|
||||
(number? v) (field 0 v put)
|
||||
:else (doall (map-indexed (fn [i x] (field i x #(put (assoc (vec v) i %))))
|
||||
v)))]))
|
||||
v)))
|
||||
(when gap? [segment-select sid id path ch left])]))
|
||||
|
||||
(defn- node-section [[sid id n]]
|
||||
(let [[start end] (:span n)]
|
||||
|
|
|
|||
|
|
@ -200,4 +200,13 @@
|
|||
(let [d (node/toggle-key b [:xform :rot] 3)]
|
||||
(is (not (:animated? (get-in d [:channels [:xform :rot]]))) "the last key off is one value again")
|
||||
(is (= 1.0 (rot d 0))))
|
||||
(is (= :hold (get-in (node/toggle-key n [:vis] 0) [:channels [:vis] :interp])) "a boolean holds")))
|
||||
(is (= :hold (get-in (node/toggle-key n [:vis] 0) [:channels [:vis] :interp])) "a boolean holds")
|
||||
(let [h (node/set-segment-interp c [:xform :pos] 0 :hold)]
|
||||
(is (= [5 5] (pos h 5)) "a gap set to hold cuts at the next key")
|
||||
(is (= [10 0] (pos h 10)))
|
||||
(is (= [7.5 2.5] (pos (node/set-segment-interp h [:xform :pos] 0 :linear) 5)) "and back to a tween")
|
||||
(is (= h (node/set-segment-interp h [:xform :pos] 10 :hold)) "the last key has no gap after it")
|
||||
(is (empty? (ch/problems (get-in h [:channels [:xform :pos]])))))
|
||||
(let [d (node/toggle-key (node/set-segment-interp c [:xform :pos] 0 :hold) [:xform :pos] 0)]
|
||||
(is (not (contains? (get-in d [:channels [:xform :pos] :segments]) 0))
|
||||
"taking a key off takes its gap's choice with it"))))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
[arthur.demo :as demo]
|
||||
[arthur.domain.channel :as channel]
|
||||
[arthur.domain.leaf :as leaf]
|
||||
[arthur.domain.node :as node]
|
||||
[arthur.domain.paint :as paint]
|
||||
[arthur.domain.symbol :as symbol]))
|
||||
|
||||
|
|
@ -17,7 +18,8 @@
|
|||
c3 (paint/add-key c2 :main :paint-test 15)
|
||||
c4 (paint/set-vertex c3 :main :paint-test 15 0 [34 10])
|
||||
held (geometry c4)
|
||||
mixed-clip (paint/set-segment-interp c4 :main :paint-test 9 :linear)
|
||||
mixed-clip (update-in c4 [:symbols :main :nodes :paint-test]
|
||||
node/set-segment-interp paint/geometry 9 :linear)
|
||||
mixed (geometry mixed-clip)]
|
||||
(is (= [3 229] (get-in c2 [:symbols :main :nodes :paint-test :span])))
|
||||
(is (= a (channel/value-at held 8)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue