mirror of
https://github.com/dataarts/dat.gui.git
synced 2024-12-12 04:08:27 +00:00
initial polymer import
This commit is contained in:
commit
8dcce60d1d
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
*.css
|
246
README.md
Normal file
246
README.md
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
# dat-gui
|
||||||
|
|
||||||
|
dat-gui creates an interface that you can use to modify variables with very little code.
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
Download the [minified library]( todo ) and include it in your html.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="gui.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create controllers by adding objects and their properties. dat-gui chooses a controller based on the variable's initial value.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var gui = new Gui();
|
||||||
|
gui.add( object, 'numberProperty', 0, 1 ); // Slider
|
||||||
|
gui.add( object, 'stringProperty' ); // Text box
|
||||||
|
gui.add( object, 'booleanProperty' ); // Check box
|
||||||
|
gui.add( object, 'functionProperty' ); // Button
|
||||||
|
```
|
||||||
|
|
||||||
|
### Limiting Input
|
||||||
|
|
||||||
|
You can specify limits on numbers. A number with a min and max value becomes a slider.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
gui.add( text, 'growthSpeed', -5, 5 ); // Min and max
|
||||||
|
gui.add( text, 'noiseStrength' ).step( 5 ); // Increment amount
|
||||||
|
gui.add( text, 'maxSize' ).min( 0 ).step( 0.25 ); // Mix and match
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also provide a list of accepted values for a dropdown.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Choose from accepted values
|
||||||
|
gui.add( text, 'message', [ 'pizza', 'chrome', 'hooray' ] );
|
||||||
|
|
||||||
|
// Choose from named values
|
||||||
|
gui.add( text, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 } );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Color Controllers
|
||||||
|
|
||||||
|
dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats.
|
||||||
|
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
text.color0 = "#ffae23"; // CSS string
|
||||||
|
text.color1 = [ 0, 128, 255 ]; // RGB array
|
||||||
|
text.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
|
||||||
|
text.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
|
||||||
|
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
gui.addColor(text, 'color0');
|
||||||
|
gui.addColor(text, 'color1');
|
||||||
|
gui.addColor(text, 'color2');
|
||||||
|
gui.addColor(text, 'color3');
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
You can listen for events on individual controllers using an event listener syntax.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var controller = gui.add(fizzyText, 'maxSize', 0, 10);
|
||||||
|
|
||||||
|
controller.onChange(function(value) {
|
||||||
|
// Fires on every change, drag, keypress, etc.
|
||||||
|
});
|
||||||
|
|
||||||
|
controller.onFinishChange(function(value) {
|
||||||
|
// Fires when a controller loses focus.
|
||||||
|
alert("The new value is " + value);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Folders & Comments
|
||||||
|
|
||||||
|
You can nest as many dat-gui as you want. Nested dat-gui act as collapsible folders.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
var f1 = gui.addFolder('Flow Field');
|
||||||
|
f1.add(text, 'speed');
|
||||||
|
f1.add(text, 'noiseStrength');
|
||||||
|
|
||||||
|
var f2 = gui.addFolder('Letters');
|
||||||
|
f2.add(text, 'growthSpeed');
|
||||||
|
f2.add(text, 'maxSize');
|
||||||
|
|
||||||
|
f2.open();
|
||||||
|
```
|
||||||
|
|
||||||
|
The comment method adds a tooltip to a controller.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
f2.add(text, 'message').comment( 'This is the comment.' );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Saving Values
|
||||||
|
|
||||||
|
Add a save menu to the interface by calling `gui.remember` on all the objects you've added to the Gui.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var fizzyText = new FizzyText();
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
gui.remember(fizzyText);
|
||||||
|
|
||||||
|
// Add controllers ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Click the gear icon to change your save settings. You can either save your dat-gui values to localStorage, or by copying and pasting a JSON object into your source code as follows:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var fizzyText = new FizzyText();
|
||||||
|
var gui = new Gui( { load: JSON } );
|
||||||
|
|
||||||
|
gui.remember( fizzyText );
|
||||||
|
|
||||||
|
// Add controllers ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Presets
|
||||||
|
|
||||||
|
The save menu also allows you to save all of your settings as presets. Click Save to modify the current preset, or New to create a new preset from existing settings. Clicking Revert will clear all unsaved changes to the current preset.
|
||||||
|
|
||||||
|
Switch between presets using the dropdown in the save menu. You can specify the default like this:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var gui = new Gui({
|
||||||
|
load: JSON,
|
||||||
|
preset: 'Flow'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
A word of caution about localStorage:
|
||||||
|
|
||||||
|
Paste the JSON save object into your source frequently. Using localStorage to save presets can make you faster, but its easy to lose your settings by clearing browsing data, changing browsers, or even by changing the URL of the page you're working on.
|
||||||
|
|
||||||
|
### Save to Disk
|
||||||
|
|
||||||
|
dat-gui comes with a node server that saves your settings to disk. This way you don't have to worry about losing your values to local storage or copying and pasting a JSON string.
|
||||||
|
|
||||||
|
First, run the node script:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ node gui-server
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, instantiate your Gui with a path to a JSON file to store settings. dat-gui will read from this file on load and write to this file on change.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var gui = new Gui( { load: 'path/to/file.json' } );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Placement
|
||||||
|
|
||||||
|
By default, Gui panels are created with fixed position, and are automatically appended to the body. You can change this behavior by setting the `autoPlace` parameter to `false`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var gui = new Gui( { autoPlace: false } );
|
||||||
|
|
||||||
|
var customContainer = document.getElementById('my-gui-container');
|
||||||
|
customContainer.appendChild(gui.domElement);
|
||||||
|
```
|
||||||
|
|
||||||
|
Since dat-gui is built using [Web Components]( todo ), you can also use HTML syntax to add controllers to the page.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<controller-number min="-2" max="2" step="1" value="0"></controller-number>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var controller = document.querySelector( 'controller-number' );
|
||||||
|
controller.onChange( function() {
|
||||||
|
|
||||||
|
// react to UI changes ...
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Defining Custom Controllers
|
||||||
|
|
||||||
|
dat-gui uses [Polymer]( todo ) under the hood to define custom elements. A dat-gui controller is just a [Polymer element]( todo ) with two important requirements:
|
||||||
|
|
||||||
|
- Controllers must extend `<controller-base>`.
|
||||||
|
- Controllers must be associated with a data type.
|
||||||
|
|
||||||
|
Take for example this (simplified) source for dat-gui's `<controller-number>`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Polymer( 'controller-number', {
|
||||||
|
|
||||||
|
// Define element ...
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Gui.register( 'controller-number', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'number';
|
||||||
|
|
||||||
|
} );
|
||||||
|
```
|
||||||
|
|
||||||
|
`Gui.register` takes an element name and a test function. The test function tells dat-gui to add a `<controller-number>` to the panel when the user adds a variable whose type is `'number'`.
|
||||||
|
|
||||||
|
A test function determines if a controller is appropriate for a given value. This example registers `<vector-controller>` for values that have properties `x`, `y` and `z`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Gui.register( 'vector-controller', function( value ) {
|
||||||
|
|
||||||
|
return value.hasOwnProperty( 'x' ) &&
|
||||||
|
value.hasOwnProperty( 'y' ) &&
|
||||||
|
value.hasOwnProperty( 'z' );
|
||||||
|
|
||||||
|
} );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publishing Custom Controllers
|
||||||
|
|
||||||
|
You should use [Bower]( todo ) and format your plugin all nice and it should have a certain prefix yada yada.
|
||||||
|
|
||||||
|
Installing third-party controllers ...
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ bower install gui-three
|
||||||
|
```
|
||||||
|
|
||||||
|
Include the source for the third-party controllers after dat-gui.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="gui.js"></script>
|
||||||
|
<script src="gui-three.js"></script>
|
||||||
|
```
|
10
TODO
Normal file
10
TODO
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
- [ ] can gui-row be baked into base-controller somehow?
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] folders
|
||||||
|
|
||||||
|
- [ ] string controller
|
||||||
|
- [ ] boolean controller
|
||||||
|
- [ ] function controller
|
||||||
|
- [ ] color controller
|
||||||
|
|
26
bower.json
Normal file
26
bower.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "polymer-gui",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Attempt at revamping dat.gui with Polymer.",
|
||||||
|
"keywords": [
|
||||||
|
"gui"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
"George Michael Brower"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"private": true,
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"polymer": "Polymer/polymer#~0.3.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"underscore": "~1.6.0"
|
||||||
|
}
|
||||||
|
}
|
1481
build/gui.html
Normal file
1481
build/gui.html
Normal file
File diff suppressed because one or more lines are too long
32
docs/examples.js
Normal file
32
docs/examples.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
var examples = {};
|
||||||
|
|
||||||
|
examples[ 'default' ] = function() {
|
||||||
|
|
||||||
|
var gui = new Gui();
|
||||||
|
gui.anon( 'hi', 'todo' );
|
||||||
|
return gui;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// "basic-usage", "limiting-input", "color-controllers", "events", "folders-comments", "saving-values", "presets", "save-to-disk", "custom-placement", "defining-custom-controllers", "publishing-custom-controllers"
|
||||||
|
examples[ 'basic-usage' ] = function() {
|
||||||
|
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
var object = {
|
||||||
|
numberProperty: 0,
|
||||||
|
stringProperty: 'hey',
|
||||||
|
booleanProperty: false,
|
||||||
|
functionProperty: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.add( object, 'numberProperty', 0, 1 ); // Slider
|
||||||
|
gui.add( object, 'stringProperty' ); // Text box
|
||||||
|
gui.add( object, 'booleanProperty' ); // Check box
|
||||||
|
gui.add( object, 'functionProperty' ); // Button
|
||||||
|
|
||||||
|
return gui;
|
||||||
|
|
||||||
|
};
|
132
docs/main.js
Normal file
132
docs/main.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
Gui.ready( init );
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
var elements = document.querySelectorAll( '#readme h3' );
|
||||||
|
|
||||||
|
for ( var i = 0; i < elements.length; i++ ) {
|
||||||
|
|
||||||
|
var initExample = examples[ elements[i].id ] || examples['default'];
|
||||||
|
|
||||||
|
elements[i].example = initExample();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sticky( elements );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sticky headers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
function sticky( elements ) {
|
||||||
|
|
||||||
|
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
|
||||||
|
|
||||||
|
el = elements[ i ];
|
||||||
|
|
||||||
|
el.sticky = el.cloneNode( true );
|
||||||
|
el.sticky.removeAttribute( 'id' );
|
||||||
|
el.sticky.style.position = 'fixed';
|
||||||
|
el.sticky.style.visibility = 'hidden';
|
||||||
|
el.sticky.style.zIndex = i;
|
||||||
|
el.sticky.classList.add( 'sticky' );
|
||||||
|
|
||||||
|
el.parentElement.insertBefore( el.sticky, el );
|
||||||
|
|
||||||
|
measure( el );
|
||||||
|
|
||||||
|
if ( i > 0 ) {
|
||||||
|
elements[ i - 1 ].next = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function measure( el ) {
|
||||||
|
|
||||||
|
el.top = el.offsetTop;
|
||||||
|
el.sticky.height = el.sticky.offsetHeight;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function resize() {
|
||||||
|
|
||||||
|
for ( var i = 0, l = elements.length; i < l; i++ ) {
|
||||||
|
|
||||||
|
measure( elements[ i ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScroll() {
|
||||||
|
|
||||||
|
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
|
||||||
|
|
||||||
|
el = elements[ i ];
|
||||||
|
|
||||||
|
var sticky = window.scrollY > el.top && window.scrollY <= el.next.top;
|
||||||
|
el.sticky.style.visibility = sticky ? 'visible' : 'hidden';
|
||||||
|
|
||||||
|
el.example.classList.toggle( 'sticky', sticky || el.bumped );
|
||||||
|
|
||||||
|
if ( el.next ) el.next.bumped = false;
|
||||||
|
|
||||||
|
if ( el.next && sticky ) {
|
||||||
|
|
||||||
|
var bottom = window.scrollY + el.sticky.height;
|
||||||
|
var bumped = bottom > el.next.top;
|
||||||
|
|
||||||
|
el.sticky.style.marginTop = Math.round( Math.min( 0, el.next.top - bottom ) ) + 'px';
|
||||||
|
el.sticky.classList.toggle( 'sticky-prev', bumped );
|
||||||
|
|
||||||
|
el.next.classList.toggle( 'sticky-next', bumped );
|
||||||
|
|
||||||
|
if ( bumped ) {
|
||||||
|
|
||||||
|
el.example.classList.remove( 'sticky' );
|
||||||
|
el.next.example.classList.add( 'sticky' );
|
||||||
|
el.next.bumped = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener( 'scroll', onScroll );
|
||||||
|
|
||||||
|
// should debounce
|
||||||
|
window.addEventListener( 'resize', function() {
|
||||||
|
|
||||||
|
resize();
|
||||||
|
onScroll();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
onScroll();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth scroll
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var body = document.body, timer;
|
||||||
|
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
clearTimeout(timer);
|
||||||
|
if(!body.classList.contains('disable-hover')) {
|
||||||
|
body.classList.add('disable-hover')
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = setTimeout(function(){
|
||||||
|
body.classList.remove('disable-hover')
|
||||||
|
}, 150);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
})();
|
78
docs/style.styl
Normal file
78
docs/style.styl
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
@import '../elements/shared.styl';
|
||||||
|
|
||||||
|
unit = 18px
|
||||||
|
body-padding = unit * 2;
|
||||||
|
|
||||||
|
readme-margin = panel-width + body-padding;
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: body-padding;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-hover,
|
||||||
|
.disable-hover * {
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, p, pre {
|
||||||
|
margin-bottom: unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: unit * 2;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: unit * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
|
||||||
|
padding: unit 0;
|
||||||
|
margin-bottom: unit * 2;
|
||||||
|
|
||||||
|
border-bottom: 1px solid rgba( 0, 0, 0, 0.2 );
|
||||||
|
transition: border-color 0.2s linear, color 0.2s linear;
|
||||||
|
|
||||||
|
&.sticky {
|
||||||
|
|
||||||
|
left: body-padding;
|
||||||
|
right: body-padding + readme-margin;
|
||||||
|
top: 0;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&.sticky-prev {
|
||||||
|
color: #eee;
|
||||||
|
border-bottom: 1px solid rgba( 0, 0, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#readme {
|
||||||
|
margin-right: readme-margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui-panel {
|
||||||
|
position: fixed;
|
||||||
|
width: panel-width;
|
||||||
|
top: 0px;
|
||||||
|
right: unit;
|
||||||
|
z-index: 9999;
|
||||||
|
transition: transform 0.4s cubic-bezier(.5,1,0,1);
|
||||||
|
transform: translate3d( 0, -200px, 0 );
|
||||||
|
&.sticky {
|
||||||
|
transform: translate3d( 0, 0, 0 );
|
||||||
|
transition-delay: 400ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
25
docs/template.html
Normal file
25
docs/template.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>dat-gui</title>
|
||||||
|
|
||||||
|
<link rel="import" href="gui.html">
|
||||||
|
<link rel="stylesheet" href="docs/style.css">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="readme"><!-- Replaced with contents of README.md --></div>
|
||||||
|
|
||||||
|
<script src="../underscore/underscore.js"></script>
|
||||||
|
|
||||||
|
<script src="docs/main.js"></script>
|
||||||
|
<script src="docs/examples.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
140
elements/Gui.js
Normal file
140
elements/Gui.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
(function( scope ) {
|
||||||
|
|
||||||
|
var ready = false;
|
||||||
|
var readyHandlers = [];
|
||||||
|
|
||||||
|
var controllers = {};
|
||||||
|
|
||||||
|
var Gui = function( params ) {
|
||||||
|
|
||||||
|
if ( !ready ) {
|
||||||
|
Gui.error( 'Gui not ready. Put your code inside Gui.ready()' );
|
||||||
|
}
|
||||||
|
|
||||||
|
params = params || {};
|
||||||
|
|
||||||
|
var panel = document.createElement( 'gui-panel' );
|
||||||
|
|
||||||
|
panel.autoPlace = params.autoPlace !== false;
|
||||||
|
|
||||||
|
if ( panel.autoPlace ) {
|
||||||
|
document.body.appendChild( panel );
|
||||||
|
}
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Register custom controllers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
Gui.register = function( elementName, test ) {
|
||||||
|
|
||||||
|
controllers[ elementName ] = test;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a controller based on a value
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
Gui.getController = function( value ) {
|
||||||
|
|
||||||
|
for ( var type in controllers ) {
|
||||||
|
|
||||||
|
var test = controllers[ type ];
|
||||||
|
|
||||||
|
if ( test( value ) ) {
|
||||||
|
|
||||||
|
return document.createElement( type );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Gui ready handler ... * shakes fist at polymer *
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
document.addEventListener( 'polymer-ready', function() {
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
readyHandlers.forEach( function( fnc ) {
|
||||||
|
|
||||||
|
fnc();
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Gui.ready = function( fnc ) {
|
||||||
|
|
||||||
|
ready ? fnc() : readyHandlers.push( fnc );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Error
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
Gui.error = function() {
|
||||||
|
var args = Array.prototype.slice.apply( arguments );
|
||||||
|
args.unshift( 'dat-gui ::' );
|
||||||
|
console.error.apply( console, args );
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui.warn = function() {
|
||||||
|
var args = Array.prototype.slice.apply( arguments );
|
||||||
|
args.unshift( 'dat-gui ::' );
|
||||||
|
console.warn.apply( console, args );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Old namespaces
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
var dat = {};
|
||||||
|
|
||||||
|
dat.gui = {};
|
||||||
|
dat.gui.GUI = Gui;
|
||||||
|
dat.GUI = dat.gui.GUI;
|
||||||
|
|
||||||
|
dat.color = {};
|
||||||
|
dat.color.Color = function() {};
|
||||||
|
|
||||||
|
dat.dom = {};
|
||||||
|
dat.dom.dom = function() {};
|
||||||
|
|
||||||
|
dat.controllers = {};
|
||||||
|
dat.controllers.Controller = constructor( 'controller-base' );
|
||||||
|
dat.controllers.NumberController = constructor( 'controller-number' );
|
||||||
|
dat.controllers.FunctionController = constructor( 'controller-function' );
|
||||||
|
dat.controllers.ColorController = constructor( 'controller-color' );
|
||||||
|
dat.controllers.BooleanController = constructor( 'controller-boolean' );
|
||||||
|
dat.controllers.OptionController = constructor( 'controller-option' );
|
||||||
|
|
||||||
|
dat.controllers.NumberControllerBox = dat.controllers.NumberController;
|
||||||
|
dat.controllers.NumberControllerSlider = dat.controllers.NumberController;
|
||||||
|
|
||||||
|
function constructor( elementName ) {
|
||||||
|
|
||||||
|
return function( object, path ) {
|
||||||
|
var el = document.createElement( elementName );
|
||||||
|
el.watch( object, path );
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Export
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
scope.dat = dat;
|
||||||
|
scope.Gui = Gui;
|
||||||
|
|
||||||
|
|
||||||
|
})( this );
|
5
elements/controller-base/controller-base.html
Normal file
5
elements/controller-base/controller-base.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
|
||||||
|
<script src="controller-base.js"></script>
|
||||||
|
|
||||||
|
<polymer-element name="controller-base" attributes="object path"></polymer-element>
|
91
elements/controller-base/controller-base.js
Normal file
91
elements/controller-base/controller-base.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
[ ] onChange( )
|
||||||
|
[ ] onFinishChange( )
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Polymer('controller-base', {
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function() {},
|
||||||
|
|
||||||
|
init: function() {},
|
||||||
|
|
||||||
|
|
||||||
|
// Observers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
watch: function( object, path ) {
|
||||||
|
|
||||||
|
this.object = object;
|
||||||
|
this.path = path;
|
||||||
|
|
||||||
|
if ( this._observer ) {
|
||||||
|
this._observer.close();
|
||||||
|
delete this._observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
this._observer = new PathObserver( this.object, this.path );
|
||||||
|
this._observer.open( function( newValue ) {
|
||||||
|
|
||||||
|
_this.value = newValue;
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.value = this.object[ this.path ];
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
valueChanged: function() {
|
||||||
|
|
||||||
|
if ( this._observer ) {
|
||||||
|
|
||||||
|
Path.get( this.path ).setValueFrom( this.object, this.value );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
map: function( x, a, b, c, d ) {
|
||||||
|
return ( x - a ) / ( b - a ) * ( d - c ) + c;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Legacy
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
listen: function() {
|
||||||
|
|
||||||
|
Gui.warn( 'controller.listen() is deprecated. All controllers are listened for free.' );
|
||||||
|
return this;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue: function() {
|
||||||
|
|
||||||
|
return this.value;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue: function( v ) {
|
||||||
|
|
||||||
|
this.value = v;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
18
elements/controller-boolean/controller-boolean.html
Normal file
18
elements/controller-boolean/controller-boolean.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../controller-base/controller-base.html">
|
||||||
|
|
||||||
|
<script src="controller-boolean.js"></script>
|
||||||
|
|
||||||
|
<polymer-element name="controller-boolean" extends="controller-base">
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="controller-boolean.css">
|
||||||
|
|
||||||
|
<label for="input" id="container" horizontal layout center>
|
||||||
|
<input id="input" type="checkbox" checked?="{{ value }}" on-change="{{ change }}">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</polymer-element>
|
30
elements/controller-boolean/controller-boolean.js
Normal file
30
elements/controller-boolean/controller-boolean.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Gui.register( 'controller-boolean', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'boolean';
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Polymer( 'controller-boolean', {
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
change: function() {
|
||||||
|
|
||||||
|
this.value = this.$.input.checked;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function() {
|
||||||
|
|
||||||
|
// should i really have to do this?
|
||||||
|
this.$.input.checked = this.value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
15
elements/controller-boolean/controller-boolean.styl
Normal file
15
elements/controller-boolean/controller-boolean.styl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@import '../shared';
|
||||||
|
|
||||||
|
#container, #input {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
// border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#input {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
20
elements/controller-function/controller-function.html
Normal file
20
elements/controller-function/controller-function.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../controller-base/controller-base.html">
|
||||||
|
|
||||||
|
<script src="controller-function.js"></script>
|
||||||
|
|
||||||
|
<polymer-element
|
||||||
|
name="controller-function"
|
||||||
|
extends="controller-base"
|
||||||
|
>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="controller-function.css">
|
||||||
|
|
||||||
|
<div id="container">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</polymer-element>
|
9
elements/controller-function/controller-function.js
Normal file
9
elements/controller-function/controller-function.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Gui.register( 'controller-function', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'function';
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Polymer( 'controller-function', {
|
||||||
|
|
||||||
|
} );
|
48
elements/controller-number/controller-number.html
Normal file
48
elements/controller-number/controller-number.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../controller-base/controller-base.html">
|
||||||
|
|
||||||
|
<script src="controller-number.js"></script>
|
||||||
|
|
||||||
|
<polymer-element
|
||||||
|
name="controller-number"
|
||||||
|
attributes="min max value step"
|
||||||
|
extends="controller-base"
|
||||||
|
>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="controller-number.css">
|
||||||
|
|
||||||
|
<div id="container" class="transition slider-{{ slider }}" horizontal layout center>
|
||||||
|
|
||||||
|
<div id="track-container"
|
||||||
|
on-down="{{ down }}"
|
||||||
|
on-up="{{ up }}"
|
||||||
|
on-trackx="{{ trackx }}"
|
||||||
|
on-tracky="{{ tracky }}"
|
||||||
|
on-trackstart="{{ trackstart }}"
|
||||||
|
horizontal layout center
|
||||||
|
hidden?="{{ !slider }}"
|
||||||
|
flex>
|
||||||
|
|
||||||
|
<div id="track">
|
||||||
|
|
||||||
|
<div id="fill"></div>
|
||||||
|
<div id="knob"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="text"
|
||||||
|
value="{{ truncate( value ) }}"
|
||||||
|
on-click="{{ click }}"
|
||||||
|
on-keydown="{{ keydown }}"
|
||||||
|
on-blur="{{ blur }}"
|
||||||
|
id="input">
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</polymer-element>
|
262
elements/controller-number/controller-number.js
Normal file
262
elements/controller-number/controller-number.js
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
[ ] arrow keys
|
||||||
|
[ ] min( ) max( ) step( ) commands of yore
|
||||||
|
|
||||||
|
[x] only validate input box on blur, not on keydown
|
||||||
|
[x] enter key blurs
|
||||||
|
[x] decimals
|
||||||
|
[x] step
|
||||||
|
[x] dy to drag friction
|
||||||
|
[x] negative slider
|
||||||
|
[x] hover behavior
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Gui.register( 'controller-number', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'number';
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Polymer( 'controller-number', {
|
||||||
|
|
||||||
|
value: 0,
|
||||||
|
decimals: 3,
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
slider: 'min !== undefined && max !== undefined'
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
window.addEventListener( 'keydown', function( e ) {
|
||||||
|
if ( e.keyCode == 18 ) _this._alt = true;
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
window.addEventListener( 'keyup', function( e ) {
|
||||||
|
if ( e.keyCode == 18 ) _this._alt = false;
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
this.super();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function( min, max, step ) {
|
||||||
|
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.step = step;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// Observers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
valueChanged: function( newValue ) {
|
||||||
|
|
||||||
|
if ( this.step !== undefined ) {
|
||||||
|
this.value = Math.round( this.value / this.step ) * this.step;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.min !== undefined ) {
|
||||||
|
this.value = Math.max( this.value, this.min );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.max !== undefined ) {
|
||||||
|
this.value = Math.min( this.value, this.max );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.super();
|
||||||
|
},
|
||||||
|
|
||||||
|
minChanged: function() {
|
||||||
|
|
||||||
|
this.value = Math.max( this.value, this.min );
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
maxChanged: function() {
|
||||||
|
|
||||||
|
this.value = Math.min( this.value, this.max );
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function() {
|
||||||
|
|
||||||
|
var ratio = this.map( this.value, this.min, this.max, 0, 1 );
|
||||||
|
|
||||||
|
if ( this.min < 0 && this.max > 0 ) {
|
||||||
|
|
||||||
|
this.$.container.classList.add( 'straddle-zero' );
|
||||||
|
|
||||||
|
var zero = this.map( 0, this.min, this.max, 0, 1 );
|
||||||
|
|
||||||
|
if ( this.value >= 0 ) {
|
||||||
|
|
||||||
|
this.$.fill.style.left = zero * 100 + '%';
|
||||||
|
this.$.fill.style.width = (ratio - zero) * 100 + '%';
|
||||||
|
this.$.fill.style.right = '';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.$.fill.style.left = '';
|
||||||
|
this.$.fill.style.width = (zero - ratio) * 100 + '%';
|
||||||
|
this.$.fill.style.right = ( 1 - zero ) * 100 + '%';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.$.container.classList.remove( 'straddle-zero' );
|
||||||
|
|
||||||
|
if ( this.max > 0 ) {
|
||||||
|
|
||||||
|
this.$.fill.style.left = 0;
|
||||||
|
this.$.fill.style.width = ratio * 100 + '%';
|
||||||
|
this.$.fill.style.right = '';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.$.fill.style.left = '';
|
||||||
|
this.$.fill.style.width = ( 1 - ratio ) * 100 + '%';
|
||||||
|
this.$.fill.style.right = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$.knob.style.left = ratio * 100 + '%';
|
||||||
|
|
||||||
|
this.$.container.classList.toggle( 'positive', this.value >= 0 );
|
||||||
|
this.$.container.classList.toggle( 'negative', this.value < 0 );
|
||||||
|
|
||||||
|
this.super();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Events
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
click: function( e ) {
|
||||||
|
|
||||||
|
this.$.input.select();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
down: function( e ) {
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
this._rect = this.$.track.getBoundingClientRect();
|
||||||
|
if ( !this._alt ) this.value = this.valueFromX( e.x );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
up: function( e ) {
|
||||||
|
|
||||||
|
// this.$.container.classList.add( 'transition' );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
trackstart: function( e ) {
|
||||||
|
|
||||||
|
// this.$.container.classList.remove( 'transition' );
|
||||||
|
this._dragFriction = 1;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
trackx: function( e ) {
|
||||||
|
|
||||||
|
if ( this.step === undefined ) {
|
||||||
|
|
||||||
|
var dv = this.valueFromDX( e.ddx );
|
||||||
|
|
||||||
|
if ( this._alt ) dv /= 10;
|
||||||
|
|
||||||
|
this.value += dv * this._dragFriction;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.value = this.valueFromX( e.pageX );
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
tracky: function( e ) {
|
||||||
|
|
||||||
|
this._dragFriction = Math.max( 0.01, Math.min( 1, this.map( e.dy, 50, 300, 1, 0.1 ) ) );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
blur: function( e ) {
|
||||||
|
|
||||||
|
var v = parseFloat( this.$.input.value );
|
||||||
|
|
||||||
|
if ( v === v ) {
|
||||||
|
this.value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
keydown: function( e ) {
|
||||||
|
|
||||||
|
if ( e.keyCode == 13 ) {
|
||||||
|
this.$.input.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
truncate: function( v ) {
|
||||||
|
|
||||||
|
if ( v % 1 !== 0 && this.decimals !== undefined ) {
|
||||||
|
return this.limitDecimals( v, this.decimals );
|
||||||
|
} else {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
limitDecimals: function( v, maxDecimals ) {
|
||||||
|
|
||||||
|
var str = v.toString();
|
||||||
|
var numDecimals = str.substring( str.indexOf( '.' ) + 1 ).length;
|
||||||
|
|
||||||
|
str = v.toFixed( Math.min( numDecimals, this.decimals ) );
|
||||||
|
|
||||||
|
for ( var z, i = 0, l = str.length; i < l; i++ ) {
|
||||||
|
if ( str.charAt( i ) !== '0' ) {
|
||||||
|
z = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.substring( 0, z+1 );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
valueFromX: function( x ) {
|
||||||
|
|
||||||
|
return this.map( x, this._rect.left, this._rect.right, this.min, this.max );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
valueFromDX: function( dx ) {
|
||||||
|
|
||||||
|
return this.map( dx, 0, this._rect.width, 0, this.max - this.min );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
105
elements/controller-number/controller-number.styl
Normal file
105
elements/controller-number/controller-number.styl
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
@import '../shared';
|
||||||
|
|
||||||
|
fill-color = number-color
|
||||||
|
track-color = light
|
||||||
|
|
||||||
|
track-size = 1px;
|
||||||
|
fill-size = 1px;
|
||||||
|
knob-size = 6px
|
||||||
|
|
||||||
|
#container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#track-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#track {
|
||||||
|
width: 100%;
|
||||||
|
height: track-size;
|
||||||
|
border-radius: track-size;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
background: track-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fill {
|
||||||
|
height: fill-size;
|
||||||
|
margin-top: ( ( track-size - fill-size ) / 2 );
|
||||||
|
margin-left: 1px;
|
||||||
|
border-radius: fill-size;
|
||||||
|
position: absolute;
|
||||||
|
background: fill-color;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#knob {
|
||||||
|
|
||||||
|
width: knob-size;
|
||||||
|
height: knob-size;
|
||||||
|
|
||||||
|
margin-left: -( knob-size / 2 );
|
||||||
|
margin-top: -( knob-size / 2 );
|
||||||
|
|
||||||
|
transition: transform 0.1s ease;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
background-color: fill-color;
|
||||||
|
border-radius: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#track-container:hover #knob {
|
||||||
|
transform: scale( 2 )
|
||||||
|
}
|
||||||
|
|
||||||
|
#track-container:active #knob {
|
||||||
|
transform: scale( 1.5 )
|
||||||
|
}
|
||||||
|
|
||||||
|
// .transition #knob {
|
||||||
|
// transition: left 0.2s ease, transform 0.1s ease;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .transition #fill {
|
||||||
|
// transition: left 0.2s ease, right 0.2s ease, width 0.2s ease;
|
||||||
|
// }
|
||||||
|
|
||||||
|
input {
|
||||||
|
|
||||||
|
input()
|
||||||
|
|
||||||
|
.slider-true & {
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
margin-left: padding;
|
||||||
|
width: 25%;
|
||||||
|
transition: width 0.2s ease;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.slider-false & {
|
||||||
|
// border-bottom: 1px solid number-color;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input::selection {
|
||||||
|
background-color: number-color;
|
||||||
|
}
|
19
elements/controller-string/controller-string.html
Normal file
19
elements/controller-string/controller-string.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../controller-base/controller-base.html">
|
||||||
|
|
||||||
|
<script src="controller-string.js"></script>
|
||||||
|
|
||||||
|
<polymer-element
|
||||||
|
name="controller-string"
|
||||||
|
extends="controller-base"
|
||||||
|
>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="controller-string.css">
|
||||||
|
|
||||||
|
<input id="input" type="text" value="{{ value }}">
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</polymer-element>
|
10
elements/controller-string/controller-string.js
Normal file
10
elements/controller-string/controller-string.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Gui.register( 'controller-string', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'string';
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Polymer( 'controller-string', {
|
||||||
|
|
||||||
|
|
||||||
|
});
|
10
elements/controller-string/controller-string.styl
Normal file
10
elements/controller-string/controller-string.styl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@import '../shared';
|
||||||
|
|
||||||
|
:host
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
input
|
||||||
|
input();
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: string-color;
|
30
elements/gui-panel/gui-panel.html
Normal file
30
elements/gui-panel/gui-panel.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../gui-row/gui-row.html">
|
||||||
|
|
||||||
|
<polymer-element
|
||||||
|
name="gui-panel"
|
||||||
|
attributes="docked autoplace open">
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="gui-panel.css">
|
||||||
|
|
||||||
|
<div id="container" class="docked-{{ docked }} autoplace-{{ autoPlace }} open-{{ open }}">
|
||||||
|
|
||||||
|
<div id="controllers">
|
||||||
|
<content></content>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="closeButton" on-tap="{{ tapClose }}" hidden?="{{ docked }}">{{ open ? 'Close' : 'Open' }} Controls</div>
|
||||||
|
|
||||||
|
<div id="closeButtonDocked" on-tap="{{ tapClose }}" hidden?="{{ !docked }}">
|
||||||
|
<div id="closeButtonDockedInner"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="gui-panel.js"></script>
|
||||||
|
|
||||||
|
</polymer-element>
|
143
elements/gui-panel/gui-panel.js
Normal file
143
elements/gui-panel/gui-panel.js
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
[ ] kill horizontal scroll when docked
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Polymer('gui-panel', {
|
||||||
|
|
||||||
|
docked: false,
|
||||||
|
open: true,
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
this.anon.values = {};
|
||||||
|
|
||||||
|
window.addEventListener( 'resize', this.checkHeight.bind( this ) );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
anon: function() {
|
||||||
|
|
||||||
|
if ( arguments.length == 1 ) {
|
||||||
|
var name = arguments[ 0 ];
|
||||||
|
return this.anon.values[ name ];
|
||||||
|
}
|
||||||
|
|
||||||
|
var initialValue = arguments[ 0 ];
|
||||||
|
var name = arguments[ 1 ];
|
||||||
|
|
||||||
|
var args = [ this.anon.values, name ];
|
||||||
|
args = args.concat( Array.prototype.slice.call( arguments, 2 ) );
|
||||||
|
|
||||||
|
this.anon.values[ name ] = initialValue;
|
||||||
|
|
||||||
|
return this.add.apply( this, args );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function( object, path ) {
|
||||||
|
|
||||||
|
// Make controller
|
||||||
|
|
||||||
|
var value = Path.get( path ).getValueFrom( object );
|
||||||
|
|
||||||
|
if ( value == null || value == undefined ) {
|
||||||
|
return Gui.error( object + ' doesn\'t have a value for path "' + path + '".' );
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = Array.prototype.slice.call( arguments, 2 );
|
||||||
|
|
||||||
|
var controller = Gui.getController( value, args );
|
||||||
|
|
||||||
|
if ( !controller ) {
|
||||||
|
return Gui.error( 'Unrecognized type:', value );
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.watch( object, path )
|
||||||
|
controller.init.apply( controller, args );
|
||||||
|
|
||||||
|
// Make row
|
||||||
|
|
||||||
|
var row = document.createElement( 'gui-row' );
|
||||||
|
row.name = path;
|
||||||
|
|
||||||
|
controller.row = row;
|
||||||
|
|
||||||
|
controller.name = function( name ) {
|
||||||
|
row.name = name;
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.comment = function( comment ) {
|
||||||
|
row.comment = comment;
|
||||||
|
};
|
||||||
|
|
||||||
|
row.appendChild( controller );
|
||||||
|
this.appendChild( row );
|
||||||
|
|
||||||
|
return controller;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Observers
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
openChanged: function() {
|
||||||
|
|
||||||
|
if ( this.open || this.docked ) {
|
||||||
|
|
||||||
|
// let the style sheet take care of things
|
||||||
|
|
||||||
|
this.$.container.style.transform = '';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// todo: need the rest of the vendor prefixes ...
|
||||||
|
// wish i could pipe javascript variables into styl.
|
||||||
|
|
||||||
|
var y = -this.$.controllers.offsetHeight + 'px';
|
||||||
|
this.$.container.style.transform = 'translate3d(0, ' + y + ', 0)';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
dockedChanged: function() {
|
||||||
|
|
||||||
|
this.openChanged();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Events
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
tapClose: function() {
|
||||||
|
this.open = !this.open;
|
||||||
|
},
|
||||||
|
|
||||||
|
checkHeight: function() {
|
||||||
|
|
||||||
|
if ( window.innerHeight < this.$.controllers.offsetHeight ) {
|
||||||
|
this.docked = true;
|
||||||
|
} else {
|
||||||
|
this.docked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Legacy
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
listenAll: function() {
|
||||||
|
|
||||||
|
Gui.warn( 'controller.listenAll() is deprecated. All controllers are listened for free.' );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// todo: domElement
|
||||||
|
|
||||||
|
});
|
93
elements/gui-panel/gui-panel.styl
Normal file
93
elements/gui-panel/gui-panel.styl
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
@import '../shared';
|
||||||
|
|
||||||
|
#controllers {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
|
||||||
|
background: panel-color;
|
||||||
|
transition: transform 0.4s cubic-bezier( 0, 0.8, 0, 1 );
|
||||||
|
|
||||||
|
&.autoplace-true {
|
||||||
|
|
||||||
|
width: panel-width;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
&.docked-false {
|
||||||
|
|
||||||
|
right: 20px;
|
||||||
|
|
||||||
|
&.open-true {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open-false {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.docked-true {
|
||||||
|
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
&.open-true {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open-false {
|
||||||
|
transform: translate3d( panel-width, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#closeButton {
|
||||||
|
|
||||||
|
panel-font()
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
padding: padding * 0.75 padding;
|
||||||
|
background: black;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: panel-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeButtonDocked {
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
right: panel-width;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
color: black;
|
||||||
|
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeButtonDockedInner {
|
||||||
|
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
}
|
42
elements/gui-row/gui-row.html
Normal file
42
elements/gui-row/gui-row.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
|
||||||
|
<polymer-element name="gui-row" attributes="name comment">
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="gui-row.css">
|
||||||
|
|
||||||
|
<div id="row" class="comment-{{ comment != null }}" layout horizontal>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="name"
|
||||||
|
on-mouseover="{{ openComment }}"
|
||||||
|
on-mouseout="{{ closeComment }}"
|
||||||
|
layout horizontal center
|
||||||
|
>
|
||||||
|
|
||||||
|
<div id="nameInner">{{ name }}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="controller" flex>
|
||||||
|
<content></content>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="comment" class="open-{{ commentOpen }}" hidden?="{{ comment == null }}">
|
||||||
|
|
||||||
|
<div id="commentInner">{{ comment }}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="gui-row.js"></script>
|
||||||
|
|
||||||
|
</polymer-element>
|
27
elements/gui-row/gui-row.js
Normal file
27
elements/gui-row/gui-row.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
[ ] comment hover behavior
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Polymer('gui-row', {
|
||||||
|
|
||||||
|
comment: null,
|
||||||
|
|
||||||
|
commentOpen: false,
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
openComment: function() {
|
||||||
|
this.commentOpen = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
closeComment: function() {
|
||||||
|
this.commentOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
106
elements/gui-row/gui-row.styl
Normal file
106
elements/gui-row/gui-row.styl
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
@import '../shared';
|
||||||
|
|
||||||
|
|
||||||
|
:host {
|
||||||
|
|
||||||
|
panel-font()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#row {
|
||||||
|
|
||||||
|
|
||||||
|
debug( blue )
|
||||||
|
|
||||||
|
height: min-row-height;
|
||||||
|
transition: background-color 0.2s linear;
|
||||||
|
border-bottom: 1px solid lighter;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
// background-color: #262626;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#controller {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#name {
|
||||||
|
|
||||||
|
debug( magenta )
|
||||||
|
|
||||||
|
// overflow: hidden;
|
||||||
|
padding: 0 padding;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 40%;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
.comment-true & {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#nameInner {
|
||||||
|
|
||||||
|
debug( red );
|
||||||
|
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment {
|
||||||
|
|
||||||
|
line-height: 16px;
|
||||||
|
user-select: text;
|
||||||
|
|
||||||
|
background: #E0CF99;
|
||||||
|
color: #333;
|
||||||
|
// box-shadow: inset 0 2px 0 dark;
|
||||||
|
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 0.15s ease;
|
||||||
|
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d( 0, 20px, 0 );
|
||||||
|
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment.open-true {
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
transition-delay: 200ms;
|
||||||
|
transform: translate3d( 0, 0, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#commentInner {
|
||||||
|
padding: padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-true #nameInner {
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px dotted light;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
// content: ' ?';
|
||||||
|
// color: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
elements/shared.styl
Normal file
52
elements/shared.styl
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
@import 'nib';
|
||||||
|
|
||||||
|
// config
|
||||||
|
|
||||||
|
support-for-ie ?= true
|
||||||
|
use-debug = false
|
||||||
|
|
||||||
|
debug( color )
|
||||||
|
if use-debug
|
||||||
|
border: 1px solid color
|
||||||
|
|
||||||
|
// constants
|
||||||
|
|
||||||
|
panel-width = 245px
|
||||||
|
min-row-height = 30px
|
||||||
|
|
||||||
|
font-color = #eee
|
||||||
|
panel-color = #1a1a1a
|
||||||
|
|
||||||
|
number-color = #25A0D8
|
||||||
|
string-color = #1EBD6E
|
||||||
|
|
||||||
|
padding = 8px
|
||||||
|
|
||||||
|
ease = cubic-bezier( .25, .25, 0, 1 )
|
||||||
|
|
||||||
|
light = rgba( 255, 255, 255, 0.25 )
|
||||||
|
lighter = rgba( 255, 255, 255, 0.05 )
|
||||||
|
|
||||||
|
dark = rgba( 0, 0, 0, 0.1 );
|
||||||
|
|
||||||
|
// common
|
||||||
|
|
||||||
|
panel-font()
|
||||||
|
font: 10px 'Lucida Grande', sans-serif;
|
||||||
|
color: font-color;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
||||||
|
input()
|
||||||
|
panel-font()
|
||||||
|
color: text-color;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
outline: none;
|
||||||
|
padding-left: padding;
|
||||||
|
transition: background-color 0.15s linear;
|
||||||
|
box-sizing: border-box;
|
||||||
|
&:hover, &:focus
|
||||||
|
background: lighter
|
34
examples/controller-custom/controller-custom.html
Normal file
34
examples/controller-custom/controller-custom.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<link rel="import" href="../../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../elements/controller-number/controller-number.html">
|
||||||
|
|
||||||
|
<polymer-element name="controller-vector" extends="controller-base">
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<controller-number id="x" object="{{ value }}" path="x" min="-1"></controller-number>
|
||||||
|
<controller-number id="y" object="{{ value }}" path="y" min="-1"></controller-number>
|
||||||
|
<controller-number id="z" object="{{ value }}" path="z" min="-2"></controller-number>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Gui.register( 'controller-vector', function( value ) {
|
||||||
|
|
||||||
|
return value instanceof THREE.Vector3;
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Polymer('controller-vector', {
|
||||||
|
|
||||||
|
ready: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</polymer-element>
|
76
examples/index.html
Normal file
76
examples/index.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>dat-gui kitchen sink</title>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var src = '../gui.html';
|
||||||
|
if ( location.search == '?built' ) src = '../build/gui.html';
|
||||||
|
document.write( '<link rel="import" href="'+src+'">' );
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
background: #aaa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
body content.
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var object = {
|
||||||
|
"listen4Free": 332,
|
||||||
|
"zeroTo1": 0,
|
||||||
|
"step": 10,
|
||||||
|
"straddleZero": 0,
|
||||||
|
"maxIsNegative": -2,
|
||||||
|
"hasComment": 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// How do we kill polymer-ready ...
|
||||||
|
Gui.ready( function() {
|
||||||
|
|
||||||
|
gui = new dat.GUI();
|
||||||
|
|
||||||
|
gui.docked = true;
|
||||||
|
|
||||||
|
gui.add( gui, 'docked' );
|
||||||
|
var r = gui.add( gui, 'open' );
|
||||||
|
|
||||||
|
gui.add( r.row, 'name' );
|
||||||
|
|
||||||
|
|
||||||
|
gui.add( object, 'listen4Free' );
|
||||||
|
gui.add( object, 'listen4Free' );
|
||||||
|
gui.add( object, 'listen4Free', 0, 1000 );
|
||||||
|
|
||||||
|
gui.add( object, 'zeroTo1', 0, 1 );
|
||||||
|
|
||||||
|
gui.add( object, 'hasComment' ).comment( 'Hi there.' );
|
||||||
|
|
||||||
|
gui.add( object, 'listen4Free' ).name( 'customName' )
|
||||||
|
|
||||||
|
gui.add( object, 'step', 0, 50, 5 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec. Sed massa felis, congue nec libero ut, condimentum hendrerit purus. Cras a cursus ante. Integer nec nibh vitae lacus convallis viverra in at urna. Donec hendrerit convallis lacus, nec condimentum neque aliquam ac. Sed suscipit leo vel ligula condimentum scelerisque. Aliquam fermentum sagittis nisi vitae accumsan. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In et dolor eros. Sed vel venenatis odio, quis porta mi. Ut sed commodo velit, in porta ante.' );
|
||||||
|
|
||||||
|
gui.add( object, 'straddleZero', -1, 1, 0.01 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec.' );
|
||||||
|
|
||||||
|
gui.add( object, 'maxIsNegative', -5, -2 );
|
||||||
|
|
||||||
|
gui.anon( 0, 'anonymousSlider', -1, 1 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus');
|
||||||
|
|
||||||
|
gui.anon( 32, 'beats', 1, 64, 1 ).comment( 'The number of beats in the song.');
|
||||||
|
gui.anon( 0, 'loops', -2, 2, 1 ).comment( 'The number of times the gif loops in a cycle.' );
|
||||||
|
gui.anon( 0, 'start', -2, 2, 1 ).comment( 'The frame of the gif where the song should start.' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
14
gui.html
Normal file
14
gui.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script src="../platform/platform.js"></script>
|
||||||
|
|
||||||
|
<!-- src -->
|
||||||
|
<script src="elements/Gui.js"></script>
|
||||||
|
|
||||||
|
<!-- base elements -->
|
||||||
|
<link rel="import" href="elements/gui-panel/gui-panel.html">
|
||||||
|
<link rel="import" href="elements/gui-row/gui-row.html">
|
||||||
|
|
||||||
|
<!-- controllers -->
|
||||||
|
<link rel="import" href="elements/controller-number/controller-number.html">
|
||||||
|
<link rel="import" href="elements/controller-string/controller-string.html">
|
||||||
|
<link rel="import" href="elements/controller-boolean/controller-boolean.html">
|
||||||
|
<link rel="import" href="elements/controller-function/controller-function.html">
|
76
gulpfile.js
Normal file
76
gulpfile.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
[ ] build without platform bundled
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gulp = require( 'gulp' ),
|
||||||
|
fs = require( 'fs' ),
|
||||||
|
$ = require( 'gulp-load-plugins' )( { 'pattern': '*' } );
|
||||||
|
|
||||||
|
var paths = {
|
||||||
|
main: 'gui.html',
|
||||||
|
css: 'elements/**/*.styl',
|
||||||
|
html: 'elements/**/*.html',
|
||||||
|
js: 'elements/**/*.js',
|
||||||
|
}
|
||||||
|
|
||||||
|
function stylus( src, dest ) {
|
||||||
|
|
||||||
|
gulp.src( src )
|
||||||
|
.pipe( $.stylus( { use: [ $.nib() ] } ) )
|
||||||
|
.pipe( gulp.dest( dest ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gulp.task( 'css', function() {
|
||||||
|
|
||||||
|
stylus( paths.css, 'elements' );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
gulp.task( 'vulcanize', function() {
|
||||||
|
|
||||||
|
gulp.src( paths.main )
|
||||||
|
.pipe( $.vulcanize( {
|
||||||
|
dest: 'build',
|
||||||
|
inline: true
|
||||||
|
// strip: true
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
gulp.task( 'docs', function() {
|
||||||
|
|
||||||
|
stylus( 'docs/*.styl', 'docs' );
|
||||||
|
|
||||||
|
var content = {
|
||||||
|
readme: $.marked( fs.readFileSync( 'README.md', 'utf8' ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
gulp.src( 'docs/template.html' )
|
||||||
|
.pipe( $.plates( content ) )
|
||||||
|
.pipe( $.rename( 'index.html' ) )
|
||||||
|
.pipe( gulp.dest( './' ) );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
gulp.task( 'test', function() {
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
gulp.task( 'build', [ 'css', 'vulcanize', 'test', 'docs' ] );
|
||||||
|
|
||||||
|
gulp.task( 'default', function() {
|
||||||
|
|
||||||
|
gulp.task( 'build' );
|
||||||
|
|
||||||
|
gulp.watch( [ paths.css ], [ 'css', 'vulcanize' ] );
|
||||||
|
gulp.watch( [ paths.js, paths.main, paths.html ], [ 'vulcanize', 'test' ] );
|
||||||
|
gulp.watch( [ 'README.md', 'docs/*' ], [ 'docs' ] );
|
||||||
|
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
|
193
index.html
Normal file
193
index.html
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>dat-gui</title>
|
||||||
|
|
||||||
|
<link rel="import" href="gui.html">
|
||||||
|
<link rel="stylesheet" href="docs/style.css">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="readme"><h1 id="dat-gui">dat-gui</h1>
|
||||||
|
<p>dat-gui creates an interface that you can use to modify variables with very little code. </p>
|
||||||
|
<h3 id="basic-usage">Basic Usage</h3>
|
||||||
|
<p>Download the <a href="todo">minified library</a> and include it in your html.</p>
|
||||||
|
<pre><code class="lang-html"><script src="gui.js"></script>
|
||||||
|
</code></pre>
|
||||||
|
<p>Create controllers by adding objects and their properties. dat-gui chooses a controller based on the variable's initial value.</p>
|
||||||
|
<pre><code class="lang-javascript">var gui = new Gui();
|
||||||
|
gui.add( object, 'numberProperty', 0, 1 ); // Slider
|
||||||
|
gui.add( object, 'stringProperty' ); // Text box
|
||||||
|
gui.add( object, 'booleanProperty' ); // Check box
|
||||||
|
gui.add( object, 'functionProperty' ); // Button
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="limiting-input">Limiting Input</h3>
|
||||||
|
<p>You can specify limits on numbers. A number with a min and max value becomes a slider.</p>
|
||||||
|
<pre><code class="lang-javascript">gui.add( text, 'growthSpeed', -5, 5 ); // Min and max
|
||||||
|
gui.add( text, 'noiseStrength' ).step( 5 ); // Increment amount
|
||||||
|
gui.add( text, 'maxSize' ).min( 0 ).step( 0.25 ); // Mix and match
|
||||||
|
</code></pre>
|
||||||
|
<p>You can also provide a list of accepted values for a dropdown.</p>
|
||||||
|
<pre><code class="lang-javascript">// Choose from accepted values
|
||||||
|
gui.add( text, 'message', [ 'pizza', 'chrome', 'hooray' ] );
|
||||||
|
|
||||||
|
// Choose from named values
|
||||||
|
gui.add( text, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 } );
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="color-controllers">Color Controllers</h3>
|
||||||
|
<p>dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats.</p>
|
||||||
|
<pre><code class="lang-javascript">text.color0 = "#ffae23"; // CSS string
|
||||||
|
text.color1 = [ 0, 128, 255 ]; // RGB array
|
||||||
|
text.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
|
||||||
|
text.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
|
||||||
|
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
gui.addColor(text, 'color0');
|
||||||
|
gui.addColor(text, 'color1');
|
||||||
|
gui.addColor(text, 'color2');
|
||||||
|
gui.addColor(text, 'color3');
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="events">Events</h3>
|
||||||
|
<p>You can listen for events on individual controllers using an event listener syntax.</p>
|
||||||
|
<pre><code class="lang-javascript">var controller = gui.add(fizzyText, 'maxSize', 0, 10);
|
||||||
|
|
||||||
|
controller.onChange(function(value) {
|
||||||
|
// Fires on every change, drag, keypress, etc.
|
||||||
|
});
|
||||||
|
|
||||||
|
controller.onFinishChange(function(value) {
|
||||||
|
// Fires when a controller loses focus.
|
||||||
|
alert("The new value is " + value);
|
||||||
|
});
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="folders-comments">Folders & Comments</h3>
|
||||||
|
<p>You can nest as many dat-gui as you want. Nested dat-gui act as collapsible folders.</p>
|
||||||
|
<pre><code class="lang-javascript">var gui = new Gui();
|
||||||
|
|
||||||
|
var f1 = gui.addFolder('Flow Field');
|
||||||
|
f1.add(text, 'speed');
|
||||||
|
f1.add(text, 'noiseStrength');
|
||||||
|
|
||||||
|
var f2 = gui.addFolder('Letters');
|
||||||
|
f2.add(text, 'growthSpeed');
|
||||||
|
f2.add(text, 'maxSize');
|
||||||
|
|
||||||
|
f2.open();
|
||||||
|
</code></pre>
|
||||||
|
<p>The comment method adds a tooltip to a controller.</p>
|
||||||
|
<pre><code class="lang-javascript">f2.add(text, 'message').comment( 'This is the comment.' );
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="saving-values">Saving Values</h3>
|
||||||
|
<p>Add a save menu to the interface by calling <code>gui.remember</code> on all the objects you've added to the Gui.</p>
|
||||||
|
<pre><code class="lang-javascript">var fizzyText = new FizzyText();
|
||||||
|
var gui = new Gui();
|
||||||
|
|
||||||
|
gui.remember(fizzyText);
|
||||||
|
|
||||||
|
// Add controllers ...
|
||||||
|
</code></pre>
|
||||||
|
<p>Click the gear icon to change your save settings. You can either save your dat-gui values to localStorage, or by copying and pasting a JSON object into your source code as follows:</p>
|
||||||
|
<pre><code class="lang-javascript">var fizzyText = new FizzyText();
|
||||||
|
var gui = new Gui( { load: JSON } );
|
||||||
|
|
||||||
|
gui.remember( fizzyText );
|
||||||
|
|
||||||
|
// Add controllers ...
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="presets">Presets</h3>
|
||||||
|
<p>The save menu also allows you to save all of your settings as presets. Click Save to modify the current preset, or New to create a new preset from existing settings. Clicking Revert will clear all unsaved changes to the current preset.</p>
|
||||||
|
<p>Switch between presets using the dropdown in the save menu. You can specify the default like this:</p>
|
||||||
|
<pre><code class="lang-javascript">var gui = new Gui({
|
||||||
|
load: JSON,
|
||||||
|
preset: 'Flow'
|
||||||
|
});
|
||||||
|
</code></pre>
|
||||||
|
<p>A word of caution about localStorage:</p>
|
||||||
|
<p>Paste the JSON save object into your source frequently. Using localStorage to save presets can make you faster, but its easy to lose your settings by clearing browsing data, changing browsers, or even by changing the URL of the page you're working on.</p>
|
||||||
|
<h3 id="save-to-disk">Save to Disk</h3>
|
||||||
|
<p>dat-gui comes with a node server that saves your settings to disk. This way you don't have to worry about losing your values to local storage or copying and pasting a JSON string.</p>
|
||||||
|
<p>First, run the node script:</p>
|
||||||
|
<pre><code class="lang-sh">$ node gui-server
|
||||||
|
</code></pre>
|
||||||
|
<p>Next, instantiate your Gui with a path to a JSON file to store settings. dat-gui will read from this file on load and write to this file on change.</p>
|
||||||
|
<pre><code class="lang-javascript">var gui = new Gui( { load: 'path/to/file.json' } );
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="custom-placement">Custom Placement</h3>
|
||||||
|
<p>By default, Gui panels are created with fixed position, and are automatically appended to the body. You can change this behavior by setting the <code>autoPlace</code> parameter to <code>false</code>.</p>
|
||||||
|
<pre><code class="lang-javascript">var gui = new Gui( { autoPlace: false } );
|
||||||
|
|
||||||
|
var customContainer = document.getElementById('my-gui-container');
|
||||||
|
customContainer.appendChild(gui.domElement);
|
||||||
|
</code></pre>
|
||||||
|
<p>Since dat-gui is built using <a href="todo">Web Components</a>, you can also use HTML syntax to add controllers to the page.</p>
|
||||||
|
<pre><code class="lang-html"><body>
|
||||||
|
|
||||||
|
<controller-number min="-2" max="2" step="1" value="0"></controller-number>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var controller = document.querySelector( 'controller-number' );
|
||||||
|
controller.onChange( function() {
|
||||||
|
|
||||||
|
// react to UI changes ...
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="defining-custom-controllers">Defining Custom Controllers</h3>
|
||||||
|
<p>dat-gui uses <a href="todo">Polymer</a> under the hood to define custom elements. A dat-gui controller is just a <a href="todo">Polymer element</a> with two important requirements:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Controllers must extend <code><controller-base></code>.</li>
|
||||||
|
<li>Controllers must be associated with a data type.</li>
|
||||||
|
</ul>
|
||||||
|
<p>Take for example this (simplified) source for dat-gui's <code><controller-number></code>:</p>
|
||||||
|
<pre><code class="lang-javascript">Polymer( 'controller-number', {
|
||||||
|
|
||||||
|
// Define element ...
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Gui.register( 'controller-number', function( value ) {
|
||||||
|
|
||||||
|
return typeof value == 'number';
|
||||||
|
|
||||||
|
} );
|
||||||
|
</code></pre>
|
||||||
|
<p><code>Gui.register</code> takes an element name and a test function. The test function tells dat-gui to add a <code><controller-number></code> to the panel when the user adds a variable whose type is <code>'number'</code>.</p>
|
||||||
|
<p>A test function determines if a controller is appropriate for a given value. This example registers <code><vector-controller></code> for values that have properties <code>x</code>, <code>y</code> and <code>z</code>.</p>
|
||||||
|
<pre><code class="lang-javascript">Gui.register( 'vector-controller', function( value ) {
|
||||||
|
|
||||||
|
return value.hasOwnProperty( 'x' ) &&
|
||||||
|
value.hasOwnProperty( 'y' ) &&
|
||||||
|
value.hasOwnProperty( 'z' );
|
||||||
|
|
||||||
|
} );
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="publishing-custom-controllers">Publishing Custom Controllers</h3>
|
||||||
|
<p>You should use <a href="todo">Bower</a> and format your plugin all nice and it should have a certain prefix yada yada.</p>
|
||||||
|
<p>Installing third-party controllers ... </p>
|
||||||
|
<pre><code class="lang-sh">$ bower install gui-three
|
||||||
|
</code></pre>
|
||||||
|
<p>Include the source for the third-party controllers after dat-gui.</p>
|
||||||
|
<pre><code class="lang-html"><script src="gui.js"></script>
|
||||||
|
<script src="gui-three.js"></script>
|
||||||
|
</code></pre>
|
||||||
|
<!-- Replaced with contents of README.md --></div>
|
||||||
|
|
||||||
|
<script src="../underscore/underscore.js"></script>
|
||||||
|
|
||||||
|
<script src="docs/main.js"></script>
|
||||||
|
<script src="docs/examples.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
17
package.json
Normal file
17
package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "polymer-gui",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"gulp": "^3.8.7",
|
||||||
|
"gulp-connect": "^2.0.6",
|
||||||
|
"gulp-load-plugins": "^0.5.3",
|
||||||
|
"gulp-plates": "0.0.5",
|
||||||
|
"gulp-qunit": "^0.3.3",
|
||||||
|
"gulp-rename": "^1.2.0",
|
||||||
|
"gulp-stylus": "^1.3.0",
|
||||||
|
"gulp-vulcanize": "^1.0.0",
|
||||||
|
"gulp-watch": "^0.6.9",
|
||||||
|
"marked": "^0.3.2",
|
||||||
|
"nib": "^1.0.3"
|
||||||
|
}
|
||||||
|
}
|
35
test/runner.html
Normal file
35
test/runner.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>dat-gui Test Runner (Mocha)</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="../../tools/test/mocha/mocha.css">
|
||||||
|
<link rel="import" href="../polymer.html">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="mocha"></div>
|
||||||
|
<script>
|
||||||
|
mocha.setup({ui: 'tdd', slow: 1000, timeout: 10000, htmlbase: ''});
|
||||||
|
</script>
|
||||||
|
<!-- -->
|
||||||
|
<script src="js/marshall.js"></script>
|
||||||
|
<script src="js/oop.js"></script>
|
||||||
|
<script src="js/bindProperties.js"></script>
|
||||||
|
<script src="js/bindMDV.js"></script>
|
||||||
|
<script src="js/attrs.js"></script>
|
||||||
|
<script src="js/properties.js"></script>
|
||||||
|
<script src="js/register.js"></script>
|
||||||
|
<script src="js/prepare.js"></script>
|
||||||
|
<script src="js/events.js"></script>
|
||||||
|
<script src="js/styling.js"></script>
|
||||||
|
<script src="js/mdv-syntax.js"></script>
|
||||||
|
<script src="js/paths.js"></script>
|
||||||
|
<script src="js/utils.js"></script>
|
||||||
|
<!-- -->
|
||||||
|
<script>
|
||||||
|
document.addEventListener('polymer-ready', function() {
|
||||||
|
mocha.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user