diff --git a/light9/web/timeline-elements.html b/light9/web/timeline-elements.html --- a/light9/web/timeline-elements.html +++ b/light9/web/timeline-elements.html @@ -26,6 +26,11 @@ position: absolute; left: 0; top: 0; right: 0; bottom: 0; } + #debug { + position: fixed; + right: 0; + bottom: 0; + }
timeline editor: song [uri] @@ -41,6 +46,7 @@ +
[[debug]]
diff --git a/light9/web/timeline.coffee b/light9/web/timeline.coffee --- a/light9/web/timeline.coffee +++ b/light9/web/timeline.coffee @@ -19,14 +19,13 @@ class Adjustable # have a associated. This object does the # layout and positioning. constructor: (@config) -> - @_center = @config.getTarget().add(@config.getSuggestedTargetOffset()) + # config has getTarget, getSuggestedTargetOffset, getValue getDisplayValue: () -> - # todo - d3.format(".4g")(@config.getValue()) + d3.format(".4g")(@_getValue()) getCenter: () -> # vec2 of pixels - @_center + @getTarget().add(@config.getSuggestedTargetOffset()) getTarget: () -> # vec2 of pixels @config.getTarget() @@ -34,11 +33,11 @@ class Adjustable subscribe: (onChange) -> # change could be displayValue or center or target. This likely # calls onChange right away if there's any data yet. - + setInterval((() => onChange()), 100) startDrag: () -> # todo - @dragStartValue = @getValue() + @dragStartValue = @_getValue() continueDrag: (pos) -> # pos is vec2 of pixels relative to the drag start @@ -50,20 +49,38 @@ class Adjustable endDrag: () -> 0 +class AdjustableFloatJsValue extends Adjustable + constructor: (@config) -> + # config has obj, key, valueLow, targetLow, valueHigh, targetHigh, getSuggestedTargetOffset, onChange + @_normalizedValue = d3.scaleLinear().domain([@config.valueLow, @config.valueHigh]).range([0, 1]) + + _getValue: () -> + @config.obj[@config.key] + + getTarget: () -> + f = @_normalizedValue(@_getValue()) + [l, h] = [@config.targetLow, @config.targetHigh] + return l.add(h.subtract(l).multiply(f)) + + continueDrag: (pos) -> + # pos is vec2 of pixels relative to the drag start + + # todo + newValue = @dragStartValue + pos.e(1) * .1 + @config.obj[@config.key] = newValue + @config.onChange() + + class AdjustableFloatObject extends Adjustable constructor: (@config) -> - # config has graph, subj, pred, ctx + # config has graph, subj, pred, ctx, getSuggestedTargetOffset super(@config) - getValue: () -> # for drag math + _getValue: () -> # for drag math @config.graph.floatValue(@config.subj, @config.pred) - getCenter: () -> - - $V([100 + 200 * @getValue(), 200]) - - getDisplayValue: () -> - d3.format(".4g")(@getValue()) + getCenter: () -> + $V([100 + 200 * @_getValue(), 200]) subscribe: (onChange) -> @config.graph.subscribe @config.subj, @config.pred, null, (patch) => @@ -81,6 +98,9 @@ Polymer behaviors: [ Polymer.IronResizableBehavior ] properties: viewState: { type: Object } + debug: {type: String, computed: '_debug(viewState.zoomSpec.t1)'} + _debug: (viewState) -> + JSON.stringify(@viewState) attached: -> @viewState = zoomSpec: @@ -95,17 +115,18 @@ Polymer animCursor = () => - @viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000) + #@viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000) @$.dia.setCursor(@$.audio.offsetTop, @$.audio.offsetHeight, - @$.zoomed.$.time.offsetTop, @$.zoomed.$.time.offsetHeight, + @$.zoomed.$.time.offsetTop, + @$.zoomed.$.time.offsetHeight, @fullZoomX, @zoomInX, @viewState.cursor) @set('viewState.zoomSpec.t1', 80 + 10 * Math.sin(Date.now() / 3000)) - setInterval(animCursor, 50) + #setInterval(animCursor, 50) setTimeout(() => - @adjs = @persistDemo()#@makeZoomAdjs().concat(@persistDemo()) + @adjs = @makeZoomAdjs().concat(@persistDemo()) , 100) persistDemo: -> @@ -130,17 +151,28 @@ Polymer ] makeZoomAdjs: -> - left = new Adjustable({ - getValue: () => (@viewState.zoomSpec.t1) - getTarget: () => $V([@fullZoomX(@viewState.zoomSpec.t1), @$.audio.offsetTop + @$.audio.offsetHeight / 2]) + + left = new AdjustableFloatJsValue({ + obj: @viewState.zoomSpec, + key: 't1' + valueLow: 0 + valueHigh: @viewState.zoomSpec.duration + targetLow: $V([0, 30]) # y = @$.audio.offsetTop + @$.audio.offsetHeight / 2] + targetHigh: $V([@offsetWidth, 30]) getSuggestedTargetOffset: () => $V([-30, 0]) - }) + onChange: () => @notifyPath('viewState.zoomSpec.t1', @viewState.zoomSpec.t1) + }) - right = new Adjustable({ - getValue: () => (@viewState.zoomSpec.t2) - getTarget: () => $V([@fullZoomX(@viewState.zoomSpec.t2), @$.audio.offsetTop + @$.audio.offsetHeight / 2]) + right = new AdjustableFloatJsValue({ + obj: @viewState.zoomSpec, + key: 't2' + valueLow: 0 + valueHigh: @viewState.zoomSpec.duration + targetLow: $V([0, 30]) # y = @$.audio.offsetTop + @$.audio.offsetHeight / 2] + targetHigh: $V([@offsetWidth, 30]) getSuggestedTargetOffset: () => $V([30, 0]) - }) + onChange: () => @notifyPath('viewState.zoomSpec.t2', @viewState.zoomSpec.t2) + }) return [left, right] @@ -160,7 +192,6 @@ Polymer type: Object onAdj: (adj) -> - console.log('adj is here', adj, @adj) @adj.subscribe () => @displayValue = @adj.getDisplayValue() center = @adj.getCenter()