Add instance playback controls to the inspector
This commit is contained in:
parent
52f25e0bb1
commit
1c520e6a68
3 changed files with 94 additions and 0 deletions
|
|
@ -757,6 +757,32 @@
|
||||||
(let [put (if (get-in db [:ui :auto-key?]) node/set-keyed-channel node/set-channel)]
|
(let [put (if (get-in db [:ui :auto-key?]) node/set-keyed-channel node/set-channel)]
|
||||||
(edit/edit db #(update-in % [:symbols sid :nodes id] put path frame value)))))
|
(edit/edit db #(update-in % [:symbols sid :nodes id] put path frame value)))))
|
||||||
|
|
||||||
|
(rf/reg-event-db
|
||||||
|
::instance-playback
|
||||||
|
(fn [db [_ sid id field value]]
|
||||||
|
(let [valid? (case field
|
||||||
|
:mode (#{:once :loop :frame} value)
|
||||||
|
(:in :speed) (and (node/finite-number? value) (<= 0 value))
|
||||||
|
false)]
|
||||||
|
(if-not valid?
|
||||||
|
db
|
||||||
|
(edit/edit
|
||||||
|
db
|
||||||
|
(fn [document]
|
||||||
|
(let [path [:symbols sid :nodes id]
|
||||||
|
n (get-in document path)]
|
||||||
|
(if-not (= :instance (:kind n))
|
||||||
|
document
|
||||||
|
(let [{:keys [speed]} (node/playback-of n)
|
||||||
|
updated (if (= :mode field)
|
||||||
|
(-> n
|
||||||
|
(update :time dissoc :loop?)
|
||||||
|
(assoc-in [:playback :end] (if (= :loop value) :loop :stop))
|
||||||
|
(assoc-in [:playback :speed]
|
||||||
|
(if (= :frame value) 0 (if (pos? speed) speed 1))))
|
||||||
|
(assoc-in n [:playback field] value))]
|
||||||
|
(assoc-in document path updated))))))))))
|
||||||
|
|
||||||
(defn- seed-palette-choice [document sid id]
|
(defn- seed-palette-choice [document sid id]
|
||||||
(if (get-in document [:symbols sid :nodes id :channels [:palette]])
|
(if (get-in document [:symbols sid :nodes id :channels [:palette]])
|
||||||
document
|
document
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,34 @@
|
||||||
:on-click #(rf/dispatch [::project/set-channel sid id [:style :color] frame i])}]))]
|
:on-click #(rf/dispatch [::project/set-channel sid id [:style :color] frame i])}]))]
|
||||||
(when keyed? [:span.dim "hold"])]))
|
(when keyed? [:span.dim "hold"])]))
|
||||||
|
|
||||||
|
(defn- instance-playback [[sid id n]]
|
||||||
|
(let [{:keys [in speed end]} (node/playback-of n)
|
||||||
|
mode (cond (zero? speed) :frame
|
||||||
|
(or (= :loop end) (get-in n [:time :loop?])) :loop
|
||||||
|
:else :once)
|
||||||
|
change! (fn [field value]
|
||||||
|
(rf/dispatch [::project/instance-playback sid id field value]))]
|
||||||
|
[section "playback"
|
||||||
|
[:div.inspector-form
|
||||||
|
[:label.inspector-field "mode"
|
||||||
|
[:select {:value (name mode)
|
||||||
|
:aria-label "instance playback mode"
|
||||||
|
:on-change #(change! :mode (keyword (.. % -target -value)))}
|
||||||
|
[:option {:value "once"} "play once"]
|
||||||
|
[:option {:value "loop"} "loop"]
|
||||||
|
[:option {:value "frame"} "hold frame"]]]
|
||||||
|
[:label.inspector-field "start frame"
|
||||||
|
[number-input {:min 0 :step 1 :value in
|
||||||
|
:aria-label "instance start frame"
|
||||||
|
:parse #(js/parseInt % 10)
|
||||||
|
:on-number #(change! :in %)}]]
|
||||||
|
[:label.inspector-field "speed"
|
||||||
|
[number-input {:min 0 :step 0.1 :value speed
|
||||||
|
:disabled (= :frame mode)
|
||||||
|
:aria-label "instance playback speed"
|
||||||
|
:parse js/parseFloat
|
||||||
|
:on-number #(change! :speed %)}]]]]))
|
||||||
|
|
||||||
(defn- node-section [[sid id n]]
|
(defn- node-section [[sid id n]]
|
||||||
(let [[start end] (:span n)
|
(let [[start end] (:span n)
|
||||||
auto-key? @(rf/subscribe [::sub/auto-key?])
|
auto-key? @(rf/subscribe [::sub/auto-key?])
|
||||||
|
|
@ -787,6 +815,7 @@
|
||||||
[palette-placement-section node]
|
[palette-placement-section node]
|
||||||
[clip-section])
|
[clip-section])
|
||||||
(when (and node (not palette-placement?)) [node-section node])
|
(when (and node (not palette-placement?)) [node-section node])
|
||||||
|
(when (and placed (not palette-placement?)) [instance-playback node])
|
||||||
(when (and node (not palette-placement?)) [palette/remap-section])
|
(when (and node (not palette-placement?)) [palette/remap-section])
|
||||||
(when (and placed (not palette-placement?)) [symbol-section placed "source symbol"])
|
(when (and placed (not palette-placement?)) [symbol-section placed "source symbol"])
|
||||||
(when (and node (not palette-placement?)) ^{:key (str (first node) "/" (second node))}
|
(when (and node (not palette-placement?)) ^{:key (str (first node) "/" (second node))}
|
||||||
|
|
|
||||||
39
frontend/test/arthur/events/instance_playback_test.cljs
Normal file
39
frontend/test/arthur/events/instance_playback_test.cljs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
(ns arthur.events.instance-playback-test
|
||||||
|
(:require [cljs.test :refer [deftest is]]
|
||||||
|
[arthur.domain.clip :as clip]
|
||||||
|
[arthur.events.project :as project]
|
||||||
|
[arthur.footage.store :as store]
|
||||||
|
[re-frame.core :as rf]
|
||||||
|
[re-frame.db :as rf-db]))
|
||||||
|
|
||||||
|
(deftest playback-controls-change-only-the-selected-instance
|
||||||
|
(let [n {:id :wheel :kind :instance :source {:symbol :spin}
|
||||||
|
:span [0 240] :playback {:in 0 :speed 2 :end :stop
|
||||||
|
:tracks {:mouth []}}}
|
||||||
|
document (-> (clip/blank)
|
||||||
|
(assoc-in [:symbols :spin] {:frames 24 :fps 30 :nodes {}})
|
||||||
|
(assoc-in [:symbols :main :nodes :wheel] n)
|
||||||
|
(assoc-in [:symbols :main :nodes :other] (assoc n :id :other)))
|
||||||
|
id (store/install! {:clip document :store {}} "instance-playback-controls")
|
||||||
|
current #(get-in (:clip (store/entry (:clip/current @rf-db/app-db)))
|
||||||
|
[:symbols :main :nodes :wheel])]
|
||||||
|
(reset! rf-db/app-db {:clip/current id :paint/revision 0})
|
||||||
|
(rf/dispatch-sync [::project/instance-playback :main :wheel :mode :loop])
|
||||||
|
(is (= 0 (:frame (clip/placed-frame document :main (current) 24))))
|
||||||
|
(is (= :loop (get-in (current) [:playback :end])))
|
||||||
|
(is (= 2 (get-in (current) [:playback :speed])))
|
||||||
|
(rf/dispatch-sync [::project/instance-playback :main :wheel :in 5])
|
||||||
|
(rf/dispatch-sync [::project/instance-playback :main :wheel :mode :frame])
|
||||||
|
(is (= 5 (:frame (clip/placed-frame document :main (current) 100))))
|
||||||
|
(rf/dispatch-sync [::project/instance-playback :main :wheel :mode :once])
|
||||||
|
(is (nil? (clip/placed-frame document :main (current) 100)))
|
||||||
|
(is (= [0 240] (:span (current))))
|
||||||
|
(is (= {:mouth []} (get-in (current) [:playback :tracks])))
|
||||||
|
(let [before (current)]
|
||||||
|
(doseq [[field value] [[:in -1] [:speed js/Infinity] [:mode :invalid]]]
|
||||||
|
(rf/dispatch-sync [::project/instance-playback :main :wheel field value]))
|
||||||
|
(is (= before (current))))
|
||||||
|
(is (= n (assoc (get-in (:clip (store/entry (:clip/current @rf-db/app-db)))
|
||||||
|
[:symbols :main :nodes :other]) :id :wheel)))
|
||||||
|
(is (= 24 (get-in (:clip (store/entry (:clip/current @rf-db/app-db)))
|
||||||
|
[:symbols :spin :frames])))))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue