├── .gitignore
├── home
├── static
│ ├── fonts
│ │ └── roboto.woff2
│ └── css
│ │ └── index.css
├── index.html
├── package.json
└── src
│ └── main.js
├── builtins
├── space-skybox
│ ├── README.md
│ ├── metadata
│ │ ├── space-skybox.png
│ │ └── metadata.json
│ ├── static
│ │ ├── fonts
│ │ │ └── roboto.woff2
│ │ ├── css
│ │ │ └── index.css
│ │ └── js
│ │ │ └── dat.gui.min.js
│ ├── package.json
│ ├── src
│ │ ├── util.js
│ │ ├── glsl
│ │ │ ├── point-stars.glsl
│ │ │ ├── skybox.glsl
│ │ │ ├── star.glsl
│ │ │ ├── sun.glsl
│ │ │ ├── nebula.glsl
│ │ │ └── classic-noise-4d.snip
│ │ ├── skybox.js
│ │ ├── main.js
│ │ ├── webgl.js
│ │ └── space-3d.js
│ └── index.html
└── space-2d
│ ├── metadata
│ ├── space2d.png
│ └── metadata.json
│ ├── static
│ ├── css
│ │ └── index.css
│ └── js
│ │ └── dat.gui.min.js
│ ├── package.json
│ ├── index.html
│ └── src
│ ├── sun.glsl
│ ├── stars.glsl
│ ├── nebula.glsl
│ ├── main.js
│ ├── space-2d.js
│ ├── classicnoise3D.glsl
│ └── webgl.js
├── npm-install-builtins.js
├── README.md
├── builtins.js
├── package.json
├── preload.js
├── LICENSE
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.zip
2 | *.tar.gz
3 | node_modules/
4 |
--------------------------------------------------------------------------------
/home/static/fonts/roboto.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwwtyro/proceduro/HEAD/home/static/fonts/roboto.woff2
--------------------------------------------------------------------------------
/builtins/space-skybox/README.md:
--------------------------------------------------------------------------------
1 | # space-3d
2 | Quickly generate procedural 3D space scenes in your browser with WebGL
3 |
--------------------------------------------------------------------------------
/builtins/space-2d/metadata/space2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwwtyro/proceduro/HEAD/builtins/space-2d/metadata/space2d.png
--------------------------------------------------------------------------------
/builtins/space-skybox/metadata/space-skybox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwwtyro/proceduro/HEAD/builtins/space-skybox/metadata/space-skybox.png
--------------------------------------------------------------------------------
/builtins/space-skybox/static/fonts/roboto.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwwtyro/proceduro/HEAD/builtins/space-skybox/static/fonts/roboto.woff2
--------------------------------------------------------------------------------
/builtins/space-2d/metadata/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Space 2D",
3 | "description": "2D space scene generation.",
4 | "screenshot": "space2d.png"
5 | }
--------------------------------------------------------------------------------
/builtins/space-skybox/metadata/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Space Skybox",
3 | "description": "3D space scene generation.",
4 | "screenshot": "space-skybox.png"
5 | }
--------------------------------------------------------------------------------
/home/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Initializing...
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/home/static/css/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Roboto';
3 | font-style: normal;
4 | font-weight: 400;
5 | src: local('Roboto'), local('Roboto-Regular'), url(../fonts/roboto.woff2) format('woff2');
6 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
7 | }
8 |
9 | body {
10 | background: #282C34;
11 | margin: 0;
12 | padding: 0;
13 | font-family: 'Roboto', sans-serif;
14 | }
15 |
16 | h1 {
17 | padding: 0px;
18 | margin: 0px;
19 | }
20 |
21 | .panel {
22 | background-size: cover;
23 | cursor: pointer;
24 | -webkit-filter: grayscale(100%);
25 | -webkit-transition: .25s ease-in-out;
26 | }
27 |
28 | .panel:hover {
29 | -webkit-filter: grayscale(0%);
30 | }
31 |
32 | .text {
33 | color: white;
34 | padding: 32px;
35 | background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0.5) 30%, rgba(0,0,0,0) 100%);
36 | }
37 |
38 | .gray panel {
39 | }
40 | .gray panel:hover {
41 | }
42 |
--------------------------------------------------------------------------------
/builtins/space-2d/src/nebula.glsl:
--------------------------------------------------------------------------------
1 | #version 100
2 | precision highp float;
3 |
4 | attribute vec3 aPosition;
5 |
6 | void main() {
7 | gl_Position = vec4(aPosition, 1);
8 | }
9 |
10 |
11 | __split__
12 |
13 |
14 | #version 100
15 | precision highp float;
16 |
17 | uniform float uFalloff;
18 | uniform float uIntensity;
19 | uniform float uScale;
20 | uniform float uRenderScale;
21 | uniform vec3 uColor;
22 | uniform vec2 uOffset;
23 |
24 | __noise3d__
25 |
26 | float noise(vec2 p) {
27 | return cnoise(vec3(p, 0)) * 0.5 + 0.5;
28 | }
29 |
30 | float nebula(vec2 p) {
31 | const int steps = 5;
32 | float scale = pow(2.0, float(steps));
33 | vec2 displace;
34 | for (int i = 0; i < steps; i++) {
35 | displace = vec2(noise(p.xy * scale + displace), noise(p.yx * scale + displace));
36 | scale *= 0.5;
37 | }
38 | return noise(p * scale + displace);
39 | }
40 |
41 | void main() {
42 | vec2 p = gl_FragCoord.xy/uRenderScale + uOffset;
43 | float c = min(1.0, nebula(p * uScale) * uIntensity);
44 | c = pow(c, uFalloff);
45 | gl_FragColor = vec4(uColor, c);
46 | }
47 |
--------------------------------------------------------------------------------
/home/src/main.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var path = require('path');
4 |
5 | function render() {
6 | var body = document.body;
7 | body.innerHTML = "";
8 | var count = Object.keys(proceduro.builtins).length;
9 | var width = '100%';
10 | var height = Math.max(window.innerHeight/count, 256);
11 | for (var key in proceduro.builtins) {
12 | let metadata = proceduro.builtins[key];
13 | var screenshot = path.join(metadata.path, 'metadata', metadata.screenshot);
14 | var style = `
15 | background-image: url("${screenshot}");
16 | width: ${width};
17 | height: ${height}px;
18 | `;
19 | body.innerHTML += `
20 |
25 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/glsl/nebula.glsl:
--------------------------------------------------------------------------------
1 | #version 100
2 | precision highp float;
3 |
4 | uniform mat4 uModel;
5 | uniform mat4 uView;
6 | uniform mat4 uProjection;
7 |
8 | attribute vec3 aPosition;
9 | varying vec3 pos;
10 |
11 | void main() {
12 | gl_Position = uProjection * uView * uModel * vec4(aPosition, 1);
13 | pos = (uModel * vec4(aPosition, 1)).xyz;
14 | }
15 |
16 |
17 | __split__
18 |
19 |
20 | #version 100
21 | precision highp float;
22 |
23 | uniform vec3 uColor;
24 | uniform vec3 uOffset;
25 | uniform float uScale;
26 | uniform float uIntensity;
27 | uniform float uFalloff;
28 |
29 | varying vec3 pos;
30 |
31 | __noise4d__
32 |
33 | float noise(vec3 p) {
34 | return 0.5 * cnoise(vec4(p, 0)) + 0.5;
35 | }
36 |
37 | float nebula(vec3 p) {
38 | const int steps = 6;
39 | float scale = pow(2.0, float(steps));
40 | vec3 displace;
41 | for (int i = 0; i < steps; i++) {
42 | displace = vec3(
43 | noise(p.xyz * scale + displace),
44 | noise(p.yzx * scale + displace),
45 | noise(p.zxy * scale + displace)
46 | );
47 | scale *= 0.5;
48 | }
49 | return noise(p * scale + displace);
50 | }
51 |
52 | void main() {
53 | vec3 posn = normalize(pos) * uScale;
54 | float c = min(1.0, nebula(posn + uOffset) * uIntensity);
55 | c = pow(c, uFalloff);
56 | gl_FragColor = vec4(uColor, c);
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/builtins/space-skybox/static/css/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Roboto';
3 | font-style: normal;
4 | font-weight: 400;
5 | src: local('Roboto'), local('Roboto-Regular'), url(../fonts/roboto.woff2) format('woff2');
6 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
7 | }
8 |
9 | body {
10 | margin: 0px;
11 | background: #282C34;
12 | font-family: 'Roboto', sans-serif;
13 | }
14 |
15 | #render-canvas {
16 | width: 100%;
17 | height: 100%;
18 | }
19 |
20 | #texture-canvas {
21 | position: fixed;
22 | left: 16px;
23 | top: 16px;
24 | width: 320px;
25 | height: 240px;
26 | border: 1px solid white;
27 | box-sizing: border-box;
28 | display: none;
29 | }
30 |
31 | #texture-container {
32 | background: rgba(255,255,255,0.1);
33 | width: 317px;
34 | height: 238px;
35 | position: fixed;
36 | left: 16px;
37 | top: 16px;
38 | }
39 |
40 | #loading {
41 | position: fixed;
42 | top: 0px;
43 | left: 0px;
44 | width: 100%;
45 | height: 100%;
46 | background: #282C34;
47 | color: #61AABA;
48 | display: flex;
49 | justify-content: center;
50 | align-items: center;
51 | font-size: 24px;
52 | font-weight: bold;
53 | }
54 |
55 | #texture-left {
56 | top: 95px;
57 | left: 16px;
58 | }
59 |
60 | #texture-right {
61 | top: 95px;
62 | left: 174px;
63 | }
64 |
65 | #texture-top {
66 | top: 16px;
67 | left: 95px;
68 | }
69 |
70 | #texture-bottom {
71 | top: 174px;
72 | left: 95px;
73 | }
74 |
75 | #texture-front {
76 | top: 95px;
77 | left: 95px;
78 | }
79 |
80 | #texture-back {
81 | top: 95px;
82 | left: 253px;
83 | }
84 |
85 | .texture {
86 | position: fixed;
87 | width: 80px;
88 | height: 80px;
89 | box-sizing: border-box;
90 | }
91 |
--------------------------------------------------------------------------------
/builtins/space-2d/src/main.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const Scene = require("./src/space-2d.js");
4 |
5 | proceduro.appendMenu(['File', 'Save as...'], function() {
6 | proceduro.dialog.showSaveDialog({
7 | defaultPath: 'space2d.png',
8 | }, function(path) {
9 | if (!path) {
10 | return;
11 | }
12 | proceduro.saveCanvasToPNG(path, document.getElementById('render-canvas'));
13 | })
14 | });
15 |
16 | window.onload = function() {
17 |
18 | var ControlsMenu = function() {
19 | this.seed = generateRandomSeed();
20 | this.randomize = function() {
21 | this.seed = "" + generateRandomSeed();
22 | render();
23 | };
24 | this.pointStars = true;
25 | this.stars = true;
26 | this.sun = true;
27 | this.nebulae = true;
28 | this.shortScale = false;
29 | this.width = 1024;
30 | this.height = 512;
31 | this.render = function() {
32 | render();
33 | };
34 | };
35 |
36 | var menu = new ControlsMenu();
37 | var gui = new dat.GUI({
38 | autoPlace: false,
39 | width: 320
40 | });
41 | gui.add(menu, 'seed').name("Seed").listen().onFinishChange(render);
42 | gui.add(menu, 'randomize').name("Randomize seed");
43 | gui.add(menu, 'pointStars').name("Point stars").onChange(render);
44 | gui.add(menu, 'stars').name("Stars").onChange(render);
45 | gui.add(menu, 'sun').name("Sun").onChange(render);
46 | gui.add(menu, 'nebulae').name("Nebulae").onChange(render);
47 | gui.add(menu, 'shortScale').name("Short scale").onChange(render);
48 | gui.add(menu, 'width').name("Width").onFinishChange(render);
49 | gui.add(menu, 'height').name("Height").onFinishChange(render);
50 | gui.add(menu, 'render').name("Render");
51 | document.body.appendChild(gui.domElement);
52 | gui.domElement.style.position = "fixed";
53 | gui.domElement.style.left = "16px";
54 | gui.domElement.style.top = "16px";
55 |
56 | var canvas = document.getElementById("render-canvas");
57 |
58 | var scene = new Scene(canvas);
59 |
60 | render();
61 |
62 | function reflow() {
63 | var ratio = canvas.width / canvas.height;
64 | var hspace = window.innerWidth - 368;
65 | var vspace = window.innerHeight - 32;
66 | var sratio = hspace/vspace;
67 | var cwidth = -1;
68 | var cheight = -1;
69 | var cleft = -1;
70 | if (ratio >= 1 && sratio < ratio) {
71 | cwidth = hspace;
72 | cheight = cwidth/ratio;
73 | cleft = 352;
74 | } else {
75 | cheight = vspace;
76 | cwidth = cheight * ratio;
77 | cleft = 352 + (hspace - cwidth) / 2.0;
78 | }
79 | canvas.style.width = Math.round(cwidth) + "px";
80 | canvas.style.height = Math.round(cheight) + "px";
81 | canvas.style.left = cleft + "px";
82 | canvas.style.display = "block";
83 | }
84 |
85 | function render() {
86 | canvas.width = menu.width;
87 | canvas.height = menu.height;
88 | reflow();
89 | scene.render({
90 | seed: menu.seed,
91 | pointStars: menu.pointStars,
92 | stars: menu.stars,
93 | sun: menu.sun,
94 | nebulae: menu.nebulae,
95 | shortScale: menu.shortScale
96 | });
97 | }
98 |
99 | window.onresize = reflow;
100 | }
101 |
102 | function generateRandomSeed() {
103 | return (Math.random() * 1000000000000000000).toString(36);
104 | }
105 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/skybox.js:
--------------------------------------------------------------------------------
1 | // jshint -W097
2 | // jshint undef: true, unused: true
3 | /* globals require,__dirname,Float32Array,module*/
4 |
5 | "use strict";
6 |
7 | var fs = require("fs");
8 | var glm = require("gl-matrix");
9 | var webgl = require("./webgl.js");
10 | var util = require("./util.js");
11 |
12 | module.exports = function(renderCanvas) {
13 |
14 | var self = this;
15 |
16 | self.initialize = function() {
17 | self.gl = renderCanvas.getContext("webgl");
18 | self.gl.pixelStorei(self.gl.UNPACK_FLIP_Y_WEBGL, true);
19 | self.pSkybox = util.loadProgram(self.gl, fs.readFileSync(__dirname + "/glsl/skybox.glsl", "utf8"));
20 | self.rSkybox = buildQuad(self.gl, self.pSkybox);
21 | self.textures = {};
22 | };
23 |
24 | self.setTextures = function(canvases) {
25 | self.textures = {};
26 | var keys = Object.keys(canvases);
27 | for (var i = 0; i < keys.length; i++) {
28 | var c = canvases[keys[i]];
29 | self.textures[keys[i]] = new webgl.Texture(self.gl, 0, c, c.width, c.height, {
30 | min: self.gl.LINEAR_MIPMAP_LINEAR,
31 | mag: self.gl.LINEAR,
32 | });
33 | }
34 | };
35 |
36 | self.render = function(view, projection) {
37 | self.gl.viewport(0, 0, renderCanvas.width, renderCanvas.height);
38 |
39 | var model = glm.mat4.create();
40 |
41 | self.pSkybox.use();
42 | self.pSkybox.setUniform("uView", "Matrix4fv", false, view);
43 | self.pSkybox.setUniform("uProjection", "Matrix4fv", false, projection);
44 |
45 | self.textures.front.bind();
46 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
47 | self.rSkybox.render();
48 |
49 | self.textures.back.bind();
50 | glm.mat4.rotateY(model, glm.mat4.create(), Math.PI);
51 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
52 | self.rSkybox.render();
53 |
54 | self.textures.left.bind();
55 | glm.mat4.rotateY(model, glm.mat4.create(), Math.PI/2);
56 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
57 | self.rSkybox.render();
58 |
59 | self.textures.right.bind();
60 | glm.mat4.rotateY(model, glm.mat4.create(), -Math.PI/2);
61 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
62 | self.rSkybox.render();
63 |
64 | self.textures.top.bind();
65 | glm.mat4.rotateX(model, glm.mat4.create(), Math.PI/2);
66 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
67 | self.rSkybox.render();
68 |
69 | self.textures.bottom.bind();
70 | glm.mat4.rotateX(model, glm.mat4.create(), -Math.PI/2);
71 | self.pSkybox.setUniform("uModel", "Matrix4fv", false, model);
72 | self.rSkybox.render();
73 | };
74 |
75 |
76 | self.initialize();
77 | };
78 |
79 |
80 | function buildQuad(gl, program) {
81 | var position = [
82 | -1, -1, -1,
83 | 1, -1, -1,
84 | 1, 1, -1,
85 | -1, -1, -1,
86 | 1, 1, -1,
87 | -1, 1, -1,
88 | ];
89 | var uv = [
90 | 0, 0,
91 | 1, 0,
92 | 1, 1,
93 | 0, 0,
94 | 1, 1,
95 | 0, 1
96 | ];
97 | var attribs = webgl.buildAttribs(gl, {aPosition: 3, aUV: 2});
98 | attribs.aPosition.buffer.set(new Float32Array(position));
99 | attribs.aUV.buffer.set(new Float32Array(uv));
100 | var count = position.length / 9;
101 | var renderable = new webgl.Renderable(gl, program, attribs, count);
102 | return renderable;
103 | }
104 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | var electron = require('electron');
4 | var app = electron.app;
5 | const {ipcMain} = require('electron');
6 | var BrowserWindow = electron.BrowserWindow;
7 | var builtins = require('./builtins');
8 |
9 | if (process.env.PROCEDURO_RELOAD) {
10 | require('electron-reload')(__dirname, {
11 | electron: require('electron-prebuilt')
12 | });
13 | }
14 |
15 | var win;
16 |
17 | function defaultMenu() {
18 | var submenu = Object.keys(builtins).map(function(bin) {
19 | bin = builtins[bin];
20 | return {
21 | label: bin.title,
22 | click() {
23 | loadApp(bin.title);
24 | }
25 | }
26 | });
27 | submenu.push.apply(submenu, [
28 | { type: 'separator' },
29 | {
30 | label: 'Home',
31 | click() {
32 | resetMenu()
33 | win.loadURL(`file://${__dirname}/home/index.html`);
34 | }
35 | },
36 | {
37 | label: 'Debug',
38 | accelerator: 'F12',
39 | click: function() {
40 | win.webContents.toggleDevTools();
41 | }
42 | },
43 | {
44 | label: 'Exit',
45 | click: function() {
46 | app.quit();
47 | }
48 | }
49 | ]);
50 | return [{
51 | label: 'Proceduro',
52 | submenu: submenu
53 | }];
54 | }
55 |
56 | let currentMenuTemplate = defaultMenu();
57 |
58 | function resetMenu() {
59 | currentMenuTemplate = defaultMenu();
60 | var menu = electron.Menu.buildFromTemplate(currentMenuTemplate);
61 | electron.Menu.setApplicationMenu(menu);
62 | }
63 |
64 | function consoleLog(msg) {
65 | win.webContents.send('log', msg);
66 | }
67 |
68 | function consoleError(msg) {
69 | win.webContents.send('error', msg);
70 | }
71 |
72 | function submenuGetItem(submenu, label) {
73 | for (let item of submenu) {
74 | if (item.label === label) {
75 | return item;
76 | }
77 | }
78 | return null;
79 | }
80 |
81 | ipcMain.on('append menu', function(e, data) {
82 | var path = data.path;
83 | var uuid = data.uuid;
84 | if (path.length === 0) {
85 | consoleError("Can't append to menu with no path.");
86 | return;
87 | }
88 | if (path[0] === 'Proceduro') {
89 | consoleError("Can't append to Proceduro menu item.");
90 | return;
91 | }
92 | let currentItem = currentMenuTemplate;
93 | for (let i = 0; i < path.length; i++) {
94 | const p = path[i];
95 | if (i === path.length - 1) {
96 | if (submenuGetItem(currentItem, p) !== null) {
97 | consoleError(`menu item "${p}" already exists.`);
98 | return;
99 | }
100 | currentItem.push({
101 | label: p,
102 | click: function() {
103 | win.webContents.send(uuid);
104 | }
105 | });
106 | } else {
107 | let item = submenuGetItem(currentItem, p);
108 | if (item === null) {
109 | item = {
110 | label: p,
111 | submenu: []
112 | }
113 | currentItem.push(item);
114 | }
115 | currentItem = item.submenu;
116 | }
117 | }
118 | var menu = electron.Menu.buildFromTemplate(currentMenuTemplate);
119 | electron.Menu.setApplicationMenu(menu);
120 | })
121 |
122 | ipcMain.on('set app menu', (event, arg) => {
123 | template = menuTemplate.slice();
124 | template.push(arg);
125 | });
126 |
127 | ipcMain.on('set application', (event, arg) => {
128 | loadApp(arg.name);
129 | });
130 |
131 | ipcMain.on('openDevTools', function(event, arg) {
132 | win.webContents.openDevTools();
133 | });
134 |
135 | function createWindow() {
136 | resetMenu();
137 | preloadPath = path.resolve(path.join(__dirname, 'preload.js'));
138 | win = new BrowserWindow({
139 | width: 1366,
140 | height: 768,
141 | transparent: true,
142 | webPreferences: {
143 | preload: preloadPath
144 | }
145 | });
146 | win.loadURL(`file://${__dirname}/home/index.html`);
147 | win.on('closed', () => {
148 | win = null;
149 | });
150 | }
151 |
152 | function loadApp(name) {
153 | resetMenu();
154 | win.loadURL(`file://${path.join(builtins[name].path, 'index.html')}`);
155 | }
156 |
157 | app.on('ready', createWindow);
158 |
159 | app.on('window-all-closed', () => {
160 | if (process.platform !== 'darwin') {
161 | app.quit();
162 | }
163 | });
164 |
165 | app.on('activate', () => {
166 | if (win === null) {
167 | createWindow();
168 | }
169 | });
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/builtins/space-2d/src/space-2d.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var fs = require("fs");
4 |
5 | var glm = require("gl-matrix");
6 | var rng = require("rng");
7 |
8 | var webgl = require("./webgl");
9 |
10 | module.exports = function(canvas) {
11 |
12 | var gl,
13 | programStars,
14 | renderableStars,
15 | programNebula,
16 | renderableNebula,
17 | programSun,
18 | renderableSun;
19 |
20 | gl = canvas.getContext("webgl", {
21 | preserveDrawingBuffer: true,
22 | });
23 | gl.clearColor(0,0,0,1);
24 | gl.enable(gl.BLEND);
25 | gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE);
26 |
27 | programStars = loadProgram(gl, fs.readFileSync(__dirname + "/stars.glsl", "utf8"));
28 | programNebula = loadProgram(gl, fs.readFileSync(__dirname + "/nebula.glsl", "utf8"));
29 | programSun = loadProgram(gl, fs.readFileSync(__dirname + "/sun.glsl", "utf8"));
30 |
31 | var position = [
32 | -1, -1, 0,
33 | 1, -1, 0,
34 | 1, 1, 0,
35 | -1, -1, 0,
36 | 1, 1, 0,
37 | -1, 1, 0
38 | ];
39 | var attribs = webgl.buildAttribs(gl, {
40 | aPosition: 3
41 | });
42 | attribs.aPosition.buffer.set(new Float32Array(position));
43 | var count = position.length / 9;
44 |
45 | renderableStars = new webgl.Renderable(gl, programStars, attribs, count);
46 | renderableNebula = new webgl.Renderable(gl, programNebula, attribs, count);
47 | renderableSun = new webgl.Renderable(gl, programSun, attribs, count);
48 |
49 | this.render = function(opts) {
50 | gl.viewport(0, 0, canvas.width, canvas.height);
51 | gl.clear(gl.COLOR_BUFFER_BIT);
52 | var uRes = [canvas.width, canvas.height];
53 | var uRenderScale = Math.max(canvas.width, canvas.height);
54 | if (opts.shortScale) {
55 | uRenderScale = Math.min(canvas.width, canvas.height);
56 | }
57 | var rand = new rng.MT(hashcode(opts.seed) + 1000);
58 | if (opts.pointStars) {
59 | programStars.setUniform("uRenderScale", "1f", uRenderScale);
60 | programStars.setUniform("uDensity", "1f", rand.random() * 0.05);
61 | renderableStars.render();
62 | }
63 | var rand = new rng.MT(hashcode(opts.seed) + 2000);
64 | while(opts.stars) {
65 | var uColor = [1,1,1];
66 | var uRadius = 0;
67 | var uPosition = [rand.random(), rand.random()];
68 | var uFalloff = rand.random() * 512 + 256;
69 | programSun.setUniform("uRes", "2fv", uRes);
70 | programSun.setUniform("uRenderScale", "1f", uRenderScale);
71 | programSun.setUniform("uPosition", "2fv", uPosition);
72 | programSun.setUniform("uRadius", "1f", uRadius);
73 | programSun.setUniform("uFalloff", "1f", uFalloff);
74 | programSun.setUniform("uColor", "3fv", uColor);
75 | renderableSun.render();
76 | if (rand.random() >= 0.8) {
77 | break;
78 | }
79 | }
80 | var rand = new rng.MT(hashcode(opts.seed) + 3000);
81 | while(opts.nebulae) {
82 | var uColor = [rand.random(), rand.random(), rand.random()];
83 | var uOffset = [rand.random() * 2000 - 1000, rand.random() * 2000 - 1000];
84 | var uFalloff = rand.random() * 3.0 + 3.0;
85 | var uIntensity = rand.random() * 0.2 + 1.0;
86 | var uScale = rand.random() * 4;
87 | programNebula.setUniform("uRenderScale", "1f", uRenderScale);
88 | programNebula.setUniform("uColor", "3fv", uColor);
89 | programNebula.setUniform("uOffset", "2fv", uOffset);
90 | programNebula.setUniform("uFalloff", "1f", uFalloff);
91 | programNebula.setUniform("uIntensity", "1f", uIntensity);
92 | programNebula.setUniform("uScale", "1f", uScale);
93 | renderableNebula.render();
94 | if (rand.random() >= 0.75) {
95 | break
96 | }
97 | }
98 | var rand = new rng.MT(hashcode(opts.seed) + 4000);
99 | if(opts.sun) {
100 | var uColor = [rand.random(), rand.random(), rand.random()];
101 | var uRadius = rand.random() * 0.025 + 0.025;
102 | var uPosition = [rand.random(), rand.random()];
103 | var uFalloff = rand.random() * 32 + 8;
104 | programSun.setUniform("uRes", "2fv", uRes)
105 | programSun.setUniform("uRenderScale", "1f", uRenderScale);
106 | programSun.setUniform("uPosition", "2fv", uPosition);
107 | programSun.setUniform("uRadius", "1f", uRadius);
108 | programSun.setUniform("uFalloff", "1f", uFalloff);
109 | programSun.setUniform("uColor", "3fv", uColor);
110 | renderableSun.render();
111 | }
112 | }
113 |
114 | }
115 |
116 | function loadProgram(gl, src) {
117 | var noise3D = fs.readFileSync(__dirname + "/classicnoise3D.glsl", "utf8");
118 | src = src.replace("__noise3d__", noise3D);
119 | src = src.split("__split__");
120 | return new webgl.Program(gl, src[0], src[1]);
121 | }
122 |
123 | function hashcode(str) {
124 | var hash = 0;
125 | for (var i = 0; i < str.length; i++) {
126 | var char = str.charCodeAt(i)
127 | hash += (i + 1) * char;
128 | }
129 | return hash;
130 | }
131 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/main.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var glm = require("gl-matrix");
4 | var Space3D = require("./src/space-3d.js");
5 | var Skybox = require("./src/skybox.js");
6 |
7 | var resolution = 1024;
8 |
9 | window.onload = function() {
10 | setTimeout(main, 100);
11 | }
12 |
13 | const main = function() {
14 |
15 | document.getElementById('loading').style.display = 'none';
16 |
17 | var ControlsMenu = function() {
18 | this.seed = generateRandomSeed();
19 | this.randomSeed = function() {
20 | this.seed = generateRandomSeed();
21 | renderTextures();
22 | };
23 | this.fov = 60;
24 | this.pointStars = true;
25 | this.stars = true;
26 | this.sun = true;
27 | this.nebulae = true;
28 | this.resolution = resolution;
29 | this.animationSpeed = 1.0;
30 | this.unifiedTexture = true;
31 | };
32 |
33 | var menu = new ControlsMenu();
34 | var gui = new dat.GUI({
35 | autoPlace: false,
36 | width: 320,
37 | });
38 | gui.add(menu, "seed").name("Seed").listen().onFinishChange(renderTextures);
39 | gui.add(menu, "randomSeed").name("Randomize seed");
40 | gui.add(menu, "fov", 10, 150, 1).name("Field of view °");
41 | gui.add(menu, "pointStars").name("Point stars").onChange(renderTextures);
42 | gui.add(menu, "stars").name("Bright stars").onChange(renderTextures);
43 | gui.add(menu, "sun").name("Sun").onChange(renderTextures);
44 | gui.add(menu, "nebulae").name("Nebulae").onChange(renderTextures);
45 | gui.add(menu, "resolution", [256, 512, 1024, 2048, 4096]).name("Resolution").onChange(renderTextures);
46 | gui.add(menu, "animationSpeed", 0, 10).name("Animation speed");
47 |
48 | document.body.appendChild(gui.domElement);
49 | gui.domElement.style.position = "fixed";
50 | gui.domElement.style.left = "16px";
51 | gui.domElement.style.top = "272px";
52 |
53 | proceduro.appendMenu(['File', 'Save unified skybox texture...'], function() {
54 | proceduro.dialog.showSaveDialog({
55 | defaultPath: 'space-skybox.png'
56 | }, function(path) {
57 | if (!path) {
58 | return;
59 | }
60 | proceduro.saveCanvasToPNG(path, document.getElementById('texture-canvas'));
61 | });
62 | });
63 |
64 | proceduro.appendMenu(['File', 'Save disjoint skybox textures...'], function() {
65 | proceduro.dialog.showSaveDialog({
66 | defaultPath: 'space-skybox'
67 | }, function(path) {
68 | if (!path) {
69 | return;
70 | }
71 | proceduro.saveCanvasToPNG(path + '-left.png', document.getElementById('texture-left'));
72 | proceduro.saveCanvasToPNG(path + '-right.png', document.getElementById('texture-right'));
73 | proceduro.saveCanvasToPNG(path + '-top.png', document.getElementById('texture-top'));
74 | proceduro.saveCanvasToPNG(path + '-bottom.png', document.getElementById('texture-bottom'));
75 | proceduro.saveCanvasToPNG(path + '-front.png', document.getElementById('texture-front'));
76 | proceduro.saveCanvasToPNG(path + '-back.png', document.getElementById('texture-back'));
77 | })
78 | });
79 |
80 | var renderCanvas = document.getElementById("render-canvas");
81 | renderCanvas.width = renderCanvas.clientWidth;
82 | renderCanvas.height = renderCanvas.clientHeight;
83 |
84 | var skybox = new Skybox(renderCanvas);
85 | var space = new Space3D(resolution);
86 |
87 | function renderTextures() {
88 | var textures = space.render({
89 | seed: menu.seed,
90 | pointStars: menu.pointStars,
91 | stars: menu.stars,
92 | sun: menu.sun,
93 | nebulae: menu.nebulae,
94 | unifiedTexture: menu.unifiedTexture,
95 | resolution: menu.resolution,
96 | });
97 | skybox.setTextures(textures);
98 | var canvas = document.getElementById("texture-canvas");
99 | canvas.width = 4 * menu.resolution;
100 | canvas.height = 3 * menu.resolution;
101 | var ctx = canvas.getContext("2d");
102 | ctx.drawImage(textures.left, menu.resolution * 0, menu.resolution * 1);
103 | ctx.drawImage(textures.right, menu.resolution * 2, menu.resolution * 1);
104 | ctx.drawImage(textures.front, menu.resolution * 1, menu.resolution * 1);
105 | ctx.drawImage(textures.back, menu.resolution * 3, menu.resolution * 1);
106 | ctx.drawImage(textures.top, menu.resolution * 1, menu.resolution * 0);
107 | ctx.drawImage(textures.bottom, menu.resolution * 1, menu.resolution * 2);
108 |
109 | function drawIndividual(source, targetid) {
110 | var canvas = document.getElementById(targetid);
111 | canvas.width = canvas.height = menu.resolution;
112 | var ctx = canvas.getContext("2d");
113 | ctx.drawImage(source, 0, 0);
114 | }
115 |
116 | drawIndividual(textures.left, "texture-left");
117 | drawIndividual(textures.right, "texture-right");
118 | drawIndividual(textures.front, "texture-front");
119 | drawIndividual(textures.back, "texture-back");
120 | drawIndividual(textures.top, "texture-top");
121 | drawIndividual(textures.bottom, "texture-bottom");
122 | }
123 |
124 | renderTextures();
125 |
126 | var tick = 0.0;
127 |
128 | function render() {
129 |
130 | tick += 0.0025 * menu.animationSpeed;
131 |
132 | var view = glm.mat4.create();
133 | var projection = glm.mat4.create();
134 |
135 | renderCanvas.width = renderCanvas.clientWidth;
136 | renderCanvas.height = renderCanvas.clientHeight;
137 |
138 | glm.mat4.lookAt(view, [0,0,0], [Math.cos(tick), Math.sin(tick * 0.555), Math.sin(tick)], [0,1,0]);
139 |
140 | var fov = (menu.fov/360)*Math.PI*2;
141 | glm.mat4.perspective(projection, fov, renderCanvas.width/renderCanvas.height, 0.1, 8);
142 |
143 | skybox.render(view, projection);
144 |
145 | requestAnimationFrame(render);
146 | }
147 |
148 | render();
149 |
150 | };
151 |
152 | function generateRandomSeed() {
153 | return (Math.random() * 1000000000000000000).toString(36);
154 | }
155 |
--------------------------------------------------------------------------------
/builtins/space-2d/src/classicnoise3D.glsl:
--------------------------------------------------------------------------------
1 | //
2 | // GLSL textureless classic 3D noise "cnoise",
3 | // with an RSL-style periodic variant "pnoise".
4 | // Author: Stefan Gustavson (stefan.gustavson@liu.se)
5 | // Version: 2011-10-11
6 | //
7 | // Many thanks to Ian McEwan of Ashima Arts for the
8 | // ideas for permutation and gradient selection.
9 | //
10 | // Copyright (c) 2011 Stefan Gustavson. All rights reserved.
11 | // Distributed under the MIT license. See LICENSE file.
12 | // https://github.com/ashima/webgl-noise
13 | //
14 |
15 | vec3 mod289(vec3 x)
16 | {
17 | return x - floor(x * (1.0 / 289.0)) * 289.0;
18 | }
19 |
20 | vec4 mod289(vec4 x)
21 | {
22 | return x - floor(x * (1.0 / 289.0)) * 289.0;
23 | }
24 |
25 | vec4 permute(vec4 x)
26 | {
27 | return mod289(((x*34.0)+1.0)*x);
28 | }
29 |
30 | vec4 taylorInvSqrt(vec4 r)
31 | {
32 | return 1.79284291400159 - 0.85373472095314 * r;
33 | }
34 |
35 | vec3 fade(vec3 t) {
36 | return t*t*t*(t*(t*6.0-15.0)+10.0);
37 | }
38 |
39 | // Classic Perlin noise
40 | float cnoise(vec3 P)
41 | {
42 | vec3 Pi0 = floor(P); // Integer part for indexing
43 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
44 | Pi0 = mod289(Pi0);
45 | Pi1 = mod289(Pi1);
46 | vec3 Pf0 = fract(P); // Fractional part for interpolation
47 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
48 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
49 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
50 | vec4 iz0 = Pi0.zzzz;
51 | vec4 iz1 = Pi1.zzzz;
52 |
53 | vec4 ixy = permute(permute(ix) + iy);
54 | vec4 ixy0 = permute(ixy + iz0);
55 | vec4 ixy1 = permute(ixy + iz1);
56 |
57 | vec4 gx0 = ixy0 * (1.0 / 7.0);
58 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
59 | gx0 = fract(gx0);
60 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
61 | vec4 sz0 = step(gz0, vec4(0.0));
62 | gx0 -= sz0 * (step(0.0, gx0) - 0.5);
63 | gy0 -= sz0 * (step(0.0, gy0) - 0.5);
64 |
65 | vec4 gx1 = ixy1 * (1.0 / 7.0);
66 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
67 | gx1 = fract(gx1);
68 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
69 | vec4 sz1 = step(gz1, vec4(0.0));
70 | gx1 -= sz1 * (step(0.0, gx1) - 0.5);
71 | gy1 -= sz1 * (step(0.0, gy1) - 0.5);
72 |
73 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
74 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
75 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
76 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
77 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
78 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
79 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
80 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
81 |
82 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
83 | g000 *= norm0.x;
84 | g010 *= norm0.y;
85 | g100 *= norm0.z;
86 | g110 *= norm0.w;
87 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
88 | g001 *= norm1.x;
89 | g011 *= norm1.y;
90 | g101 *= norm1.z;
91 | g111 *= norm1.w;
92 |
93 | float n000 = dot(g000, Pf0);
94 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
95 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
96 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
97 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
98 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
99 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
100 | float n111 = dot(g111, Pf1);
101 |
102 | vec3 fade_xyz = fade(Pf0);
103 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
104 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
105 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
106 | return 2.2 * n_xyz;
107 | }
108 |
109 | // Classic Perlin noise, periodic variant
110 | float pnoise(vec3 P, vec3 rep)
111 | {
112 | vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period
113 | vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period
114 | Pi0 = mod289(Pi0);
115 | Pi1 = mod289(Pi1);
116 | vec3 Pf0 = fract(P); // Fractional part for interpolation
117 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
118 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
119 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
120 | vec4 iz0 = Pi0.zzzz;
121 | vec4 iz1 = Pi1.zzzz;
122 |
123 | vec4 ixy = permute(permute(ix) + iy);
124 | vec4 ixy0 = permute(ixy + iz0);
125 | vec4 ixy1 = permute(ixy + iz1);
126 |
127 | vec4 gx0 = ixy0 * (1.0 / 7.0);
128 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
129 | gx0 = fract(gx0);
130 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
131 | vec4 sz0 = step(gz0, vec4(0.0));
132 | gx0 -= sz0 * (step(0.0, gx0) - 0.5);
133 | gy0 -= sz0 * (step(0.0, gy0) - 0.5);
134 |
135 | vec4 gx1 = ixy1 * (1.0 / 7.0);
136 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
137 | gx1 = fract(gx1);
138 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
139 | vec4 sz1 = step(gz1, vec4(0.0));
140 | gx1 -= sz1 * (step(0.0, gx1) - 0.5);
141 | gy1 -= sz1 * (step(0.0, gy1) - 0.5);
142 |
143 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
144 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
145 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
146 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
147 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
148 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
149 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
150 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
151 |
152 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
153 | g000 *= norm0.x;
154 | g010 *= norm0.y;
155 | g100 *= norm0.z;
156 | g110 *= norm0.w;
157 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
158 | g001 *= norm1.x;
159 | g011 *= norm1.y;
160 | g101 *= norm1.z;
161 | g111 *= norm1.w;
162 |
163 | float n000 = dot(g000, Pf0);
164 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
165 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
166 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
167 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
168 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
169 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
170 | float n111 = dot(g111, Pf1);
171 |
172 | vec3 fade_xyz = fade(Pf0);
173 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
174 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
175 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
176 | return 2.2 * n_xyz;
177 | }
178 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/glsl/classic-noise-4d.snip:
--------------------------------------------------------------------------------
1 | //
2 | // GLSL textureless classic 4D noise "cnoise",
3 | // with an RSL-style periodic variant "pnoise".
4 | // Author: Stefan Gustavson (stefan.gustavson@liu.se)
5 | // Version: 2011-08-22
6 | //
7 | // Many thanks to Ian McEwan of Ashima Arts for the
8 | // ideas for permutation and gradient selection.
9 | //
10 | // Copyright (c) 2011 Stefan Gustavson. All rights reserved.
11 | // Distributed under the MIT license. See LICENSE file.
12 | // https://github.com/ashima/webgl-noise
13 | //
14 |
15 | vec4 mod289(vec4 x)
16 | {
17 | return x - floor(x * (1.0 / 289.0)) * 289.0;
18 | }
19 |
20 | vec4 permute(vec4 x)
21 | {
22 | return mod289(((x*34.0)+1.0)*x);
23 | }
24 |
25 | vec4 taylorInvSqrt(vec4 r)
26 | {
27 | return 1.79284291400159 - 0.85373472095314 * r;
28 | }
29 |
30 | vec4 fade(vec4 t) {
31 | return t*t*t*(t*(t*6.0-15.0)+10.0);
32 | }
33 |
34 | // Classic Perlin noise
35 | float cnoise(vec4 P)
36 | {
37 | vec4 Pi0 = floor(P); // Integer part for indexing
38 | vec4 Pi1 = Pi0 + 1.0; // Integer part + 1
39 | Pi0 = mod289(Pi0);
40 | Pi1 = mod289(Pi1);
41 | vec4 Pf0 = fract(P); // Fractional part for interpolation
42 | vec4 Pf1 = Pf0 - 1.0; // Fractional part - 1.0
43 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
44 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
45 | vec4 iz0 = vec4(Pi0.zzzz);
46 | vec4 iz1 = vec4(Pi1.zzzz);
47 | vec4 iw0 = vec4(Pi0.wwww);
48 | vec4 iw1 = vec4(Pi1.wwww);
49 |
50 | vec4 ixy = permute(permute(ix) + iy);
51 | vec4 ixy0 = permute(ixy + iz0);
52 | vec4 ixy1 = permute(ixy + iz1);
53 | vec4 ixy00 = permute(ixy0 + iw0);
54 | vec4 ixy01 = permute(ixy0 + iw1);
55 | vec4 ixy10 = permute(ixy1 + iw0);
56 | vec4 ixy11 = permute(ixy1 + iw1);
57 |
58 | vec4 gx00 = ixy00 * (1.0 / 7.0);
59 | vec4 gy00 = floor(gx00) * (1.0 / 7.0);
60 | vec4 gz00 = floor(gy00) * (1.0 / 6.0);
61 | gx00 = fract(gx00) - 0.5;
62 | gy00 = fract(gy00) - 0.5;
63 | gz00 = fract(gz00) - 0.5;
64 | vec4 gw00 = vec4(0.75) - abs(gx00) - abs(gy00) - abs(gz00);
65 | vec4 sw00 = step(gw00, vec4(0.0));
66 | gx00 -= sw00 * (step(0.0, gx00) - 0.5);
67 | gy00 -= sw00 * (step(0.0, gy00) - 0.5);
68 |
69 | vec4 gx01 = ixy01 * (1.0 / 7.0);
70 | vec4 gy01 = floor(gx01) * (1.0 / 7.0);
71 | vec4 gz01 = floor(gy01) * (1.0 / 6.0);
72 | gx01 = fract(gx01) - 0.5;
73 | gy01 = fract(gy01) - 0.5;
74 | gz01 = fract(gz01) - 0.5;
75 | vec4 gw01 = vec4(0.75) - abs(gx01) - abs(gy01) - abs(gz01);
76 | vec4 sw01 = step(gw01, vec4(0.0));
77 | gx01 -= sw01 * (step(0.0, gx01) - 0.5);
78 | gy01 -= sw01 * (step(0.0, gy01) - 0.5);
79 |
80 | vec4 gx10 = ixy10 * (1.0 / 7.0);
81 | vec4 gy10 = floor(gx10) * (1.0 / 7.0);
82 | vec4 gz10 = floor(gy10) * (1.0 / 6.0);
83 | gx10 = fract(gx10) - 0.5;
84 | gy10 = fract(gy10) - 0.5;
85 | gz10 = fract(gz10) - 0.5;
86 | vec4 gw10 = vec4(0.75) - abs(gx10) - abs(gy10) - abs(gz10);
87 | vec4 sw10 = step(gw10, vec4(0.0));
88 | gx10 -= sw10 * (step(0.0, gx10) - 0.5);
89 | gy10 -= sw10 * (step(0.0, gy10) - 0.5);
90 |
91 | vec4 gx11 = ixy11 * (1.0 / 7.0);
92 | vec4 gy11 = floor(gx11) * (1.0 / 7.0);
93 | vec4 gz11 = floor(gy11) * (1.0 / 6.0);
94 | gx11 = fract(gx11) - 0.5;
95 | gy11 = fract(gy11) - 0.5;
96 | gz11 = fract(gz11) - 0.5;
97 | vec4 gw11 = vec4(0.75) - abs(gx11) - abs(gy11) - abs(gz11);
98 | vec4 sw11 = step(gw11, vec4(0.0));
99 | gx11 -= sw11 * (step(0.0, gx11) - 0.5);
100 | gy11 -= sw11 * (step(0.0, gy11) - 0.5);
101 |
102 | vec4 g0000 = vec4(gx00.x,gy00.x,gz00.x,gw00.x);
103 | vec4 g1000 = vec4(gx00.y,gy00.y,gz00.y,gw00.y);
104 | vec4 g0100 = vec4(gx00.z,gy00.z,gz00.z,gw00.z);
105 | vec4 g1100 = vec4(gx00.w,gy00.w,gz00.w,gw00.w);
106 | vec4 g0010 = vec4(gx10.x,gy10.x,gz10.x,gw10.x);
107 | vec4 g1010 = vec4(gx10.y,gy10.y,gz10.y,gw10.y);
108 | vec4 g0110 = vec4(gx10.z,gy10.z,gz10.z,gw10.z);
109 | vec4 g1110 = vec4(gx10.w,gy10.w,gz10.w,gw10.w);
110 | vec4 g0001 = vec4(gx01.x,gy01.x,gz01.x,gw01.x);
111 | vec4 g1001 = vec4(gx01.y,gy01.y,gz01.y,gw01.y);
112 | vec4 g0101 = vec4(gx01.z,gy01.z,gz01.z,gw01.z);
113 | vec4 g1101 = vec4(gx01.w,gy01.w,gz01.w,gw01.w);
114 | vec4 g0011 = vec4(gx11.x,gy11.x,gz11.x,gw11.x);
115 | vec4 g1011 = vec4(gx11.y,gy11.y,gz11.y,gw11.y);
116 | vec4 g0111 = vec4(gx11.z,gy11.z,gz11.z,gw11.z);
117 | vec4 g1111 = vec4(gx11.w,gy11.w,gz11.w,gw11.w);
118 |
119 | vec4 norm00 = taylorInvSqrt(vec4(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100)));
120 | g0000 *= norm00.x;
121 | g0100 *= norm00.y;
122 | g1000 *= norm00.z;
123 | g1100 *= norm00.w;
124 |
125 | vec4 norm01 = taylorInvSqrt(vec4(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101)));
126 | g0001 *= norm01.x;
127 | g0101 *= norm01.y;
128 | g1001 *= norm01.z;
129 | g1101 *= norm01.w;
130 |
131 | vec4 norm10 = taylorInvSqrt(vec4(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110)));
132 | g0010 *= norm10.x;
133 | g0110 *= norm10.y;
134 | g1010 *= norm10.z;
135 | g1110 *= norm10.w;
136 |
137 | vec4 norm11 = taylorInvSqrt(vec4(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111)));
138 | g0011 *= norm11.x;
139 | g0111 *= norm11.y;
140 | g1011 *= norm11.z;
141 | g1111 *= norm11.w;
142 |
143 | float n0000 = dot(g0000, Pf0);
144 | float n1000 = dot(g1000, vec4(Pf1.x, Pf0.yzw));
145 | float n0100 = dot(g0100, vec4(Pf0.x, Pf1.y, Pf0.zw));
146 | float n1100 = dot(g1100, vec4(Pf1.xy, Pf0.zw));
147 | float n0010 = dot(g0010, vec4(Pf0.xy, Pf1.z, Pf0.w));
148 | float n1010 = dot(g1010, vec4(Pf1.x, Pf0.y, Pf1.z, Pf0.w));
149 | float n0110 = dot(g0110, vec4(Pf0.x, Pf1.yz, Pf0.w));
150 | float n1110 = dot(g1110, vec4(Pf1.xyz, Pf0.w));
151 | float n0001 = dot(g0001, vec4(Pf0.xyz, Pf1.w));
152 | float n1001 = dot(g1001, vec4(Pf1.x, Pf0.yz, Pf1.w));
153 | float n0101 = dot(g0101, vec4(Pf0.x, Pf1.y, Pf0.z, Pf1.w));
154 | float n1101 = dot(g1101, vec4(Pf1.xy, Pf0.z, Pf1.w));
155 | float n0011 = dot(g0011, vec4(Pf0.xy, Pf1.zw));
156 | float n1011 = dot(g1011, vec4(Pf1.x, Pf0.y, Pf1.zw));
157 | float n0111 = dot(g0111, vec4(Pf0.x, Pf1.yzw));
158 | float n1111 = dot(g1111, Pf1);
159 |
160 | vec4 fade_xyzw = fade(Pf0);
161 | vec4 n_0w = mix(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w);
162 | vec4 n_1w = mix(vec4(n0010, n1010, n0110, n1110), vec4(n0011, n1011, n0111, n1111), fade_xyzw.w);
163 | vec4 n_zw = mix(n_0w, n_1w, fade_xyzw.z);
164 | vec2 n_yzw = mix(n_zw.xy, n_zw.zw, fade_xyzw.y);
165 | float n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x);
166 | return 2.2 * n_xyzw;
167 | }
168 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/webgl.js:
--------------------------------------------------------------------------------
1 |
2 | /*...........................................................................*/
3 | function buildAttribs(gl, layout) {
4 | var attribs = {};
5 | for (var key in layout) {
6 | attribs[key] = {
7 | buffer: new GLBuffer(gl),
8 | size: layout[key]
9 | }
10 | }
11 | return attribs;
12 | }
13 |
14 | module.exports.buildAttribs = buildAttribs;
15 |
16 |
17 | /*...........................................................................*/
18 | function getExtensions(gl, extArray) {
19 | var ext = {};
20 | for (var i = 0; i < extArray.length; i++) {
21 | var e = gl.getExtension(extArray[i]);
22 | if (e === null) {
23 | throw "Extension " + extArray[i] + " not available.";
24 | }
25 | ext[extArray[i]] = e;
26 | }
27 | return ext;
28 | };
29 |
30 | module.exports.getExtensions = getExtensions;
31 |
32 |
33 | /*...........................................................................*/
34 | function Framebuffer(gl, color, depth, ext) {
35 |
36 | var self = this;
37 |
38 | self.initialize = function() {
39 | self.fb = gl.createFramebuffer();
40 | self.bind();
41 | if (color.length > 1) {
42 | var drawBuffers = [];
43 | for (var i = 0; i < color.length; i++) {
44 | drawBuffers.push(ext["COLOR_ATTACHMENT" + i + "_WEBGL"]);
45 | }
46 | ext.drawBuffersWEBGL(drawBuffers);
47 | for (var i = 0; i < color.length; i++) {
48 | gl.framebufferTexture2D(gl.FRAMEBUFFER, ext["COLOR_ATTACHMENT" + i + "_WEBGL"],
49 | gl.TEXTURE_2D, color[i].texture, 0);
50 | }
51 | } else {
52 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, color[0].texture, 0);
53 | }
54 | if (depth !== undefined) {
55 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depth.texture, 0);
56 | }
57 | };
58 |
59 | self.bind = function() {
60 | gl.bindFramebuffer(gl.FRAMEBUFFER, self.fb);
61 | }
62 |
63 | self.initialize();
64 |
65 | };
66 |
67 | module.exports.Framebuffer = Framebuffer;
68 |
69 |
70 | /*...........................................................................*/
71 | function Texture(gl, index, data, width, height, options) {
72 | options = options || {};
73 | options.target = options.target || gl.TEXTURE_2D;
74 | options.mag = options.mag || gl.NEAREST;
75 | options.min = options.min || gl.NEAREST;
76 | options.wraps = options.wraps || gl.CLAMP_TO_EDGE;
77 | options.wrapt = options.wrapt || gl.CLAMP_TO_EDGE;
78 | options.internalFormat = options.internalFormat || gl.RGBA;
79 | options.format = options.format || gl.RGBA;
80 | options.type = options.type || gl.UNSIGNED_BYTE;
81 |
82 | var self = this;
83 |
84 | self.initialize = function() {
85 | self.index = index;
86 | self.activate();
87 | self.texture = gl.createTexture();
88 | self.bind();
89 | gl.texImage2D(options.target, 0, options.internalFormat, options.format, options.type, data);
90 | gl.texParameteri(options.target, gl.TEXTURE_MAG_FILTER, options.mag);
91 | gl.texParameteri(options.target, gl.TEXTURE_MIN_FILTER, options.min);
92 | gl.texParameteri(options.target, gl.TEXTURE_WRAP_S, options.wraps);
93 | gl.texParameteri(options.target, gl.TEXTURE_WRAP_T, options.wrapt);
94 | if (options.mag != gl.NEAREST || options.min != gl.NEAREST) {
95 | gl.generateMipmap(options.target);
96 | }
97 | }
98 |
99 | self.bind = function() {
100 | gl.bindTexture(options.target, self.texture);
101 | };
102 |
103 | self.activate = function() {
104 | gl.activeTexture(gl.TEXTURE0 + self.index);
105 | };
106 |
107 | self.reset = function() {
108 | self.activate();
109 | self.bind();
110 | gl.texImage2D(options.target, 0, options.internalFormat, width, height,
111 | 0, options.format, options.type, data);
112 | }
113 |
114 | self.initialize();
115 | }
116 |
117 | module.exports.Texture = Texture;
118 |
119 |
120 | /*...........................................................................*/
121 | function GLBuffer(gl) {
122 |
123 | var self = this;
124 |
125 | self.initialize = function() {
126 | self.buffer = gl.createBuffer();
127 | }
128 |
129 | self.bind = function() {
130 | gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
131 | }
132 |
133 | self.set = function(data) {
134 | self.bind();
135 | gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
136 | }
137 |
138 | self.initialize();
139 | };
140 |
141 | module.exports.GLBuffer = GLBuffer;
142 |
143 |
144 | /*...........................................................................*/
145 | function Renderable(gl, program, buffers, primitiveCount) {
146 |
147 | var self = this;
148 |
149 | self.primitiveCount = primitiveCount;
150 |
151 | self.initialize = function() {
152 | }
153 |
154 | self.render = function() {
155 | program.use();
156 | for (name in buffers) {
157 | var buffer = buffers[name].buffer;
158 | var size = buffers[name].size;
159 | try {
160 | var location = program.attribs[name].location;
161 | } catch (e) {
162 | console.log("Could not find location for", name);
163 | throw e;
164 | }
165 | buffer.bind();
166 | gl.enableVertexAttribArray(location);
167 | gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
168 | }
169 | gl.drawArrays(gl.TRIANGLES, 0, 3 * primitiveCount);
170 | for (name in self.buffers) {
171 | gl.disableVertexAttribArray(program.attributes[name].location);
172 | }
173 | }
174 |
175 | self.initialize();
176 | };
177 |
178 | module.exports.Renderable = Renderable;
179 |
180 |
181 | /*...........................................................................*/
182 | function InstancedRenderable(gl, program, buffers, primitiveCount, instancedExt) {
183 |
184 | var self = this;
185 |
186 | self.initialize = function() {
187 | }
188 |
189 | self.render = function() {
190 | program.use();
191 | for (name in buffers) {
192 | var buffer = buffers[name].buffer;
193 | var size = buffers[name].size;
194 | try {
195 | var location = program.attribs[name].location;
196 | } catch (e) {
197 | console.log("Could not find location for", name);
198 | throw e;
199 | }
200 | buffer.bind();
201 | gl.enableVertexAttribArray(location);
202 | gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
203 | instancedExt.vertexAttribDivisorANGLE(location, buffers[name].divisor);
204 | }
205 | instancedExt.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6*2*3, primitiveCount)
206 | for (name in self.buffers) {
207 | gl.disableVertexAttribArray(program.attributes[name].location);
208 | }
209 | }
210 |
211 | self.initialize();
212 | };
213 |
214 | module.exports.InstancedRenderable = InstancedRenderable;
215 |
216 |
217 | /*...........................................................................*/
218 | function Program(gl, vertexSource, fragmentSource) {
219 |
220 | var self = this;
221 |
222 | self.initialize = function() {
223 | self.program = self.compileProgram(vertexSource, fragmentSource);
224 | self.attribs = self.gatherAttribs();
225 | self.uniforms = self.gatherUniforms();
226 | }
227 |
228 | self.use = function() {
229 | gl.useProgram(self.program);
230 | }
231 |
232 | self.compileProgram = function(vertexSource, fragmentSource) {
233 | var vertexShader = self.compileShader(vertexSource, gl.VERTEX_SHADER);
234 | var fragmentShader = self.compileShader(fragmentSource, gl.FRAGMENT_SHADER);
235 | var program = gl.createProgram();
236 | gl.attachShader(program, vertexShader);
237 | gl.attachShader(program, fragmentShader);
238 | gl.linkProgram(program);
239 | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
240 | console.log(gl.getProgramInfoLog(program));
241 | throw "Failed to compile program.";
242 | }
243 | return program;
244 | }
245 |
246 | self.compileShader = function(source, type) {
247 | var shader = gl.createShader(type);
248 | gl.shaderSource(shader, source);
249 | gl.compileShader(shader);
250 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
251 | var err = gl.getShaderInfoLog(shader);
252 | var lineno = parseInt(err.split(':')[2]);
253 | var split = source.split("\n");
254 | for (var i in split) {
255 | var q = parseInt(i);
256 | console.log(q + " " + split[i]);
257 | if (i == lineno - 1) {
258 | console.warn(err);
259 | }
260 | }
261 | typeString = type == gl.VERTEX_SHADER ? "vertex" : "fragment";
262 | throw "Failed to compile " + typeString + " shader.";
263 | }
264 | return shader;
265 | }
266 |
267 | self.setUniform = function(name, type, value) {
268 | var args = Array.prototype.slice.call(arguments, 2);
269 | self.use(); // Make this idempotent. At the context level, perhaps?
270 | try {
271 | var location = self.uniforms[name].location;
272 | }
273 | catch(e) {
274 | console.log(name);
275 | throw e;
276 | }
277 | gl['uniform' + type].apply(gl, [location].concat(args));
278 | }
279 |
280 | self.gatherUniforms = function() {
281 | var uniforms = {};
282 | var nUniforms = gl.getProgramParameter(self.program, gl.ACTIVE_UNIFORMS);
283 | for (var i = 0; i < nUniforms; i++) {
284 | var uniform = gl.getActiveUniform(self.program, i);
285 | uniforms[uniform.name] = {
286 | name: uniform.name,
287 | location: gl.getUniformLocation(self.program, uniform.name),
288 | type: uniform.type,
289 | size: uniform.size
290 | };
291 | }
292 | return uniforms;
293 | }
294 |
295 | self.gatherAttribs = function() {
296 | var attribs = {};
297 | var nAttribs = gl.getProgramParameter(self.program, gl.ACTIVE_ATTRIBUTES);
298 | for (var i = 0; i < nAttribs; i++) {
299 | var attrib = gl.getActiveAttrib(self.program, i);
300 | attribs[attrib.name] = {
301 | name: attrib.name,
302 | location: gl.getAttribLocation(self.program, attrib.name),
303 | type: attrib.type,
304 | size: attrib.size
305 | };
306 | }
307 | return attribs;
308 | }
309 |
310 | /*...........................................................................*/
311 | self.initialize();
312 |
313 | };
314 |
315 | /*...........................................................................*/
316 | module.exports.Program = Program;
317 |
--------------------------------------------------------------------------------
/builtins/space-2d/src/webgl.js:
--------------------------------------------------------------------------------
1 |
2 | /*...........................................................................*/
3 | function buildAttribs(gl, layout) {
4 | var attribs = {};
5 | for (var key in layout) {
6 | attribs[key] = {
7 | buffer: new GLBuffer(gl),
8 | size: layout[key]
9 | }
10 | }
11 | return attribs;
12 | }
13 |
14 | module.exports.buildAttribs = buildAttribs;
15 |
16 |
17 | /*...........................................................................*/
18 | function getExtensions(gl, extArray) {
19 | var ext = {};
20 | for (var i = 0; i < extArray.length; i++) {
21 | var e = gl.getExtension(extArray[i]);
22 | if (e === null) {
23 | throw "Extension " + extArray[i] + " not available.";
24 | }
25 | ext[extArray[i]] = e;
26 | }
27 | return ext;
28 | };
29 |
30 | module.exports.getExtensions = getExtensions;
31 |
32 |
33 | /*...........................................................................*/
34 | function Framebuffer(gl, color, depth, ext) {
35 |
36 | var self = this;
37 |
38 | self.initialize = function() {
39 | self.fb = gl.createFramebuffer();
40 | self.bind();
41 | if (color.length > 1) {
42 | var drawBuffers = [];
43 | for (var i = 0; i < color.length; i++) {
44 | drawBuffers.push(ext["COLOR_ATTACHMENT" + i + "_WEBGL"]);
45 | }
46 | ext.drawBuffersWEBGL(drawBuffers);
47 | for (var i = 0; i < color.length; i++) {
48 | gl.framebufferTexture2D(gl.FRAMEBUFFER, ext["COLOR_ATTACHMENT" + i + "_WEBGL"],
49 | gl.TEXTURE_2D, color[i].texture, 0);
50 | }
51 | } else {
52 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, color[0].texture, 0);
53 | }
54 | if (depth !== undefined) {
55 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depth.texture, 0);
56 | }
57 | };
58 |
59 | self.bind = function() {
60 | gl.bindFramebuffer(gl.FRAMEBUFFER, self.fb);
61 | }
62 |
63 | self.initialize();
64 |
65 | };
66 |
67 | module.exports.Framebuffer = Framebuffer;
68 |
69 |
70 | /*...........................................................................*/
71 | function Texture(gl, index, data, width, height, options) {
72 | options = options || {};
73 | options.target = options.target || gl.TEXTURE_2D;
74 | options.mag = options.mag || gl.NEAREST;
75 | options.min = options.min || gl.NEAREST;
76 | options.wraps = options.wraps || gl.CLAMP_TO_EDGE;
77 | options.wrapt = options.wrapt || gl.CLAMP_TO_EDGE;
78 | options.internalFormat = options.internalFormat || gl.RGBA;
79 | options.format = options.format || gl.RGBA;
80 | options.type = options.type || gl.UNSIGNED_BYTE;
81 |
82 | var self = this;
83 |
84 | self.initialize = function() {
85 | self.index = index;
86 | self.activate();
87 | self.texture = gl.createTexture();
88 | self.bind();
89 | gl.texImage2D(options.target, 0, options.internalFormat, width, height,
90 | 0, options.format, options.type, data);
91 | gl.texParameteri(options.target, gl.TEXTURE_MAG_FILTER, options.mag);
92 | gl.texParameteri(options.target, gl.TEXTURE_MIN_FILTER, options.min);
93 | gl.texParameteri(options.target, gl.TEXTURE_WRAP_S, options.wraps);
94 | gl.texParameteri(options.target, gl.TEXTURE_WRAP_T, options.wrapt);
95 | if (options.mag != gl.NEAREST || options.min != gl.NEAREST) {
96 | gl.generateMipmap(options.target);
97 | }
98 | }
99 |
100 | self.bind = function() {
101 | gl.bindTexture(options.target, self.texture);
102 | };
103 |
104 | self.activate = function() {
105 | gl.activeTexture(gl.TEXTURE0 + self.index);
106 | };
107 |
108 | self.reset = function() {
109 | self.activate();
110 | self.bind();
111 | gl.texImage2D(options.target, 0, options.internalFormat, width, height,
112 | 0, options.format, options.type, data);
113 | }
114 |
115 | self.initialize();
116 | }
117 |
118 | module.exports.Texture = Texture;
119 |
120 |
121 | /*...........................................................................*/
122 | function GLBuffer(gl) {
123 |
124 | var self = this;
125 |
126 | self.initialize = function() {
127 | self.buffer = gl.createBuffer();
128 | }
129 |
130 | self.bind = function() {
131 | gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
132 | }
133 |
134 | self.set = function(data) {
135 | self.bind();
136 | gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
137 | }
138 |
139 | self.initialize();
140 | };
141 |
142 | module.exports.GLBuffer = GLBuffer;
143 |
144 |
145 | /*...........................................................................*/
146 | function Renderable(gl, program, buffers, primitiveCount) {
147 |
148 | var self = this;
149 |
150 | self.primitiveCount = primitiveCount;
151 |
152 | self.initialize = function() {
153 | }
154 |
155 | self.render = function() {
156 | program.use();
157 | for (name in buffers) {
158 | var buffer = buffers[name].buffer;
159 | var size = buffers[name].size;
160 | try {
161 | var location = program.attribs[name].location;
162 | } catch (e) {
163 | console.log("Could not find location for", name);
164 | throw e;
165 | }
166 | buffer.bind();
167 | gl.enableVertexAttribArray(location);
168 | gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
169 | }
170 | gl.drawArrays(gl.TRIANGLES, 0, 3 * primitiveCount);
171 | for (name in self.buffers) {
172 | gl.disableVertexAttribArray(program.attributes[name].location);
173 | }
174 | }
175 |
176 | self.initialize();
177 | };
178 |
179 | module.exports.Renderable = Renderable;
180 |
181 |
182 | /*...........................................................................*/
183 | function InstancedRenderable(gl, program, buffers, primitiveCount, instancedExt) {
184 |
185 | var self = this;
186 |
187 | self.initialize = function() {
188 | }
189 |
190 | self.render = function() {
191 | program.use();
192 | for (name in buffers) {
193 | var buffer = buffers[name].buffer;
194 | var size = buffers[name].size;
195 | try {
196 | var location = program.attribs[name].location;
197 | } catch (e) {
198 | console.log("Could not find location for", name);
199 | throw e;
200 | }
201 | buffer.bind();
202 | gl.enableVertexAttribArray(location);
203 | gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
204 | instancedExt.vertexAttribDivisorANGLE(location, buffers[name].divisor);
205 | }
206 | instancedExt.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6*2*3, primitiveCount)
207 | for (name in self.buffers) {
208 | gl.disableVertexAttribArray(program.attributes[name].location);
209 | }
210 | }
211 |
212 | self.initialize();
213 | };
214 |
215 | module.exports.InstancedRenderable = InstancedRenderable;
216 |
217 |
218 | /*...........................................................................*/
219 | function Program(gl, vertexSource, fragmentSource) {
220 |
221 | var self = this;
222 |
223 | self.initialize = function() {
224 | self.program = self.compileProgram(vertexSource, fragmentSource);
225 | self.attribs = self.gatherAttribs();
226 | self.uniforms = self.gatherUniforms();
227 | }
228 |
229 | self.use = function() {
230 | gl.useProgram(self.program);
231 | }
232 |
233 | self.compileProgram = function(vertexSource, fragmentSource) {
234 | var vertexShader = self.compileShader(vertexSource, gl.VERTEX_SHADER);
235 | var fragmentShader = self.compileShader(fragmentSource, gl.FRAGMENT_SHADER);
236 | var program = gl.createProgram();
237 | gl.attachShader(program, vertexShader);
238 | gl.attachShader(program, fragmentShader);
239 | gl.linkProgram(program);
240 | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
241 | console.log(gl.getProgramInfoLog(program));
242 | throw "Failed to compile program.";
243 | }
244 | return program;
245 | }
246 |
247 | self.compileShader = function(source, type) {
248 | var shader = gl.createShader(type);
249 | gl.shaderSource(shader, source);
250 | gl.compileShader(shader);
251 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
252 | var err = gl.getShaderInfoLog(shader);
253 | var lineno = parseInt(err.split(':')[2]);
254 | var split = source.split("\n");
255 | for (var i in split) {
256 | var q = parseInt(i);
257 | console.log(q + " " + split[i]);
258 | if (i == lineno - 1) {
259 | console.warn(err);
260 | }
261 | }
262 | typeString = type == gl.VERTEX_SHADER ? "vertex" : "fragment";
263 | throw "Failed to compile " + typeString + " shader.";
264 | }
265 | return shader;
266 | }
267 |
268 | self.setUniform = function(name, type, value) {
269 | var args = Array.prototype.slice.call(arguments, 2);
270 | self.use(); // Make this idempotent. At the context level, perhaps?
271 | try {
272 | var location = self.uniforms[name].location;
273 | }
274 | catch(e) {
275 | console.log(name);
276 | throw e;
277 | }
278 | gl['uniform' + type].apply(gl, [location].concat(args));
279 | }
280 |
281 | self.gatherUniforms = function() {
282 | var uniforms = {};
283 | var nUniforms = gl.getProgramParameter(self.program, gl.ACTIVE_UNIFORMS);
284 | for (var i = 0; i < nUniforms; i++) {
285 | var uniform = gl.getActiveUniform(self.program, i);
286 | uniforms[uniform.name] = {
287 | name: uniform.name,
288 | location: gl.getUniformLocation(self.program, uniform.name),
289 | type: uniform.type,
290 | size: uniform.size
291 | };
292 | }
293 | return uniforms;
294 | }
295 |
296 | self.gatherAttribs = function() {
297 | var attribs = {};
298 | var nAttribs = gl.getProgramParameter(self.program, gl.ACTIVE_ATTRIBUTES);
299 | for (var i = 0; i < nAttribs; i++) {
300 | var attrib = gl.getActiveAttrib(self.program, i);
301 | attribs[attrib.name] = {
302 | name: attrib.name,
303 | location: gl.getAttribLocation(self.program, attrib.name),
304 | type: attrib.type,
305 | size: attrib.size
306 | };
307 | }
308 | return attribs;
309 | }
310 |
311 | /*...........................................................................*/
312 | self.initialize();
313 |
314 | };
315 |
316 | /*...........................................................................*/
317 | module.exports.Program = Program;
318 |
--------------------------------------------------------------------------------
/builtins/space-skybox/src/space-3d.js:
--------------------------------------------------------------------------------
1 | // jshint -W097
2 | // jshint undef: true, unused: true
3 | /* globals require,document,__dirname,Float32Array,module*/
4 |
5 | "use strict";
6 |
7 | var fs = require("fs");
8 | var glm = require("gl-matrix");
9 | var webgl = require("./webgl.js");
10 | var util = require("./util.js");
11 | var rng = require("rng");
12 |
13 | var NSTARS = 100000;
14 |
15 | module.exports = function() {
16 |
17 | var self = this;
18 |
19 | self.initialize = function() {
20 |
21 | // Initialize the offscreen rendering canvas.
22 | self.canvas = document.createElement("canvas");
23 |
24 | // Initialize the gl context.
25 | self.gl = self.canvas.getContext("webgl");
26 | self.gl.enable(self.gl.BLEND);
27 | self.gl.blendFuncSeparate(self.gl.SRC_ALPHA, self.gl.ONE_MINUS_SRC_ALPHA, self.gl.ZERO, self.gl.ONE);
28 |
29 | // Load the programs.
30 | self.pNebula = util.loadProgram(self.gl, fs.readFileSync(__dirname + "/glsl/nebula.glsl", "utf8"));
31 | self.pPointStars = util.loadProgram(self.gl, fs.readFileSync(__dirname + "/glsl/point-stars.glsl", "utf8"));
32 | self.pStar = util.loadProgram(self.gl, fs.readFileSync(__dirname + "/glsl/star.glsl", "utf8"));
33 | self.pSun = util.loadProgram(self.gl, fs.readFileSync(__dirname + "/glsl/sun.glsl", "utf8"));
34 |
35 | // Create the point stars renderable.
36 | var rand = new rng.MT(hashcode("best seed ever") + 5000);
37 | var position = new Float32Array(18 * NSTARS);
38 | var color = new Float32Array(18 * NSTARS);
39 | for (var i = 0; i < NSTARS; i++) {
40 | var size = 0.05;
41 | var pos = glm.vec3.random(glm.vec3.create(), 1.0);
42 | var star = buildStar(size, pos, 128.0, rand);
43 | position.set(star.position, i * 18);
44 | color.set(star.color, i * 18);
45 | }
46 | var attribs = webgl.buildAttribs(self.gl, {aPosition:3, aColor:3});
47 | attribs.aPosition.buffer.set(position);
48 | attribs.aColor.buffer.set(color);
49 | var count = position.length / 9;
50 | self.rPointStars = new webgl.Renderable(self.gl, self.pPointStars, attribs, count);
51 |
52 | // Create the nebula, sun, and star renderables.
53 | self.rNebula = buildBox(self.gl, self.pNebula);
54 | self.rSun = buildBox(self.gl, self.pSun);
55 | self.rStar = buildBox(self.gl, self.pStar);
56 | };
57 |
58 | self.render = function(params) {
59 |
60 | // We'll be returning a map of direction to texture.
61 | var textures = {};
62 |
63 | // Handle changes to resolution.
64 | self.canvas.width = self.canvas.height = params.resolution;
65 | self.gl.viewport(0, 0, params.resolution, params.resolution);
66 |
67 | // Initialize the point star parameters.
68 | var rand = new rng.MT(hashcode(params.seed) + 1000);
69 | var pStarParams = [];
70 | while (params.pointStars) {
71 | pStarParams.push({
72 | rotation: randomRotation(rand),
73 | });
74 | if (rand.random() < 0.2) {
75 | break;
76 | }
77 | }
78 |
79 | // Initialize the star parameters.
80 | var rand = new rng.MT(hashcode(params.seed) + 3000);
81 | var starParams = [];
82 | while (params.stars) {
83 | starParams.push({
84 | pos: randomVec3(rand),
85 | color: [1,1,1],
86 | size: 0.0,
87 | falloff: rand.random() * Math.pow(2, 20) + Math.pow(2, 20),
88 | });
89 | if (rand.random() < 0.01) {
90 | break;
91 | }
92 | }
93 |
94 | // Initialize the nebula parameters.
95 | var rand = new rng.MT(hashcode(params.seed) + 2000);
96 | var nebulaParams = [];
97 | while (params.nebulae) {
98 | nebulaParams.push({
99 | scale: rand.random() * 0.5 + 0.25,
100 | color: [rand.random(), rand.random(), rand.random()],
101 | intensity: rand.random() * 0.2 + 0.9,
102 | falloff: rand.random() * 3.0 + 3.0,
103 | offset: [rand.random() * 2000 - 1000, rand.random() * 2000 - 1000, rand.random() * 2000 - 1000],
104 | });
105 | if (rand.random() < 0.5) {
106 | break;
107 | }
108 | }
109 |
110 | // Initialize the sun parameters.
111 | var rand = new rng.MT(hashcode(params.seed) + 4000);
112 | var sunParams = [];
113 | if (params.sun) {
114 | sunParams.push({
115 | pos: randomVec3(rand),
116 | color: [rand.random(), rand.random(), rand.random()],
117 | size: rand.random() * 0.0001 + 0.0001,
118 | falloff: rand.random() * 16.0 + 8.0,
119 | });
120 | }
121 |
122 | // Create a list of directions we'll be iterating over.
123 | var dirs = {
124 | front: {
125 | target: [0, 0, -1],
126 | up: [0, 1, 0]
127 | },
128 | back: {
129 | target: [0, 0, 1],
130 | up: [0, 1, 0]
131 | },
132 | left: {
133 | target: [-1, 0, 0],
134 | up: [0, 1, 0]
135 | },
136 | right: {
137 | target: [1, 0, 0],
138 | up: [0, 1, 0]
139 | },
140 | top: {
141 | target: [0, 1, 0],
142 | up: [0, 0, 1]
143 | },
144 | bottom: {
145 | target: [0, -1, 0],
146 | up: [0, 0, -1]
147 | }
148 | };
149 |
150 | // Define and initialize the model, view, and projection matrices.
151 | var model = glm.mat4.create();
152 | var view = glm.mat4.create();
153 | var projection = glm.mat4.create();
154 | glm.mat4.perspective(projection, Math.PI/2, 1.0, 0.1, 256);
155 |
156 | // Iterate over the directions to render and create the textures.
157 | var keys = Object.keys(dirs);
158 | for (var i = 0; i < keys.length; i++) {
159 |
160 | // Clear the context.
161 | self.gl.clearColor(0,0,0,1);
162 | self.gl.clear(self.gl.COLOR_BUFFER_BIT);
163 |
164 | // Look in the direection for this texture.
165 | var dir = dirs[keys[i]];
166 | glm.mat4.lookAt(view, [0,0,0], dir.target, dir.up);
167 |
168 | // Render the point stars.
169 | self.pPointStars.use();
170 | model = glm.mat4.create();
171 | self.pPointStars.setUniform("uView", "Matrix4fv", false, view);
172 | self.pPointStars.setUniform("uProjection", "Matrix4fv", false, projection);
173 | for (var j = 0; j < pStarParams.length; j++) {
174 | var ps = pStarParams[j];
175 | glm.mat4.mul(model, ps.rotation, model);
176 | self.pPointStars.setUniform("uModel", "Matrix4fv", false, model);
177 | self.rPointStars.render();
178 | }
179 |
180 | // Render the stars.
181 | self.pStar.use();
182 | self.pStar.setUniform("uView", "Matrix4fv", false, view);
183 | self.pStar.setUniform("uProjection", "Matrix4fv", false, projection);
184 | self.pStar.setUniform("uModel", "Matrix4fv", false, model);
185 | for (j = 0; j < starParams.length; j++) {
186 | var s = starParams[j];
187 | self.pStar.setUniform("uPosition", "3fv", s.pos);
188 | self.pStar.setUniform("uColor", "3fv", s.color);
189 | self.pStar.setUniform("uSize", "1f", s.size);
190 | self.pStar.setUniform("uFalloff", "1f", s.falloff);
191 | self.rStar.render();
192 | }
193 |
194 | // Render the nebulae.
195 | self.pNebula.use();
196 | model = glm.mat4.create();
197 | for (j = 0; j < nebulaParams.length; j++) {
198 | var p = nebulaParams[j];
199 | self.pNebula.setUniform("uModel", "Matrix4fv", false, model);
200 | self.pNebula.setUniform("uView", "Matrix4fv", false, view);
201 | self.pNebula.setUniform("uProjection", "Matrix4fv", false, projection);
202 | self.pNebula.setUniform("uScale", "1f", p.scale);
203 | self.pNebula.setUniform("uColor", "3fv", p.color);
204 | self.pNebula.setUniform("uIntensity", "1f", p.intensity);
205 | self.pNebula.setUniform("uFalloff", "1f", p.falloff);
206 | self.pNebula.setUniform("uOffset", "3fv", p.offset);
207 | self.rNebula.render();
208 |
209 | }
210 |
211 | // Render the suns.
212 | self.pSun.use();
213 | self.pSun.setUniform("uView", "Matrix4fv", false, view);
214 | self.pSun.setUniform("uProjection", "Matrix4fv", false, projection);
215 | self.pSun.setUniform("uModel", "Matrix4fv", false, model);
216 | for (j = 0; j < sunParams.length; j++) {
217 | var sun = sunParams[j];
218 | self.pSun.setUniform("uPosition", "3fv", sun.pos);
219 | self.pSun.setUniform("uColor", "3fv", sun.color);
220 | self.pSun.setUniform("uSize", "1f", sun.size);
221 | self.pSun.setUniform("uFalloff", "1f", sun.falloff);
222 | self.rSun.render();
223 | }
224 |
225 | // Create the texture.
226 | var c = document.createElement("canvas");
227 | c.width = c.height = params.resolution;
228 | var ctx = c.getContext("2d");
229 | ctx.drawImage(self.canvas, 0, 0);
230 | textures[keys[i]] = c;
231 | }
232 |
233 | return textures;
234 | };
235 |
236 | self.initialize();
237 | };
238 |
239 |
240 | function buildStar(size, pos, dist, rand) {
241 |
242 | var c = Math.pow(rand.random(), 4.0);
243 | var color = [
244 | c, c, c,
245 | c, c, c,
246 | c, c, c,
247 | c, c, c,
248 | c, c, c,
249 | c, c, c
250 | ];
251 |
252 | var vertices = [
253 | [-size, -size, 0],
254 | [ size, -size, 0],
255 | [ size, size, 0],
256 | [-size, -size, 0],
257 | [ size, size, 0],
258 | [-size, size, 0]
259 | ];
260 |
261 | var position = [];
262 |
263 | for (var ii = 0; ii < 6; ii++) {
264 | var rot = quatRotFromForward(pos);
265 | glm.vec3.transformQuat(vertices[ii], vertices[ii], rot);
266 | vertices[ii][0] += pos[0] * dist;
267 | vertices[ii][1] += pos[1] * dist;
268 | vertices[ii][2] += pos[2] * dist;
269 | position.push.apply(position, vertices[ii]);
270 | }
271 |
272 | return {
273 | position: position,
274 | color: color
275 | };
276 | }
277 |
278 |
279 | function buildBox(gl, program) {
280 | var position = [
281 | -1, -1, -1,
282 | 1, -1, -1,
283 | 1, 1, -1,
284 | -1, -1, -1,
285 | 1, 1, -1,
286 | -1, 1, -1,
287 |
288 | 1, -1, 1,
289 | -1, -1, 1,
290 | -1, 1, 1,
291 | 1, -1, 1,
292 | -1, 1, 1,
293 | 1, 1, 1,
294 |
295 | 1, -1, -1,
296 | 1, -1, 1,
297 | 1, 1, 1,
298 | 1, -1, -1,
299 | 1, 1, 1,
300 | 1, 1, -1,
301 |
302 | -1, -1, 1,
303 | -1, -1, -1,
304 | -1, 1, -1,
305 | -1, -1, 1,
306 | -1, 1, -1,
307 | -1, 1, 1,
308 |
309 | -1, 1, -1,
310 | 1, 1, -1,
311 | 1, 1, 1,
312 | -1, 1, -1,
313 | 1, 1, 1,
314 | -1, 1, 1,
315 |
316 | -1, -1, 1,
317 | 1, -1, 1,
318 | 1, -1, -1,
319 | -1, -1, 1,
320 | 1, -1, -1,
321 | -1, -1, -1
322 | ];
323 | var attribs = webgl.buildAttribs(gl, {aPosition: 3});
324 | attribs.aPosition.buffer.set(new Float32Array(position));
325 | var count = position.length / 9;
326 | var renderable = new webgl.Renderable(gl, program, attribs, count);
327 | return renderable;
328 | }
329 |
330 |
331 | function quatRotBetweenVecs(a, b) {
332 | var theta = Math.acos(glm.vec3.dot(a, b));
333 | var omega = glm.vec3.create();
334 | glm.vec3.cross(omega, a, b);
335 | glm.vec3.normalize(omega, omega);
336 | var rot = glm.quat.create();
337 | glm.quat.setAxisAngle(rot, omega, theta);
338 | return rot;
339 | }
340 |
341 |
342 | function quatRotFromForward(b) {
343 | return quatRotBetweenVecs(glm.vec3.fromValues(0, 0, -1), b);
344 | }
345 |
346 |
347 | function randomRotation(rand) {
348 | var rot = glm.mat4.create();
349 | glm.mat4.rotateX(rot, rot, rand.random() * Math.PI * 2);
350 | glm.mat4.rotateY(rot, rot, rand.random() * Math.PI * 2);
351 | glm.mat4.rotateZ(rot, rot, rand.random() * Math.PI * 2);
352 | return rot;
353 | }
354 |
355 | function randomVec3(rand) {
356 | var v = [0, 0, 1];
357 | var rot = randomRotation(rand);
358 | glm.vec3.transformMat4(v, v, rot);
359 | glm.vec3.normalize(v, v);
360 | return v;
361 | }
362 |
363 | function hashcode(str) {
364 | var hash = 0;
365 | for (var i = 0; i < str.length; i++) {
366 | var char = str.charCodeAt(i);
367 | hash += (i + 1) * char;
368 | }
369 | return hash;
370 | }
371 |
--------------------------------------------------------------------------------
/builtins/space-2d/static/js/dat.gui.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * dat-gui JavaScript Controller Library
3 | * http://code.google.com/p/dat-gui
4 | *
5 | * Copyright 2011 Data Arts Team, Google Creative Lab
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | */
13 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(f,a){a=a||document;var d=a.createElement("link");d.type="text/css";d.rel="stylesheet";d.href=f;a.getElementsByTagName("head")[0].appendChild(d)},inject:function(f,a){a=a||document;var d=document.createElement("style");d.type="text/css";d.innerHTML=f;a.getElementsByTagName("head")[0].appendChild(d)}}}();
14 | dat.utils.common=function(){var f=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(d){this.each(a.call(arguments,1),function(a){for(var c in a)this.isUndefined(a[c])||(d[c]=a[c])},this);return d},defaults:function(d){this.each(a.call(arguments,1),function(a){for(var c in a)this.isUndefined(d[c])&&(d[c]=a[c])},this);return d},compose:function(){var d=a.call(arguments);return function(){for(var e=a.call(arguments),c=d.length-1;0<=c;c--)e=[d[c].apply(this,e)];return e[0]}},
15 | each:function(a,e,c){if(a)if(f&&a.forEach&&a.forEach===f)a.forEach(e,c);else if(a.length===a.length+0)for(var b=0,p=a.length;bthis.__max&&(a=this.__max);void 0!==this.__step&&0!=a%this.__step&&(a=Math.round(a/this.__step)*this.__step);return e.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__impliedStep=this.__step=a;this.__precision=d(a);return this}});return e}(dat.controllers.Controller,dat.utils.common);
29 | dat.controllers.NumberControllerBox=function(f,a,d){var e=function(c,b,f){function q(){var a=parseFloat(n.__input.value);d.isNaN(a)||n.setValue(a)}function l(a){var b=u-a.clientY;n.setValue(n.getValue()+b*n.__impliedStep);u=a.clientY}function r(){a.unbind(window,"mousemove",l);a.unbind(window,"mouseup",r)}this.__truncationSuspended=!1;e.superclass.call(this,c,b,f);var n=this,u;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",q);a.bind(this.__input,
30 | "blur",function(){q();n.__onFinishChange&&n.__onFinishChange.call(n,n.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",l);a.bind(window,"mouseup",r);u=b.clientY});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&(n.__truncationSuspended=!0,this.blur(),n.__truncationSuspended=!1)});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype,f.prototype,{updateDisplay:function(){var a=this.__input,b;if(this.__truncationSuspended)b=
31 | this.getValue();else{b=this.getValue();var d=Math.pow(10,this.__precision);b=Math.round(b*d)/d}a.value=b;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common);
32 | dat.controllers.NumberControllerSlider=function(f,a,d,e,c){function b(a,b,c,e,d){return e+(a-b)/(c-b)*(d-e)}var p=function(c,e,d,f,u){function A(c){c.preventDefault();var e=a.getOffset(k.__background),d=a.getWidth(k.__background);k.setValue(b(c.clientX,e.left,e.left+d,k.__min,k.__max));return!1}function g(){a.unbind(window,"mousemove",A);a.unbind(window,"mouseup",g);k.__onFinishChange&&k.__onFinishChange.call(k,k.getValue())}p.superclass.call(this,c,e,{min:d,max:f,step:u});var k=this;this.__background=
33 | document.createElement("div");this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",A);a.bind(window,"mouseup",g);A(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};p.superclass=f;p.useDefaultStyles=function(){d.inject(c)};e.extend(p.prototype,f.prototype,{updateDisplay:function(){var a=
34 | (this.getValue()-this.__min)/(this.__max-this.__min);this.__foreground.style.width=100*a+"%";return p.superclass.prototype.updateDisplay.call(this)}});return p}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}");
35 | dat.controllers.FunctionController=function(f,a,d){var e=function(c,b,d){e.superclass.call(this,c,b);var f=this;this.__button=document.createElement("div");this.__button.innerHTML=void 0===d?"Fire":d;a.bind(this.__button,"click",function(a){a.preventDefault();f.fire();return!1});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};e.superclass=f;d.extend(e.prototype,f.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.getValue().call(this.object);
36 | this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue())}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
37 | dat.controllers.BooleanController=function(f,a,d){var e=function(c,b){e.superclass.call(this,c,b);var d=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){d.setValue(!d.__prev)},!1);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};e.superclass=f;d.extend(e.prototype,f.prototype,{setValue:function(a){a=e.superclass.prototype.setValue.call(this,a);this.__onFinishChange&&
38 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){!0===this.getValue()?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=!0):this.__checkbox.checked=!1;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
39 | dat.color.toString=function(f){return function(a){if(1==a.a||f.isUndefined(a.a)){for(a=a.hex.toString(16);6>a.length;)a="0"+a;return"#"+a}return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common);
40 | dat.color.interpret=function(f,a){var d,e,c=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:f},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:f},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
41 | return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:f},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:f}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return 3!=
42 | a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return 4!=a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&&
43 | a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){e=!1;
44 | var b=1\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n \n\n
Automatically save\n values to
localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n',
71 | ".dg {\n /** Clear list styles */\n /* Auto-place container */\n /* Auto-placed GUI's */\n /* Line items that don't contain folders. */\n /** Folder names */\n /** Hides closed items */\n /** Controller row */\n /** Name-half (left) */\n /** Controller-half (right) */\n /** Controller placement */\n /** Shorter number boxes when slider is present. */\n /** Ensure the entire boolean and function row shows a hand */ }\n .dg ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n clear: both; }\n .dg.ac {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 0;\n z-index: 0; }\n .dg:not(.ac) .main {\n /** Exclude mains in ac so that we don't hide close button */\n overflow: hidden; }\n .dg.main {\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear; }\n .dg.main.taller-than-window {\n overflow-y: auto; }\n .dg.main.taller-than-window .close-button {\n opacity: 1;\n /* TODO, these are style notes */\n margin-top: -1px;\n border-top: 1px solid #2c2c2c; }\n .dg.main ul.closed .close-button {\n opacity: 1 !important; }\n .dg.main:hover .close-button,\n .dg.main .close-button.drag {\n opacity: 1; }\n .dg.main .close-button {\n /*opacity: 0;*/\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear;\n border: 0;\n position: absolute;\n line-height: 19px;\n height: 20px;\n /* TODO, these are style notes */\n cursor: pointer;\n text-align: center;\n background-color: #000; }\n .dg.main .close-button:hover {\n background-color: #111; }\n .dg.a {\n float: right;\n margin-right: 15px;\n overflow-x: hidden; }\n .dg.a.has-save > ul {\n margin-top: 27px; }\n .dg.a.has-save > ul.closed {\n margin-top: 0; }\n .dg.a .save-row {\n position: fixed;\n top: 0;\n z-index: 1002; }\n .dg li {\n -webkit-transition: height 0.1s ease-out;\n -o-transition: height 0.1s ease-out;\n -moz-transition: height 0.1s ease-out;\n transition: height 0.1s ease-out; }\n .dg li:not(.folder) {\n cursor: auto;\n height: 27px;\n line-height: 27px;\n overflow: hidden;\n padding: 0 4px 0 5px; }\n .dg li.folder {\n padding: 0;\n border-left: 4px solid rgba(0, 0, 0, 0); }\n .dg li.title {\n cursor: pointer;\n margin-left: -4px; }\n .dg .closed li:not(.title),\n .dg .closed ul li,\n .dg .closed ul li > * {\n height: 0;\n overflow: hidden;\n border: 0; }\n .dg .cr {\n clear: both;\n padding-left: 3px;\n height: 27px; }\n .dg .property-name {\n cursor: default;\n float: left;\n clear: left;\n width: 40%;\n overflow: hidden;\n text-overflow: ellipsis; }\n .dg .c {\n float: left;\n width: 60%; }\n .dg .c input[type=text] {\n border: 0;\n margin-top: 4px;\n padding: 3px;\n width: 100%;\n float: right; }\n .dg .has-slider input[type=text] {\n width: 30%;\n /*display: none;*/\n margin-left: 0; }\n .dg .slider {\n float: left;\n width: 66%;\n margin-left: -5px;\n margin-right: 0;\n height: 19px;\n margin-top: 4px; }\n .dg .slider-fg {\n height: 100%; }\n .dg .c input[type=checkbox] {\n margin-top: 9px; }\n .dg .c select {\n margin-top: 5px; }\n .dg .cr.function,\n .dg .cr.function .property-name,\n .dg .cr.function *,\n .dg .cr.boolean,\n .dg .cr.boolean * {\n cursor: pointer; }\n .dg .selector {\n display: none;\n position: absolute;\n margin-left: -9px;\n margin-top: 23px;\n z-index: 10; }\n .dg .c:hover .selector,\n .dg .selector.drag {\n display: block; }\n .dg li.save-row {\n padding: 0; }\n .dg li.save-row .button {\n display: inline-block;\n padding: 0px 6px; }\n .dg.dialogue {\n background-color: #222;\n width: 460px;\n padding: 15px;\n font-size: 13px;\n line-height: 15px; }\n\n/* TODO Separate style and structure */\n#dg-new-constructor {\n padding: 10px;\n color: #222;\n font-family: Monaco, monospace;\n font-size: 10px;\n border: 0;\n resize: none;\n box-shadow: inset 1px 1px 1px #888;\n word-wrap: break-word;\n margin: 12px 0;\n display: block;\n width: 440px;\n overflow-y: scroll;\n height: 100px;\n position: relative; }\n\n#dg-local-explain {\n display: none;\n font-size: 11px;\n line-height: 17px;\n border-radius: 3px;\n background-color: #333;\n padding: 8px;\n margin-top: 10px; }\n #dg-local-explain code {\n font-size: 10px; }\n\n#dat-gui-save-locally {\n display: none; }\n\n/** Main type */\n.dg {\n color: #eee;\n font: 11px 'Lucida Grande', sans-serif;\n text-shadow: 0 -1px 0 #111;\n /** Auto place */\n /* Controller row, */\n /** Controllers */ }\n .dg.main {\n /** Scrollbar */ }\n .dg.main::-webkit-scrollbar {\n width: 5px;\n background: #1a1a1a; }\n .dg.main::-webkit-scrollbar-corner {\n height: 0;\n display: none; }\n .dg.main::-webkit-scrollbar-thumb {\n border-radius: 5px;\n background: #676767; }\n .dg li:not(.folder) {\n background: #1a1a1a;\n border-bottom: 1px solid #2c2c2c; }\n .dg li.save-row {\n line-height: 25px;\n background: #dad5cb;\n border: 0; }\n .dg li.save-row select {\n margin-left: 5px;\n width: 108px; }\n .dg li.save-row .button {\n margin-left: 5px;\n margin-top: 1px;\n border-radius: 2px;\n font-size: 9px;\n line-height: 7px;\n padding: 4px 4px 5px 4px;\n background: #c5bdad;\n color: #fff;\n text-shadow: 0 1px 0 #b0a58f;\n box-shadow: 0 -1px 0 #b0a58f;\n cursor: pointer; }\n .dg li.save-row .button.gears {\n background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;\n height: 7px;\n width: 8px; }\n .dg li.save-row .button:hover {\n background-color: #bab19e;\n box-shadow: 0 -1px 0 #b0a58f; }\n .dg li.folder {\n border-bottom: 0; }\n .dg li.title {\n padding-left: 16px;\n background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;\n cursor: pointer;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2); }\n .dg .closed li.title {\n background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }\n .dg .cr.boolean {\n border-left: 3px solid #806787; }\n .dg .cr.function {\n border-left: 3px solid #e61d5f; }\n .dg .cr.number {\n border-left: 3px solid #2fa1d6; }\n .dg .cr.number input[type=text] {\n color: #2fa1d6; }\n .dg .cr.string {\n border-left: 3px solid #1ed36f; }\n .dg .cr.string input[type=text] {\n color: #1ed36f; }\n .dg .cr.function:hover, .dg .cr.boolean:hover {\n background: #111; }\n .dg .c input[type=text] {\n background: #303030;\n outline: none; }\n .dg .c input[type=text]:hover {\n background: #3c3c3c; }\n .dg .c input[type=text]:focus {\n background: #494949;\n color: #fff; }\n .dg .c .slider {\n background: #303030;\n cursor: ew-resize; }\n .dg .c .slider-fg {\n background: #2fa1d6; }\n .dg .c .slider:hover {\n background: #3c3c3c; }\n .dg .c .slider:hover .slider-fg {\n background: #44abda; }\n",
72 | dat.controllers.factory=function(f,a,d,e,c,b,p){return function(q,l,r,n){var u=q[l];if(p.isArray(r)||p.isObject(r))return new f(q,l,r);if(p.isNumber(u))return p.isNumber(r)&&p.isNumber(n)?new d(q,l,r,n):new a(q,l,{min:r,max:n});if(p.isString(u))return new e(q,l);if(p.isFunction(u))return new c(q,l,"");if(p.isBoolean(u))return new b(q,l)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(f,a,d){var e=
73 | function(c,b){function d(){f.setValue(f.__input.value)}e.superclass.call(this,c,b);var f=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",d);a.bind(this.__input,"change",d);a.bind(this.__input,"blur",function(){f.__onFinishChange&&f.__onFinishChange.call(f,f.getValue())});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype,
74 | f.prototype,{updateDisplay:function(){a.isActive(this.__input)||(this.__input.value=this.getValue());return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController,
75 | dat.controllers.ColorController=function(f,a,d,e,c){function b(a,b,d,e){a.style.background="";c.each(l,function(c){a.style.cssText+="background: "+c+"linear-gradient("+b+", "+d+" 0%, "+e+" 100%); "})}function p(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
76 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var q=function(f,n){function u(b){v(b);a.bind(window,"mousemove",v);a.bind(window,
77 | "mouseup",l)}function l(){a.unbind(window,"mousemove",v);a.unbind(window,"mouseup",l)}function g(){var a=e(this.value);!1!==a?(t.__color.__state=a,t.setValue(t.__color.toOriginal())):this.value=t.__color.toString()}function k(){a.unbind(window,"mousemove",w);a.unbind(window,"mouseup",k)}function v(b){b.preventDefault();var c=a.getWidth(t.__saturation_field),d=a.getOffset(t.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c;b=1-(b.clientY-d.top+document.body.scrollTop)/c;1
78 | b&&(b=0);1e&&(e=0);t.__color.v=b;t.__color.s=e;t.setValue(t.__color.toOriginal());return!1}function w(b){b.preventDefault();var c=a.getHeight(t.__hue_field),d=a.getOffset(t.__hue_field);b=1-(b.clientY-d.top+document.body.scrollTop)/c;1b&&(b=0);t.__color.h=360*b;t.setValue(t.__color.toOriginal());return!1}q.superclass.call(this,f,n);this.__color=new d(this.getValue());this.__temp=new d(0);var t=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,!1);
79 | this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=document.createElement("input");
80 | this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){13===a.keyCode&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(b){a.addClass(this,"drag").bind(window,"mouseup",function(b){a.removeClass(t.__selector,"drag")})});var y=document.createElement("div");c.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});c.extend(this.__field_knob.style,
81 | {position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(.5>this.__color.v?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});c.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});c.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});c.extend(y.style,{width:"100%",height:"100%",
82 | background:"none"});b(y,"top","rgba(0,0,0,0)","#000");c.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});p(this.__hue_field);c.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",u);a.bind(this.__field_knob,"mousedown",u);a.bind(this.__hue_field,"mousedown",function(b){w(b);a.bind(window,
83 | "mousemove",w);a.bind(window,"mouseup",k)});this.__saturation_field.appendChild(y);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};q.superclass=f;c.extend(q.prototype,f.prototype,{updateDisplay:function(){var a=e(this.getValue());if(!1!==a){var f=!1;
84 | c.each(d.COMPONENTS,function(b){if(!c.isUndefined(a[b])&&!c.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return f=!0,{}},this);f&&c.extend(this.__color.__state,a)}c.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var l=.5>this.__color.v||.5a&&(a+=1);return{h:360*a,s:c/b,v:b/255}},rgb_to_hex:function(a,d,e){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,d);return a=this.hex_with_component(a,0,e)},component_from_hex:function(a,d){return a>>8*d&255},hex_with_component:function(a,d,e){return e<<(f=8*d)|a&~(255<this.__max&&(a=this.__max);void 0!==this.__step&&0!=a%this.__step&&(a=Math.round(a/this.__step)*this.__step);return e.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__impliedStep=this.__step=a;this.__precision=d(a);return this}});return e}(dat.controllers.Controller,dat.utils.common);
29 | dat.controllers.NumberControllerBox=function(f,a,d){var e=function(c,b,f){function q(){var a=parseFloat(n.__input.value);d.isNaN(a)||n.setValue(a)}function l(a){var b=u-a.clientY;n.setValue(n.getValue()+b*n.__impliedStep);u=a.clientY}function r(){a.unbind(window,"mousemove",l);a.unbind(window,"mouseup",r)}this.__truncationSuspended=!1;e.superclass.call(this,c,b,f);var n=this,u;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",q);a.bind(this.__input,
30 | "blur",function(){q();n.__onFinishChange&&n.__onFinishChange.call(n,n.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",l);a.bind(window,"mouseup",r);u=b.clientY});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&(n.__truncationSuspended=!0,this.blur(),n.__truncationSuspended=!1)});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype,f.prototype,{updateDisplay:function(){var a=this.__input,b;if(this.__truncationSuspended)b=
31 | this.getValue();else{b=this.getValue();var d=Math.pow(10,this.__precision);b=Math.round(b*d)/d}a.value=b;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common);
32 | dat.controllers.NumberControllerSlider=function(f,a,d,e,c){function b(a,b,c,e,d){return e+(a-b)/(c-b)*(d-e)}var p=function(c,e,d,f,u){function A(c){c.preventDefault();var e=a.getOffset(k.__background),d=a.getWidth(k.__background);k.setValue(b(c.clientX,e.left,e.left+d,k.__min,k.__max));return!1}function g(){a.unbind(window,"mousemove",A);a.unbind(window,"mouseup",g);k.__onFinishChange&&k.__onFinishChange.call(k,k.getValue())}p.superclass.call(this,c,e,{min:d,max:f,step:u});var k=this;this.__background=
33 | document.createElement("div");this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",A);a.bind(window,"mouseup",g);A(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};p.superclass=f;p.useDefaultStyles=function(){d.inject(c)};e.extend(p.prototype,f.prototype,{updateDisplay:function(){var a=
34 | (this.getValue()-this.__min)/(this.__max-this.__min);this.__foreground.style.width=100*a+"%";return p.superclass.prototype.updateDisplay.call(this)}});return p}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}");
35 | dat.controllers.FunctionController=function(f,a,d){var e=function(c,b,d){e.superclass.call(this,c,b);var f=this;this.__button=document.createElement("div");this.__button.innerHTML=void 0===d?"Fire":d;a.bind(this.__button,"click",function(a){a.preventDefault();f.fire();return!1});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};e.superclass=f;d.extend(e.prototype,f.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.getValue().call(this.object);
36 | this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue())}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
37 | dat.controllers.BooleanController=function(f,a,d){var e=function(c,b){e.superclass.call(this,c,b);var d=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){d.setValue(!d.__prev)},!1);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};e.superclass=f;d.extend(e.prototype,f.prototype,{setValue:function(a){a=e.superclass.prototype.setValue.call(this,a);this.__onFinishChange&&
38 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){!0===this.getValue()?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=!0):this.__checkbox.checked=!1;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
39 | dat.color.toString=function(f){return function(a){if(1==a.a||f.isUndefined(a.a)){for(a=a.hex.toString(16);6>a.length;)a="0"+a;return"#"+a}return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common);
40 | dat.color.interpret=function(f,a){var d,e,c=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:f},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:f},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
41 | return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:f},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:f}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return 3!=
42 | a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return 4!=a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&&
43 | a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){e=!1;
44 | var b=1\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n \n\n
Automatically save\n values to
localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n',
71 | ".dg {\n /** Clear list styles */\n /* Auto-place container */\n /* Auto-placed GUI's */\n /* Line items that don't contain folders. */\n /** Folder names */\n /** Hides closed items */\n /** Controller row */\n /** Name-half (left) */\n /** Controller-half (right) */\n /** Controller placement */\n /** Shorter number boxes when slider is present. */\n /** Ensure the entire boolean and function row shows a hand */ }\n .dg ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n clear: both; }\n .dg.ac {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 0;\n z-index: 0; }\n .dg:not(.ac) .main {\n /** Exclude mains in ac so that we don't hide close button */\n overflow: hidden; }\n .dg.main {\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear; }\n .dg.main.taller-than-window {\n overflow-y: auto; }\n .dg.main.taller-than-window .close-button {\n opacity: 1;\n /* TODO, these are style notes */\n margin-top: -1px;\n border-top: 1px solid #2c2c2c; }\n .dg.main ul.closed .close-button {\n opacity: 1 !important; }\n .dg.main:hover .close-button,\n .dg.main .close-button.drag {\n opacity: 1; }\n .dg.main .close-button {\n /*opacity: 0;*/\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear;\n border: 0;\n position: absolute;\n line-height: 19px;\n height: 20px;\n /* TODO, these are style notes */\n cursor: pointer;\n text-align: center;\n background-color: #000; }\n .dg.main .close-button:hover {\n background-color: #111; }\n .dg.a {\n float: right;\n margin-right: 15px;\n overflow-x: hidden; }\n .dg.a.has-save > ul {\n margin-top: 27px; }\n .dg.a.has-save > ul.closed {\n margin-top: 0; }\n .dg.a .save-row {\n position: fixed;\n top: 0;\n z-index: 1002; }\n .dg li {\n -webkit-transition: height 0.1s ease-out;\n -o-transition: height 0.1s ease-out;\n -moz-transition: height 0.1s ease-out;\n transition: height 0.1s ease-out; }\n .dg li:not(.folder) {\n cursor: auto;\n height: 27px;\n line-height: 27px;\n overflow: hidden;\n padding: 0 4px 0 5px; }\n .dg li.folder {\n padding: 0;\n border-left: 4px solid rgba(0, 0, 0, 0); }\n .dg li.title {\n cursor: pointer;\n margin-left: -4px; }\n .dg .closed li:not(.title),\n .dg .closed ul li,\n .dg .closed ul li > * {\n height: 0;\n overflow: hidden;\n border: 0; }\n .dg .cr {\n clear: both;\n padding-left: 3px;\n height: 27px; }\n .dg .property-name {\n cursor: default;\n float: left;\n clear: left;\n width: 40%;\n overflow: hidden;\n text-overflow: ellipsis; }\n .dg .c {\n float: left;\n width: 60%; }\n .dg .c input[type=text] {\n border: 0;\n margin-top: 4px;\n padding: 3px;\n width: 100%;\n float: right; }\n .dg .has-slider input[type=text] {\n width: 30%;\n /*display: none;*/\n margin-left: 0; }\n .dg .slider {\n float: left;\n width: 66%;\n margin-left: -5px;\n margin-right: 0;\n height: 19px;\n margin-top: 4px; }\n .dg .slider-fg {\n height: 100%; }\n .dg .c input[type=checkbox] {\n margin-top: 9px; }\n .dg .c select {\n margin-top: 5px; }\n .dg .cr.function,\n .dg .cr.function .property-name,\n .dg .cr.function *,\n .dg .cr.boolean,\n .dg .cr.boolean * {\n cursor: pointer; }\n .dg .selector {\n display: none;\n position: absolute;\n margin-left: -9px;\n margin-top: 23px;\n z-index: 10; }\n .dg .c:hover .selector,\n .dg .selector.drag {\n display: block; }\n .dg li.save-row {\n padding: 0; }\n .dg li.save-row .button {\n display: inline-block;\n padding: 0px 6px; }\n .dg.dialogue {\n background-color: #222;\n width: 460px;\n padding: 15px;\n font-size: 13px;\n line-height: 15px; }\n\n/* TODO Separate style and structure */\n#dg-new-constructor {\n padding: 10px;\n color: #222;\n font-family: Monaco, monospace;\n font-size: 10px;\n border: 0;\n resize: none;\n box-shadow: inset 1px 1px 1px #888;\n word-wrap: break-word;\n margin: 12px 0;\n display: block;\n width: 440px;\n overflow-y: scroll;\n height: 100px;\n position: relative; }\n\n#dg-local-explain {\n display: none;\n font-size: 11px;\n line-height: 17px;\n border-radius: 3px;\n background-color: #333;\n padding: 8px;\n margin-top: 10px; }\n #dg-local-explain code {\n font-size: 10px; }\n\n#dat-gui-save-locally {\n display: none; }\n\n/** Main type */\n.dg {\n color: #eee;\n font: 11px 'Lucida Grande', sans-serif;\n text-shadow: 0 -1px 0 #111;\n /** Auto place */\n /* Controller row, */\n /** Controllers */ }\n .dg.main {\n /** Scrollbar */ }\n .dg.main::-webkit-scrollbar {\n width: 5px;\n background: #1a1a1a; }\n .dg.main::-webkit-scrollbar-corner {\n height: 0;\n display: none; }\n .dg.main::-webkit-scrollbar-thumb {\n border-radius: 5px;\n background: #676767; }\n .dg li:not(.folder) {\n background: #1a1a1a;\n border-bottom: 1px solid #2c2c2c; }\n .dg li.save-row {\n line-height: 25px;\n background: #dad5cb;\n border: 0; }\n .dg li.save-row select {\n margin-left: 5px;\n width: 108px; }\n .dg li.save-row .button {\n margin-left: 5px;\n margin-top: 1px;\n border-radius: 2px;\n font-size: 9px;\n line-height: 7px;\n padding: 4px 4px 5px 4px;\n background: #c5bdad;\n color: #fff;\n text-shadow: 0 1px 0 #b0a58f;\n box-shadow: 0 -1px 0 #b0a58f;\n cursor: pointer; }\n .dg li.save-row .button.gears {\n background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;\n height: 7px;\n width: 8px; }\n .dg li.save-row .button:hover {\n background-color: #bab19e;\n box-shadow: 0 -1px 0 #b0a58f; }\n .dg li.folder {\n border-bottom: 0; }\n .dg li.title {\n padding-left: 16px;\n background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;\n cursor: pointer;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2); }\n .dg .closed li.title {\n background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }\n .dg .cr.boolean {\n border-left: 3px solid #806787; }\n .dg .cr.function {\n border-left: 3px solid #e61d5f; }\n .dg .cr.number {\n border-left: 3px solid #2fa1d6; }\n .dg .cr.number input[type=text] {\n color: #2fa1d6; }\n .dg .cr.string {\n border-left: 3px solid #1ed36f; }\n .dg .cr.string input[type=text] {\n color: #1ed36f; }\n .dg .cr.function:hover, .dg .cr.boolean:hover {\n background: #111; }\n .dg .c input[type=text] {\n background: #303030;\n outline: none; }\n .dg .c input[type=text]:hover {\n background: #3c3c3c; }\n .dg .c input[type=text]:focus {\n background: #494949;\n color: #fff; }\n .dg .c .slider {\n background: #303030;\n cursor: ew-resize; }\n .dg .c .slider-fg {\n background: #2fa1d6; }\n .dg .c .slider:hover {\n background: #3c3c3c; }\n .dg .c .slider:hover .slider-fg {\n background: #44abda; }\n",
72 | dat.controllers.factory=function(f,a,d,e,c,b,p){return function(q,l,r,n){var u=q[l];if(p.isArray(r)||p.isObject(r))return new f(q,l,r);if(p.isNumber(u))return p.isNumber(r)&&p.isNumber(n)?new d(q,l,r,n):new a(q,l,{min:r,max:n});if(p.isString(u))return new e(q,l);if(p.isFunction(u))return new c(q,l,"");if(p.isBoolean(u))return new b(q,l)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(f,a,d){var e=
73 | function(c,b){function d(){f.setValue(f.__input.value)}e.superclass.call(this,c,b);var f=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",d);a.bind(this.__input,"change",d);a.bind(this.__input,"blur",function(){f.__onFinishChange&&f.__onFinishChange.call(f,f.getValue())});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype,
74 | f.prototype,{updateDisplay:function(){a.isActive(this.__input)||(this.__input.value=this.getValue());return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController,
75 | dat.controllers.ColorController=function(f,a,d,e,c){function b(a,b,d,e){a.style.background="";c.each(l,function(c){a.style.cssText+="background: "+c+"linear-gradient("+b+", "+d+" 0%, "+e+" 100%); "})}function p(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
76 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var q=function(f,n){function u(b){v(b);a.bind(window,"mousemove",v);a.bind(window,
77 | "mouseup",l)}function l(){a.unbind(window,"mousemove",v);a.unbind(window,"mouseup",l)}function g(){var a=e(this.value);!1!==a?(t.__color.__state=a,t.setValue(t.__color.toOriginal())):this.value=t.__color.toString()}function k(){a.unbind(window,"mousemove",w);a.unbind(window,"mouseup",k)}function v(b){b.preventDefault();var c=a.getWidth(t.__saturation_field),d=a.getOffset(t.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c;b=1-(b.clientY-d.top+document.body.scrollTop)/c;1
78 | b&&(b=0);1e&&(e=0);t.__color.v=b;t.__color.s=e;t.setValue(t.__color.toOriginal());return!1}function w(b){b.preventDefault();var c=a.getHeight(t.__hue_field),d=a.getOffset(t.__hue_field);b=1-(b.clientY-d.top+document.body.scrollTop)/c;1b&&(b=0);t.__color.h=360*b;t.setValue(t.__color.toOriginal());return!1}q.superclass.call(this,f,n);this.__color=new d(this.getValue());this.__temp=new d(0);var t=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,!1);
79 | this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=document.createElement("input");
80 | this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){13===a.keyCode&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(b){a.addClass(this,"drag").bind(window,"mouseup",function(b){a.removeClass(t.__selector,"drag")})});var y=document.createElement("div");c.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});c.extend(this.__field_knob.style,
81 | {position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(.5>this.__color.v?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});c.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});c.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});c.extend(y.style,{width:"100%",height:"100%",
82 | background:"none"});b(y,"top","rgba(0,0,0,0)","#000");c.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});p(this.__hue_field);c.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",u);a.bind(this.__field_knob,"mousedown",u);a.bind(this.__hue_field,"mousedown",function(b){w(b);a.bind(window,
83 | "mousemove",w);a.bind(window,"mouseup",k)});this.__saturation_field.appendChild(y);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};q.superclass=f;c.extend(q.prototype,f.prototype,{updateDisplay:function(){var a=e(this.getValue());if(!1!==a){var f=!1;
84 | c.each(d.COMPONENTS,function(b){if(!c.isUndefined(a[b])&&!c.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return f=!0,{}},this);f&&c.extend(this.__color.__state,a)}c.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var l=.5>this.__color.v||.5a&&(a+=1);return{h:360*a,s:c/b,v:b/255}},rgb_to_hex:function(a,d,e){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,d);return a=this.hex_with_component(a,0,e)},component_from_hex:function(a,d){return a>>8*d&255},hex_with_component:function(a,d,e){return e<<(f=8*d)|a&~(255<