diff --git a/controllers/controller.js b/controllers/controller.js index d5b4047..59865fd 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -3,6 +3,7 @@ GUI.Controller = function() { this.parent = arguments[0]; this.object = arguments[1]; this.propertyName = arguments[2]; + this.changeListeners = []; if (arguments.length > 0) this.initialValue = this.propertyName[this.object]; @@ -20,7 +21,7 @@ GUI.Controller = function() { }; -GUI.Controller.prototype.changeFunction = null; + GUI.Controller.prototype.name = function(n) { this.propertyNameElement.innerHTML = n; @@ -44,8 +45,8 @@ GUI.Controller.prototype.unlisten = function() { GUI.Controller.prototype.setValue = function(n) { this.object[this.propertyName] = n; - if (this.changeFunction != null) { - this.changeFunction.call(this, n); + for (var i in this.changeListeners) { + this.changeListeners[i].call(this, n); } // Whenever you call setValue, the display will be updated automatically. // This reduces some clutter in subclasses. We can also use this method for listen(). @@ -59,7 +60,7 @@ GUI.Controller.prototype.getValue = function() { GUI.Controller.prototype.updateDisplay = function() {} -GUI.Controller.prototype.onChange = function(fnc) { - this.changeFunction = fnc; +GUI.Controller.prototype.addChangeListener = function(fnc) { + this.changeListeners.push(fnc); return this; } diff --git a/controllers/scrubber.js b/controllers/scrubber.js index bea770a..2edd8fe 100644 --- a/controllers/scrubber.js +++ b/controllers/scrubber.js @@ -1,7 +1,7 @@ // Would really love to make it so that as FEW changes as possible are required to gui.js in order to make this work. Would love to make it so you simply include gui.scrubber.min.js in addition to gui.min.js. GUI.Controller.prototype.at = function(when, what, tween) { - new GUI.ScrubberPoint(this.scrubber, when, what); + this.scrubber.add(new GUI.ScrubberPoint(this.scrubber, when, what)); this.scrubber.render(); return this; } @@ -14,7 +14,30 @@ GUI.Scrubber = function(controller, timer) { this.timer = timer; this.controller = controller; this.controller.scrubber = this; - + this.playing = false; + + this.sort = function() { + this.points.sort(function(a,b) { + return a.time - b.time; + }); + } + + this.add = function(p) { + this.points.push(p); + this.sort(); + } + + this.controller.addChangeListener(function(newVal) { + if (!_this.playing) { + if (_this.timer.activePoint == null) { + console.log(_this, _this.timer.playhead, newVal); + _this.timer.activePoint = new GUI.ScrubberPoint(_this, _this.timer.playhead, newVal); + _this.render(); + } else { + _this.timer.activePoint.value = newVal; + } + } + }); this.domElement = document.createElement('div'); this.domElement.setAttribute('class', 'guidat-time'); @@ -25,6 +48,7 @@ GUI.Scrubber = function(controller, timer) { this.g = canvas.getContext('2d'); var width; + var position; var height; this.__defineGetter__("width", function() { @@ -61,9 +85,12 @@ GUI.Scrubber = function(controller, timer) { this.render(); + + var onResize = function() { canvas.width = width = _this.domElement.offsetWidth; canvas.height = height = _this.domElement.offsetHeight; + position = GUI.getOffset(canvas); _this.render(); }; @@ -71,12 +98,55 @@ GUI.Scrubber = function(controller, timer) { onResize(); }, false); + var scrub = function(e) { + var t = GUI.map(e.pageX, position.left, position.left+width, _this.timer.windowMin, _this.timer.windowMin+_this.timer.windowWidth); + _this.timer.playhead = t; + } + + canvas.addEventListener('mousedown', function(e) { + if (_this.timer.hoverPoint != null) { + + _this.timer.activePoint = _this.timer.hoverPoint; + _this.timer.playhead = _this.timer.activePoint.time; + + } else { + + _this.timer.activePoint = null; + scrub(e); + document.body.style.cursor = "text"; + document.addEventListener('mousemove', scrub, false); + _this.render(); + + } + + }, false); + + canvas.addEventListener('mousemove', function(e) { + _this.timer.hoverPoint = null; + for (var i in _this.points) { + var cur = _this.points[i]; + if (cur.isHovering(e.pageX-position.left)) { + _this.timer.hoverPoint = cur; + } + } + _this.render(); + }); + + document.addEventListener('mouseup', function() { + document.body.style.cursor = "auto"; + document.removeEventListener('mousemove', scrub, false); + }, false); + + + onResize(); this.timer.addPlayListener(this.render); var onPlayChange = function(curTime, prevTime) { + _this.playing = true; + // This assumes a SORTED point array // And a PROGRESSING/INCREASING/GROWING playhead @@ -87,10 +157,10 @@ GUI.Scrubber = function(controller, timer) { var cur = _this.points[i]; if (cur.time >= curTime && i > 0) { closestToLeft = _this.points[i-1]; + break; } } - if (closestToLeft == null || closestToLeft.time > curTime) return; var n = closestToLeft.next; @@ -122,6 +192,8 @@ GUI.Scrubber = function(controller, timer) { } + _this.playing = false; + }; var pointHandlers = { @@ -151,20 +223,29 @@ GUI.ScrubberPoint = function(scrubber, time, value) { var _this = this; - scrubber.points.push(this); - scrubber.points.sort(function(a,b) { - return a.time - b.time; - }); var g = scrubber.g; var timer = scrubber.timer; var type = scrubber.controller.type; + var x, y; + + this.hold = false; + + this.value = value; + + var barSize = 4; + var rectSize = 7; + + var c1 = "#ffd800"; + var c2 = "#ff9000"; this.tween = function(t) { return t; }; - this.hold = false; + this.isHovering = function(xx) { + return xx >= x-rectSize/2 && xx <= x+rectSize/2; + }; this.__defineGetter__("next", function() { if (scrubber.points.length <= 1) { @@ -177,38 +258,28 @@ GUI.ScrubberPoint = function(scrubber, time, value) { } return scrubber.points[i+1]; + }); - - - this.value = value; - var barSize = 4; - var rectSize = 7; - - var c1 = "#ffd800"; - var c2 = "#ff9000"; - this.__defineGetter__("time", function() { return time; }); this.render = function() { - - - var x = GUI.map(time, timer.windowMin, timer.windowMin+timer.windowWidth, 0, 1); + x = GUI.map(time, timer.windowMin, timer.windowMin+timer.windowWidth, 0, 1); if (x >= 0 && x <= 1) { x = Math.round(GUI.map(x, 0, 1, 0, scrubber.width)); } + y = scrubber.height/2; + switch (type) { case "number": g.save(); - var y = scrubber.height/2; - var n = this.next; if (n != null) { @@ -240,9 +311,16 @@ GUI.ScrubberPoint = function(scrubber, time, value) { default: g.save(); g.translate(x-barSize/2, 0); - g.fillStyle = c1; + if (scrubber.timer.activePoint == this) { + g.fillStyle = "red"; // + } else if (scrubber.timer.hoverPoint == this) { + g.fillStyle = "green"; + } else { + g.fillStyle = "blue"; + } + //g.fillStyle = c1; g.fillRect(0, 0, barSize/2, scrubber.height-1); - g.fillStyle = c2; + //g.fillStyle = c2; g.fillRect(barSize/2, 0, barSize/2, scrubber.height-1); g.restore(); diff --git a/controllers/slider.js b/controllers/slider.js index 9c7c28e..6543293 100644 --- a/controllers/slider.js +++ b/controllers/slider.js @@ -17,16 +17,6 @@ GUI.Slider = function(numberController, min, max, step, initValue) { this.domElement.appendChild(this.fg); - var findPos = function(obj) { - var curleft = curtop = 0; - if (obj.offsetParent) { - do { - curleft += obj.offsetLeft; - curtop += obj.offsetTop; - } while (obj = obj.offsetParent); - return [curleft,curtop]; - } - } this.__defineSetter__('value', function(e) { var pct = GUI.map(e, min, max, 0, 100); @@ -35,8 +25,8 @@ GUI.Slider = function(numberController, min, max, step, initValue) { var onDrag = function(e) { if (!clicked) return; - var pos = findPos(_this.domElement); - var val = GUI.map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); + var pos = GUI.getOffset(_this.domElement); + var val = GUI.map(e.pageX, pos.left, pos.top + _this.domElement.offsetWidth, min, max); val = Math.round(val/step)*step; numberController.setValue(val); } diff --git a/controllers/timer.js b/controllers/timer.js index 020329d..f9a0e26 100644 --- a/controllers/timer.js +++ b/controllers/timer.js @@ -2,6 +2,9 @@ GUI.Timer = function(gui) { var _this = this; + this.hoverPoint = null; + this.activePoint = null; + this.gui = gui; this.gui.timer = this; diff --git a/gui.js b/gui.js index a8b4c93..3bcbc5c 100644 --- a/gui.js +++ b/gui.js @@ -627,6 +627,17 @@ GUI.error = function(str) { } }; +GUI.getOffset = function(obj) { + var curleft = curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while (obj = obj.offsetParent); + return {left: curleft,top: curtop}; + } +} + GUI.roundToDecimal = function(n, decimals) { var t = Math.pow(10, decimals); return Math.round(n*t)/t; diff --git a/index.html b/index.html index 323b2b4..9b0d467 100644 --- a/index.html +++ b/index.html @@ -56,12 +56,13 @@ // Sliders with min, max and increment. gui.add(fizzyText, "noiseStrength", 10, 100, 5). at(1000, 30). - at(4500, 20); + at(4500, 20). + at(7000, 100); // Boolean checkbox gui.add(fizzyText, "displayOutline") - .at(50, true) - .at(250, false); + .at(250, true) + .at(450, false); // Fires a function called "explode" gui.add(fizzyText, "explode")