Coalesce continuous annotation bars into one jump point
A continuous selection across N clips is N marks → N bars, and OTIO's fractional media offsets leave ~1-frame gaps between adjacent clips, so the jump control showed "jump (5)" for a continuous stretch. merge-bars snaps bar endpoints to whole frames and joins touching ranges; only a real >=1-frame gap splits. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
fcac22fe83
commit
0d73b204e6
3 changed files with 26 additions and 1 deletions
|
|
@ -54,6 +54,21 @@
|
||||||
(when (< lo hi) [(+ c (- lo a)) (+ c (- hi a))])))
|
(when (< lo hi) [(+ c (- lo a)) (+ c (- hi a))])))
|
||||||
segs)))
|
segs)))
|
||||||
|
|
||||||
|
(defn merge-bars
|
||||||
|
"Coalesce [lo hi) ranges that meet at a frame boundary into single bars, so a
|
||||||
|
continuous selection spanning several clips reads as one piece. Endpoints snap
|
||||||
|
to whole frames first, which absorbs the sub-frame gaps OTIO's fractional
|
||||||
|
media offsets leave between adjacent clips; only a real (≥1 frame) gap splits."
|
||||||
|
[bars]
|
||||||
|
(reduce (fn [acc [lo hi]]
|
||||||
|
(let [lo (js/Math.floor lo) hi (js/Math.ceil hi)
|
||||||
|
[plo phi] (peek acc)]
|
||||||
|
(if (and plo (<= lo phi))
|
||||||
|
(conj (pop acc) [plo (max phi hi)])
|
||||||
|
(conj acc [lo hi]))))
|
||||||
|
[]
|
||||||
|
(sort-by first bars)))
|
||||||
|
|
||||||
(defn slice
|
(defn slice
|
||||||
"Sub-segments of `segs` covering local range [la lb), src + local re-cut."
|
"Sub-segments of `segs` covering local range [la lb), src + local re-cut."
|
||||||
[segs la lb]
|
[segs la lb]
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,8 @@
|
||||||
(keep (fn [[gid g]]
|
(keep (fn [[gid g]]
|
||||||
(when (and (= :annotation (:type g)) (= ctx (:parent g)))
|
(when (and (= :annotation (:type g)) (= ctx (:parent g)))
|
||||||
(let [src-segs (scene/resolve scene gid)
|
(let [src-segs (scene/resolve scene gid)
|
||||||
bars (vec (mapcat (fn [{[a b] :src}] (scene/pieces segs a b)) src-segs))
|
bars (scene/merge-bars
|
||||||
|
(mapcat (fn [{[a b] :src}] (scene/pieces segs a b)) src-segs))
|
||||||
reason (scene/broken-reason scene gid)]
|
reason (scene/broken-reason scene gid)]
|
||||||
{:id gid :name (:name g) :color (or (:color g) "#4e8fc2")
|
{:id gid :name (:name g) :color (or (:color g) "#4e8fc2")
|
||||||
:content (:content g) :children (count (:marks g))
|
:content (:content g) :children (count (:marks g))
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,15 @@
|
||||||
(is (= 0 (get-in (first marks) [:start :at])))
|
(is (= 0 (get-in (first marks) [:start :at])))
|
||||||
(is (= 30 (get-in (first marks) [:end :at])))))))
|
(is (= 30 (get-in (first marks) [:end :at])))))))
|
||||||
|
|
||||||
|
(deftest merge-bars-coalesces-continuous-run
|
||||||
|
(testing "sub-frame OTIO gaps collapse to one bar; a real gap stays split"
|
||||||
|
;; foobar's real bars (continuous 5-clip selection, ~0.9-frame source gaps)
|
||||||
|
(is (= [[128 542]]
|
||||||
|
(s/merge-bars [[128.87 190.87] [191.80 265.80] [266.73 384.73]
|
||||||
|
[385.61 413.61] [414.58 541.58]])))
|
||||||
|
(is (= [[0 50] [200 260]] (s/merge-bars [[0 50] [200 260]]))) ; real gap → two
|
||||||
|
(is (= [] (s/merge-bars [])))))
|
||||||
|
|
||||||
(deftest restore-annotations-rekeywordizes-json
|
(deftest restore-annotations-rekeywordizes-json
|
||||||
(testing "a JSON-roundtripped annotation (string :type/:parent/:ref) is restored + resolves"
|
(testing "a JSON-roundtripped annotation (string :type/:parent/:ref) is restored + resolves"
|
||||||
(let [json-like {:ann-1 {:type "annotation" :parent "root" :name "x"
|
(let [json-like {:ann-1 {:type "annotation" :parent "root" :name "x"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue