Changeset - 792bf30de608
[Not reviewed]
default
0 3 1
Drew Perttula - 7 years ago 2018-06-03 10:37:00
drewp@bigasterisk.com
brick mode works. fix some refresh issues.
Ignore-this: a613da1b0281ef8774e0df90d1e39c82
4 files changed with 67 insertions and 34 deletions:
0 comments (0 inline, 0 general)
light9/web/timeline/brick_layout.coffee
Show inline comments
 
new file 100644
 

	
 
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      
light9/web/timeline/timeline-elements.html
Show inline comments
 
@@ -202,10 +202,11 @@
 
<script src="/node_modules/pixi.js/dist/pixi.min.js"></script>
 
<script src="/node_modules/tinycolor2/dist/tinycolor-min.js"></script>
 

	
 
<script src="drawing.js"></script>
 
<script src="../coffee_element.js"></script>
 
<script src="viewstate.js"></script>
 
<script src="brick_layout.js"></script>
 
<script src="adjustable.js"></script>
 
<script src="adjusters.js"></script>
 
<script src="timeline.js"></script>
 
<script src="cursor_canvas.js"></script>
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -274,37 +274,12 @@ coffeeElementSetup(class TimelineEditor 
 
      getSuggestedTargetOffset: () => $V([0, 0])
 
      getValueForPos: valForPos
 
    }))
 
)
 

	
 

	
 
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.
 
coffeeElementSetup(class TimeZoomed extends Polymer.mixinBehaviors([Polymer.IronResizableBehavior], Polymer.Element)
 
  @is: 'light9-timeline-time-zoomed'
 
  @getter_properties:
 
@@ -367,13 +342,12 @@ coffeeElementSetup(class TimeZoomed exte
 
    @brickLayout = new BrickLayout(@viewState, @numRows)
 

	
 
  noteDirty: -> @dirty()
 
    
 
  onZoom: ->
 
    updateZoomFlattened = ->
 
      log('updateZoomFlattened')
 
      @zoomFlattened = ko.toJS(@viewState.zoomSpec)
 
    ko.computed(updateZoomFlattened.bind(@))
 

	
 
  gatherNotes: ->
 
    U = (x) => @graph.Uri(x)
 
    return unless @song?
 
@@ -415,13 +389,13 @@ coffeeElementSetup(class TimeZoomed exte
 
    con.interactive=true
 
    @stage.addChild(con)
 
    
 
    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) ->
 
    n = @noteByUriStr.get(uriStr)
 
    @brickLayout.delNote(n)
 
    @stage.removeChild(n.container)
 
@@ -485,12 +459,13 @@ coffeeElementSetup(class TimeAxis extend
 

	
 
# Maintains a pixi object, some adjusters, and inlineattrs corresponding to a note
 
# in the graph.
 
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}")
 
    ko.computed @update.bind(@)
 

	
 
  destroy: ->
 
@@ -531,32 +506,40 @@ class Note
 
                                yForV(pt.e(2))) for pt in worldPts)
 
    return {
 
      yForV: yForV
 
      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)
 
    @graphics.drawShape(shape)
 
    @graphics.endFill()
 

	
 
    @_traceBorder(params.screenPts, 2, 0xffd900)
 

	
 
    @_addMouseBindings()
 
                 
 
  update: ->
 
    if not @parentElem.isActiveNote(@uri)
 
      # stale redraw call
 
      return
 

	
 
@@ -566,14 +549,12 @@ class Note
 

	
 
    params = @_planDrawing()
 
    @worldPts = params.worldPts
 

	
 
    @redraw(params)
 

	
 
    @_addMouseBindings()
 

	
 
    curveWidthCalc = () => @project.curveWidth(@worldPts)
 
    @_updateAdjusters(params.screenPts, @worldPts, curveWidthCalc,
 
                      params.yForV, @viewState.zoomInX, @song)
 
    @_updateInlineAttrs(params.screenPts, params.yForV)
 
    @parentElem.noteDirty()
 

	
light9/web/timeline/viewstate.coffee
Show inline comments
 
@@ -27,13 +27,12 @@ class window.ViewState
 
 
 
  setWidth: (w) ->
 
    @width(w)
 
    @maintainZoomLimitsAndScales() # before other handlers run
 
    
 
  maintainZoomLimitsAndScales: () ->
 
    log('maintainZoomLimitsAndScales')
 
    # not for cursor updates
 

	
 
    if @zoomSpec.t1() < 0
 
      @zoomSpec.t1(0)
 
    if @zoomSpec.duration() and @zoomSpec.t2() > @zoomSpec.duration()
 
      @zoomSpec.t2(@zoomSpec.duration())
0 comments (0 inline, 0 general)