From eeec992896d13005d449ea594f1921276215cbc0 Mon Sep 17 00:00:00 2001 From: AARON WELLES Date: Wed, 19 Jun 2019 02:26:56 -0400 Subject: [PATCH 1/4] .add(controller) --- src/dat/gui/GUI.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/dat/gui/GUI.js b/src/dat/gui/GUI.js index 972c3073..aea13a60 100644 --- a/src/dat/gui/GUI.js +++ b/src/dat/gui/GUI.js @@ -1131,17 +1131,23 @@ function recallSavedValue(gui, controller) { } function add(gui, object, property, params) { - if (object[property] === undefined) { - throw new Error(`Object "${object}" has no property "${property}"`); - } - let controller; - if (params.color) { - controller = new ColorController(object, property); + if (object instanceof Controller) { + controller = object; } else { - const factoryArgs = [object, property].concat(params.factoryArgs); - controller = ControllerFactory.apply(gui, factoryArgs); + + if (object[property] === undefined) { + throw new Error(`Object "${object}" has no property "${property}"`); + } + + if (params.color) { + controller = new ColorController(object, property); + } else { + const factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + } if (params.before instanceof Controller) { From e0741f7ce9b10a9a4e3f9cb9c1f13808fafedf50 Mon Sep 17 00:00:00 2001 From: AARON WELLES Date: Wed, 19 Jun 2019 14:22:53 -0400 Subject: [PATCH 2/4] Add custom PlotterController Add to example --- example.html | 58 ++++++++---- src/dat/controllers/PlotterController.js | 69 ++++++++++++++ src/dat/gui/GUI.js | 17 ++-- src/dat/gui/_structure.scss | 16 +++- src/dat/gui/style.scss | 13 ++- src/dat/index.js | 4 +- src/dat/utils/plotter.js | 112 +++++++++++++++++++++++ 7 files changed, 261 insertions(+), 28 deletions(-) create mode 100644 src/dat/controllers/PlotterController.js create mode 100644 src/dat/utils/plotter.js diff --git a/example.html b/example.html index 2c3d7c3f..27c079b5 100644 --- a/example.html +++ b/example.html @@ -1,32 +1,36 @@ + + - + + \ No newline at end of file diff --git a/src/dat/controllers/PlotterController.js b/src/dat/controllers/PlotterController.js new file mode 100644 index 00000000..a7e26514 --- /dev/null +++ b/src/dat/controllers/PlotterController.js @@ -0,0 +1,69 @@ +/** + * dat-gui JavaScript Controller Library + * http://code.google.com/p/dat-gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +import Controller from './Controller'; +import Plotter from '../utils/plotter'; + +/** + * @class Provides a canvas that graphically displays the value of the object property at the specified interval + * + * @extends dat.controllers.Controller + * + * @param {Object} object The object to be manipulated + * @param {string} property The name of the property to be manipulated + * @param {Object} params Contains the max and period and liClass properties + */ +class PlotterController extends Controller { + constructor(object, property, params) { + super(object, property); + + params = params || {}; + + /** The graph will be these many units high */ + this.max = params.max || 3; + + /** The containing li will have this class added */ + this.liClass = params.liClass || 'plotter'; + + /** Refresh rate. Value of 0 disables auto-refresh */ + this.period = params.period; + + /** Stores the current value for comparison during animation frame */ + this.prevValue = this.getValue(); + + /** Allows acurate timing for the period to be checked during animation frame */ + this.lastUpdate = Date.now(); + + this.__panel = new Plotter(params.fgColor, params.bgColor, params.type); + this.domElement.appendChild(this.__panel.dom); + } + + updateDisplay() { + const value = this.getValue(); + if (this.period < 1 && value !== this.prevValue) { + /* Update only on value change when auto-refresh is off */ + this.__panel.update(value, this.max); + } else if ((Date.now() - this.lastUpdate) > this.period) { + /* Update if elapsed time since last update is greater than the period */ + this.__panel.update(value, this.max); + this.lastUpdate = Date.now() * 2 - this.lastUpdate - this.period; + } + + this.prevValue = value; + + return super.updateDisplay(); + } + +} + +export default PlotterController; \ No newline at end of file diff --git a/src/dat/gui/GUI.js b/src/dat/gui/GUI.js index aea13a60..d396c54e 100644 --- a/src/dat/gui/GUI.js +++ b/src/dat/gui/GUI.js @@ -20,6 +20,7 @@ import FunctionController from '../controllers/FunctionController'; import NumberControllerBox from '../controllers/NumberControllerBox'; import NumberControllerSlider from '../controllers/NumberControllerSlider'; import ColorController from '../controllers/ColorController'; +import PlotterController from '../controllers/PlotterController'; import requestAnimationFrame from '../utils/requestAnimationFrame'; import CenteredDiv from '../dom/CenteredDiv'; import dom from '../dom/dom'; @@ -125,12 +126,12 @@ const GUI = function(pars) { * @example * [ * { - * propertyName: Controller, - * anotherPropertyName: Controller - * }, + * propertyName: Controller, + * anotherPropertyName: Controller + * }, * { - * propertyName: Controller - * } + * propertyName: Controller + * } * ] */ this.__rememberedObjectIndecesToControllers = []; @@ -168,7 +169,7 @@ const GUI = function(pars) { if (params.autoPlace && common.isUndefined(params.scrollable)) { params.scrollable = true; } -// params.scrollable = common.isUndefined(params.parent) && params.scrollable === true; + // params.scrollable = common.isUndefined(params.parent) && params.scrollable === true; // Not part of params because I don't want people passing this in via // constructor. Should be a 'remembered' value. @@ -1171,6 +1172,10 @@ function add(gui, object, property, params) { dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); if (controller instanceof ColorController) { dom.addClass(li, 'color'); + } else if (controller.liClass) { + dom.addClass(li, controller.liClass); + } else if (params.liClass) { + dom.addClass(li, params.liClass); } else { dom.addClass(li, typeof controller.getValue()); } diff --git a/src/dat/gui/_structure.scss b/src/dat/gui/_structure.scss index 3193f8e0..8d750a4a 100644 --- a/src/dat/gui/_structure.scss +++ b/src/dat/gui/_structure.scss @@ -70,12 +70,15 @@ $button-height: 20px; cursor: pointer; text-align: center; background-color: #000; + &.close-top { position: relative; } + &.close-bottom { position: absolute; } + &:hover { background-color: #111; } @@ -89,13 +92,14 @@ $button-height: 20px; float: right; margin-right: 15px; - overflow-y:visible; + overflow-y: visible; &.has-save > ul { &.close-top { margin-top: 0; } + &.close-bottom { margin-top: $row-height; } @@ -112,6 +116,7 @@ $button-height: 20px; &.close-top { position: relative; } + &.close-bottom { position: fixed; } @@ -195,6 +200,12 @@ $button-height: 20px; margin-left: 0; } + /** Reduce margin and set height for plotter */ + .c canvas { + padding: 0; + height: 53px; + } + .slider { float: left; width: 66%; @@ -290,6 +301,7 @@ $button-height: 20px; background-color: #333; padding: 8px; margin-top: 10px; + code { font-size: 10px; } @@ -297,4 +309,4 @@ $button-height: 20px; #dat-gui-save-locally { display: none; -} +} \ No newline at end of file diff --git a/src/dat/gui/style.scss b/src/dat/gui/style.scss index 89705cd4..0fa8112a 100644 --- a/src/dat/gui/style.scss +++ b/src/dat/gui/style.scss @@ -63,10 +63,12 @@ $input-color: lighten($background-color, 8.5%); width: 5px; background: $background-color; } + &::-webkit-scrollbar-corner { height: 0; display: none; } + &::-webkit-scrollbar-thumb { border-radius: 5px; background: lighten($background-color, 30%); @@ -138,12 +140,17 @@ $input-color: lighten($background-color, 8.5%); border-left: 3px solid; } + &.plotter { + height: 58px; + } + &.function { border-left: 3px solid $function-color; } &.number { border-left: 3px solid $number-color; + input[type=text] { color: $number-color; } @@ -151,6 +158,7 @@ $input-color: lighten($background-color, 8.5%); &.string { border-left: 3px solid $string-color; + input[type=text] { color: $string-color; } @@ -170,9 +178,11 @@ $input-color: lighten($background-color, 8.5%); background: $input-color; outline: none; + &:hover { background: lighten($input-color, $hover-lighten); } + &:focus { background: lighten($input-color, $active-lighten); color: #fff; @@ -192,6 +202,7 @@ $input-color: lighten($background-color, 8.5%); .slider:hover { background: lighten($input-color, $hover-lighten); + .slider-fg { background: lighten($number-color, $hover-lighten); } @@ -199,4 +210,4 @@ $input-color: lighten($background-color, 8.5%); } -} +} \ No newline at end of file diff --git a/src/dat/index.js b/src/dat/index.js index 87b1a1ec..756cc326 100644 --- a/src/dat/index.js +++ b/src/dat/index.js @@ -24,6 +24,7 @@ import NumberControllerBox from './controllers/NumberControllerBox'; import NumberControllerSlider from './controllers/NumberControllerSlider'; import FunctionController from './controllers/FunctionController'; import ColorController from './controllers/ColorController'; +import PlotterController from './controllers/PlotterController'; import domImport from './dom/dom'; import GUIImport from './gui/GUI'; @@ -43,7 +44,8 @@ export const controllers = { NumberControllerBox: NumberControllerBox, NumberControllerSlider: NumberControllerSlider, FunctionController: FunctionController, - ColorController: ColorController + ColorController: ColorController, + PlotterController: PlotterController }; export const dom = { dom: domImport }; diff --git a/src/dat/utils/plotter.js b/src/dat/utils/plotter.js new file mode 100644 index 00000000..b9cb58e3 --- /dev/null +++ b/src/dat/utils/plotter.js @@ -0,0 +1,112 @@ +/** + * dat-gui JavaScript Controller Library + * http://code.google.com/p/dat-gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @author mrdoob / http://mrdoob.com/ + * Original code from stats.js r17: https://github.com/mrdoob/stats.js + * Modified by MacroMan + * Licence from that project: + + The MIT License + +Copyright (c) 2009-2016 stats.js authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ +const plotter = function(fg, bg, type) { + let min = Infinity; + let max = 0; + const round = Math.round; + const PR = round(window.devicePixelRatio || 1); + + const WIDTH = 160 * PR; + const HEIGHT = 60 * PR; + const GRAPH_X = 3 * PR; + const GRAPH_Y = 3 * PR; + const GRAPH_WIDTH = 154 * PR; + const GRAPH_HEIGHT = 54 * PR; + + const canvas = document.createElement('canvas'); + canvas.width = WIDTH; + canvas.height = HEIGHT; + + const context = canvas.getContext('2d'); + context.font = 'bold ' + (9 * PR) + 'px Helvetica,Arial,sans-serif'; + context.textBaseline = 'top'; + + context.fillStyle = bg; + context.fillRect(0, 0, WIDTH, HEIGHT); + + context.fillStyle = fg; + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + return { + dom: canvas, + update: function(value, maxValue) { + min = Math.min(min, value); + max = Math.max(max, value); + + context.globalAlpha = 1; + context.fillStyle = fg; + + // Move graph over 1px + context.drawImage(canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT); + + // Draw fg color + context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + + // Blank out above the value + context.fillRect( + GRAPH_X + GRAPH_WIDTH - PR, + GRAPH_Y, + PR, + round((1 - (value / maxValue)) * GRAPH_HEIGHT) + ); + + // Blank out below the value if line + if (type === 'line') { + context.fillRect( + GRAPH_X + GRAPH_WIDTH - PR, + round((1 - (value / maxValue)) * GRAPH_HEIGHT) + PR + 3, + PR, + round((value / maxValue) * GRAPH_HEIGHT) + ); + } + } + }; +}; + +export default plotter; \ No newline at end of file From 79af5ccfae312b0ffaf091654e5fb65e23c80910 Mon Sep 17 00:00:00 2001 From: AARON WELLES Date: Wed, 19 Jun 2019 14:35:18 -0400 Subject: [PATCH 3/4] Fixed custom PlotterController Fixed example.html --- example.html | 6 +++--- src/dat/controllers/PlotterController.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example.html b/example.html index 27c079b5..cd0c3624 100644 --- a/example.html +++ b/example.html @@ -30,7 +30,7 @@ color2: [ 0, 128, 255, 0.3 ], // RGB with alpha color3: { h: 350, s: 0.9, v: 0.3 }, // Hue, saturation, value - plotme: 0 + plotter: 0 }; var gui = new dat.gui.GUI(); @@ -63,7 +63,7 @@ f3.add(obj, 'growthSpeed'); var f4 = gui.addFolder('Custom Controllers'); - plotter = new dat.controllers.PlotterController(obj, 'plotme'); + plotter = new dat.controllers.PlotterController(obj, 'plotter'); f4.add(plotter); plotter.listen(); @@ -75,7 +75,7 @@ angle = 0; } - obj.plotme = Math.sin(angle) + 1.5; + obj.plotter = Math.sin(angle) + 1.5; }, 10); diff --git a/src/dat/controllers/PlotterController.js b/src/dat/controllers/PlotterController.js index a7e26514..3d73de79 100644 --- a/src/dat/controllers/PlotterController.js +++ b/src/dat/controllers/PlotterController.js @@ -36,7 +36,7 @@ class PlotterController extends Controller { this.liClass = params.liClass || 'plotter'; /** Refresh rate. Value of 0 disables auto-refresh */ - this.period = params.period; + this.period = params.period || 0; /** Stores the current value for comparison during animation frame */ this.prevValue = this.getValue(); @@ -44,11 +44,11 @@ class PlotterController extends Controller { /** Allows acurate timing for the period to be checked during animation frame */ this.lastUpdate = Date.now(); - this.__panel = new Plotter(params.fgColor, params.bgColor, params.type); + this.__panel = new Plotter(params.fgColor || '#fff', params.bgColor || '#000', params.type || 'line'); this.domElement.appendChild(this.__panel.dom); } - updateDisplay() { + updateDisplay () { const value = this.getValue(); if (this.period < 1 && value !== this.prevValue) { /* Update only on value change when auto-refresh is off */ From fbffd2d2e8ac92f739d1b07a33c42f90b54feba4 Mon Sep 17 00:00:00 2001 From: AARON WELLES Date: Thu, 20 Jun 2019 00:56:01 -0400 Subject: [PATCH 4/4] enabled params on add( controller, params ) ex. gui.add( new dat.controllers.PlotterController(obj, 'plotThis'),{ liClass: 'plotter' }); Also added 2 ways to call each controller on examples.html, first running through ControllerFactory, the second using .add( controller ). --- example.html | 12 +++++++++++- src/dat/gui/GUI.js | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/example.html b/example.html index cd0c3624..cb320abc 100644 --- a/example.html +++ b/example.html @@ -38,23 +38,33 @@ gui.remember(obj); gui.add(obj, 'message'); + gui.add( new dat.controllers.StringController(obj,'message') ); + gui.add(obj, 'displayOutline'); + gui.add( new dat.controllers.BooleanController(obj,'displayOutline') ); + gui.add(obj, 'explode'); gui.add(obj, 'maxSize').min(-10).max(10).step(0.25); + gui.add( new dat.controllers.NumberControllerSlider(obj, 'maxSize', -10, 10, 0.25) ); + gui.add(obj, 'height').step(5); // Increment amount + gui.add( new dat.controllers.NumberControllerBox(obj,'height',{step: 5}) ); // Choose from accepted values gui.add(obj, 'type', [ 'one', 'two', 'three' ]); + gui.add( new dat.controllers.OptionController(obj,'type',[ 'one', 'two', 'three' ]) ); // Choose from named values gui.add(obj, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 }); + gui.add( new dat.controllers.OptionController(obj, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 }) ); var f1 = gui.addFolder('Colors'); f1.addColor(obj, 'color0'); f1.addColor(obj, 'color1'); f1.addColor(obj, 'color2'); f1.addColor(obj, 'color3'); + f1.add( new dat.controllers.ColorController(obj, 'color0') ); var f2 = gui.addFolder('Another Folder'); f2.add(obj, 'noiseStrength'); @@ -64,7 +74,7 @@ var f4 = gui.addFolder('Custom Controllers'); plotter = new dat.controllers.PlotterController(obj, 'plotter'); - f4.add(plotter); + f4.add(plotter, { liClass: 'plotter' }); plotter.listen(); var angle = 0, diff --git a/src/dat/gui/GUI.js b/src/dat/gui/GUI.js index d396c54e..4c0ccbf9 100644 --- a/src/dat/gui/GUI.js +++ b/src/dat/gui/GUI.js @@ -1134,8 +1134,10 @@ function recallSavedValue(gui, controller) { function add(gui, object, property, params) { let controller; + // add( new SomeCustomerController(a,b,c), params) if (object instanceof Controller) { controller = object; + params = property || { }; } else { if (object[property] === undefined) { @@ -1172,10 +1174,10 @@ function add(gui, object, property, params) { dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); if (controller instanceof ColorController) { dom.addClass(li, 'color'); - } else if (controller.liClass) { - dom.addClass(li, controller.liClass); } else if (params.liClass) { dom.addClass(li, params.liClass); + } else if (controller.liClass) { + dom.addClass(li, controller.liClass); } else { dom.addClass(li, typeof controller.getValue()); }