Changeset - 6001c86f9fca
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 9 years ago 2016-06-11 21:16:06
drewp@bigasterisk.com
timeline: 1 row for now since i think the others were duplicating all notes (and also not showing them)
Ignore-this: a763f8f93b04f6473600944e9533437d
1 file changed with 2 insertions and 2 deletions:
0 comments (0 inline, 0 general)
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -116,270 +116,270 @@ Polymer
 
      scale = Math.pow(1.005, ev.deltaY)
 

	
 
      zs.t1(center - left * scale)
 
      zs.t2(center + right * scale)
 

	
 
  animatedZoom: (newT1, newT2, secs) ->
 
    fps = 30
 
    oldT1 = @viewState.zoomSpec.t1()
 
    oldT2 = @viewState.zoomSpec.t2()
 
    lastTime = 0
 
    for step in [0..secs * fps]
 
      frac = step / (secs * fps)
 
      do (frac) =>
 
        gotoStep = =>
 
          @viewState.zoomSpec.t1((1 - frac) * oldT1 + frac * newT1)
 
          @viewState.zoomSpec.t2((1 - frac) * oldT2 + frac * newT2)
 
        delay = frac * secs * 1000
 
        setTimeout(gotoStep, delay)
 
        lastTime = delay
 
    setTimeout(=>
 
        @viewState.zoomSpec.t1(newT1)
 
        @viewState.zoomSpec.t2(newT2)
 
      , lastTime + 10)  
 
    
 
  bindKeys: ->
 
    shortcut.add "Ctrl+P", (ev) =>
 
      @$.music.seekPlayOrPause(@latestMouseTime())
 

	
 
    zoomAnimSec = .1
 
    shortcut.add "Ctrl+Escape", =>
 
      @animatedZoom(0, @viewState.zoomSpec.duration(), zoomAnimSec)
 
    shortcut.add "Shift+Escape", =>
 
      @animatedZoom(@songTime - 2, @viewState.zoomSpec.duration(), zoomAnimSec)
 
    shortcut.add "Escape", =>
 
      zs = @viewState.zoomSpec
 
      visSeconds = zs.t2() - zs.t1()
 
      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)
 

	
 
  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({
 
      observable: @viewState.zoomSpec.t1,
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t1()), yMid])
 
      getSuggestedTargetOffset: () => $V([-50, 0])
 
      getValueForPos: valForPos
 
    }))
 

	
 
    @setAdjuster('zoom-right', new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t2,
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t2()), yMid])
 
      getSuggestedTargetOffset: () => $V([50, 0])
 
      getValueForPos: valForPos
 
    }))
 

	
 
    panObs = ko.pureComputed({
 
        read: () =>
 
          (@viewState.zoomSpec.t1() + @viewState.zoomSpec.t2()) / 2
 
        write: (value) =>
 
          zs = @viewState.zoomSpec
 
          span = zs.t2() - zs.t1()
 
          zs.t1(value - span / 2)
 
          zs.t2(value + span / 2)
 
      })
 

	
 
    @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])
 
      getValueForPos: valForPos
 
      }))
 
      
 

	
 
