Changeset - a2faa1b70dbe
[Not reviewed]
default
0 2 0
Drew Perttula - 7 years ago 2018-05-17 07:44:34
drewp@bigasterisk.com
redoing Note draw object and note adjusters
Ignore-this: 85e32623f7696a7c8ed47ab8eac05b66
2 files changed with 52 insertions and 168 deletions:
0 comments (0 inline, 0 general)
light9/web/rdfdbclient.coffee
Show inline comments
 
@@ -9,20 +9,20 @@ if require?
 

	
 
toJsonPatch = (jsPatch, cb) ->
 
  out = {patch: {adds: '', deletes: ''}}
 

	
 
  writeDels = (cb) ->
 
    writer = N3.Writer({ format: 'N-Quads' })
 
    writer.addTriples(jsPatch.delQuads)
 
    writer.addQuads(jsPatch.delQuads)
 
    writer.end((err, result) ->
 
      out.patch.deletes = result
 
      cb())
 

	
 
  writeAdds = (cb) ->
 
    writer = N3.Writer({ format: 'N-Quads' })
 
    writer.addTriples(jsPatch.addQuads)
 
    writer.addQuads(jsPatch.addQuads)
 
    writer.end((err, result) ->
 
      out.patch.adds = result
 
      cb())
 
    
 
  async.parallel([writeDels, writeAdds], (err) ->
 
      cb(JSON.stringify(out))
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -294,13 +294,13 @@ coffeeElementSetup(class TimeZoomed exte
 
  ]
 
  constructor: ->
 
    super()
 
    @stage = new PIXI.Container()
 
    
 
    @renderer = PIXI.autoDetectRenderer({
 
         backgroundColor: 0xff6060,
 
         backgroundColor: 0x606060,
 
    })
 
     
 
  ready: ->
 
    super.ready()
 
     
 
    @addEventListener('iron-resize', @update.bind(@))
 
@@ -324,42 +324,21 @@ coffeeElementSetup(class TimeZoomed exte
 
    #ko.computed(@gatherNotes.bind(@))
 
    
 
  gatherNotes: ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    log('assign rows',@song, 'graph has', @graph.quads().length)
 
    graphics = new PIXI.Graphics({nativeLines: true})
 

	
 
    @stage.children.splice(0)
 
    noteNum = 0
 
    for uri in _.sortBy(@graph.objects(@song, U(':note')), 'uri')
 
      #should only make new ones
 
      # 
 
      #child = new Note(@graph, @selection, @dia, uri, @setAdjuster, @song, @viewState.zoomInX)
 
      originTime = @graph.floatValue(uri, U(':originTime'))
 
      effect = @graph.uriValue(uri, U(':effectClass'))
 
      for curve in @graph.objects(uri, U(':curve'))
 
        if @graph.uriValue(curve, U(':attr')).equals(U(':strength'))
 

	
 
          [@pointUris, @worldPts] = @project.getCurvePoints(curve, originTime)
 
          curveWidthCalc = () => @_curveWidth(@worldPts)
 

	
 
          h = 150 #@offsetHeight
 
          dependOn = [@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2(), @viewState.width()]
 
          screenPts = ($V([@viewState.zoomInX(pt.e(1)), @offsetTop + (1 - pt.e(2)) * h]) for pt in @worldPts)
 
          graphics.beginFill(0xFF3300);
 
          graphics.lineStyle(4, 0xffd900, 1)
 

	
 
          graphics.moveTo(screenPts[0].e(1), screenPts[0].e(2))
 
          for p in screenPts.slice(1)
 
            graphics.lineTo(p.e(1), p.e(2))
 
         graphics.endFill()
 
    
 
     @rows = []#(new NoteRow(@graph, @dia, @song, @zoomInX, @noteUris, i, @selection) for i in [0...ROW_COUNT])
 

	
 
     @stage.children.splice(0)
 
     @stage.addChild(graphics)
 
     @renderer.render(@stage)
 
      note = new Note(@project, @graph, @selection, uri, @setAdjuster, @song, @viewState, @stage, @offsetTop + 150 * (noteNum % 4))
 
      note.draw()
 
      noteNum = noteNum + 1
 
 
 
    @renderer.render(@stage)
 
    
 
  onDrop: (effect, pos) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    return unless effect and effect.match(/^http/)
 

	
 
@@ -392,74 +371,55 @@ coffeeElementSetup(class TimeAxis extend
 
      pxPerTick = 50
 
      axis = d3.axisTop(@viewState.zoomInX).ticks(@viewState.width() / pxPerTick)
 
      d3.select(@$.axis).call(axis)
 
)
 

	
 

	
 
class NoteRow
 
  constructor: (@graph, @dia, @song, @zoomInX, @noteUris, @rowIndex, @selection) ->
 
    @graph.runHandler(@update.bind(@), "row notes #{@rowIndex}")
 

	
 
  observers: [
 
    'observedUpdate(graph, song, rowIndex)'
 
    'onZoom(zoomInX)'
 
    ]
 

	
 
  observedUpdate: (graph, song, rowIndex) ->
 
    @update() # old behavior
 
    #@graph.runHandler(@update.bind(@), "row notes #{@rowIndex}")
 

	
 
  update: (patch) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    notesForThisRow = []
 
    i = 0
 
    for n in _.sortBy(@graph.objects(@song, U(':note')), 'uri')
 
      if (i % ROW_COUNT) == @rowIndex
 
        notesForThisRow.push(n)
 
      i++
 

	
 
    for newUri in notesForThisRow
 
      #should only make new ones
 
      child = new Note(@graph, @selection, @dia, newUri, @setAdjuster, @song, @zoomInX)
 
# Maintains a pixi object and some adjusters corresponding to a note
 
# in the graph.
 
class Note
 
  constructor: (@project, @graph, @selection, @uri, @setAdjuster, @song, @viewState, @stage, @rowTopY) ->
 
    @adjusterIds = {} # id : true
 

	
 
  onZoom: ->
 
    for e in @children
 
      e.zoomInX = @zoomInX
 

	
 
class Note
 
  constructor: (@graph, @selection, @dia, @uri, @setAdjuster, @song, @zoomInX)->0
 
  @is: 'light9-timeline-note'
 
  @behaviors: [ Polymer.IronResizableBehavior ]
 
  @properties:
 
    graph: { type: Object, notify: true }
 
    selection: { type: Object, notify: true }
 
    dia: { type: Object, notify: true }
 
    uri: { type: String, notify: true }
 
    zoomInX: { type: Object, notify: true }
 
    setAdjuster: {type: Function, notify: true }
 
    inlineRect: { type: Object, notify: true }
 
    song: { type: String, notify: true }
 
  @observers: [
 
    'onUri(graph, dia, uri, zoomInX, setAdjuster, song)'
 
    'update(graph, dia, uri, zoomInX, setAdjuster, song)'
 
    ]
 
  ready: ->
 
    @adjusterIds = {} # id : true
 
    @addEventListener('iron-resize', @update)
 

	
 
  detached: ->
 
    log('detatch', @uri)
 
    @dia.clearNote(@uri)
 
  destroy: ->
 
    log('destroy', @uri)
 
    # pixi rm
 
    @isDetached = true
 
    @clearAdjusters()
 

	
 
  clearAdjusters: ->
 
    for i in Object.keys(@adjusterIds)
 
      @setAdjuster(i, null)
 

	
 
  draw: ->
 
    U = (x) => @graph.Uri(x)
 
    originTime = @graph.floatValue(@uri, U(':originTime'))
 
    effect = @graph.uriValue(@uri, U(':effectClass'))
 
    graphics = new PIXI.Graphics({nativeLines: true})
 

	
 
    for curve in @graph.objects(@uri, U(':curve'))
 
      if @graph.uriValue(curve, U(':attr')).equals(U(':strength'))
 

	
 
        [pointUris, worldPts] = @project.getCurvePoints(curve, originTime)
 
        curveWidthCalc = () => @project.curveWidth(worldPts)
 

	
 
        h = 150 #@offsetHeight
 
        yForV = (v) => @rowTopY + (1 - v) * h
 
        dependOn = [@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2(), @viewState.width()]
 
        screenPts = ($V([@viewState.zoomInX(pt.e(1)), yForV(pt.e(2))]) for pt in worldPts)
 
        graphics.beginFill(0xFF3300)
 
        graphics.lineStyle(4, 0xffd900, 1)
 

	
 
        graphics.moveTo(screenPts[0].e(1), screenPts[0].e(2))
 
        for p in screenPts.slice(1)
 
          graphics.lineTo(p.e(1), p.e(2))
 
       graphics.endFill()
 
       @_updateAdjusters(screenPts, worldPts, curveWidthCalc, yForV, @song)
 
       @_updateInlineAttrs(screenPts)
 
    @stage.addChild(graphics)
 
    
 
  onUri: ->
 
    @graph.runHandler(@update.bind(@), "note updates #{@uri}")
 

	
 
  patchCouldAffectMe: (patch) ->
 
    if patch and patch.addQuads # sometimes patch is a polymer-sent value. @update is used as a listener too
 
      if patch.addQuads.length == patch.delQuads.length == 1
 
@@ -481,39 +441,19 @@ class Note
 
      return
 
    if @isDetached?
 
      return
 

	
 
    @_updateDisplay()
 

	
 
  _updateDisplay: ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    # @offsetTop causes some CSS layout to run!
 
    yForV = (v) => @offsetTop + (1 - v) * @offsetHeight
 

	
 
    originTime = @graph.floatValue(@uri, U(':originTime'))
 
    effect = @graph.uriValue(@uri, U(':effectClass'))
 
    for curve in @graph.objects(@uri, U(':curve'))
 
      if @graph.uriValue(curve, U(':attr')).equals(U(':strength'))
 

	
 
        [@pointUris, @worldPts] = @_getCurvePoints(curve, originTime)
 
        curveWidthCalc = () => @_curveWidth(@worldPts)
 
        screenPts = ($V([@zoomInX(pt.e(1)), @offsetTop + (1 - pt.e(2)) * @offsetHeight]) for pt in @worldPts)
 

	
 
        @dia.setNote(@uri, screenPts, effect)
 
        @_updateAdjusters(screenPts, curveWidthCalc, yForV, U(@song))
 
        @_updateInlineAttrs(screenPts)
 
        
 
    return
 
  _updateAdjusters: (screenPts, curveWidthCalc, yForV, ctx) ->
 
  _updateAdjusters: (screenPts, worldPts, curveWidthCalc, yForV, ctx) ->
 
    if screenPts[screenPts.length - 1].e(1) - screenPts[0].e(1) < 100
 
      @clearAdjusters()
 
    else
 
      @_makeOffsetAdjuster(yForV, curveWidthCalc, ctx)
 
      @_makeCurvePointAdjusters(yForV, @worldPts, ctx)
 
      @_makeFadeAdjusters(yForV, ctx)
 
      @_makeCurvePointAdjusters(yForV, worldPts, ctx)
 
      #@_makeFadeAdjusters(yForV, ctx)
 

	
 
  _updateInlineAttrs: (screenPts) ->
 
    leftX = Math.max(2, screenPts[Math.min(1, screenPts.length - 1)].e(1) + 5)
 
    rightX = screenPts[Math.min(2, screenPts.length - 1)].e(1) - 5
 
    if screenPts.length < 3
 
      rightX = leftX + 120
 
@@ -544,16 +484,16 @@ class Note
 
      adj = new AdjustableFloatObject({
 
        graph: @graph
 
        subj: worldPts[pointNum].uri
 
        pred: U(':time')
 
        ctx: ctx
 
        getTargetPosForValue: (value) =>
 
          $V([@zoomInX(value), yForV(worldPts[pointNum].e(2))])
 
          $V([@viewState.zoomInX(value), yForV(worldPts[pointNum].e(2))])
 
        getValueForPos: (pos) =>
 
          origin = @graph.floatValue(@uri, U(':originTime'))
 
          (@zoomInX.invert(pos.e(1)) - origin)
 
          (@viewState.zoomInX.invert(pos.e(1)) - origin)
 
        getSuggestedTargetOffset: () => @_suggestedOffset(worldPts[pointNum]),
 
      })
 
      adj._getValue = (=>
 
        # note: don't use originTime from the closure- we need the
 
        # graph dependency
 
        adj._currentValue + @graph.floatValue(@uri, U(':originTime'))
 
@@ -571,15 +511,15 @@ class Note
 
        subj: @uri
 
        pred: U(':originTime')
 
        ctx: ctx
 
        getDisplayValue: (v, dv) => "o=#{dv}"
 
        getTargetPosForValue: (value) =>
 
          # display bug: should be working from pt[0].t, not from origin
 
          $V([@zoomInX(value + curveWidthCalc() / 2), yForV(.5)])
 
          $V([@viewState.zoomInX(value + curveWidthCalc() / 2), yForV(.5)])
 
        getValueForPos: (pos) =>
 
          @zoomInX.invert(pos.e(1)) - curveWidthCalc() / 2
 
          @viewState.zoomInX.invert(pos.e(1)) - curveWidthCalc() / 2
 
        getSuggestedTargetOffset: () => $V([-10, 0])
 
      })
 
      adj
 

	
 
  _makeFadeAdjusters: (yForV, ctx) ->
 
    @_makeFadeAdjuster(yForV, ctx, @uri + '/fadeIn', 0, 1, $V([-50, -10]))
 
@@ -595,64 +535,12 @@ class Note
 
      $V([0, 30])
 
    else
 
      $V([0, -30])
 
    
 
  
 
  
 
coffeeElementSetup(class DiagramLayer extends Polymer.Element
 
  # note boxes. 
 
  @is: 'light9-timeline-diagram-layer'
 
  @getter_properties: {
 
    selection: {type: Object, notify: true}
 
  }
 
  ready: ->
 
    super.ready()
 
    @elemById = {}
 

	
 
 
 
  getOrCreateElem: (uri, groupId, tag, attrs, moreBuild) ->
 
    elem = @elemById[uri]
 
    if !elem
 
      elem = @elemById[uri] = document.createElementNS("http://www.w3.org/2000/svg", tag)
 
      @$[groupId].appendChild(elem)
 
      elem.setAttribute('id', uri)
 
      for k,v of attrs
 
        elem.setAttribute(k, v)
 
      if moreBuild
 
        moreBuild(elem)
 
    return elem
 

	
 
  _clearElem: (uri, suffixes) ->
 
    for suff in suffixes
 
      elem = @elemById[uri+suff]
 
      if elem
 
        ko.removeNode(elem)
 
        delete @elemById[uri+suff]
 

	
 
  _anyPointsInView: (pts) ->
 
    for pt in pts
 
      # wrong:
 
      if pt.e(1) > -100 && pt.e(1) < 2500
 
        return true
 
    return false
 
    
 
  setNote: (uri, curvePts, effect) ->
 
    @debounce("setNote #{uri}", () => @_setNoteThrottle(uri, curvePts, effect))
 
    
 
  _setNoteThrottle: (uri, curvePts, effect) ->
 
    areaId = uri + '/area'
 
    if not @_anyPointsInView(curvePts)
 
      @clearNote(uri)
 
      return
 

	
 
    attrs = @_noteAttrs(effect)
 
    elem = @getOrCreateElem areaId, 'notes', 'path', attrs, (elem) =>
 
      @_addNoteListeners(elem, uri)
 
    elem.setAttribute('d', Drawing.svgPathFromPoints(curvePts))
 
    @_updateNotePathClasses(uri, elem)
 

	
 
  _addNoteListeners: (elem, uri) ->
 
    elem.addEventListener 'mouseenter', =>
 
      @selection.hover(uri)
 
    elem.addEventListener 'mousedown', (ev) =>
 
      sel = @selection.selected()
 
      if ev.getModifierState('Control')
 
@@ -677,15 +565,12 @@ coffeeElementSetup(class DiagramLayer ex
 
        hash += effect.charCodeAt(i)
 
      hue = (hash * 8) % 360
 
      sat = 40 + (hash % 20) # don't conceal colorscale too much
 

	
 
    {style: "fill:hsla(#{hue}, #{sat}%, 58%, 0.313);"}
 

	
 
  clearNote: (uri) ->
 
    @_clearElem(uri, ['/area'])
 

	
 
  _noteInDiagram: (uri) ->
 
    return !!@elemById[uri + '/area']
 

	
 
  _updateNotePathClasses: (uri, elem) ->
 
    ko.computed =>
 
      return if not @_noteInDiagram(uri)
 
@@ -693,7 +578,6 @@ coffeeElementSetup(class DiagramLayer ex
 
      elem.setAttribute('class', classes)
 
    
 
    #elem = @getOrCreateElem(uri+'/label', 'noteLabels', 'text', {style: "font-size:13px;line-height:125%;font-family:'Verana Sans';text-align:start;text-anchor:start;fill:#000000;"})
 
    #elem.setAttribute('x', curvePts[0].e(1)+20)
 
    #elem.setAttribute('y', curvePts[0].e(2)-10)
 
    #elem.innerHTML = effectLabel;
 
)
 
\ No newline at end of file
0 comments (0 inline, 0 general)