Changeset - ecce64268006
[Not reviewed]
default
0 3 0
drewp@bigasterisk.com - 9 years ago 2016-06-12 04:23:03
drewp@bigasterisk.com
big improvements to TL adjuster creation, though it still doesn't work right
Ignore-this: 661cd6d830060fb167fde5a969f59782
3 files changed with 85 insertions and 39 deletions:
0 comments (0 inline, 0 general)
light9/web/timeline/adjustable.coffee
Show inline comments
 
@@ -18,13 +18,16 @@ class Adjustable
 
    
 
    # updated later by layout algoritm
 
    @centerOffset = $V([0, 0])
 

	
 
  getDisplayValue: () ->
 
    return '' if @config.emptyBox
 
    d3.format(".4g")(@_getValue())
 
    defaultFormat = d3.format(".4g")(@_getValue())
 
    if @config.getDisplayValue?
 
      return @config.getDisplayValue(@_getValue(), defaultFormat) 
 
    defaultFormat
 

	
 
  getSuggestedCenter: () ->
 
    @getTarget().add(@config.getSuggestedTargetOffset())
 

	
 
  getCenter: () -> # vec2 of pixels
 
    @getTarget().add(@centerOffset)
light9/web/timeline/timeline-elements.html
Show inline comments
 
@@ -33,12 +33,13 @@
 
         left: 0; top: 0; right: 0; bottom: 0;
 
     }
 
     #debug {
 
      background: white;
 
      font-family: monospace;
 
      font-size: 125%;
 
      height: 15px;
 
     }
 
    </style>
 
    <div>
 
      <rdfdb-synced-graph graph="{{graph}}"></rdfdb-synced-graph>
 
      <light9-music id="music"
 
                    song="{{playerSong}}"
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -31,13 +31,15 @@ Polymer
 
  _onSongDuration: (d) ->
 
    @viewState.zoomSpec.duration(d)
 
  setSong: (s) ->
 
    @song = @playerSong if @followPlayerSong
 

	
 
  ready: ->
 
    @debug_zoomOrLayoutChangedCount = 0
 
    window.debug_zoomOrLayoutChangedCount = 0
 
    window.debug_adjUpdateDisplay = 0
 
    
 
    @viewState =
 
      zoomSpec:
 
        duration: ko.observable(100)
 
        t1: ko.observable(0) # need validation to stay in bounds and not go too close
 
        t2: ko.observable(100)
 
      cursor:
 
@@ -48,13 +50,20 @@ Polymer
 
    @zoomInX = d3.scaleLinear()
 
    @setAdjuster = @$.adjusters.setAdjuster.bind(@$.adjusters)
 

	
 
    setInterval(@updateDebugSummary.bind(@), 100)
 

	
 
  updateDebugSummary: ->
 
    @debug = "#{@debug_zoomOrLayoutChangedCount} layout change, "
 
    elemCount = (tag) -> document.getElementsByTagName(tag).length
 
    @debug = "#{window.debug_zoomOrLayoutChangedCount} layout change,
 
     #{elemCount('light9-timeline-note')} notes,
 
     #{elemCount('light9-timeline-adjuster')} adjusters,
 
     #{elemCount('light9-timeline-graph-row')} rows,
 
     #{window.debug_adjsCount} adjuster items registered,
 
     #{window.debug_adjUpdateDisplay} adjuster updateDisplay calls,
 
    "
 
    
 
  attached: ->
 
    @dia = @$.dia
 
    ko.computed(@zoomOrLayoutChanged.bind(@)).extend({rateLimit: 5})
 
    ko.computed(@songTimeChanged.bind(@))
 

	
 
@@ -64,13 +73,13 @@ Polymer
 

	
 
    @makeZoomAdjs()
 

	
 
  zoomOrLayoutChanged: ->
 
    # not for cursor updates
 

	
 
    @debug_zoomOrLayoutChangedCount++
 
    window.debug_zoomOrLayoutChangedCount++
 
    @fullZoomX.domain([0, @viewState.zoomSpec.duration()])
 
    @fullZoomX.range([0, @width()])
 

	
 
    # had trouble making notes update when this changes
 
    zoomInX = d3.scaleLinear()
 
    zoomInX.domain([@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2()])
 
