entangled-worlds-orbiters-shared 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- package/package.json +49 -0
- package/public/config/textures.json +332 -0
- package/src/arrow-ui/BooleanController.js +31 -0
- package/src/arrow-ui/ColorController.js +108 -0
- package/src/arrow-ui/Controller.js +447 -0
- package/src/arrow-ui/FunctionController.js +27 -0
- package/src/arrow-ui/GUI.js +595 -0
- package/src/arrow-ui/NumberController.js +567 -0
- package/src/arrow-ui/OptionController.js +64 -0
- package/src/arrow-ui/StringController.js +41 -0
- package/src/arrow-ui/index.js +13 -0
- package/src/arrow-ui/lilGuiLoader.js +10 -0
- package/src/arrow-ui/utils/getColorFormat.js +75 -0
- package/src/arrow-ui/utils/injectStyles.js +10 -0
- package/src/arrow-ui/utils/normalizeColorString.js +29 -0
- package/src/config/index.js +8 -0
- package/src/config/textureConfig.js +299 -0
- package/src/core/index.js +3 -0
- package/src/core/lightFresnel.js +64 -0
- package/src/core/lights.js +43 -0
- package/src/index.js +8 -0
- package/src/loaders/bodyTextureLoader.js +39 -0
- package/src/loaders/cubeMapLoader.js +264 -0
- package/src/loaders/glbLoader.js +71 -0
- package/src/loaders/index.js +4 -0
- package/src/moons/index.js +3 -0
- package/src/moons/moonsGeneration.js +228 -0
- package/src/moons/moonsManager.js +64 -0
- package/src/utils/dispose.js +20 -0
- package/src/utils/index.js +3 -0
- package/src/utils/materials.js +31 -0
- package/src/world/cloudShell.js +89 -0
- package/src/world/index.js +6 -0
- package/src/world/worldGLB.js +7 -0
- package/src/world/worldManager.js +93 -0
- package/src/world/worldNormal.js +25 -0
- package/src/world/worldTexture.js +239 -0
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
/** @module GUI */
|
|
2
|
+
|
|
3
|
+
import BooleanController from './BooleanController';
|
|
4
|
+
import ColorController from './ColorController';
|
|
5
|
+
import FunctionController from './FunctionController';
|
|
6
|
+
import NumberController from './NumberController';
|
|
7
|
+
import OptionController from './OptionController';
|
|
8
|
+
import StringController from './StringController';
|
|
9
|
+
|
|
10
|
+
// Styles are now loaded externally via <link> tag in index.html
|
|
11
|
+
|
|
12
|
+
export default class GUI {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a panel that holds controllers.
|
|
16
|
+
* @example
|
|
17
|
+
* new GUI();
|
|
18
|
+
* new GUI( { container: document.getElementById( 'custom' ) } );
|
|
19
|
+
*
|
|
20
|
+
* @param {object} [options]
|
|
21
|
+
* @param {boolean} [options.autoPlace=true]
|
|
22
|
+
* Adds the GUI to `document.body` and fixes it to the top right of the page.
|
|
23
|
+
*
|
|
24
|
+
* @param {HTMLElement} [options.container]
|
|
25
|
+
* Adds the GUI to this DOM element. Overrides `autoPlace`.
|
|
26
|
+
*
|
|
27
|
+
* @param {number} [options.width=245]
|
|
28
|
+
* Width of the GUI in pixels, usually set when name labels become too long. Note that you can make
|
|
29
|
+
* name labels wider in CSS with `.lil‑gui { ‑‑name‑width: 55% }`.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} [options.title=Controls]
|
|
32
|
+
* Name to display in the title bar.
|
|
33
|
+
*
|
|
34
|
+
* @param {boolean} [options.closeFolders=false]
|
|
35
|
+
* Pass `true` to close all folders in this GUI by default.
|
|
36
|
+
*
|
|
37
|
+
* @param {boolean} [options.injectStyles=true]
|
|
38
|
+
* Injects the default stylesheet into the page if this is the first GUI.
|
|
39
|
+
* Pass `false` to use your own stylesheet.
|
|
40
|
+
*
|
|
41
|
+
* @param {number} [options.touchStyles=true]
|
|
42
|
+
* Makes controllers larger on touch devices. Pass `false` to disable touch styles.
|
|
43
|
+
*
|
|
44
|
+
* @param {GUI} [options.parent]
|
|
45
|
+
* Adds this GUI as a child in another GUI. Usually this is done for you by `addFolder()`.
|
|
46
|
+
*/
|
|
47
|
+
constructor( {
|
|
48
|
+
parent,
|
|
49
|
+
autoPlace = parent === undefined,
|
|
50
|
+
container,
|
|
51
|
+
width,
|
|
52
|
+
title = 'Controls',
|
|
53
|
+
closeFolders = false,
|
|
54
|
+
injectStyles = true,
|
|
55
|
+
touchStyles = true
|
|
56
|
+
} = {} ) {
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The GUI containing this folder, or `undefined` if this is the root GUI.
|
|
60
|
+
* @type {GUI}
|
|
61
|
+
*/
|
|
62
|
+
this.parent = parent;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The top level GUI containing this folder, or `this` if this is the root GUI.
|
|
66
|
+
* @type {GUI}
|
|
67
|
+
*/
|
|
68
|
+
this.root = parent ? parent.root : this;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The list of controllers and folders contained by this GUI.
|
|
72
|
+
* @type {Array<GUI|Controller>}
|
|
73
|
+
*/
|
|
74
|
+
this.children = [];
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The list of controllers contained by this GUI.
|
|
78
|
+
* @type {Array<Controller>}
|
|
79
|
+
*/
|
|
80
|
+
this.controllers = [];
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The list of folders contained by this GUI.
|
|
84
|
+
* @type {Array<GUI>}
|
|
85
|
+
*/
|
|
86
|
+
this.folders = [];
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Used to determine if the GUI is closed. Use `gui.open()` or `gui.close()` to change this.
|
|
90
|
+
* @type {boolean}
|
|
91
|
+
*/
|
|
92
|
+
this._closed = false;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Used to determine if the GUI is hidden. Use `gui.show()` or `gui.hide()` to change this.
|
|
96
|
+
* @type {boolean}
|
|
97
|
+
*/
|
|
98
|
+
this._hidden = false;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The outermost container element.
|
|
102
|
+
* @type {HTMLElement}
|
|
103
|
+
*/
|
|
104
|
+
this.domElement = document.createElement( 'div' );
|
|
105
|
+
this.domElement.classList.add( 'lil-gui' );
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The DOM element that contains the title.
|
|
109
|
+
* @type {HTMLElement}
|
|
110
|
+
*/
|
|
111
|
+
this.$title = document.createElement( 'button' );
|
|
112
|
+
this.$title.classList.add( 'title' );
|
|
113
|
+
this.$title.setAttribute( 'aria-expanded', true );
|
|
114
|
+
|
|
115
|
+
this.$title.addEventListener( 'click', () => this.openAnimated( this._closed ) );
|
|
116
|
+
|
|
117
|
+
// enables :active pseudo class on mobile
|
|
118
|
+
this.$title.addEventListener( 'touchstart', () => {}, { passive: true } );
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The DOM element that contains children.
|
|
122
|
+
* @type {HTMLElement}
|
|
123
|
+
*/
|
|
124
|
+
this.$children = document.createElement( 'div' );
|
|
125
|
+
this.$children.classList.add( 'children' );
|
|
126
|
+
|
|
127
|
+
this.domElement.appendChild( this.$title );
|
|
128
|
+
this.domElement.appendChild( this.$children );
|
|
129
|
+
|
|
130
|
+
this.title( title );
|
|
131
|
+
|
|
132
|
+
if ( this.parent ) {
|
|
133
|
+
|
|
134
|
+
this.parent.children.push( this );
|
|
135
|
+
this.parent.folders.push( this );
|
|
136
|
+
|
|
137
|
+
this.parent.$children.appendChild( this.domElement );
|
|
138
|
+
|
|
139
|
+
// Stop the constructor early, everything onward only applies to root GUI's
|
|
140
|
+
return;
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.domElement.classList.add( 'root' );
|
|
145
|
+
|
|
146
|
+
if ( touchStyles ) {
|
|
147
|
+
this.domElement.classList.add( 'allow-touch-styles' );
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Styles are loaded externally via <link> tag in index.html - no injection needed
|
|
151
|
+
|
|
152
|
+
if ( container ) {
|
|
153
|
+
|
|
154
|
+
container.appendChild( this.domElement );
|
|
155
|
+
|
|
156
|
+
} else if ( autoPlace ) {
|
|
157
|
+
|
|
158
|
+
this.domElement.classList.add( 'autoPlace' );
|
|
159
|
+
document.body.appendChild( this.domElement );
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if ( width ) {
|
|
164
|
+
this.domElement.style.setProperty( '--width', width + 'px' );
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this._closeFolders = closeFolders;
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Adds a controller to the GUI, inferring controller type using the `typeof` operator.
|
|
173
|
+
* @example
|
|
174
|
+
* gui.add( object, 'property' );
|
|
175
|
+
* gui.add( object, 'number', 0, 100, 1 );
|
|
176
|
+
* gui.add( object, 'options', [ 1, 2, 3 ] );
|
|
177
|
+
*
|
|
178
|
+
* @param {object} object The object the controller will modify.
|
|
179
|
+
* @param {string} property Name of the property to control.
|
|
180
|
+
* @param {number|object|Array} [$1] Minimum value for number controllers, or the set of
|
|
181
|
+
* selectable values for a dropdown.
|
|
182
|
+
* @param {number} [max] Maximum value for number controllers.
|
|
183
|
+
* @param {number} [step] Step value for number controllers.
|
|
184
|
+
* @returns {Controller}
|
|
185
|
+
*/
|
|
186
|
+
add( object, property, $1, max, step ) {
|
|
187
|
+
|
|
188
|
+
if ( Object( $1 ) === $1 ) {
|
|
189
|
+
|
|
190
|
+
return new OptionController( this, object, property, $1 );
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const initialValue = object[ property ];
|
|
195
|
+
|
|
196
|
+
switch ( typeof initialValue ) {
|
|
197
|
+
|
|
198
|
+
case 'number':
|
|
199
|
+
|
|
200
|
+
return new NumberController( this, object, property, $1, max, step );
|
|
201
|
+
|
|
202
|
+
case 'boolean':
|
|
203
|
+
|
|
204
|
+
return new BooleanController( this, object, property );
|
|
205
|
+
|
|
206
|
+
case 'string':
|
|
207
|
+
|
|
208
|
+
return new StringController( this, object, property );
|
|
209
|
+
|
|
210
|
+
case 'function':
|
|
211
|
+
|
|
212
|
+
return new FunctionController( this, object, property );
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// eslint-disable-next-line no-console
|
|
217
|
+
console.error( `gui.add failed
|
|
218
|
+
property:`, property, `
|
|
219
|
+
object:`, object, `
|
|
220
|
+
value:`, initialValue );
|
|
221
|
+
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Adds a color controller to the GUI.
|
|
226
|
+
* @example
|
|
227
|
+
* params = {
|
|
228
|
+
* cssColor: '#ff00ff',
|
|
229
|
+
* rgbColor: { r: 0, g: 0.2, b: 0.4 },
|
|
230
|
+
* customRange: [ 0, 127, 255 ],
|
|
231
|
+
* };
|
|
232
|
+
*
|
|
233
|
+
* gui.addColor( params, 'cssColor' );
|
|
234
|
+
* gui.addColor( params, 'rgbColor' );
|
|
235
|
+
* gui.addColor( params, 'customRange', 255 );
|
|
236
|
+
*
|
|
237
|
+
* @param {object} object The object the controller will modify.
|
|
238
|
+
* @param {string} property Name of the property to control.
|
|
239
|
+
* @param {number} rgbScale Maximum value for a color channel when using an RGB color. You may
|
|
240
|
+
* need to set this to 255 if your colors are too bright.
|
|
241
|
+
* @returns {Controller}
|
|
242
|
+
*/
|
|
243
|
+
addColor( object, property, rgbScale = 1 ) {
|
|
244
|
+
return new ColorController( this, object, property, rgbScale );
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Adds a folder to the GUI, which is just another GUI. This method returns
|
|
249
|
+
* the nested GUI so you can add controllers to it.
|
|
250
|
+
* @example
|
|
251
|
+
* const folder = gui.addFolder( 'Position' );
|
|
252
|
+
* folder.add( position, 'x' );
|
|
253
|
+
* folder.add( position, 'y' );
|
|
254
|
+
* folder.add( position, 'z' );
|
|
255
|
+
*
|
|
256
|
+
* @param {string} title Name to display in the folder's title bar.
|
|
257
|
+
* @returns {GUI}
|
|
258
|
+
*/
|
|
259
|
+
addFolder( title ) {
|
|
260
|
+
const folder = new GUI( { parent: this, title } );
|
|
261
|
+
if ( this.root._closeFolders ) folder.close();
|
|
262
|
+
return folder;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Recalls values that were saved with `gui.save()`.
|
|
267
|
+
* @param {object} obj
|
|
268
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
269
|
+
* @returns {this}
|
|
270
|
+
*/
|
|
271
|
+
load( obj, recursive = true ) {
|
|
272
|
+
|
|
273
|
+
if ( obj.controllers ) {
|
|
274
|
+
|
|
275
|
+
this.controllers.forEach( c => {
|
|
276
|
+
|
|
277
|
+
if ( c instanceof FunctionController ) return;
|
|
278
|
+
|
|
279
|
+
if ( c._name in obj.controllers ) {
|
|
280
|
+
c.load( obj.controllers[ c._name ] );
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
} );
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if ( recursive && obj.folders ) {
|
|
288
|
+
|
|
289
|
+
this.folders.forEach( f => {
|
|
290
|
+
|
|
291
|
+
if ( f._title in obj.folders ) {
|
|
292
|
+
f.load( obj.folders[ f._title ] );
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
} );
|
|
296
|
+
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return this;
|
|
300
|
+
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Returns an object mapping controller names to values. The object can be passed to `gui.load()` to
|
|
305
|
+
* recall these values.
|
|
306
|
+
* @example
|
|
307
|
+
* {
|
|
308
|
+
* controllers: {
|
|
309
|
+
* prop1: 1,
|
|
310
|
+
* prop2: 'value',
|
|
311
|
+
* ...
|
|
312
|
+
* },
|
|
313
|
+
* folders: {
|
|
314
|
+
* folderName1: { controllers, folders },
|
|
315
|
+
* folderName2: { controllers, folders }
|
|
316
|
+
* ...
|
|
317
|
+
* }
|
|
318
|
+
* }
|
|
319
|
+
*
|
|
320
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
321
|
+
* @returns {object}
|
|
322
|
+
*/
|
|
323
|
+
save( recursive = true ) {
|
|
324
|
+
|
|
325
|
+
const obj = {
|
|
326
|
+
controllers: {},
|
|
327
|
+
folders: {}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
this.controllers.forEach( c => {
|
|
331
|
+
|
|
332
|
+
if ( c instanceof FunctionController ) return;
|
|
333
|
+
|
|
334
|
+
if ( c._name in obj.controllers ) {
|
|
335
|
+
throw new Error( `Cannot save GUI with duplicate property "${c._name}"` );
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
obj.controllers[ c._name ] = c.save();
|
|
339
|
+
|
|
340
|
+
} );
|
|
341
|
+
|
|
342
|
+
if ( recursive ) {
|
|
343
|
+
|
|
344
|
+
this.folders.forEach( f => {
|
|
345
|
+
|
|
346
|
+
if ( f._title in obj.folders ) {
|
|
347
|
+
throw new Error( `Cannot save GUI with duplicate folder "${f._title}"` );
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
obj.folders[ f._title ] = f.save();
|
|
351
|
+
|
|
352
|
+
} );
|
|
353
|
+
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return obj;
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Opens a GUI or folder. GUI and folders are open by default.
|
|
362
|
+
* @param {boolean} open Pass false to close.
|
|
363
|
+
* @returns {this}
|
|
364
|
+
* @example
|
|
365
|
+
* gui.open(); // open
|
|
366
|
+
* gui.open( false ); // close
|
|
367
|
+
* gui.open( gui._closed ); // toggle
|
|
368
|
+
*/
|
|
369
|
+
open( open = true ) {
|
|
370
|
+
|
|
371
|
+
this._setClosed( !open );
|
|
372
|
+
|
|
373
|
+
this.$title.setAttribute( 'aria-expanded', !this._closed );
|
|
374
|
+
this.domElement.classList.toggle( 'closed', this._closed );
|
|
375
|
+
|
|
376
|
+
return this;
|
|
377
|
+
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Closes the GUI.
|
|
382
|
+
* @returns {this}
|
|
383
|
+
*/
|
|
384
|
+
close() {
|
|
385
|
+
return this.open( false );
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
_setClosed( closed ) {
|
|
389
|
+
if ( this._closed === closed ) return;
|
|
390
|
+
this._closed = closed;
|
|
391
|
+
this._callOnOpenClose( this );
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Shows the GUI after it's been hidden.
|
|
396
|
+
* @param {boolean} show
|
|
397
|
+
* @returns {this}
|
|
398
|
+
* @example
|
|
399
|
+
* gui.show();
|
|
400
|
+
* gui.show( false ); // hide
|
|
401
|
+
* gui.show( gui._hidden ); // toggle
|
|
402
|
+
*/
|
|
403
|
+
show( show = true ) {
|
|
404
|
+
|
|
405
|
+
this._hidden = !show;
|
|
406
|
+
|
|
407
|
+
this.domElement.style.display = this._hidden ? 'none' : '';
|
|
408
|
+
|
|
409
|
+
return this;
|
|
410
|
+
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Hides the GUI.
|
|
415
|
+
* @returns {this}
|
|
416
|
+
*/
|
|
417
|
+
hide() {
|
|
418
|
+
return this.show( false );
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
openAnimated( open = true ) {
|
|
422
|
+
// Simplified: directly toggle without height animation to avoid overlap bugs
|
|
423
|
+
this.open( open );
|
|
424
|
+
return this;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Change the title of this GUI.
|
|
429
|
+
* @param {string} title
|
|
430
|
+
* @returns {this}
|
|
431
|
+
*/
|
|
432
|
+
title( title ) {
|
|
433
|
+
/**
|
|
434
|
+
* Current title of the GUI. Use `gui.title( 'Title' )` to modify this value.
|
|
435
|
+
* @type {string}
|
|
436
|
+
*/
|
|
437
|
+
this._title = title;
|
|
438
|
+
this.$title.textContent = title;
|
|
439
|
+
return this;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Resets all controllers to their initial values.
|
|
444
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
445
|
+
* @returns {this}
|
|
446
|
+
*/
|
|
447
|
+
reset( recursive = true ) {
|
|
448
|
+
const controllers = recursive ? this.controllersRecursive() : this.controllers;
|
|
449
|
+
controllers.forEach( c => c.reset() );
|
|
450
|
+
return this;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Pass a function to be called whenever a controller in this GUI changes.
|
|
455
|
+
* @param {function({object:object, property:string, value:any, controller:Controller})} callback
|
|
456
|
+
* @returns {this}
|
|
457
|
+
* @example
|
|
458
|
+
* gui.onChange( event => {
|
|
459
|
+
* event.object // object that was modified
|
|
460
|
+
* event.property // string, name of property
|
|
461
|
+
* event.value // new value of controller
|
|
462
|
+
* event.controller // controller that was modified
|
|
463
|
+
* } );
|
|
464
|
+
*/
|
|
465
|
+
onChange( callback ) {
|
|
466
|
+
/**
|
|
467
|
+
* Used to access the function bound to `onChange` events. Don't modify this value
|
|
468
|
+
* directly. Use the `gui.onChange( callback )` method instead.
|
|
469
|
+
* @type {Function}
|
|
470
|
+
*/
|
|
471
|
+
this._onChange = callback;
|
|
472
|
+
return this;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
_callOnChange( controller ) {
|
|
476
|
+
|
|
477
|
+
if ( this.parent ) {
|
|
478
|
+
this.parent._callOnChange( controller );
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if ( this._onChange !== undefined ) {
|
|
482
|
+
this._onChange.call( this, {
|
|
483
|
+
object: controller.object,
|
|
484
|
+
property: controller.property,
|
|
485
|
+
value: controller.getValue(),
|
|
486
|
+
controller
|
|
487
|
+
} );
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Pass a function to be called whenever a controller in this GUI has finished changing.
|
|
493
|
+
* @param {function({object:object, property:string, value:any, controller:Controller})} callback
|
|
494
|
+
* @returns {this}
|
|
495
|
+
* @example
|
|
496
|
+
* gui.onFinishChange( event => {
|
|
497
|
+
* event.object // object that was modified
|
|
498
|
+
* event.property // string, name of property
|
|
499
|
+
* event.value // new value of controller
|
|
500
|
+
* event.controller // controller that was modified
|
|
501
|
+
* } );
|
|
502
|
+
*/
|
|
503
|
+
onFinishChange( callback ) {
|
|
504
|
+
/**
|
|
505
|
+
* Used to access the function bound to `onFinishChange` events. Don't modify this value
|
|
506
|
+
* directly. Use the `gui.onFinishChange( callback )` method instead.
|
|
507
|
+
* @type {Function}
|
|
508
|
+
*/
|
|
509
|
+
this._onFinishChange = callback;
|
|
510
|
+
return this;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
_callOnFinishChange( controller ) {
|
|
514
|
+
|
|
515
|
+
if ( this.parent ) {
|
|
516
|
+
this.parent._callOnFinishChange( controller );
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if ( this._onFinishChange !== undefined ) {
|
|
520
|
+
this._onFinishChange.call( this, {
|
|
521
|
+
object: controller.object,
|
|
522
|
+
property: controller.property,
|
|
523
|
+
value: controller.getValue(),
|
|
524
|
+
controller
|
|
525
|
+
} );
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Pass a function to be called when this GUI or its descendants are opened or closed.
|
|
531
|
+
* @param {function(GUI)} callback
|
|
532
|
+
* @returns {this}
|
|
533
|
+
* @example
|
|
534
|
+
* gui.onOpenClose( changedGUI => {
|
|
535
|
+
* console.log( changedGUI._closed );
|
|
536
|
+
* } );
|
|
537
|
+
*/
|
|
538
|
+
onOpenClose( callback ) {
|
|
539
|
+
this._onOpenClose = callback;
|
|
540
|
+
return this;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
_callOnOpenClose( changedGUI ) {
|
|
544
|
+
if ( this.parent ) {
|
|
545
|
+
this.parent._callOnOpenClose( changedGUI );
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if ( this._onOpenClose !== undefined ) {
|
|
549
|
+
this._onOpenClose.call( this, changedGUI );
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Destroys all DOM elements and event listeners associated with this GUI.
|
|
555
|
+
*/
|
|
556
|
+
destroy() {
|
|
557
|
+
|
|
558
|
+
if ( this.parent ) {
|
|
559
|
+
this.parent.children.splice( this.parent.children.indexOf( this ), 1 );
|
|
560
|
+
this.parent.folders.splice( this.parent.folders.indexOf( this ), 1 );
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if ( this.domElement.parentElement ) {
|
|
564
|
+
this.domElement.parentElement.removeChild( this.domElement );
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
Array.from( this.children ).forEach( c => c.destroy() );
|
|
568
|
+
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Returns an array of controllers contained by this GUI and its descendents.
|
|
573
|
+
* @returns {Controller[]}
|
|
574
|
+
*/
|
|
575
|
+
controllersRecursive() {
|
|
576
|
+
let controllers = Array.from( this.controllers );
|
|
577
|
+
this.folders.forEach( f => {
|
|
578
|
+
controllers = controllers.concat( f.controllersRecursive() );
|
|
579
|
+
} );
|
|
580
|
+
return controllers;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Returns an array of folders contained by this GUI and its descendents.
|
|
585
|
+
* @returns {GUI[]}
|
|
586
|
+
*/
|
|
587
|
+
foldersRecursive() {
|
|
588
|
+
let folders = Array.from( this.folders );
|
|
589
|
+
this.folders.forEach( f => {
|
|
590
|
+
folders = folders.concat( f.foldersRecursive() );
|
|
591
|
+
} );
|
|
592
|
+
return folders;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
}
|