# HG changeset patch # User Drew Perttula # Date 2018-06-03 10:37:00 # Node ID 792bf30de608c983fc87959e96a9d9fad1659872 # Parent 48e4e25f37a3c83256b7d44baf473825cebb0fa4 brick mode works. fix some refresh issues. Ignore-this: a613da1b0281ef8774e0df90d1e39c82 diff --git a/light9/web/timeline/brick_layout.coffee b/light9/web/timeline/brick_layout.coffee new file mode 100644 --- /dev/null +++ b/light9/web/timeline/brick_layout.coffee @@ -0,0 +1,52 @@ + +class window.BrickLayout + constructor: (@viewState, @numRows) -> + @noteRow = {} # uristr: row, t0, t1, onRowChange + + addNote: (n, onRowChange) -> + @noteRow[n.uri.value] = {row: 0, t0: 0, t1: 0, onRowChange: onRowChange} + + setNoteSpan: (n, t0, t1) -> + @noteRow[n.uri.value].t0 = t0 + @noteRow[n.uri.value].t1 = t1 + @_recompute() + + delNote: (n) -> + delete @noteRow[n.uri.value] + @_recompute() + + _recompute: -> + for u, row of @noteRow + row.prev = row.row + row.row = null + overlap = (a, b) -> a.t0 < b.t1 and a.t1 > b.t0 + + notesByWidth = _.sortBy( + ({dur: row.t1 - row.t0 + row.t0 * .0001, uri: u} for u, row of @noteRow), + 'dur') + notesByWidth.reverse() + + for n in notesByWidth + blockedRows = new Set() + for u, other of @noteRow + if other.row != null + if overlap(other, @noteRow[n.uri]) + blockedRows.add(other.row) + + for r in [0 ... @numRows] + if not blockedRows.has(r) + @noteRow[n.uri].row = r + break + if @noteRow[n.uri].row == null + log("warning: couldn't place #{n.uri}") + @noteRow[n.uri].row = 0 + if @noteRow[n.uri].row != @noteRow[n.uri].prev + @noteRow[n.uri].onRowChange() + + rowBottom: (row) -> @viewState.rowsY() + 20 + 150 * row + 140 + + yForVFor: (n) -> + row = @noteRow[n.uri.value].row + rowBottom = @rowBottom(row) + rowTop = rowBottom - 140 + (v) => rowBottom + (rowTop - rowBottom) * v diff --git a/light9/web/timeline/timeline-elements.html b/light9/web/timeline/timeline-elements.html --- a/light9/web/timeline/timeline-elements.html +++ b/light9/web/timeline/timeline-elements.html @@ -205,6 +205,7 @@ + diff --git a/light9/web/timeline/timeline.coffee b/light9/web/timeline/timeline.coffee --- a/light9/web/timeline/timeline.coffee +++ b/light9/web/timeline/timeline.coffee @@ -277,31 +277,6 @@ coffeeElementSetup(class TimelineEditor ) -class BrickLayout - constructor: (@viewState, @numRows) -> - @noteRow = {} # uristr: row, t0, t1 - addNote: (n) -> - @noteRow[n.uri.value] = {row: 0, t0: 0, t1: 0} - - setNoteSpan: (n, t0, t1) -> - @noteRow[n.uri.value].t0 = t0 - @noteRow[n.uri.value].t1 = t1 - @_recompute() - delNote: (n) -> - delete @noteRow[n.uri.value] - _recompute: -> - notesByWidth = _.sortBy([{dur: row.t1 - row.t0 + row.t0 * .0001, uri: u} for u, row of @noteRow], 'dur') - notesByWidth.reverse() - for n in notesByWidth - @noteRow[n.uri].row = 0 - - rowBottom: (row) -> @viewState.rowsY() + 20 + 150 * row + 140 - yForVFor: (n) -> - row = @noteRow[n.uri.value].row - rowBottom = @rowBottom(row) - rowTop = rowBottom - 140 - (v) => rowBottom + (rowTop - rowBottom) * v - # plan: in here, turn all the notes into simple js objects with all # their timing data and whatever's needed for adjusters. From that, do # the brick layout. update only changing adjusters. @@ -370,7 +345,6 @@ coffeeElementSetup(class TimeZoomed exte onZoom: -> updateZoomFlattened = -> - log('updateZoomFlattened') @zoomFlattened = ko.toJS(@viewState.zoomSpec) ko.computed(updateZoomFlattened.bind(@)) @@ -418,7 +392,7 @@ coffeeElementSetup(class TimeZoomed exte note = new Note(@, con, @project, @graph, @selection, uri, @setAdjuster, U(@song), @viewState, @brickLayout) # this must come before the first Note.draw @noteByUriStr.set(uri.value, note) - @brickLayout.addNote(note) + @brickLayout.addNote(note, note.onRowChange.bind(note)) note.initWatchers() _delNote: (uriStr) -> @@ -488,6 +462,7 @@ coffeeElementSetup(class TimeAxis extend class Note constructor: (@parentElem, @container, @project, @graph, @selection, @uri, @setAdjuster, @song, @viewState, @brickLayout) -> @adjusterIds = new Set() # id string + @updateSoon = _.debounce(@update.bind(@), 30) initWatchers: -> @graph.runHandler(@update.bind(@), "note update #{@uri.value}") @@ -534,19 +509,25 @@ class Note worldPts: worldPts screenPts: screenPts effect: effect + hover: @uri.equals(@selection.hover()) + selected: @selection.selected().filter((s) => s.equals(@uri)).length } + onRowChange: -> + @clearAdjusters() + @updateSoon() + redraw: (params) -> + # no observable or graph deps in here @container.removeChildren() @graphics = new PIXI.Graphics({nativeLines: false}) @graphics.interactive = true @container.addChild(@graphics) - if @uri.equals(@selection.hover()) + if params.hover @_traceBorder(params.screenPts, 12, 0x888888) - @selection.selected().forEach (s) => - if s.equals(@uri) - @_traceBorder(params.screenPts, 6, 0xff2900) + if params.selected + @_traceBorder(params.screenPts, 6, 0xff2900) shape = new PIXI.Polygon(params.screenPts) @graphics.beginFill(@_noteColor(params.effect), .313) @@ -554,6 +535,8 @@ class Note @graphics.endFill() @_traceBorder(params.screenPts, 2, 0xffd900) + + @_addMouseBindings() update: -> if not @parentElem.isActiveNote(@uri) @@ -569,8 +552,6 @@ class Note @redraw(params) - @_addMouseBindings() - curveWidthCalc = () => @project.curveWidth(@worldPts) @_updateAdjusters(params.screenPts, @worldPts, curveWidthCalc, params.yForV, @viewState.zoomInX, @song) diff --git a/light9/web/timeline/viewstate.coffee b/light9/web/timeline/viewstate.coffee --- a/light9/web/timeline/viewstate.coffee +++ b/light9/web/timeline/viewstate.coffee @@ -30,7 +30,6 @@ class window.ViewState @maintainZoomLimitsAndScales() # before other handlers run maintainZoomLimitsAndScales: () -> - log('maintainZoomLimitsAndScales') # not for cursor updates if @zoomSpec.t1() < 0