@@ -162,30 +171,32 @@ Polymer
 
      margin = visSeconds * .4
 
      # buggy: really needs t1/t2 to limit their ranges
 
      if @songTime < zs.t1() or @songTime > zs.t2() - visSeconds * .6
 
        newCenter = @songTime + margin
 
        @animatedZoom(newCenter - visSeconds / 2,
 
                      newCenter + visSeconds / 2, zoomAnimSec)
 
    shortcut.add "L", =>
 
      @$.adjusters.layoutCenters()
 

	
 
  makeZoomAdjs: ->
 
    log('makeZoomAdjs', @adjs)
 
    yMid = @$.audio.offsetTop + @$.audio.offsetHeight / 2
 
    dur = @viewState.zoomSpec.duration
 
    
 
    valForPos = (pos) =>
 
        x = pos.e(1)
 
        t = @fullZoomX.invert(x)
 
    @setAdjuster('zoom-left', new AdjustableFloatObservable({
 
    @setAdjuster('zoom-left', => new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t1,
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t1()), yMid])
 
      getSuggestedTargetOffset: () => $V([-50, 0])
 
      getValueForPos: valForPos
 
    }))
 

	
 
    @setAdjuster('zoom-right', new AdjustableFloatObservable({
 
    @setAdjuster('zoom-right', => new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t2,
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t2()), yMid])
 
      getSuggestedTargetOffset: () => $V([50, 0])
 
      getValueForPos: valForPos
 
    }))
 
