diff --git a/frontend/src/arthur/events/ui.cljs b/frontend/src/arthur/events/ui.cljs index b61f2d2..c6999f0 100644 --- a/frontend/src/arthur/events/ui.cljs +++ b/frontend/src/arthur/events/ui.cljs @@ -702,7 +702,7 @@ (-> db (edit/transaction (constantly (:clip result))) (selected selection) - (update-in [:ui :expanded] (fnil into #{}) + (update-in [:ui :expanded] (fnil clojure.core/into #{}) (rest (reductions conj [] down)))))))) (rf/reg-event-db diff --git a/frontend/src/arthur/ui/icon.cljs b/frontend/src/arthur/ui/icon.cljs index d83239f..bc7cb6b 100644 --- a/frontend/src/arthur/ui/icon.cljs +++ b/frontend/src/arthur/ui/icon.cljs @@ -43,6 +43,9 @@ :stroke ["M8 4.1a2.7 2.7 0 0 1 0 3.8"]} :muted {:fill ["M2.4 4.6h1.8L6.4 2.6v6.8L4.2 7.4H2.4z"] :stroke ["M7.9 4.4 10.7 7.6" "M10.7 4.4 7.9 7.6"]} + ;; A nested timeline: the larger frame is the symbol and the inset frame is + ;; the content it owns. + :symbol {:stroke ["M1.5 2.5h9v7h-9z" "M3.5 4.5h5v3h-5z"]} ;; A strip divided into cels: what a lane IS, drawn rather than named, so one ;; row out of a dozen says at a glance that its blocks follow one another in ;; time instead of being on screen together. Whole and half coordinates, so diff --git a/frontend/src/arthur/ui/location.cljs b/frontend/src/arthur/ui/location.cljs index 1aac0a7..9b51740 100644 --- a/frontend/src/arthur/ui/location.cljs +++ b/frontend/src/arthur/ui/location.cljs @@ -26,7 +26,6 @@ [arthur.events.ui :as ui] [arthur.subs.render :as render] [arthur.subs.ui :as sub] - [arthur.ui.menu :as menu] [re-frame.core :as rf])) (defn- crumb-label @@ -140,11 +139,7 @@ crumbs (trail clip open (if (and n (seq path)) path (when n [id]))) last-i (dec (count crumbs)) shared (shared-with clip n) - says (whereabouts clip n inside) - ;; The effective parent can be an active ancestor of the primary row - ;; when the preferred occurrence is off the playhead. - destination (let [{:keys [id node]} @(rf/subscribe [::sub/creation-placement])] - (when node (crumb-label clip id node)))] + says (whereabouts clip n inside)] [:section.loc [:nav.crumbs {:aria-label "editing location"} (doall @@ -172,27 +167,4 @@ [:button.link {:title "give this cel its own copy; other cels keep sharing" :on-click #(rf/dispatch [::ui/make-unique])} "make unique"]]) - [:span.spacer] - ;; CREATION LIVES HERE because this bar is what says where it would land. - ;; `lane-model.md`: "Creation controls next to the breadcrumb act in that - ;; explicit location." Both commands read the selection, and the trail to - ;; the left of them is that selection written out. - [menu/view - {:label "new" :title "add to the document" - :items [{:label "inside" - :sub (if destination - (str "a symbol in " destination " — the outlined one") - (str "a symbol at the top of " (clip/symbol-name clip open) - ", since no nested row is active here")) - :on-click #(rf/dispatch [::ui/new-symbol :inside])} - ;; THE SECOND ITEM IS THE POINT OF THE MENU. With one item it was - ;; impossible to add anything at the top of the open symbol - ;; without first clearing the active row. - {:label "at top" - :disabled? (nil? destination) - :sub (str "a symbol straight into " (clip/symbol-name clip open) - ", ignoring the active row") - :on-click #(rf/dispatch [::ui/new-symbol :top])} - {:label "lane" - :sub (str "a row for symbol clips in " (clip/symbol-name clip open)) - :on-click #(rf/dispatch [::ui/new-lane])}]}]])) + [:span.spacer]])) diff --git a/frontend/src/arthur/ui/palette.cljs b/frontend/src/arthur/ui/palette.cljs index cf12058..444887c 100644 --- a/frontend/src/arthur/ui/palette.cljs +++ b/frontend/src/arthur/ui/palette.cljs @@ -52,7 +52,6 @@ placements @(rf/subscribe [::sub/selected-placements]) selections @(rf/subscribe [::sub/selections]) tool @(rf/subscribe [::sub/tool]) - auto? @(rf/subscribe [::sub/auto-key?]) draft @(rf/subscribe [::sub/draft])] [:div.palette-bar [:select {:value (str pid) @@ -70,13 +69,6 @@ (when (> (count selections) 1) [:span.dim (str (count selections) " selected")]) [:span {:style {:flex 1}}] - [:button.auto-key {:class (when auto? "on") - :aria-pressed auto? - :title (if auto? - "auto-key is on — edited parameters get a key at this frame" - "auto-key edited parameters at this frame") - :on-click #(rf/dispatch [::ui/toggle-auto-key])} - "◆ auto key"] (if (= :polygon tool) [:<> [:span.dim (str (quot (count draft) 2) " points")] diff --git a/frontend/src/arthur/ui/timeline.cljs b/frontend/src/arthur/ui/timeline.cljs index 3772771..fc5a684 100644 --- a/frontend/src/arthur/ui/timeline.cljs +++ b/frontend/src/arthur/ui/timeline.cljs @@ -87,15 +87,22 @@ (if (keyword? id) (subs (str id) 1) (subs (str id) 0 8)))) (defn- channel-rows [n path depth ->open span] - (for [[cpath ch] (sort-by (comp str key) (node/channels n))] - {:path (conj path cpath) - :depth depth - :label (str/join " " (map name cpath)) - :kind :channel - :select nil - :span (when (or (:dense ch) (seq (:keys ch))) span) - :keys (mapv ->open (keyed-frames ch)) - :dense? (boolean (:dense ch))})) + (let [keyed (filter (comp seq :keys val) + (sort-by (comp str key) (node/channels n)))] + (if (seq keyed) + (for [[cpath ch] keyed] + {:path (conj path cpath) + :depth depth + :label (str/join " " (map name cpath)) + :kind :channel + :select nil + :span span + :keys (mapv ->open (keyed-frames ch)) + :dense? (boolean (:dense ch))}) + [{:path (conj path ::automation-hint) + :depth depth + :kind :hint + :label "automation would show here if this track had keyframes"}]))) (defn rows "The visible rows of symbol `sid`, outermost first. `expanded` is a set of row @@ -453,6 +460,7 @@ rate @(rf/subscribe [::playback/rate]) loop? @(rf/subscribe [::playback/loop?]) muted? @(rf/subscribe [::playback/muted?]) + auto? @(rf/subscribe [::sub/auto-key?]) frame @(rf/subscribe [::playback/frame]) frames @(rf/subscribe [::render/frames]) {:keys [fps drop]} @player/meter @@ -535,6 +543,21 @@ [:button {:disabled (not cuttable?) :aria-label "trim out" :title "move the selected clip's end to the playhead" :on-click (act [::ui/trim :out])} "out"]] + [:span.sep] + [:div.group.creation-controls {:aria-label "create"} + [:button {:title "create a symbol in the selected location" + :on-click (act [::ui/new-symbol :inside])} + [icon/view :symbol] " symbol"] + [:button {:title "create a lane in the selected location" + :on-click (act [::ui/new-lane])} + [icon/view :lane] " lane"]] + [:button.auto-key {:class (when auto? "on") + :aria-pressed auto? + :title (if auto? + "auto-key is on — edited parameters get a key at this frame" + "auto-key edited parameters at this frame") + :on-click (act [::ui/toggle-auto-key])} + "◆ auto key"] [:span.spacer] ;; How many pixels a frame is. The tracks are positioned in percentages of ;; their own width, so this is one custom property on the grid and no diff --git a/static/arthur/app.css b/static/arthur/app.css index c3c82c2..6c69f65 100644 --- a/static/arthur/app.css +++ b/static/arthur/app.css @@ -787,7 +787,7 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); } border-bottom: 1px solid var(--line); } -.palette-bar .auto-key.on { +.auto-key.on { color: #145c2b; background: var(--live-bg); border-color: var(--live); @@ -985,6 +985,8 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); } .loc-fact::before, .loc-shared::before { content: "· "; color: var(--line); } .loc-shared { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 5px; } .loc .spacer { flex: 1; } +.creation-controls button { display: inline-flex; align-items: center; gap: 4px; } +.creation-controls svg { width: 11px; height: 11px; } /* -------------------------------------------------------------------------- timeline */