Polymer
 
  is: 'light9-timeline-time-zoomed'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  properties:
 
    graph: { type: Object, notify: true }
 
    dia: { type: Object, notify: true }
 
    song: { type: String, notify: true }
 
    zoomInX: { type: Object, notify: true }
 
    rows: { value: [0, 1, 2] }
 
    rows: { value: [0] }
 
    zoom: { type: Object, notify: true, observer: 'onZoom' }
 
    zoomFlattened: { type: Object, notify: true }
 
  onZoom: ->
 
    updateZoomFlattened = ->
 
      @zoomFlattened = ko.toJS(@zoom)
 
    ko.computed(updateZoomFlattened.bind(@))
 
  ready: ->
 

	
 
  attached: ->
 
    root = @closest('light9-timeline-editor')
 
    setupDrop @, @$.rows, root, (effect, pos) =>
 
      U = (x) -> @graph.Uri(x)
 

	
 
      # we could probably accept some initial overrides right on the
 
      # effect uri, maybe as query params
 
      
 
      if not @graph.contains(effect, RDF + 'type', U(':Effect'))
 
        log("drop #{effect} is not an effect")
 
        return
 
      
 
      dropTime = @zoomInX.invert(pos.e(1))
 
      @makeNewNote(effect, dropTime)
 
      
 
  makeNewNote: (effect, dropTime) ->
 
    U = (x) -> @graph.Uri(x)
 
    quad = (s, p, o) => {subject: s, predicate: p, object: o, graph: @song}
 
      
 
    newNote = @graph.nextNumberedResource("#{@song}/n")
 
    newCurve = @graph.nextNumberedResource("#{newNote}c")
 
    points = @graph.nextNumberedResources("#{newCurve}p", 4)
 

	
 
    curveQuads = [
 
        quad(@song, U(':note'), newNote)
 
        quad(newNote, RDF + 'type', U(':Note'))
 
        quad(newNote, U(':originTime'), @graph.LiteralRoundedFloat(dropTime))
 
        quad(newNote, U(':effectClass'), effect)
 
        quad(newNote, U(':curve'), newCurve)
 
        quad(newCurve, RDF + 'type', U(':Curve'))
 
        quad(newCurve, U(':attr'), U(':strength'))
 
      ]        
 
    pointQuads = []
 
    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(':value'), @graph.LiteralRoundedFloat(i == 1 or i == 2)))
 

	
 
    patch = {
 
      delQuads: []
 
      addQuads: curveQuads.concat(pointQuads)
 
      }
 
    @graph.applyAndSendPatch(patch)
 

	
 
Polymer
 
  is: "light9-timeline-time-axis",
 
  # for now since it's just one line calling dia,
 
  # light9-timeline-editor does our drawing work.
 

	
 
Polymer
 
  is: 'light9-timeline-graph-row'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  properties:
 
    graph: { type: Object, notify: true }
 
    dia: { type: Object, notify: true }
 
    song:  { type: String, notify: true }
 
    zoomInX: { type: Object, notify: true }
 
    noteUris: { type: Array, notify: true }
 
    rowIndex: { type: Object, notify: true }
 
  observers: [
 
    'onGraph(graph)'
 
    'update(song)'
 
    ]
 
  onGraph: ->
 
    @graph.runHandler(@update.bind(@), "row notes #{@rowIndex}")
 
  update: ->
 
    U = (x) -> @graph.Uri(x)
 

	
 
    log("row #{@rowIndex} updating")
 
    @noteUris = []
 
    for note in @graph.objects(@song, U(':note'))
 
      @push('noteUris', note)
 

	
 

	
 
getCurvePoints = (graph, curve, xOffset) ->
 
  worldPts = []
 
  for pt in graph.objects(curve, graph.Uri(':point'))
 
    v = $V([xOffset + graph.floatValue(pt, graph.Uri(':time')),
 
            graph.floatValue(pt, graph.Uri(':value'))])
 
    v.uri = pt
 
    worldPts.push(v)
 
  worldPts.sort((a,b) -> a.e(1) > b.e(1))
 
  return worldPts
 

	
 
Polymer
 
  is: 'light9-timeline-note'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  listeners: 'iron-resize': 'update'
 
  properties:
 
    graph: { type: Object, notify: true }
 
    dia: { type: Object, notify: true }
 
    uri: { type: String, notify: true }
 
    zoomInX: { type: Object, notify: true }
 
    setAdjuster: {type: Function, notify: true}
 
  observers: [
 
    'onUri(graph, dia, uri)'
 
    'update(graph, dia, uri, zoomInX, setAdjuster)'
 
    ]
 
  ready: ->
 

	
 
  detached: ->
 
    @dia.clearElem(@uri)
 

	
 
  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)
 

	
 
      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({
 
            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])
 
          }))
 

	
 
          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'))
 
              )
 
            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)
 

	
 
    catch e
 
      log("during resize of #{@uri}: #{@e}")
 

	
 
Polymer
 
  is: "light9-timeline-adjusters"
 
  properties:
 
    adjs: { type: Object, notify: true }, # adjId: Adjustable
 
    dia: { type: Object }
 

	
 
  ready: ->
 
    @adjs = {}
 
    
 
  setAdjuster: (adjId, adjustable) ->
 
    # callers register/unregister the Adjustables they want us
0 comments (0 inline, 0 general)