@@ -197,13 +208,13 @@ Polymer
 
          zs = @viewState.zoomSpec
 
          span = zs.t2() - zs.t1()
 
          zs.t1(value - span / 2)
 
          zs.t2(value + span / 2)
 
      })
 

	
 
    @setAdjuster('zoom-pan', new AdjustableFloatObservable({
 
    @setAdjuster('zoom-pan', => new AdjustableFloatObservable({
 
      observable: panObs
 
      emptyBox: true
 
      # fullzoom is not right- the sides shouldn't be able to go
 
      # offscreen
 
      getTarget: () => $V([@fullZoomX(panObs()), yMid])
 
      getSuggestedTargetOffset: () => $V([0, 0])
 
@@ -258,16 +269,20 @@ Polymer
 
        quad(newNote, U(':effectClass'), effect)
 
        quad(newNote, U(':curve'), newCurve)
 
        quad(newCurve, RDF + 'type', U(':Curve'))
 
        quad(newCurve, U(':attr'), U(':strength'))
 
      ]        
 
    pointQuads = []
 

	
 
    desiredWidthX = @offsetWidth * .1
 
    desiredWidthT = @zoomInX.invert(desiredWidthX) - @zoomInX.invert(0)
 
    
 
    for i in [0...4]
 
      pt = points[i]
 
      pointQuads.push(quad(newCurve, U(':point'), pt))
 
      pointQuads.push(quad(pt, U(':time'), @graph.LiteralRoundedFloat(i)))
 
      pointQuads.push(quad(pt, U(':time'), @graph.LiteralRoundedFloat(i/3 * desiredWidthT)))
 
      pointQuads.push(quad(pt, U(':value'), @graph.LiteralRoundedFloat(i == 1 or i == 2)))
 

	
 
    patch = {
 
      delQuads: []
 
      addQuads: curveQuads.concat(pointQuads)
 
      }
 
@@ -324,58 +339,75 @@ Polymer
 
    setAdjuster: {type: Function, notify: true}
 
  observers: [
 
    'onUri(graph, dia, uri)'
 
    'update(graph, dia, uri, zoomInX, setAdjuster)'
 
    ]
 
  ready: ->
 

	
 
    @adjusterIds = []
 
  detached: ->
 
    @dia.clearElem(@uri)
 
    for i in @adjusterIds
 
      @setAdjuster(i, null)
 

	
 
  onUri: ->
 
    @graph.runHandler(@update.bind(@), "note updates #{@uri}")
 
    
 
  update: ->
 
    # update our note DOM and SVG elements based on the graph
 
    U = (x) -> @graph.Uri(x)
 
    try
 
      worldPts = [] # (song time, value)
 

	
 
      yForV = (v) => @offsetTop + (1 - v) * @offsetHeight
 

	
 
      originTime = @graph.floatValue(@uri, U(':originTime'))
 
      for curve in @graph.objects(@uri, U(':curve'))
 
        if @graph.uriValue(curve, U(':attr')) == U(':strength')
 
          worldPts = getCurvePoints(@graph, curve, originTime)
 
          @setAdjuster(@uri+'/offset', new AdjustableFloatObject({
 

	
 
          curveWidth = =>
 
            tMin = @graph.floatValue(worldPts[0].uri, U(':time'))
 
            tMax = @graph.floatValue(worldPts[3].uri, U(':time'))
 
            tMax - tMin            
 
          
 
          @setAdjuster(@uri+'/offset', => new AdjustableFloatObject({
 
            graph: @graph
 
            subj: @uri
 
            pred: @graph.Uri(':originTime')
 
            ctx: @graph.Uri(@song)
 
            getTargetPosForValue: (value) => $V([@zoomInX(value), 600])
 
            getValueForPos: (pos) => @zoomInX.invert(pos.e(1))
 
            getSuggestedTargetOffset: () => $V([0, -80])
 
            getDisplayValue: (v, dv) => "o=#{dv}"
 
            getTargetPosForValue: (value) =>
 
              # display bug: should be working from pt[0].t, not from origin
 
              $V([@zoomInX(value + curveWidth() / 2), yForV(.5)])
 
            getValueForPos: (pos) =>
 
              @zoomInX.invert(pos.e(1)) - curveWidth() / 2
 
            getSuggestedTargetOffset: () => $V([-10, 0])
 
          }))
 

	
 
          for pointNum in [0, 2, 3]
 
            @setAdjuster(@uri+'/p'+pointNum, adj = new AdjustableFloatObject({
 
              graph: @graph
 
              subj: worldPts[pointNum].uri
 
              pred: @graph.Uri(':time')
 
              ctx: @graph.Uri(@song)
 
              getTargetPosForValue: (value) => $V([@zoomInX(value), 600])
 
              getValueForPos: (pos) =>
 
                origin = @graph.floatValue(@uri, U(':originTime'))
 
                (@zoomInX.invert(pos.e(1)) - origin)
 
              getSuggestedTargetOffset: () => $V([0, -80])
 
            }))
 
            adj._getValue = (=>
 
              # note: don't use originTime from the closure- we need the
 
              # graph dependency
 
              adj._currentValue + @graph.floatValue(@uri, U(':originTime'))
 
          for pointNum in [0, 1, 2, 3]
 
            @setAdjuster(@uri+'/p'+pointNum, =>
 
                adj = new AdjustableFloatObject({
 
                  graph: @graph
 
                  subj: worldPts[pointNum].uri
 
                  pred: @graph.Uri(':time')
 
                  ctx: @graph.Uri(@song)
 
                  getTargetPosForValue: (value) => $V([@zoomInX(value), yForV(0)])
 
                  getValueForPos: (pos) =>
 
                    origin = @graph.floatValue(@uri, U(':originTime'))
 
                    (@zoomInX.invert(pos.e(1)) - origin)
 
                  getSuggestedTargetOffset: () => $V([0, -80])
 
                })
 
                adj._getValue = (=>
 
                  # note: don't use originTime from the closure- we need the
 
                  # graph dependency
 
                  adj._currentValue + @graph.floatValue(@uri, U(':originTime'))
 
                  )
 
                log('note made this point adj', adj)
 
                adj
 
              )
 
            console.log(adj)
 
          
 
            
 
      screenPos = (pt) =>
 
        $V([@zoomInX(pt.e(1)), @offsetTop + (1 - pt.e(2)) * @offsetHeight])
 

	
 
      label = @graph.uriValue(@uri, U(':effectClass')).replace(/.*\//, '')
 
      @dia.setNote(@uri, (screenPos(pt) for pt in worldPts), label)
 

	
 
@@ -388,19 +420,29 @@ Polymer
 
    adjs: { type: Object, notify: true }, # adjId: Adjustable
 
    dia: { type: Object }
 

	
 
  ready: ->
 
    @adjs = {}
 
    
 
  setAdjuster: (adjId, adjustable) ->
 
    # callers register/unregister the Adjustables they want us
 
    # to make adjuster elements for. Caller invents adjId.
 
    adjustable.id = adjId
 
    if not @adjs[adjId] or not adjustable?
 
      @adjs[adjId] = adjustable
 
  setAdjuster: (adjId, makeAdjustable) ->
 
    # callers register/unregister the Adjustables they want us to make
 
    # adjuster elements for. Caller invents adjId.  makeAdjustable is
 
    # a function returning the Adjustable or it is null to clear any
 
    # adjusters with this id.
 

	
 
    
 
    
 
    if not @adjs[adjId] or not makeAdjustable?
 
      if not makeAdjustable?
 
        delete @adjs[adjId]
 
      else
 
        adj = makeAdjustable()
 
        @adjs[adjId] = adj
 
        adj.id = adjId
 
      @debounce('adjsChanged', @adjsChanged.bind(@), 1)
 
    window.debug_adjsCount = Object.keys(@adjs).length
 
    
 
  adjsChanged: ->
 

	
 
    added = removed = 0
 
    newIds = Object.keys(@adjs)
 

	
 
@@ -471,18 +513,18 @@ Polymer
 
  onAdj: (adj) ->
 
    log('onAdj', @id)
 
    @adj.subscribe(@updateDisplay.bind(this))
 
    @graph.runHandler(@updateDisplay.bind(@))
 

	
 
  updateDisplay: () ->
 
    log('updateDisplay', @id)
 
    window.debug_adjUpdateDisplay++
 
    @spanClass = if @adj.config.emptyBox then 'empty' else ''
 
    @displayValue = @adj.getDisplayValue()
 
    center = @adj.getCenter()
 
    target = @adj.getTarget()
 
    log('ct', center.elements, target.elements)
 
    #log("adj updateDisplay center #{center.elements} target #{target.elements}")
 
    return if isNaN(center.e(1))
 
    @centerStyle = {x: center.e(1), y: center.e(2)}
 
    @dia?.setAdjusterConnector(@adj.id + '/conn', center, target)
 
        
 
  attached: ->
 
    drag = d3.drag()
0 comments (0 inline, 0 general)