{"mappings":"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","sources":["node_modules/@parcel/runtime-js/lib/runtime-5c933ca2f31e526b.js","src/dev/App.ts","node_modules/three/examples/jsm/controls/OrbitControls.js","node_modules/lil-gui/dist/lil-gui.esm.js","node_modules/stats.js/build/stats.min.js","node_modules/@parcel/runtime-js/lib/runtime-227c3168808d6d71.js"],"sourcesContent":["require('./helpers/bundle-manifest').register(JSON.parse(\"{\\\"3Qx6i\\\":\\\"index.06fb0362.js\\\",\\\"lWGOs\\\":\\\"DomeFacade.2b11c864.obj\\\",\\\"fTkA1\\\":\\\"index.313a274a.js\\\"}\"));","\"use strict\";\n\nimport * as THREE from \"three\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls\";\n\nimport GUI from 'lil-gui';\nimport Stats from 'stats.js';\n\nimport Garden from '../Garden';\n\nclass App {\n\n // Three.js\n scene: THREE.Scene;\n camera: THREE.Camera;\n renderer: THREE.WebGLRenderer;\n clock = new THREE.Clock(true);\n controls: OrbitControls;\n\n stats = new Stats();\n\n garden: Garden;\n\n constructor() {\n\n document.addEventListener(\"click\", (event) => {\n event.preventDefault();\n let x = (event.clientX / window.innerWidth) * 2 - 1;\n let y = - (event.clientY / window.innerHeight) * 2 + 1;\n\n this.garden.click({ x, y }, this.camera);\n });\n\n // Stats\n this.stats.showPanel(0);\n document.body.appendChild(this.stats.dom);\n\n // Gui\n const gui = new GUI();\n const guiObject = {\n progress: 1,\n ar: () => {\n window.open('/ar/index.html');\n },\n report: () => {\n console.log(this.renderer.info.render);\n },\n generate: () => {\n this.garden.generate();\n },\n capture: async () => {\n let canvas = this.renderer.domElement;\n\n // Prepare canvas\n this.renderer.setClearColor(0x000000, 0);\n this.resize(4096, 4096);\n await new Promise(r => setTimeout(r, 10));\n\n // Capture image.\n let imageUrl = canvas.toDataURL();\n console.log(imageUrl);\n\n // Fake click.\n const anchor = document.createElement('a');\n anchor.download = 'image.png';\n anchor.href = imageUrl;\n anchor.click();\n anchor.remove();\n\n // Restore canvas.\n this.renderer.setClearColor(0x000000, 1);\n this.resize(window.innerWidth, window.innerHeight);\n }\n };\n\n gui.add(guiObject, 'progress', 0, 1).onChange(value => {\n this.garden.progress(value);\n });\n\n gui.add(guiObject, 'ar');\n gui.add(guiObject, 'report');\n gui.add(guiObject, 'generate');\n gui.add(guiObject, 'capture');\n\n // Three setup.\n\n this.scene = new THREE.Scene();\n\n // Perspective camera.\n this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);\n\n // Orthographic camera.\n // let width = window.innerWidth;\n // let height = window.innerHeight;\n // this.camera = new THREE.OrthographicCamera(width / - 2, width / 2, height / 2, height / - 2, .001, 10000);\n // this.camera.scale.set(.025, .025, .025);\n\n this.renderer = new THREE.WebGLRenderer({\n \"antialias\": true,\n \"alpha\": true,\n \"preserveDrawingBuffer\": true\n });\n this.renderer.setClearColor(0x000000, 1);\n\n\n this.renderer.setPixelRatio(window.devicePixelRatio);\n this.renderer.setSize(window.innerWidth, window.innerHeight);\n document.body.appendChild(this.renderer.domElement);\n\n // this.camera.position.set(0, 96, 0); // Capture B\n // this.camera.position.set(0, 72, 0); // Capture A\n\n // this.controls.target.set(0, 0, 0);\n //this.camera.position.z = 12;\n\n // this.camera.position.set(0, 14, 0);// Bloom\n\n // this.camera.position.set(0, 0, 5);// Dome\n this.camera.position.set(0, 0, 2);// Circle\n\n // this.camera.position.set(0, 0, 2);// Bloom\n\n // Controls\n this.controls = new OrbitControls(this.camera, this.renderer.domElement);\n // this.controls.target.set(0, 0, 0);\n this.controls.target.set(0, 0, 0);\n this.controls.update();\n\n // Garden.\n this.garden = new Garden();\n this.scene.add(this.garden);\n\n // let circleView = new Garden.Views.GeometryView(\n // {\n // modelUrl: new URL(\"../assets/models/Circle.obj\", import.meta.url).toString(),\n // maxBloomRadius: .20,\n // minBloomRadius: .08,\n // minSurfaceOffset: .04,\n // maxSurfaceOffset: .18,\n // textureScale: 8\n // }\n // );\n // this.garden.add(circleView);\n // this.garden.views.push(circleView);\n\n {\n let domeView = new Garden.Views.GeometryView(\n {\n modelUrl: new URL(\"../assets/models/DomeFacade.obj\", import.meta.url).toString(),\n maxBloomRadius: .28,\n minBloomRadius: .08,\n minSurfaceOffset: .04,\n maxSurfaceOffset: .18,\n textureScale: 12\n }\n );\n this.garden.add(domeView);\n this.garden.views.push(domeView);\n }\n\n // let bloomView = new Garden.Views.BloomView();\n // this.garden.add(bloomView);\n // this.garden.views.push(bloomView);\n // this.camera.position.set(0, 14, 0);\n // this.controls.target.set(0, 0, 0);\n\n // Click off animation.\n this.animate();\n\n window.addEventListener('resize', () => {\n this.resize(window.innerWidth, window.innerHeight);\n });\n }\n\n resize(width, height) {\n this.camera.aspect = width / height;\n this.camera.updateProjectionMatrix();\n this.renderer.setSize(width, height);\n }\n\n animate() {\n\n this.stats.begin();\n\n this.controls.update();\n\n this.garden.update();\n\n this.renderer.render(this.scene, this.camera);\n\n this.stats.end();\n\n requestAnimationFrame(this.animate.bind(this));\n };\n}\n\nexport default new App();","import {\n\tEventDispatcher,\n\tMOUSE,\n\tQuaternion,\n\tSpherical,\n\tTOUCH,\n\tVector2,\n\tVector3\n} from 'three';\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n//\n// Orbit - left mouse / touch: one-finger move\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move\n\nconst _changeEvent = { type: 'change' };\nconst _startEvent = { type: 'start' };\nconst _endEvent = { type: 'end' };\n\nclass OrbitControls extends EventDispatcher {\n\n\tconstructor( object, domElement ) {\n\n\t\tsuper();\n\n\t\tif ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter \"domElement\" is now mandatory.' );\n\t\tif ( domElement === document ) console.error( 'THREE.OrbitControls: \"document\" should not be used as the target \"domElement\". Please use \"renderer.domElement\" instead.' );\n\n\t\tthis.object = object;\n\t\tthis.domElement = domElement;\n\t\tthis.domElement.style.touchAction = 'none'; // disable touch scroll\n\n\t\t// Set to false to disable this control\n\t\tthis.enabled = true;\n\n\t\t// \"target\" sets the location of focus, where the object orbits around\n\t\tthis.target = new Vector3();\n\n\t\t// How far you can dolly in and out ( PerspectiveCamera only )\n\t\tthis.minDistance = 0;\n\t\tthis.maxDistance = Infinity;\n\n\t\t// How far you can zoom in and out ( OrthographicCamera only )\n\t\tthis.minZoom = 0;\n\t\tthis.maxZoom = Infinity;\n\n\t\t// How far you can orbit vertically, upper and lower limits.\n\t\t// Range is 0 to Math.PI radians.\n\t\tthis.minPolarAngle = 0; // radians\n\t\tthis.maxPolarAngle = Math.PI; // radians\n\n\t\t// How far you can orbit horizontally, upper and lower limits.\n\t\t// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )\n\t\tthis.minAzimuthAngle = - Infinity; // radians\n\t\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t\t// Set to true to enable damping (inertia)\n\t\t// If damping is enabled, you must call controls.update() in your animation loop\n\t\tthis.enableDamping = false;\n\t\tthis.dampingFactor = 0.05;\n\n\t\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t\t// Set to false to disable zooming\n\t\tthis.enableZoom = true;\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t// Set to false to disable rotating\n\t\tthis.enableRotate = true;\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t// Set to false to disable panning\n\t\tthis.enablePan = true;\n\t\tthis.panSpeed = 1.0;\n\t\tthis.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up\n\t\tthis.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\n\n\t\t// Set to true to automatically rotate around the target\n\t\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\t\tthis.autoRotate = false;\n\t\tthis.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60\n\n\t\t// The four arrow keys\n\t\tthis.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };\n\n\t\t// Mouse buttons\n\t\tthis.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n\t\t// Touch fingers\n\t\tthis.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n\t\t// for reset\n\t\tthis.target0 = this.target.clone();\n\t\tthis.position0 = this.object.position.clone();\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\t// the target DOM element for key events\n\t\tthis._domElementKeyEvents = null;\n\n\t\t//\n\t\t// public methods\n\t\t//\n\n\t\tthis.getPolarAngle = function () {\n\n\t\t\treturn spherical.phi;\n\n\t\t};\n\n\t\tthis.getAzimuthalAngle = function () {\n\n\t\t\treturn spherical.theta;\n\n\t\t};\n\n\t\tthis.getDistance = function () {\n\n\t\t\treturn this.object.position.distanceTo( this.target );\n\n\t\t};\n\n\t\tthis.listenToKeyEvents = function ( domElement ) {\n\n\t\t\tdomElement.addEventListener( 'keydown', onKeyDown );\n\t\t\tthis._domElementKeyEvents = domElement;\n\n\t\t};\n\n\t\tthis.saveState = function () {\n\n\t\t\tscope.target0.copy( scope.target );\n\t\t\tscope.position0.copy( scope.object.position );\n\t\t\tscope.zoom0 = scope.object.zoom;\n\n\t\t};\n\n\t\tthis.reset = function () {\n\n\t\t\tscope.target.copy( scope.target0 );\n\t\t\tscope.object.position.copy( scope.position0 );\n\t\t\tscope.object.zoom = scope.zoom0;\n\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tscope.dispatchEvent( _changeEvent );\n\n\t\t\tscope.update();\n\n\t\t\tstate = STATE.NONE;\n\n\t\t};\n\n\t\t// this method is exposed, but perhaps it would be better if we can make it private...\n\t\tthis.update = function () {\n\n\t\t\tconst offset = new Vector3();\n\n\t\t\t// so camera.up is the orbit axis\n\t\t\tconst quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n\t\t\tconst quatInverse = quat.clone().invert();\n\n\t\t\tconst lastPosition = new Vector3();\n\t\t\tconst lastQuaternion = new Quaternion();\n\n\t\t\tconst twoPI = 2 * Math.PI;\n\n\t\t\treturn function update() {\n\n\t\t\t\tconst position = scope.object.position;\n\n\t\t\t\toffset.copy( position ).sub( scope.target );\n\n\t\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\t\toffset.applyQuaternion( quat );\n\n\t\t\t\t// angle from z-axis around y-axis\n\t\t\t\tspherical.setFromVector3( offset );\n\n\t\t\t\tif ( scope.autoRotate && state === STATE.NONE ) {\n\n\t\t\t\t\trotateLeft( getAutoRotationAngle() );\n\n\t\t\t\t}\n\n\t\t\t\tif ( scope.enableDamping ) {\n\n\t\t\t\t\tspherical.theta += sphericalDelta.theta * scope.dampingFactor;\n\t\t\t\t\tspherical.phi += sphericalDelta.phi * scope.dampingFactor;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\t\tspherical.phi += sphericalDelta.phi;\n\n\t\t\t\t}\n\n\t\t\t\t// restrict theta to be between desired limits\n\n\t\t\t\tlet min = scope.minAzimuthAngle;\n\t\t\t\tlet max = scope.maxAzimuthAngle;\n\n\t\t\t\tif ( isFinite( min ) && isFinite( max ) ) {\n\n\t\t\t\t\tif ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;\n\n\t\t\t\t\tif ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;\n\n\t\t\t\t\tif ( min <= max ) {\n\n\t\t\t\t\t\tspherical.theta = Math.max( min, Math.min( max, spherical.theta ) );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tspherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?\n\t\t\t\t\t\t\tMath.max( min, spherical.theta ) :\n\t\t\t\t\t\t\tMath.min( max, spherical.theta );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// restrict phi to be between desired limits\n\t\t\t\tspherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n\t\t\t\tspherical.makeSafe();\n\n\n\t\t\t\tspherical.radius *= scale;\n\n\t\t\t\t// restrict radius to be between desired limits\n\t\t\t\tspherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\n\n\t\t\t\t// move target to panned location\n\n\t\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\t\tscope.target.addScaledVector( panOffset, scope.dampingFactor );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tscope.target.add( panOffset );\n\n\t\t\t\t}\n\n\t\t\t\toffset.setFromSpherical( spherical );\n\n\t\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\t\toffset.applyQuaternion( quatInverse );\n\n\t\t\t\tposition.copy( scope.target ).add( offset );\n\n\t\t\t\tscope.object.lookAt( scope.target );\n\n\t\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\t\tsphericalDelta.theta *= ( 1 - scope.dampingFactor );\n\t\t\t\t\tsphericalDelta.phi *= ( 1 - scope.dampingFactor );\n\n\t\t\t\t\tpanOffset.multiplyScalar( 1 - scope.dampingFactor );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tsphericalDelta.set( 0, 0, 0 );\n\n\t\t\t\t\tpanOffset.set( 0, 0, 0 );\n\n\t\t\t\t}\n\n\t\t\t\tscale = 1;\n\n\t\t\t\t// update condition is:\n\t\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n\t\t\t\tif ( zoomChanged ||\n\t\t\t\t\tlastPosition.distanceToSquared( scope.object.position ) > EPS ||\n\t\t\t\t\t8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\n\n\t\t\t\t\tscope.dispatchEvent( _changeEvent );\n\n\t\t\t\t\tlastPosition.copy( scope.object.position );\n\t\t\t\t\tlastQuaternion.copy( scope.object.quaternion );\n\t\t\t\t\tzoomChanged = false;\n\n\t\t\t\t\treturn true;\n\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\n\t\t\t};\n\n\t\t}();\n\n\t\tthis.dispose = function () {\n\n\t\t\tscope.domElement.removeEventListener( 'contextmenu', onContextMenu );\n\n\t\t\tscope.domElement.removeEventListener( 'pointerdown', onPointerDown );\n\t\t\tscope.domElement.removeEventListener( 'pointercancel', onPointerCancel );\n\t\t\tscope.domElement.removeEventListener( 'wheel', onMouseWheel );\n\n\t\t\tscope.domElement.removeEventListener( 'pointermove', onPointerMove );\n\t\t\tscope.domElement.removeEventListener( 'pointerup', onPointerUp );\n\n\n\t\t\tif ( scope._domElementKeyEvents !== null ) {\n\n\t\t\t\tscope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );\n\n\t\t\t}\n\n\t\t\t//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?\n\n\t\t};\n\n\t\t//\n\t\t// internals\n\t\t//\n\n\t\tconst scope = this;\n\n\t\tconst STATE = {\n\t\t\tNONE: - 1,\n\t\t\tROTATE: 0,\n\t\t\tDOLLY: 1,\n\t\t\tPAN: 2,\n\t\t\tTOUCH_ROTATE: 3,\n\t\t\tTOUCH_PAN: 4,\n\t\t\tTOUCH_DOLLY_PAN: 5,\n\t\t\tTOUCH_DOLLY_ROTATE: 6\n\t\t};\n\n\t\tlet state = STATE.NONE;\n\n\t\tconst EPS = 0.000001;\n\n\t\t// current position in spherical coordinates\n\t\tconst spherical = new Spherical();\n\t\tconst sphericalDelta = new Spherical();\n\n\t\tlet scale = 1;\n\t\tconst panOffset = new Vector3();\n\t\tlet zoomChanged = false;\n\n\t\tconst rotateStart = new Vector2();\n\t\tconst rotateEnd = new Vector2();\n\t\tconst rotateDelta = new Vector2();\n\n\t\tconst panStart = new Vector2();\n\t\tconst panEnd = new Vector2();\n\t\tconst panDelta = new Vector2();\n\n\t\tconst dollyStart = new Vector2();\n\t\tconst dollyEnd = new Vector2();\n\t\tconst dollyDelta = new Vector2();\n\n\t\tconst pointers = [];\n\t\tconst pointerPositions = {};\n\n\t\tfunction getAutoRotationAngle() {\n\n\t\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\n\t\t}\n\n\t\tfunction getZoomScale() {\n\n\t\t\treturn Math.pow( 0.95, scope.zoomSpeed );\n\n\t\t}\n\n\t\tfunction rotateLeft( angle ) {\n\n\t\t\tsphericalDelta.theta -= angle;\n\n\t\t}\n\n\t\tfunction rotateUp( angle ) {\n\n\t\t\tsphericalDelta.phi -= angle;\n\n\t\t}\n\n\t\tconst panLeft = function () {\n\n\t\t\tconst v = new Vector3();\n\n\t\t\treturn function panLeft( distance, objectMatrix ) {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n\t\t\t\tv.multiplyScalar( - distance );\n\n\t\t\t\tpanOffset.add( v );\n\n\t\t\t};\n\n\t\t}();\n\n\t\tconst panUp = function () {\n\n\t\t\tconst v = new Vector3();\n\n\t\t\treturn function panUp( distance, objectMatrix ) {\n\n\t\t\t\tif ( scope.screenSpacePanning === true ) {\n\n\t\t\t\t\tv.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tv.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t\t\tv.crossVectors( scope.object.up, v );\n\n\t\t\t\t}\n\n\t\t\t\tv.multiplyScalar( distance );\n\n\t\t\t\tpanOffset.add( v );\n\n\t\t\t};\n\n\t\t}();\n\n\t\t// deltaX and deltaY are in pixels; right and down are positive\n\t\tconst pan = function () {\n\n\t\t\tconst offset = new Vector3();\n\n\t\t\treturn function pan( deltaX, deltaY ) {\n\n\t\t\t\tconst element = scope.domElement;\n\n\t\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\t\t// perspective\n\t\t\t\t\tconst position = scope.object.position;\n\t\t\t\t\toffset.copy( position ).sub( scope.target );\n\t\t\t\t\tlet targetDistance = offset.length();\n\n\t\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\t\ttargetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t\t\t// we use only clientHeight here so aspect ratio does not distort speed\n\t\t\t\t\tpanLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\n\t\t\t\t\tpanUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\n\n\t\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\t\t// orthographic\n\t\t\t\t\tpanLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\n\t\t\t\t\tpanUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\t\t\tscope.enablePan = false;\n\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t}();\n\n\t\tfunction dollyOut( dollyScale ) {\n\n\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\tscale /= dollyScale;\n\n\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\t\tscope.enableZoom = false;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction dollyIn( dollyScale ) {\n\n\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\tscale *= dollyScale;\n\n\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\t\tscope.enableZoom = false;\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\t\t// event callbacks - update the object state\n\t\t//\n\n\t\tfunction handleMouseDownRotate( event ) {\n\n\t\t\trotateStart.set( event.clientX, event.clientY );\n\n\t\t}\n\n\t\tfunction handleMouseDownDolly( event ) {\n\n\t\t\tdollyStart.set( event.clientX, event.clientY );\n\n\t\t}\n\n\t\tfunction handleMouseDownPan( event ) {\n\n\t\t\tpanStart.set( event.clientX, event.clientY );\n\n\t\t}\n\n\t\tfunction handleMouseMoveRotate( event ) {\n\n\t\t\trotateEnd.set( event.clientX, event.clientY );\n\n\t\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\t\tconst element = scope.domElement;\n\n\t\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\t\trotateStart.copy( rotateEnd );\n\n\t\t\tscope.update();\n\n\t\t}\n\n\t\tfunction handleMouseMoveDolly( event ) {\n\n\t\t\tdollyEnd.set( event.clientX, event.clientY );\n\n\t\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\t\tif ( dollyDelta.y > 0 ) {\n\n\t\t\t\tdollyOut( getZoomScale() );\n\n\t\t\t} else if ( dollyDelta.y < 0 ) {\n\n\t\t\t\tdollyIn( getZoomScale() );\n\n\t\t\t}\n\n\t\t\tdollyStart.copy( dollyEnd );\n\n\t\t\tscope.update();\n\n\t\t}\n\n\t\tfunction handleMouseMovePan( event ) {\n\n\t\t\tpanEnd.set( event.clientX, event.clientY );\n\n\t\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\t\tpan( panDelta.x, panDelta.y );\n\n\t\t\tpanStart.copy( panEnd );\n\n\t\t\tscope.update();\n\n\t\t}\n\n\t\tfunction handleMouseWheel( event ) {\n\n\t\t\tif ( event.deltaY < 0 ) {\n\n\t\t\t\tdollyIn( getZoomScale() );\n\n\t\t\t} else if ( event.deltaY > 0 ) {\n\n\t\t\t\tdollyOut( getZoomScale() );\n\n\t\t\t}\n\n\t\t\tscope.update();\n\n\t\t}\n\n\t\tfunction handleKeyDown( event ) {\n\n\t\t\tlet needsUpdate = false;\n\n\t\t\tswitch ( event.code ) {\n\n\t\t\t\tcase scope.keys.UP:\n\t\t\t\t\tpan( 0, scope.keyPanSpeed );\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\t\tpan( 0, - scope.keyPanSpeed );\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase scope.keys.LEFT:\n\t\t\t\t\tpan( scope.keyPanSpeed, 0 );\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase scope.keys.RIGHT:\n\t\t\t\t\tpan( - scope.keyPanSpeed, 0 );\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( needsUpdate ) {\n\n\t\t\t\t// prevent the browser from scrolling on cursor keys\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tscope.update();\n\n\t\t\t}\n\n\n\t\t}\n\n\t\tfunction handleTouchStartRotate() {\n\n\t\t\tif ( pointers.length === 1 ) {\n\n\t\t\t\trotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );\n\n\t\t\t} else {\n\n\t\t\t\tconst x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );\n\t\t\t\tconst y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );\n\n\t\t\t\trotateStart.set( x, y );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction handleTouchStartPan() {\n\n\t\t\tif ( pointers.length === 1 ) {\n\n\t\t\t\tpanStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );\n\n\t\t\t} else {\n\n\t\t\t\tconst x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );\n\t\t\t\tconst y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );\n\n\t\t\t\tpanStart.set( x, y );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction handleTouchStartDolly() {\n\n\t\t\tconst dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX;\n\t\t\tconst dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY;\n\n\t\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\tdollyStart.set( 0, distance );\n\n\t\t}\n\n\t\tfunction handleTouchStartDollyPan() {\n\n\t\t\tif ( scope.enableZoom ) handleTouchStartDolly();\n\n\t\t\tif ( scope.enablePan ) handleTouchStartPan();\n\n\t\t}\n\n\t\tfunction handleTouchStartDollyRotate() {\n\n\t\t\tif ( scope.enableZoom ) handleTouchStartDolly();\n\n\t\t\tif ( scope.enableRotate ) handleTouchStartRotate();\n\n\t\t}\n\n\t\tfunction handleTouchMoveRotate( event ) {\n\n\t\t\tif ( pointers.length == 1 ) {\n\n\t\t\t\trotateEnd.set( event.pageX, event.pageY );\n\n\t\t\t} else {\n\n\t\t\t\tconst position = getSecondPointerPosition( event );\n\n\t\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\t\trotateEnd.set( x, y );\n\n\t\t\t}\n\n\t\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\t\tconst element = scope.domElement;\n\n\t\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\t\trotateStart.copy( rotateEnd );\n\n\t\t}\n\n\t\tfunction handleTouchMovePan( event ) {\n\n\t\t\tif ( pointers.length === 1 ) {\n\n\t\t\t\tpanEnd.set( event.pageX, event.pageY );\n\n\t\t\t} else {\n\n\t\t\t\tconst position = getSecondPointerPosition( event );\n\n\t\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\t\tpanEnd.set( x, y );\n\n\t\t\t}\n\n\t\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\t\tpan( panDelta.x, panDelta.y );\n\n\t\t\tpanStart.copy( panEnd );\n\n\t\t}\n\n\t\tfunction handleTouchMoveDolly( event ) {\n\n\t\t\tconst position = getSecondPointerPosition( event );\n\n\t\t\tconst dx = event.pageX - position.x;\n\t\t\tconst dy = event.pageY - position.y;\n\n\t\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\tdollyEnd.set( 0, distance );\n\n\t\t\tdollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );\n\n\t\t\tdollyOut( dollyDelta.y );\n\n\t\t\tdollyStart.copy( dollyEnd );\n\n\t\t}\n\n\t\tfunction handleTouchMoveDollyPan( event ) {\n\n\t\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\t\tif ( scope.enablePan ) handleTouchMovePan( event );\n\n\t\t}\n\n\t\tfunction handleTouchMoveDollyRotate( event ) {\n\n\t\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\t\tif ( scope.enableRotate ) handleTouchMoveRotate( event );\n\n\t\t}\n\n\t\t//\n\t\t// event handlers - FSM: listen for events and reset state\n\t\t//\n\n\t\tfunction onPointerDown( event ) {\n\n\t\t\tif ( scope.enabled === false ) return;\n\n\t\t\tif ( pointers.length === 0 ) {\n\n\t\t\t\tscope.domElement.setPointerCapture( event.pointerId );\n\n\t\t\t\tscope.domElement.addEventListener( 'pointermove', onPointerMove );\n\t\t\t\tscope.domElement.addEventListener( 'pointerup', onPointerUp );\n\n\t\t\t}\n\n\t\t\t//\n\n\t\t\taddPointer( event );\n\n\t\t\tif ( event.pointerType === 'touch' ) {\n\n\t\t\t\tonTouchStart( event );\n\n\t\t\t} else {\n\n\t\t\t\tonMouseDown( event );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onPointerMove( event ) {\n\n\t\t\tif ( scope.enabled === false ) return;\n\n\t\t\tif ( event.pointerType === 'touch' ) {\n\n\t\t\t\tonTouchMove( event );\n\n\t\t\t} else {\n\n\t\t\t\tonMouseMove( event );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onPointerUp( event ) {\n\n\t\t removePointer( event );\n\n\t\t if ( pointers.length === 0 ) {\n\n\t\t scope.domElement.releasePointerCapture( event.pointerId );\n\n\t\t scope.domElement.removeEventListener( 'pointermove', onPointerMove );\n\t\t scope.domElement.removeEventListener( 'pointerup', onPointerUp );\n\n\t\t }\n\n\t\t scope.dispatchEvent( _endEvent );\n\n\t\t state = STATE.NONE;\n\n\t\t}\n\n\t\tfunction onPointerCancel( event ) {\n\n\t\t\tremovePointer( event );\n\n\t\t}\n\n\t\tfunction onMouseDown( event ) {\n\n\t\t\tlet mouseAction;\n\n\t\t\tswitch ( event.button ) {\n\n\t\t\t\tcase 0:\n\n\t\t\t\t\tmouseAction = scope.mouseButtons.LEFT;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1:\n\n\t\t\t\t\tmouseAction = scope.mouseButtons.MIDDLE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\n\t\t\t\t\tmouseAction = scope.mouseButtons.RIGHT;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tmouseAction = - 1;\n\n\t\t\t}\n\n\t\t\tswitch ( mouseAction ) {\n\n\t\t\t\tcase MOUSE.DOLLY:\n\n\t\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\t\thandleMouseDownDolly( event );\n\n\t\t\t\t\tstate = STATE.DOLLY;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MOUSE.ROTATE:\n\n\t\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MOUSE.PAN:\n\n\t\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t}\n\n\t\t\tif ( state !== STATE.NONE ) {\n\n\t\t\t\tscope.dispatchEvent( _startEvent );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onMouseMove( event ) {\n\n\t\t\tif ( scope.enabled === false ) return;\n\n\t\t\tswitch ( state ) {\n\n\t\t\t\tcase STATE.ROTATE:\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseMoveRotate( event );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STATE.DOLLY:\n\n\t\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\t\thandleMouseMoveDolly( event );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STATE.PAN:\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseMovePan( event );\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onMouseWheel( event ) {\n\n\t\t\tif ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;\n\n\t\t\tevent.preventDefault();\n\n\t\t\tscope.dispatchEvent( _startEvent );\n\n\t\t\thandleMouseWheel( event );\n\n\t\t\tscope.dispatchEvent( _endEvent );\n\n\t\t}\n\n\t\tfunction onKeyDown( event ) {\n\n\t\t\tif ( scope.enabled === false || scope.enablePan === false ) return;\n\n\t\t\thandleKeyDown( event );\n\n\t\t}\n\n\t\tfunction onTouchStart( event ) {\n\n\t\t\ttrackPointer( event );\n\n\t\t\tswitch ( pointers.length ) {\n\n\t\t\t\tcase 1:\n\n\t\t\t\t\tswitch ( scope.touches.ONE ) {\n\n\t\t\t\t\t\tcase TOUCH.ROTATE:\n\n\t\t\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\t\t\thandleTouchStartRotate();\n\n\t\t\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOUCH.PAN:\n\n\t\t\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\t\t\thandleTouchStartPan();\n\n\t\t\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\n\t\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2:\n\n\t\t\t\t\tswitch ( scope.touches.TWO ) {\n\n\t\t\t\t\t\tcase TOUCH.DOLLY_PAN:\n\n\t\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\t\t\t\thandleTouchStartDollyPan();\n\n\t\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TOUCH.DOLLY_ROTATE:\n\n\t\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\t\t\t\thandleTouchStartDollyRotate();\n\n\t\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_ROTATE;\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\n\t\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t}\n\n\t\t\tif ( state !== STATE.NONE ) {\n\n\t\t\t\tscope.dispatchEvent( _startEvent );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onTouchMove( event ) {\n\n\t\t\ttrackPointer( event );\n\n\t\t\tswitch ( state ) {\n\n\t\t\t\tcase STATE.TOUCH_ROTATE:\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleTouchMoveRotate( event );\n\n\t\t\t\t\tscope.update();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STATE.TOUCH_PAN:\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleTouchMovePan( event );\n\n\t\t\t\t\tscope.update();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STATE.TOUCH_DOLLY_PAN:\n\n\t\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\t\thandleTouchMoveDollyPan( event );\n\n\t\t\t\t\tscope.update();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STATE.TOUCH_DOLLY_ROTATE:\n\n\t\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleTouchMoveDollyRotate( event );\n\n\t\t\t\t\tscope.update();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction onContextMenu( event ) {\n\n\t\t\tif ( scope.enabled === false ) return;\n\n\t\t\tevent.preventDefault();\n\n\t\t}\n\n\t\tfunction addPointer( event ) {\n\n\t\t\tpointers.push( event );\n\n\t\t}\n\n\t\tfunction removePointer( event ) {\n\n\t\t\tdelete pointerPositions[ event.pointerId ];\n\n\t\t\tfor ( let i = 0; i < pointers.length; i ++ ) {\n\n\t\t\t\tif ( pointers[ i ].pointerId == event.pointerId ) {\n\n\t\t\t\t\tpointers.splice( i, 1 );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction trackPointer( event ) {\n\n\t\t\tlet position = pointerPositions[ event.pointerId ];\n\n\t\t\tif ( position === undefined ) {\n\n\t\t\t\tposition = new Vector2();\n\t\t\t\tpointerPositions[ event.pointerId ] = position;\n\n\t\t\t}\n\n\t\t\tposition.set( event.pageX, event.pageY );\n\n\t\t}\n\n\t\tfunction getSecondPointerPosition( event ) {\n\n\t\t\tconst pointer = ( event.pointerId === pointers[ 0 ].pointerId ) ? pointers[ 1 ] : pointers[ 0 ];\n\n\t\t\treturn pointerPositions[ pointer.pointerId ];\n\n\t\t}\n\n\t\t//\n\n\t\tscope.domElement.addEventListener( 'contextmenu', onContextMenu );\n\n\t\tscope.domElement.addEventListener( 'pointerdown', onPointerDown );\n\t\tscope.domElement.addEventListener( 'pointercancel', onPointerCancel );\n\t\tscope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );\n\n\t\t// force an update at start\n\n\t\tthis.update();\n\n\t}\n\n}\n\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n// This is very similar to OrbitControls, another set of touch behavior\n//\n// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - left mouse, or arrow keys / touch: one-finger move\n\nclass MapControls extends OrbitControls {\n\n\tconstructor( object, domElement ) {\n\n\t\tsuper( object, domElement );\n\n\t\tthis.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up\n\n\t\tthis.mouseButtons.LEFT = MOUSE.PAN;\n\t\tthis.mouseButtons.RIGHT = MOUSE.ROTATE;\n\n\t\tthis.touches.ONE = TOUCH.PAN;\n\t\tthis.touches.TWO = TOUCH.DOLLY_ROTATE;\n\n\t}\n\n}\n\nexport { OrbitControls, MapControls };\n","/**\n * lil-gui\n * https://lil-gui.georgealways.com\n * @version 0.16.1\n * @author George Michael Brower\n * @license MIT\n */\n\n/**\n * Base class for all controllers.\n */\nclass Controller {\n\n\tconstructor( parent, object, property, className, widgetTag = 'div' ) {\n\n\t\t/**\n\t\t * The GUI that contains this controller.\n\t\t * @type {GUI}\n\t\t */\n\t\tthis.parent = parent;\n\n\t\t/**\n\t\t * The object this controller will modify.\n\t\t * @type {object}\n\t\t */\n\t\tthis.object = object;\n\n\t\t/**\n\t\t * The name of the property to control.\n\t\t * @type {string}\n\t\t */\n\t\tthis.property = property;\n\n\t\t/**\n\t\t * Used to determine if the controller is disabled.\n\t\t * Use `controller.disable( true|false )` to modify this value\n\t\t * @type {boolean}\n\t\t */\n\t\tthis._disabled = false;\n\n\t\t/**\n\t\t * The value of `object[ property ]` when the controller was created.\n\t\t * @type {any}\n\t\t */\n\t\tthis.initialValue = this.getValue();\n\n\t\t/**\n\t\t * The outermost container DOM element for this controller.\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.domElement = document.createElement( 'div' );\n\t\tthis.domElement.classList.add( 'controller' );\n\t\tthis.domElement.classList.add( className );\n\n\t\t/**\n\t\t * The DOM element that contains the controller's name.\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.$name = document.createElement( 'div' );\n\t\tthis.$name.classList.add( 'name' );\n\n\t\tController.nextNameID = Controller.nextNameID || 0;\n\t\tthis.$name.id = `lil-gui-name-${++Controller.nextNameID}`;\n\n\t\t/**\n\t\t * The DOM element that contains the controller's \"widget\" (which differs by controller type).\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.$widget = document.createElement( widgetTag );\n\t\tthis.$widget.classList.add( 'widget' );\n\n\t\t/**\n\t\t * The DOM element that receives the disabled attribute when using disable()\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.$disable = this.$widget;\n\n\t\tthis.domElement.appendChild( this.$name );\n\t\tthis.domElement.appendChild( this.$widget );\n\n\t\tthis.parent.children.push( this );\n\t\tthis.parent.controllers.push( this );\n\n\t\tthis.parent.$children.appendChild( this.domElement );\n\n\t\tthis._listenCallback = this._listenCallback.bind( this );\n\n\t\tthis.name( property );\n\n\t}\n\n\t/**\n\t * Sets the name of the controller and its label in the GUI.\n\t * @param {string} name\n\t * @returns {this}\n\t */\n\tname( name ) {\n\t\t/**\n\t\t * The controller's name. Use `controller.name( 'Name' )` to modify this value.\n\t\t * @type {string}\n\t\t */\n\t\tthis._name = name;\n\t\tthis.$name.innerHTML = name;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Pass a function to be called whenever the value is modified by this controller.\n\t * The function receives the new value as its first parameter. The value of `this` will be the\n\t * controller.\n\t * @param {Function} callback\n\t * @returns {this}\n\t * @example\n\t * const controller = gui.add( object, 'property' );\n\t *\n\t * controller.onChange( function( v ) {\n\t * \tconsole.log( 'The value is now ' + v );\n\t * \tconsole.assert( this === controller );\n\t * } );\n\t */\n\tonChange( callback ) {\n\t\t/**\n\t\t * Used to access the function bound to `onChange` events. Don't modify this value directly.\n\t\t * Use the `controller.onChange( callback )` method instead.\n\t\t * @type {Function}\n\t\t */\n\t\tthis._onChange = callback;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Calls the onChange methods of this controller and its parent GUI.\n\t * @protected\n\t */\n\t_callOnChange() {\n\n\t\tthis.parent._callOnChange( this );\n\n\t\tif ( this._onChange !== undefined ) {\n\t\t\tthis._onChange.call( this, this.getValue() );\n\t\t}\n\n\t\tthis._changed = true;\n\n\t}\n\n\t/**\n\t * Pass a function to be called after this controller has been modified and loses focus.\n\t * @param {Function} callback\n\t * @returns {this}\n\t * @example\n\t * const controller = gui.add( object, 'property' );\n\t *\n\t * controller.onFinishChange( function( v ) {\n\t * \tconsole.log( 'Changes complete: ' + v );\n\t * \tconsole.assert( this === controller );\n\t * } );\n\t */\n\tonFinishChange( callback ) {\n\t\t/**\n\t\t * Used to access the function bound to `onFinishChange` events. Don't modify this value\n\t\t * directly. Use the `controller.onFinishChange( callback )` method instead.\n\t\t * @type {Function}\n\t\t */\n\t\tthis._onFinishChange = callback;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Should be called by Controller when its widgets lose focus.\n\t * @protected\n\t */\n\t_callOnFinishChange() {\n\n\t\tif ( this._changed ) {\n\n\t\t\tthis.parent._callOnFinishChange( this );\n\n\t\t\tif ( this._onFinishChange !== undefined ) {\n\t\t\t\tthis._onFinishChange.call( this, this.getValue() );\n\t\t\t}\n\n\t\t}\n\n\t\tthis._changed = false;\n\n\t}\n\n\t/**\n\t * Sets the controller back to its initial value.\n\t * @returns {this}\n\t */\n\treset() {\n\t\tthis.setValue( this.initialValue );\n\t\tthis._callOnFinishChange();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Enables this controller.\n\t * @param {boolean} enabled\n\t * @returns {this}\n\t * @example\n\t * controller.enable();\n\t * controller.enable( false ); // disable\n\t * controller.enable( controller._disabled ); // toggle\n\t */\n\tenable( enabled = true ) {\n\t\treturn this.disable( !enabled );\n\t}\n\n\t/**\n\t * Disables this controller.\n\t * @param {boolean} disabled\n\t * @returns {this}\n\t * @example\n\t * controller.disable();\n\t * controller.disable( false ); // enable\n\t * controller.disable( !controller._disabled ); // toggle\n\t */\n\tdisable( disabled = true ) {\n\n\t\tif ( disabled === this._disabled ) return this;\n\n\t\tthis._disabled = disabled;\n\n\t\tthis.domElement.classList.toggle( 'disabled', disabled );\n\t\tthis.$disable.toggleAttribute( 'disabled', disabled );\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Destroys this controller and replaces it with a new option controller. Provided as a more\n\t * descriptive syntax for `gui.add`, but primarily for compatibility with dat.gui.\n\t *\n\t * Use caution, as this method will destroy old references to this controller. It will also\n\t * change controller order if called out of sequence, moving the option controller to the end of\n\t * the GUI.\n\t * @example\n\t * // safe usage\n\t *\n\t * gui.add( object1, 'property' ).options( [ 'a', 'b', 'c' ] );\n\t * gui.add( object2, 'property' );\n\t *\n\t * // danger\n\t *\n\t * const c = gui.add( object1, 'property' );\n\t * gui.add( object2, 'property' );\n\t *\n\t * c.options( [ 'a', 'b', 'c' ] );\n\t * // controller is now at the end of the GUI even though it was added first\n\t *\n\t * assert( c.parent.children.indexOf( c ) === -1 )\n\t * // c references a controller that no longer exists\n\t *\n\t * @param {object|Array} options\n\t * @returns {Controller}\n\t */\n\toptions( options ) {\n\t\tconst controller = this.parent.add( this.object, this.property, options );\n\t\tcontroller.name( this._name );\n\t\tthis.destroy();\n\t\treturn controller;\n\t}\n\n\t/**\n\t * Sets the minimum value. Only works on number controllers.\n\t * @param {number} min\n\t * @returns {this}\n\t */\n\tmin( min ) {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the maximum value. Only works on number controllers.\n\t * @param {number} max\n\t * @returns {this}\n\t */\n\tmax( max ) {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the step. Only works on number controllers.\n\t * @param {number} step\n\t * @returns {this}\n\t */\n\tstep( step ) {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Calls `updateDisplay()` every animation frame. Pass `false` to stop listening.\n\t * @param {boolean} listen\n\t * @returns {this}\n\t */\n\tlisten( listen = true ) {\n\n\t\t/**\n\t\t * Used to determine if the controller is currently listening. Don't modify this value\n\t\t * directly. Use the `controller.listen( true|false )` method instead.\n\t\t * @type {boolean}\n\t\t */\n\t\tthis._listening = listen;\n\n\t\tif ( this._listenCallbackID !== undefined ) {\n\t\t\tcancelAnimationFrame( this._listenCallbackID );\n\t\t\tthis._listenCallbackID = undefined;\n\t\t}\n\n\t\tif ( this._listening ) {\n\t\t\tthis._listenCallback();\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t_listenCallback() {\n\n\t\tthis._listenCallbackID = requestAnimationFrame( this._listenCallback );\n\n\t\t// To prevent framerate loss, make sure the value has changed before updating the display.\n\t\t// Note: save() is used here instead of getValue() only because of ColorController. The !== operator\n\t\t// won't work for color objects or arrays, but ColorController.save() always returns a string.\n\n\t\tconst curValue = this.save();\n\n\t\tif ( curValue !== this._listenPrevValue ) {\n\t\t\tthis.updateDisplay();\n\t\t}\n\n\t\tthis._listenPrevValue = curValue;\n\n\t}\n\n\t/**\n\t * Returns `object[ property ]`.\n\t * @returns {any}\n\t */\n\tgetValue() {\n\t\treturn this.object[ this.property ];\n\t}\n\n\t/**\n\t * Sets the value of `object[ property ]`, invokes any `onChange` handlers and updates the display.\n\t * @param {any} value\n\t * @returns {this}\n\t */\n\tsetValue( value ) {\n\t\tthis.object[ this.property ] = value;\n\t\tthis._callOnChange();\n\t\tthis.updateDisplay();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Updates the display to keep it in sync with the current value. Useful for updating your\n\t * controllers when their values have been modified outside of the GUI.\n\t * @returns {this}\n\t */\n\tupdateDisplay() {\n\t\treturn this;\n\t}\n\n\tload( value ) {\n\t\tthis.setValue( value );\n\t\tthis._callOnFinishChange();\n\t\treturn this;\n\t}\n\n\tsave() {\n\t\treturn this.getValue();\n\t}\n\n\t/**\n\t * Destroys this controller and removes it from the parent GUI.\n\t */\n\tdestroy() {\n\t\tthis.listen( false );\n\t\tthis.parent.children.splice( this.parent.children.indexOf( this ), 1 );\n\t\tthis.parent.controllers.splice( this.parent.controllers.indexOf( this ), 1 );\n\t\tthis.parent.$children.removeChild( this.domElement );\n\t}\n\n}\n\nclass BooleanController extends Controller {\n\n\tconstructor( parent, object, property ) {\n\n\t\tsuper( parent, object, property, 'boolean', 'label' );\n\n\t\tthis.$input = document.createElement( 'input' );\n\t\tthis.$input.setAttribute( 'type', 'checkbox' );\n\t\tthis.$input.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$widget.appendChild( this.$input );\n\n\t\tthis.$input.addEventListener( 'change', () => {\n\t\t\tthis.setValue( this.$input.checked );\n\t\t\tthis._callOnFinishChange();\n\t\t} );\n\n\t\tthis.$disable = this.$input;\n\n\t\tthis.updateDisplay();\n\n\t}\n\n\tupdateDisplay() {\n\t\tthis.$input.checked = this.getValue();\n\t\treturn this;\n\t}\n\n}\n\nfunction normalizeColorString( string ) {\n\n\tlet match, result;\n\n\tif ( match = string.match( /(#|0x)?([a-f0-9]{6})/i ) ) {\n\n\t\tresult = match[ 2 ];\n\n\t} else if ( match = string.match( /rgb\\(\\s*(\\d*)\\s*,\\s*(\\d*)\\s*,\\s*(\\d*)\\s*\\)/ ) ) {\n\n\t\tresult = parseInt( match[ 1 ] ).toString( 16 ).padStart( 2, 0 )\n\t\t\t+ parseInt( match[ 2 ] ).toString( 16 ).padStart( 2, 0 )\n\t\t\t+ parseInt( match[ 3 ] ).toString( 16 ).padStart( 2, 0 );\n\n\t} else if ( match = string.match( /^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i ) ) {\n\n\t\tresult = match[ 1 ] + match[ 1 ] + match[ 2 ] + match[ 2 ] + match[ 3 ] + match[ 3 ];\n\n\t}\n\n\tif ( result ) {\n\t\treturn '#' + result;\n\t}\n\n\treturn false;\n\n}\n\nconst STRING = {\n\tisPrimitive: true,\n\tmatch: v => typeof v === 'string',\n\tfromHexString: normalizeColorString,\n\ttoHexString: normalizeColorString\n};\n\nconst INT = {\n\tisPrimitive: true,\n\tmatch: v => typeof v === 'number',\n\tfromHexString: string => parseInt( string.substring( 1 ), 16 ),\n\ttoHexString: value => '#' + value.toString( 16 ).padStart( 6, 0 )\n};\n\nconst ARRAY = {\n\tisPrimitive: false,\n\tmatch: Array.isArray,\n\tfromHexString( string, target, rgbScale = 1 ) {\n\n\t\tconst int = INT.fromHexString( string );\n\n\t\ttarget[ 0 ] = ( int >> 16 & 255 ) / 255 * rgbScale;\n\t\ttarget[ 1 ] = ( int >> 8 & 255 ) / 255 * rgbScale;\n\t\ttarget[ 2 ] = ( int & 255 ) / 255 * rgbScale;\n\n\t},\n\ttoHexString( [ r, g, b ], rgbScale = 1 ) {\n\n\t\trgbScale = 255 / rgbScale;\n\n\t\tconst int = ( r * rgbScale ) << 16 ^\n\t\t\t( g * rgbScale ) << 8 ^\n\t\t\t( b * rgbScale ) << 0;\n\n\t\treturn INT.toHexString( int );\n\n\t}\n};\n\nconst OBJECT = {\n\tisPrimitive: false,\n\tmatch: v => Object( v ) === v,\n\tfromHexString( string, target, rgbScale = 1 ) {\n\n\t\tconst int = INT.fromHexString( string );\n\n\t\ttarget.r = ( int >> 16 & 255 ) / 255 * rgbScale;\n\t\ttarget.g = ( int >> 8 & 255 ) / 255 * rgbScale;\n\t\ttarget.b = ( int & 255 ) / 255 * rgbScale;\n\n\t},\n\ttoHexString( { r, g, b }, rgbScale = 1 ) {\n\n\t\trgbScale = 255 / rgbScale;\n\n\t\tconst int = ( r * rgbScale ) << 16 ^\n\t\t\t( g * rgbScale ) << 8 ^\n\t\t\t( b * rgbScale ) << 0;\n\n\t\treturn INT.toHexString( int );\n\n\t}\n};\n\nconst FORMATS = [ STRING, INT, ARRAY, OBJECT ];\n\nfunction getColorFormat( value ) {\n\treturn FORMATS.find( format => format.match( value ) );\n}\n\nclass ColorController extends Controller {\n\n\tconstructor( parent, object, property, rgbScale ) {\n\n\t\tsuper( parent, object, property, 'color' );\n\n\t\tthis.$input = document.createElement( 'input' );\n\t\tthis.$input.setAttribute( 'type', 'color' );\n\t\tthis.$input.setAttribute( 'tabindex', -1 );\n\t\tthis.$input.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$text = document.createElement( 'input' );\n\t\tthis.$text.setAttribute( 'type', 'text' );\n\t\tthis.$text.setAttribute( 'spellcheck', 'false' );\n\t\tthis.$text.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$display = document.createElement( 'div' );\n\t\tthis.$display.classList.add( 'display' );\n\n\t\tthis.$display.appendChild( this.$input );\n\t\tthis.$widget.appendChild( this.$display );\n\t\tthis.$widget.appendChild( this.$text );\n\n\t\tthis._format = getColorFormat( this.initialValue );\n\t\tthis._rgbScale = rgbScale;\n\n\t\tthis._initialValueHexString = this.save();\n\t\tthis._textFocused = false;\n\n\t\tthis.$input.addEventListener( 'input', () => {\n\t\t\tthis._setValueFromHexString( this.$input.value );\n\t\t} );\n\n\t\tthis.$input.addEventListener( 'blur', () => {\n\t\t\tthis._callOnFinishChange();\n\t\t} );\n\n\t\tthis.$text.addEventListener( 'input', () => {\n\t\t\tconst tryParse = normalizeColorString( this.$text.value );\n\t\t\tif ( tryParse ) {\n\t\t\t\tthis._setValueFromHexString( tryParse );\n\t\t\t}\n\t\t} );\n\n\t\tthis.$text.addEventListener( 'focus', () => {\n\t\t\tthis._textFocused = true;\n\t\t\tthis.$text.select();\n\t\t} );\n\n\t\tthis.$text.addEventListener( 'blur', () => {\n\t\t\tthis._textFocused = false;\n\t\t\tthis.updateDisplay();\n\t\t\tthis._callOnFinishChange();\n\t\t} );\n\n\t\tthis.$disable = this.$text;\n\n\t\tthis.updateDisplay();\n\n\t}\n\n\treset() {\n\t\tthis._setValueFromHexString( this._initialValueHexString );\n\t\treturn this;\n\t}\n\n\t_setValueFromHexString( value ) {\n\n\t\tif ( this._format.isPrimitive ) {\n\n\t\t\tconst newValue = this._format.fromHexString( value );\n\t\t\tthis.setValue( newValue );\n\n\t\t} else {\n\n\t\t\tthis._format.fromHexString( value, this.getValue(), this._rgbScale );\n\t\t\tthis._callOnChange();\n\t\t\tthis.updateDisplay();\n\n\t\t}\n\n\t}\n\n\tsave() {\n\t\treturn this._format.toHexString( this.getValue(), this._rgbScale );\n\t}\n\n\tload( value ) {\n\t\tthis._setValueFromHexString( value );\n\t\tthis._callOnFinishChange();\n\t\treturn this;\n\t}\n\n\tupdateDisplay() {\n\t\tthis.$input.value = this._format.toHexString( this.getValue(), this._rgbScale );\n\t\tif ( !this._textFocused ) {\n\t\t\tthis.$text.value = this.$input.value.substring( 1 );\n\t\t}\n\t\tthis.$display.style.backgroundColor = this.$input.value;\n\t\treturn this;\n\t}\n\n}\n\nclass FunctionController extends Controller {\n\n\tconstructor( parent, object, property ) {\n\n\t\tsuper( parent, object, property, 'function' );\n\n\t\t// Buttons are the only case where widget contains name\n\t\tthis.$button = document.createElement( 'button' );\n\t\tthis.$button.appendChild( this.$name );\n\t\tthis.$widget.appendChild( this.$button );\n\n\t\tthis.$button.addEventListener( 'click', e => {\n\t\t\te.preventDefault();\n\t\t\tthis.getValue().call( this.object );\n\t\t} );\n\n\t\t// enables :active pseudo class on mobile\n\t\tthis.$button.addEventListener( 'touchstart', () => {}, { passive: true } );\n\n\t\tthis.$disable = this.$button;\n\n\t}\n\n}\n\nclass NumberController extends Controller {\n\n\tconstructor( parent, object, property, min, max, step ) {\n\n\t\tsuper( parent, object, property, 'number' );\n\n\t\tthis._initInput();\n\n\t\tthis.min( min );\n\t\tthis.max( max );\n\n\t\tconst stepExplicit = step !== undefined;\n\t\tthis.step( stepExplicit ? step : this._getImplicitStep(), stepExplicit );\n\n\t\tthis.updateDisplay();\n\n\t}\n\n\tmin( min ) {\n\t\tthis._min = min;\n\t\tthis._onUpdateMinMax();\n\t\treturn this;\n\t}\n\n\tmax( max ) {\n\t\tthis._max = max;\n\t\tthis._onUpdateMinMax();\n\t\treturn this;\n\t}\n\n\tstep( step, explicit = true ) {\n\t\tthis._step = step;\n\t\tthis._stepExplicit = explicit;\n\t\treturn this;\n\t}\n\n\tupdateDisplay() {\n\n\t\tconst value = this.getValue();\n\n\t\tif ( this._hasSlider ) {\n\n\t\t\tlet percent = ( value - this._min ) / ( this._max - this._min );\n\t\t\tpercent = Math.max( 0, Math.min( percent, 1 ) );\n\n\t\t\tthis.$fill.style.width = percent * 100 + '%';\n\n\t\t}\n\n\t\tif ( !this._inputFocused ) {\n\t\t\tthis.$input.value = value;\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t_initInput() {\n\n\t\tthis.$input = document.createElement( 'input' );\n\t\tthis.$input.setAttribute( 'type', 'number' );\n\t\tthis.$input.setAttribute( 'step', 'any' );\n\t\tthis.$input.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$widget.appendChild( this.$input );\n\n\t\tthis.$disable = this.$input;\n\n\t\tconst onInput = () => {\n\n\t\t\tconst value = parseFloat( this.$input.value );\n\n\t\t\tif ( isNaN( value ) ) return;\n\n\t\t\tthis.setValue( this._clamp( value ) );\n\n\t\t};\n\n\t\t// Keys & mouse wheel\n\t\t// ---------------------------------------------------------------------\n\n\t\tconst increment = delta => {\n\n\t\t\tconst value = parseFloat( this.$input.value );\n\n\t\t\tif ( isNaN( value ) ) return;\n\n\t\t\tthis._snapClampSetValue( value + delta );\n\n\t\t\t// Force the input to updateDisplay when it's focused\n\t\t\tthis.$input.value = this.getValue();\n\n\t\t};\n\n\t\tconst onKeyDown = e => {\n\t\t\tif ( e.code === 'Enter' ) {\n\t\t\t\tthis.$input.blur();\n\t\t\t}\n\t\t\tif ( e.code === 'ArrowUp' ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tincrement( this._step * this._arrowKeyMultiplier( e ) );\n\t\t\t}\n\t\t\tif ( e.code === 'ArrowDown' ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tincrement( this._step * this._arrowKeyMultiplier( e ) * -1 );\n\t\t\t}\n\t\t};\n\n\t\tconst onWheel = e => {\n\t\t\tif ( this._inputFocused ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tincrement( this._step * this._normalizeMouseWheel( e ) );\n\t\t\t}\n\t\t};\n\n\t\t// Vertical drag\n\t\t// ---------------------------------------------------------------------\n\n\t\tlet testingForVerticalDrag = false,\n\t\t\tinitClientX,\n\t\t\tinitClientY,\n\t\t\tprevClientY,\n\t\t\tinitValue,\n\t\t\tdragDelta;\n\n\t\t// Once the mouse is dragged more than DRAG_THRESH px on any axis, we decide\n\t\t// on the user's intent: horizontal means highlight, vertical means drag.\n\t\tconst DRAG_THRESH = 5;\n\n\t\tconst onMouseDown = e => {\n\n\t\t\tinitClientX = e.clientX;\n\t\t\tinitClientY = prevClientY = e.clientY;\n\t\t\ttestingForVerticalDrag = true;\n\n\t\t\tinitValue = this.getValue();\n\t\t\tdragDelta = 0;\n\n\t\t\twindow.addEventListener( 'mousemove', onMouseMove );\n\t\t\twindow.addEventListener( 'mouseup', onMouseUp );\n\n\t\t};\n\n\t\tconst onMouseMove = e => {\n\n\t\t\tif ( testingForVerticalDrag ) {\n\n\t\t\t\tconst dx = e.clientX - initClientX;\n\t\t\t\tconst dy = e.clientY - initClientY;\n\n\t\t\t\tif ( Math.abs( dy ) > DRAG_THRESH ) {\n\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.$input.blur();\n\t\t\t\t\ttestingForVerticalDrag = false;\n\t\t\t\t\tthis._setDraggingStyle( true, 'vertical' );\n\n\t\t\t\t} else if ( Math.abs( dx ) > DRAG_THRESH ) {\n\n\t\t\t\t\tonMouseUp();\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// This isn't an else so that the first move counts towards dragDelta\n\t\t\tif ( !testingForVerticalDrag ) {\n\n\t\t\t\tconst dy = e.clientY - prevClientY;\n\n\t\t\t\tdragDelta -= dy * this._step * this._arrowKeyMultiplier( e );\n\n\t\t\t\t// Clamp dragDelta so we don't have 'dead space' after dragging past bounds.\n\t\t\t\t// We're okay with the fact that bounds can be undefined here.\n\t\t\t\tif ( initValue + dragDelta > this._max ) {\n\t\t\t\t\tdragDelta = this._max - initValue;\n\t\t\t\t} else if ( initValue + dragDelta < this._min ) {\n\t\t\t\t\tdragDelta = this._min - initValue;\n\t\t\t\t}\n\n\t\t\t\tthis._snapClampSetValue( initValue + dragDelta );\n\n\t\t\t}\n\n\t\t\tprevClientY = e.clientY;\n\n\t\t};\n\n\t\tconst onMouseUp = () => {\n\t\t\tthis._setDraggingStyle( false, 'vertical' );\n\t\t\tthis._callOnFinishChange();\n\t\t\twindow.removeEventListener( 'mousemove', onMouseMove );\n\t\t\twindow.removeEventListener( 'mouseup', onMouseUp );\n\t\t};\n\n\t\t// Focus state & onFinishChange\n\t\t// ---------------------------------------------------------------------\n\n\t\tconst onFocus = () => {\n\t\t\tthis._inputFocused = true;\n\t\t};\n\n\t\tconst onBlur = () => {\n\t\t\tthis._inputFocused = false;\n\t\t\tthis.updateDisplay();\n\t\t\tthis._callOnFinishChange();\n\t\t};\n\n\t\tthis.$input.addEventListener( 'input', onInput );\n\t\tthis.$input.addEventListener( 'keydown', onKeyDown );\n\t\tthis.$input.addEventListener( 'wheel', onWheel, { passive: false } );\n\t\tthis.$input.addEventListener( 'mousedown', onMouseDown );\n\t\tthis.$input.addEventListener( 'focus', onFocus );\n\t\tthis.$input.addEventListener( 'blur', onBlur );\n\n\t}\n\n\t_initSlider() {\n\n\t\tthis._hasSlider = true;\n\n\t\t// Build DOM\n\t\t// ---------------------------------------------------------------------\n\n\t\tthis.$slider = document.createElement( 'div' );\n\t\tthis.$slider.classList.add( 'slider' );\n\n\t\tthis.$fill = document.createElement( 'div' );\n\t\tthis.$fill.classList.add( 'fill' );\n\n\t\tthis.$slider.appendChild( this.$fill );\n\t\tthis.$widget.insertBefore( this.$slider, this.$input );\n\n\t\tthis.domElement.classList.add( 'hasSlider' );\n\n\t\t// Map clientX to value\n\t\t// ---------------------------------------------------------------------\n\n\t\tconst map = ( v, a, b, c, d ) => {\n\t\t\treturn ( v - a ) / ( b - a ) * ( d - c ) + c;\n\t\t};\n\n\t\tconst setValueFromX = clientX => {\n\t\t\tconst rect = this.$slider.getBoundingClientRect();\n\t\t\tlet value = map( clientX, rect.left, rect.right, this._min, this._max );\n\t\t\tthis._snapClampSetValue( value );\n\t\t};\n\n\t\t// Mouse drag\n\t\t// ---------------------------------------------------------------------\n\n\t\tconst mouseDown = e => {\n\t\t\tthis._setDraggingStyle( true );\n\t\t\tsetValueFromX( e.clientX );\n\t\t\twindow.addEventListener( 'mousemove', mouseMove );\n\t\t\twindow.addEventListener( 'mouseup', mouseUp );\n\t\t};\n\n\t\tconst mouseMove = e => {\n\t\t\tsetValueFromX( e.clientX );\n\t\t};\n\n\t\tconst mouseUp = () => {\n\t\t\tthis._callOnFinishChange();\n\t\t\tthis._setDraggingStyle( false );\n\t\t\twindow.removeEventListener( 'mousemove', mouseMove );\n\t\t\twindow.removeEventListener( 'mouseup', mouseUp );\n\t\t};\n\n\t\t// Touch drag\n\t\t// ---------------------------------------------------------------------\n\n\t\tlet testingForScroll = false, prevClientX, prevClientY;\n\n\t\tconst beginTouchDrag = e => {\n\t\t\te.preventDefault();\n\t\t\tthis._setDraggingStyle( true );\n\t\t\tsetValueFromX( e.touches[ 0 ].clientX );\n\t\t\ttestingForScroll = false;\n\t\t};\n\n\t\tconst onTouchStart = e => {\n\n\t\t\tif ( e.touches.length > 1 ) return;\n\n\t\t\t// If we're in a scrollable container, we should wait for the first\n\t\t\t// touchmove to see if the user is trying to slide or scroll.\n\t\t\tif ( this._hasScrollBar ) {\n\n\t\t\t\tprevClientX = e.touches[ 0 ].clientX;\n\t\t\t\tprevClientY = e.touches[ 0 ].clientY;\n\t\t\t\ttestingForScroll = true;\n\n\t\t\t} else {\n\n\t\t\t\t// Otherwise, we can set the value straight away on touchstart.\n\t\t\t\tbeginTouchDrag( e );\n\n\t\t\t}\n\n\t\t\twindow.addEventListener( 'touchmove', onTouchMove );\n\t\t\twindow.addEventListener( 'touchend', onTouchEnd );\n\n\t\t};\n\n\t\tconst onTouchMove = e => {\n\n\t\t\tif ( testingForScroll ) {\n\n\t\t\t\tconst dx = e.touches[ 0 ].clientX - prevClientX;\n\t\t\t\tconst dy = e.touches[ 0 ].clientY - prevClientY;\n\n\t\t\t\tif ( Math.abs( dx ) > Math.abs( dy ) ) {\n\n\t\t\t\t\t// We moved horizontally, set the value and stop checking.\n\t\t\t\t\tbeginTouchDrag( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// This was, in fact, an attempt to scroll. Abort.\n\t\t\t\t\twindow.removeEventListener( 'touchmove', onTouchMove );\n\t\t\t\t\twindow.removeEventListener( 'touchend', onTouchEnd );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\te.preventDefault();\n\t\t\t\tsetValueFromX( e.touches[ 0 ].clientX );\n\n\t\t\t}\n\n\t\t};\n\n\t\tconst onTouchEnd = () => {\n\t\t\tthis._callOnFinishChange();\n\t\t\tthis._setDraggingStyle( false );\n\t\t\twindow.removeEventListener( 'touchmove', onTouchMove );\n\t\t\twindow.removeEventListener( 'touchend', onTouchEnd );\n\t\t};\n\n\t\t// Mouse wheel\n\t\t// ---------------------------------------------------------------------\n\n\t\t// We have to use a debounced function to call onFinishChange because\n\t\t// there's no way to tell when the user is \"done\" mouse-wheeling.\n\t\tconst callOnFinishChange = this._callOnFinishChange.bind( this );\n\t\tconst WHEEL_DEBOUNCE_TIME = 400;\n\t\tlet wheelFinishChangeTimeout;\n\n\t\tconst onWheel = e => {\n\n\t\t\t// ignore vertical wheels if there's a scrollbar\n\t\t\tconst isVertical = Math.abs( e.deltaX ) < Math.abs( e.deltaY );\n\t\t\tif ( isVertical && this._hasScrollBar ) return;\n\n\t\t\te.preventDefault();\n\n\t\t\t// set value\n\t\t\tconst delta = this._normalizeMouseWheel( e ) * this._step;\n\t\t\tthis._snapClampSetValue( this.getValue() + delta );\n\n\t\t\t// force the input to updateDisplay when it's focused\n\t\t\tthis.$input.value = this.getValue();\n\n\t\t\t// debounce onFinishChange\n\t\t\tclearTimeout( wheelFinishChangeTimeout );\n\t\t\twheelFinishChangeTimeout = setTimeout( callOnFinishChange, WHEEL_DEBOUNCE_TIME );\n\n\t\t};\n\n\t\tthis.$slider.addEventListener( 'mousedown', mouseDown );\n\t\tthis.$slider.addEventListener( 'touchstart', onTouchStart, { passive: false } );\n\t\tthis.$slider.addEventListener( 'wheel', onWheel, { passive: false } );\n\n\t}\n\n\t_setDraggingStyle( active, axis = 'horizontal' ) {\n\t\tif ( this.$slider ) {\n\t\t\tthis.$slider.classList.toggle( 'active', active );\n\t\t}\n\t\tdocument.body.classList.toggle( 'lil-gui-dragging', active );\n\t\tdocument.body.classList.toggle( `lil-gui-${axis}`, active );\n\t}\n\n\t_getImplicitStep() {\n\n\t\tif ( this._hasMin && this._hasMax ) {\n\t\t\treturn ( this._max - this._min ) / 1000;\n\t\t}\n\n\t\treturn 0.1;\n\n\t}\n\n\t_onUpdateMinMax() {\n\n\t\tif ( !this._hasSlider && this._hasMin && this._hasMax ) {\n\n\t\t\t// If this is the first time we're hearing about min and max\n\t\t\t// and we haven't explicitly stated what our step is, let's\n\t\t\t// update that too.\n\t\t\tif ( !this._stepExplicit ) {\n\t\t\t\tthis.step( this._getImplicitStep(), false );\n\t\t\t}\n\n\t\t\tthis._initSlider();\n\t\t\tthis.updateDisplay();\n\n\t\t}\n\n\t}\n\n\t_normalizeMouseWheel( e ) {\n\n\t\tlet { deltaX, deltaY } = e;\n\n\t\t// Safari and Chrome report weird non-integral values for a notched wheel,\n\t\t// but still expose actual lines scrolled via wheelDelta. Notched wheels\n\t\t// should behave the same way as arrow keys.\n\t\tif ( Math.floor( e.deltaY ) !== e.deltaY && e.wheelDelta ) {\n\t\t\tdeltaX = 0;\n\t\t\tdeltaY = -e.wheelDelta / 120;\n\t\t\tdeltaY *= this._stepExplicit ? 1 : 10;\n\t\t}\n\n\t\tconst wheel = deltaX + -deltaY;\n\n\t\treturn wheel;\n\n\t}\n\n\t_arrowKeyMultiplier( e ) {\n\n\t\tlet mult = this._stepExplicit ? 1 : 10;\n\n\t\tif ( e.shiftKey ) {\n\t\t\tmult *= 10;\n\t\t} else if ( e.altKey ) {\n\t\t\tmult /= 10;\n\t\t}\n\n\t\treturn mult;\n\n\t}\n\n\t_snap( value ) {\n\n\t\t// This would be the logical way to do things, but floating point errors.\n\t\t// return Math.round( value / this._step ) * this._step;\n\n\t\t// Using inverse step solves a lot of them, but not all\n\t\t// const inverseStep = 1 / this._step;\n\t\t// return Math.round( value * inverseStep ) / inverseStep;\n\n\t\t// Not happy about this, but haven't seen it break.\n\t\tconst r = Math.round( value / this._step ) * this._step;\n\t\treturn parseFloat( r.toPrecision( 15 ) );\n\n\t}\n\n\t_clamp( value ) {\n\t\t// either condition is false if min or max is undefined\n\t\tif ( value < this._min ) value = this._min;\n\t\tif ( value > this._max ) value = this._max;\n\t\treturn value;\n\t}\n\n\t_snapClampSetValue( value ) {\n\t\tthis.setValue( this._clamp( this._snap( value ) ) );\n\t}\n\n\tget _hasScrollBar() {\n\t\tconst root = this.parent.root.$children;\n\t\treturn root.scrollHeight > root.clientHeight;\n\t}\n\n\tget _hasMin() {\n\t\treturn this._min !== undefined;\n\t}\n\n\tget _hasMax() {\n\t\treturn this._max !== undefined;\n\t}\n\n}\n\nclass OptionController extends Controller {\n\n\tconstructor( parent, object, property, options ) {\n\n\t\tsuper( parent, object, property, 'option' );\n\n\t\tthis.$select = document.createElement( 'select' );\n\t\tthis.$select.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$display = document.createElement( 'div' );\n\t\tthis.$display.classList.add( 'display' );\n\n\t\tthis._values = Array.isArray( options ) ? options : Object.values( options );\n\t\tthis._names = Array.isArray( options ) ? options : Object.keys( options );\n\n\t\tthis._names.forEach( name => {\n\t\t\tconst $option = document.createElement( 'option' );\n\t\t\t$option.innerHTML = name;\n\t\t\tthis.$select.appendChild( $option );\n\t\t} );\n\n\t\tthis.$select.addEventListener( 'change', () => {\n\t\t\tthis.setValue( this._values[ this.$select.selectedIndex ] );\n\t\t\tthis._callOnFinishChange();\n\t\t} );\n\n\t\tthis.$select.addEventListener( 'focus', () => {\n\t\t\tthis.$display.classList.add( 'focus' );\n\t\t} );\n\n\t\tthis.$select.addEventListener( 'blur', () => {\n\t\t\tthis.$display.classList.remove( 'focus' );\n\t\t} );\n\n\t\tthis.$widget.appendChild( this.$select );\n\t\tthis.$widget.appendChild( this.$display );\n\n\t\tthis.$disable = this.$select;\n\n\t\tthis.updateDisplay();\n\n\t}\n\n\tupdateDisplay() {\n\t\tconst value = this.getValue();\n\t\tconst index = this._values.indexOf( value );\n\t\tthis.$select.selectedIndex = index;\n\t\tthis.$display.innerHTML = index === -1 ? value : this._names[ index ];\n\t\treturn this;\n\t}\n\n}\n\nclass StringController extends Controller {\n\n\tconstructor( parent, object, property ) {\n\n\t\tsuper( parent, object, property, 'string' );\n\n\t\tthis.$input = document.createElement( 'input' );\n\t\tthis.$input.setAttribute( 'type', 'text' );\n\t\tthis.$input.setAttribute( 'aria-labelledby', this.$name.id );\n\n\t\tthis.$input.addEventListener( 'input', () => {\n\t\t\tthis.setValue( this.$input.value );\n\t\t} );\n\n\t\tthis.$input.addEventListener( 'keydown', e => {\n\t\t\tif ( e.code === 'Enter' ) {\n\t\t\t\tthis.$input.blur();\n\t\t\t}\n\t\t} );\n\n\t\tthis.$input.addEventListener( 'blur', () => {\n\t\t\tthis._callOnFinishChange();\n\t\t} );\n\n\t\tthis.$widget.appendChild( this.$input );\n\n\t\tthis.$disable = this.$input;\n\n\t\tthis.updateDisplay();\n\n\t}\n\n\tupdateDisplay() {\n\t\tthis.$input.value = this.getValue();\n\t\treturn this;\n\t}\n\n}\n\nconst stylesheet = `.lil-gui {\n font-family: var(--font-family);\n font-size: var(--font-size);\n line-height: 1;\n font-weight: normal;\n font-style: normal;\n text-align: left;\n background-color: var(--background-color);\n color: var(--text-color);\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n --background-color: #1f1f1f;\n --text-color: #ebebeb;\n --title-background-color: #111111;\n --title-text-color: #ebebeb;\n --widget-color: #424242;\n --hover-color: #4f4f4f;\n --focus-color: #595959;\n --number-color: #2cc9ff;\n --string-color: #a2db3c;\n --font-size: 11px;\n --input-font-size: 11px;\n --font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Arial, sans-serif;\n --font-family-mono: Menlo, Monaco, Consolas, \"Droid Sans Mono\", monospace;\n --padding: 4px;\n --spacing: 4px;\n --widget-height: 20px;\n --name-width: 45%;\n --slider-knob-width: 2px;\n --slider-input-width: 27%;\n --color-input-width: 27%;\n --slider-input-min-width: 45px;\n --color-input-min-width: 45px;\n --folder-indent: 7px;\n --widget-padding: 0 0 0 3px;\n --widget-border-radius: 2px;\n --checkbox-size: calc(0.75 * var(--widget-height));\n --scrollbar-width: 5px;\n}\n.lil-gui, .lil-gui * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n.lil-gui.root {\n width: var(--width, 245px);\n display: flex;\n flex-direction: column;\n}\n.lil-gui.root > .title {\n background: var(--title-background-color);\n color: var(--title-text-color);\n}\n.lil-gui.root > .children {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.lil-gui.root > .children::-webkit-scrollbar {\n width: var(--scrollbar-width);\n height: var(--scrollbar-width);\n background: var(--background-color);\n}\n.lil-gui.root > .children::-webkit-scrollbar-thumb {\n border-radius: var(--scrollbar-width);\n background: var(--focus-color);\n}\n@media (pointer: coarse) {\n .lil-gui.allow-touch-styles {\n --widget-height: 28px;\n --padding: 6px;\n --spacing: 6px;\n --font-size: 13px;\n --input-font-size: 16px;\n --folder-indent: 10px;\n --scrollbar-width: 7px;\n --slider-input-min-width: 50px;\n --color-input-min-width: 65px;\n }\n}\n.lil-gui.force-touch-styles {\n --widget-height: 28px;\n --padding: 6px;\n --spacing: 6px;\n --font-size: 13px;\n --input-font-size: 16px;\n --folder-indent: 10px;\n --scrollbar-width: 7px;\n --slider-input-min-width: 50px;\n --color-input-min-width: 65px;\n}\n.lil-gui.autoPlace {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 1001;\n}\n\n.lil-gui .controller {\n display: flex;\n align-items: center;\n padding: 0 var(--padding);\n margin: var(--spacing) 0;\n}\n.lil-gui .controller.disabled {\n opacity: 0.5;\n}\n.lil-gui .controller.disabled, .lil-gui .controller.disabled * {\n pointer-events: none !important;\n}\n.lil-gui .controller > .name {\n min-width: var(--name-width);\n flex-shrink: 0;\n white-space: pre;\n padding-right: var(--spacing);\n line-height: var(--widget-height);\n}\n.lil-gui .controller .widget {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-height: var(--widget-height);\n}\n.lil-gui .controller.string input {\n color: var(--string-color);\n}\n.lil-gui .controller.boolean .widget {\n cursor: pointer;\n}\n.lil-gui .controller.color .display {\n width: 100%;\n height: var(--widget-height);\n border-radius: var(--widget-border-radius);\n position: relative;\n}\n@media (hover: hover) {\n .lil-gui .controller.color .display:hover:before {\n content: \" \";\n display: block;\n position: absolute;\n border-radius: var(--widget-border-radius);\n border: 1px solid #fff9;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n.lil-gui .controller.color input[type=color] {\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n}\n.lil-gui .controller.color input[type=text] {\n margin-left: var(--spacing);\n font-family: var(--font-family-mono);\n min-width: var(--color-input-min-width);\n width: var(--color-input-width);\n flex-shrink: 0;\n}\n.lil-gui .controller.option select {\n opacity: 0;\n position: absolute;\n width: 100%;\n max-width: 100%;\n}\n.lil-gui .controller.option .display {\n position: relative;\n pointer-events: none;\n border-radius: var(--widget-border-radius);\n height: var(--widget-height);\n line-height: var(--widget-height);\n max-width: 100%;\n overflow: hidden;\n word-break: break-all;\n padding-left: 0.55em;\n padding-right: 1.75em;\n background: var(--widget-color);\n}\n@media (hover: hover) {\n .lil-gui .controller.option .display.focus {\n background: var(--focus-color);\n }\n}\n.lil-gui .controller.option .display.active {\n background: var(--focus-color);\n}\n.lil-gui .controller.option .display:after {\n font-family: \"lil-gui\";\n content: \"↕\";\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n padding-right: 0.375em;\n}\n.lil-gui .controller.option .widget,\n.lil-gui .controller.option select {\n cursor: pointer;\n}\n@media (hover: hover) {\n .lil-gui .controller.option .widget:hover .display {\n background: var(--hover-color);\n }\n}\n.lil-gui .controller.number input {\n color: var(--number-color);\n}\n.lil-gui .controller.number.hasSlider input {\n margin-left: var(--spacing);\n width: var(--slider-input-width);\n min-width: var(--slider-input-min-width);\n flex-shrink: 0;\n}\n.lil-gui .controller.number .slider {\n width: 100%;\n height: var(--widget-height);\n background-color: var(--widget-color);\n border-radius: var(--widget-border-radius);\n padding-right: var(--slider-knob-width);\n overflow: hidden;\n cursor: ew-resize;\n touch-action: pan-y;\n}\n@media (hover: hover) {\n .lil-gui .controller.number .slider:hover {\n background-color: var(--hover-color);\n }\n}\n.lil-gui .controller.number .slider.active {\n background-color: var(--focus-color);\n}\n.lil-gui .controller.number .slider.active .fill {\n opacity: 0.95;\n}\n.lil-gui .controller.number .fill {\n height: 100%;\n border-right: var(--slider-knob-width) solid var(--number-color);\n box-sizing: content-box;\n}\n\n.lil-gui-dragging .lil-gui {\n --hover-color: var(--widget-color);\n}\n.lil-gui-dragging * {\n cursor: ew-resize !important;\n}\n\n.lil-gui-dragging.lil-gui-vertical * {\n cursor: ns-resize !important;\n}\n\n.lil-gui .title {\n --title-height: calc(var(--widget-height) + var(--spacing) * 1.25);\n height: var(--title-height);\n line-height: calc(var(--title-height) - 4px);\n font-weight: 600;\n padding: 0 var(--padding);\n -webkit-tap-highlight-color: transparent;\n cursor: pointer;\n outline: none;\n text-decoration-skip: objects;\n}\n.lil-gui .title:before {\n font-family: \"lil-gui\";\n content: \"▾\";\n padding-right: 2px;\n display: inline-block;\n}\n.lil-gui .title:active {\n background: var(--title-background-color);\n opacity: 0.75;\n}\n@media (hover: hover) {\n body:not(.lil-gui-dragging) .lil-gui .title:hover {\n background: var(--title-background-color);\n opacity: 0.85;\n }\n .lil-gui .title:focus {\n text-decoration: underline var(--focus-color);\n }\n}\n.lil-gui.root > .title:focus {\n text-decoration: none !important;\n}\n.lil-gui.closed > .title:before {\n content: \"▸\";\n}\n.lil-gui.closed > .children {\n transform: translateY(-7px);\n opacity: 0;\n}\n.lil-gui.closed:not(.transition) > .children {\n display: none;\n}\n.lil-gui.transition > .children {\n transition-duration: 300ms;\n transition-property: height, opacity, transform;\n transition-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);\n overflow: hidden;\n pointer-events: none;\n}\n.lil-gui .children:empty:before {\n content: \"Empty\";\n padding: 0 var(--padding);\n margin: var(--spacing) 0;\n display: block;\n height: var(--widget-height);\n font-style: italic;\n line-height: var(--widget-height);\n opacity: 0.5;\n}\n.lil-gui.root > .children > .lil-gui > .title {\n border: 0 solid var(--widget-color);\n border-width: 1px 0;\n transition: border-color 300ms;\n}\n.lil-gui.root > .children > .lil-gui.closed > .title {\n border-bottom-color: transparent;\n}\n.lil-gui + .controller {\n border-top: 1px solid var(--widget-color);\n margin-top: 0;\n padding-top: var(--spacing);\n}\n.lil-gui .lil-gui .lil-gui > .title {\n border: none;\n}\n.lil-gui .lil-gui .lil-gui > .children {\n border: none;\n margin-left: var(--folder-indent);\n border-left: 2px solid var(--widget-color);\n}\n.lil-gui .lil-gui .controller {\n border: none;\n}\n\n.lil-gui input {\n -webkit-tap-highlight-color: transparent;\n border: 0;\n outline: none;\n font-family: var(--font-family);\n font-size: var(--input-font-size);\n border-radius: var(--widget-border-radius);\n height: var(--widget-height);\n background: var(--widget-color);\n color: var(--text-color);\n width: 100%;\n}\n@media (hover: hover) {\n .lil-gui input:hover {\n background: var(--hover-color);\n }\n .lil-gui input:active {\n background: var(--focus-color);\n }\n}\n.lil-gui input:disabled {\n opacity: 1;\n}\n.lil-gui input[type=text],\n.lil-gui input[type=number] {\n padding: var(--widget-padding);\n}\n.lil-gui input[type=text]:focus,\n.lil-gui input[type=number]:focus {\n background: var(--focus-color);\n}\n.lil-gui input::-webkit-outer-spin-button,\n.lil-gui input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n.lil-gui input[type=number] {\n -moz-appearance: textfield;\n}\n.lil-gui input[type=checkbox] {\n appearance: none;\n -webkit-appearance: none;\n height: var(--checkbox-size);\n width: var(--checkbox-size);\n border-radius: var(--widget-border-radius);\n text-align: center;\n cursor: pointer;\n}\n.lil-gui input[type=checkbox]:checked:before {\n font-family: \"lil-gui\";\n content: \"✓\";\n font-size: var(--checkbox-size);\n line-height: var(--checkbox-size);\n}\n@media (hover: hover) {\n .lil-gui input[type=checkbox]:focus {\n box-shadow: inset 0 0 0 1px var(--focus-color);\n }\n}\n.lil-gui button {\n -webkit-tap-highlight-color: transparent;\n outline: none;\n cursor: pointer;\n font-family: var(--font-family);\n font-size: var(--font-size);\n color: var(--text-color);\n width: 100%;\n height: var(--widget-height);\n text-transform: none;\n background: var(--widget-color);\n border-radius: var(--widget-border-radius);\n border: 1px solid var(--widget-color);\n text-align: center;\n line-height: calc(var(--widget-height) - 4px);\n}\n@media (hover: hover) {\n .lil-gui button:hover {\n background: var(--hover-color);\n border-color: var(--hover-color);\n }\n .lil-gui button:focus {\n border-color: var(--focus-color);\n }\n}\n.lil-gui button:active {\n background: var(--focus-color);\n}\n\n@font-face {\n font-family: \"lil-gui\";\n src: url(\"data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAUsAAsAAAAACJwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAAH4AAADAImwmYE9TLzIAAAGIAAAAPwAAAGBKqH5SY21hcAAAAcgAAAD0AAACrukyyJBnbHlmAAACvAAAAF8AAACEIZpWH2hlYWQAAAMcAAAAJwAAADZfcj2zaGhlYQAAA0QAAAAYAAAAJAC5AHhobXR4AAADXAAAABAAAABMAZAAAGxvY2EAAANsAAAAFAAAACgCEgIybWF4cAAAA4AAAAAeAAAAIAEfABJuYW1lAAADoAAAASIAAAIK9SUU/XBvc3QAAATEAAAAZgAAAJCTcMc2eJxVjbEOgjAURU+hFRBK1dGRL+ALnAiToyMLEzFpnPz/eAshwSa97517c/MwwJmeB9kwPl+0cf5+uGPZXsqPu4nvZabcSZldZ6kfyWnomFY/eScKqZNWupKJO6kXN3K9uCVoL7iInPr1X5baXs3tjuMqCtzEuagm/AAlzQgPAAB4nGNgYRBlnMDAysDAYM/gBiT5oLQBAwuDJAMDEwMrMwNWEJDmmsJwgCFeXZghBcjlZMgFCzOiKOIFAB71Bb8AeJy1kjFuwkAQRZ+DwRAwBtNQRUGKQ8OdKCAWUhAgKLhIuAsVSpWz5Bbkj3dEgYiUIszqWdpZe+Z7/wB1oCYmIoboiwiLT2WjKl/jscrHfGg/pKdMkyklC5Zs2LEfHYpjcRoPzme9MWWmk3dWbK9ObkWkikOetJ554fWyoEsmdSlt+uR0pCJR34b6t/TVg1SY3sYvdf8vuiKrpyaDXDISiegp17p7579Gp3p++y7HPAiY9pmTibljrr85qSidtlg4+l25GLCaS8e6rRxNBmsnERunKbaOObRz7N72ju5vdAjYpBXHgJylOAVsMseDAPEP8LYoUHicY2BiAAEfhiAGJgZWBgZ7RnFRdnVJELCQlBSRlATJMoLV2DK4glSYs6ubq5vbKrJLSbGrgEmovDuDJVhe3VzcXFwNLCOILB/C4IuQ1xTn5FPilBTj5FPmBAB4WwoqAHicY2BkYGAA4sk1sR/j+W2+MnAzpDBgAyEMQUCSg4EJxAEAwUgFHgB4nGNgZGBgSGFggJMhDIwMqEAYAByHATJ4nGNgAIIUNEwmAABl3AGReJxjYAACIQYlBiMGJ3wQAEcQBEV4nGNgZGBgEGZgY2BiAAEQyQWEDAz/wXwGAAsPATIAAHicXdBNSsNAHAXwl35iA0UQXYnMShfS9GPZA7T7LgIu03SSpkwzYTIt1BN4Ak/gKTyAeCxfw39jZkjymzcvAwmAW/wgwHUEGDb36+jQQ3GXGot79L24jxCP4gHzF/EIr4jEIe7wxhOC3g2TMYy4Q7+Lu/SHuEd/ivt4wJd4wPxbPEKMX3GI5+DJFGaSn4qNzk8mcbKSR6xdXdhSzaOZJGtdapd4vVPbi6rP+cL7TGXOHtXKll4bY1Xl7EGnPtp7Xy2n00zyKLVHfkHBa4IcJ2oD3cgggWvt/V/FbDrUlEUJhTn/0azVWbNTNr0Ens8de1tceK9xZmfB1CPjOmPH4kitmvOubcNpmVTN3oFJyjzCvnmrwhJTzqzVj9jiSX911FjeAAB4nG3HMRKCMBBA0f0giiKi4DU8k0V2GWbIZDOh4PoWWvq6J5V8If9NVNQcaDhyouXMhY4rPTcG7jwYmXhKq8Wz+p762aNaeYXom2n3m2dLTVgsrCgFJ7OTmIkYbwIbC6vIB7WmFfAAAA==\") format(\"woff\");\n}`;\n\nfunction _injectStyles( cssContent ) {\n\tconst injected = document.createElement( 'style' );\n\tinjected.innerHTML = cssContent;\n\tconst before = document.querySelector( 'head link[rel=stylesheet], head style' );\n\tif ( before ) {\n\t\tdocument.head.insertBefore( injected, before );\n\t} else {\n\t\tdocument.head.appendChild( injected );\n\t}\n}\n\nlet stylesInjected = false;\n\nclass GUI {\n\n\t/**\n\t * Creates a panel that holds controllers.\n\t * @example\n\t * new GUI();\n\t * new GUI( { container: document.getElementById( 'custom' ) } );\n\t *\n\t * @param {object} [options]\n\t * @param {boolean} [options.autoPlace=true]\n\t * Adds the GUI to `document.body` and fixes it to the top right of the page.\n\t *\n\t * @param {HTMLElement} [options.container]\n\t * Adds the GUI to this DOM element. Overrides `autoPlace`.\n\t *\n\t * @param {number} [options.width=245]\n\t * Width of the GUI in pixels, usually set when name labels become too long. Note that you can make\n\t * name labels wider in CSS with `.lil‑gui { ‑‑name‑width: 55% }`\n\t *\n\t * @param {string} [options.title=Controls]\n\t * Name to display in the title bar.\n\t *\n\t * @param {boolean} [options.injectStyles=true]\n\t * Injects the default stylesheet into the page if this is the first GUI.\n\t * Pass `false` to use your own stylesheet.\n\t *\n\t * @param {number} [options.touchStyles=true]\n\t * Makes controllers larger on touch devices. Pass `false` to disable touch styles.\n\t *\n\t * @param {GUI} [options.parent]\n\t * Adds this GUI as a child in another GUI. Usually this is done for you by `addFolder()`.\n\t *\n\t */\n\tconstructor( {\n\t\tparent,\n\t\tautoPlace = parent === undefined,\n\t\tcontainer,\n\t\twidth,\n\t\ttitle = 'Controls',\n\t\tinjectStyles = true,\n\t\ttouchStyles = true\n\t} = {} ) {\n\n\t\t/**\n\t\t * The GUI containing this folder, or `undefined` if this is the root GUI.\n\t\t * @type {GUI}\n\t\t */\n\t\tthis.parent = parent;\n\n\t\t/**\n\t\t * The top level GUI containing this folder, or `this` if this is the root GUI.\n\t\t * @type {GUI}\n\t\t */\n\t\tthis.root = parent ? parent.root : this;\n\n\t\t/**\n\t\t * The list of controllers and folders contained by this GUI.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.children = [];\n\n\t\t/**\n\t\t * The list of controllers contained by this GUI.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.controllers = [];\n\n\t\t/**\n\t\t * The list of folders contained by this GUI.\n\t\t * @type {Array}\n\t\t */\n\t\tthis.folders = [];\n\n\t\t/**\n\t\t * Used to determine if the GUI is closed. Use `gui.open()` or `gui.close()` to change this.\n\t\t * @type {boolean}\n\t\t */\n\t\tthis._closed = false;\n\n\t\t/**\n\t\t * Used to determine if the GUI is hidden. Use `gui.show()` or `gui.hide()` to change this.\n\t\t * @type {boolean}\n\t\t */\n\t\tthis._hidden = false;\n\n\t\t/**\n\t\t * The outermost container element.\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.domElement = document.createElement( 'div' );\n\t\tthis.domElement.classList.add( 'lil-gui' );\n\n\t\t/**\n\t\t * The DOM element that contains the title.\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.$title = document.createElement( 'div' );\n\t\tthis.$title.classList.add( 'title' );\n\t\tthis.$title.setAttribute( 'role', 'button' );\n\t\tthis.$title.setAttribute( 'aria-expanded', true );\n\t\tthis.$title.setAttribute( 'tabindex', 0 );\n\n\t\tthis.$title.addEventListener( 'click', () => this.openAnimated( this._closed ) );\n\t\tthis.$title.addEventListener( 'keydown', e => {\n\t\t\tif ( e.code === 'Enter' || e.code === 'Space' ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis.$title.click();\n\t\t\t}\n\t\t} );\n\n\t\t// enables :active pseudo class on mobile\n\t\tthis.$title.addEventListener( 'touchstart', () => {}, { passive: true } );\n\n\t\t/**\n\t\t * The DOM element that contains children.\n\t\t * @type {HTMLElement}\n\t\t */\n\t\tthis.$children = document.createElement( 'div' );\n\t\tthis.$children.classList.add( 'children' );\n\n\t\tthis.domElement.appendChild( this.$title );\n\t\tthis.domElement.appendChild( this.$children );\n\n\t\tthis.title( title );\n\n\t\tif ( touchStyles ) {\n\t\t\tthis.domElement.classList.add( 'allow-touch-styles' );\n\t\t}\n\n\t\tif ( this.parent ) {\n\n\t\t\tthis.parent.children.push( this );\n\t\t\tthis.parent.folders.push( this );\n\n\t\t\tthis.parent.$children.appendChild( this.domElement );\n\n\t\t\t// Stop the constructor early, everything onward only applies to root GUI's\n\t\t\treturn;\n\n\t\t}\n\n\t\tthis.domElement.classList.add( 'root' );\n\n\t\t// Inject stylesheet if we haven't done that yet\n\t\tif ( !stylesInjected && injectStyles ) {\n\t\t\t_injectStyles( stylesheet );\n\t\t\tstylesInjected = true;\n\t\t}\n\n\t\tif ( container ) {\n\n\t\t\tcontainer.appendChild( this.domElement );\n\n\t\t} else if ( autoPlace ) {\n\n\t\t\tthis.domElement.classList.add( 'autoPlace' );\n\t\t\tdocument.body.appendChild( this.domElement );\n\n\t\t}\n\n\t\tif ( width ) {\n\t\t\tthis.domElement.style.setProperty( '--width', width + 'px' );\n\t\t}\n\n\t\t// Don't fire global key events while typing in the GUI:\n\t\tthis.domElement.addEventListener( 'keydown', e => e.stopPropagation() );\n\t\tthis.domElement.addEventListener( 'keyup', e => e.stopPropagation() );\n\n\t}\n\n\t/**\n\t * Adds a controller to the GUI, inferring controller type using the `typeof` operator.\n\t * @example\n\t * gui.add( object, 'property' );\n\t * gui.add( object, 'number', 0, 100, 1 );\n\t * gui.add( object, 'options', [ 1, 2, 3 ] );\n\t *\n\t * @param {object} object The object the controller will modify.\n\t * @param {string} property Name of the property to control.\n\t * @param {number|object|Array} [$1] Minimum value for number controllers, or the set of\n\t * selectable values for a dropdown.\n\t * @param {number} [max] Maximum value for number controllers.\n\t * @param {number} [step] Step value for number controllers.\n\t * @returns {Controller}\n\t */\n\tadd( object, property, $1, max, step ) {\n\n\t\tif ( Object( $1 ) === $1 ) {\n\n\t\t\treturn new OptionController( this, object, property, $1 );\n\n\t\t}\n\n\t\tconst initialValue = object[ property ];\n\n\t\tswitch ( typeof initialValue ) {\n\n\t\t\tcase 'number':\n\n\t\t\t\treturn new NumberController( this, object, property, $1, max, step );\n\n\t\t\tcase 'boolean':\n\n\t\t\t\treturn new BooleanController( this, object, property );\n\n\t\t\tcase 'string':\n\n\t\t\t\treturn new StringController( this, object, property );\n\n\t\t\tcase 'function':\n\n\t\t\t\treturn new FunctionController( this, object, property );\n\n\t\t}\n\n\t\tconsole.error( `gui.add failed\n\tproperty:`, property, `\n\tobject:`, object, `\n\tvalue:`, initialValue );\n\n\t}\n\n\t/**\n\t * Adds a color controller to the GUI.\n\t * @example\n\t * params = {\n\t * \tcssColor: '#ff00ff',\n\t * \trgbColor: { r: 0, g: 0.2, b: 0.4 },\n\t * \tcustomRange: [ 0, 127, 255 ],\n\t * };\n\t *\n\t * gui.addColor( params, 'cssColor' );\n\t * gui.addColor( params, 'rgbColor' );\n\t * gui.addColor( params, 'customRange', 255 );\n\t *\n\t * @param {object} object The object the controller will modify.\n\t * @param {string} property Name of the property to control.\n\t * @param {number} rgbScale Maximum value for a color channel when using an RGB color. You may\n\t * need to set this to 255 if your colors are too dark.\n\t * @returns {Controller}\n\t */\n\taddColor( object, property, rgbScale = 1 ) {\n\t\treturn new ColorController( this, object, property, rgbScale );\n\t}\n\n\t/**\n\t * Adds a folder to the GUI, which is just another GUI. This method returns\n\t * the nested GUI so you can add controllers to it.\n\t * @example\n\t * const folder = gui.addFolder( 'Position' );\n\t * folder.add( position, 'x' );\n\t * folder.add( position, 'y' );\n\t * folder.add( position, 'z' );\n\t *\n\t * @param {string} title Name to display in the folder's title bar.\n\t * @returns {GUI}\n\t */\n\taddFolder( title ) {\n\t\treturn new GUI( { parent: this, title } );\n\t}\n\n\t/**\n\t * Recalls values that were saved with `gui.save()`.\n\t * @param {object} obj\n\t * @param {boolean} recursive Pass false to exclude folders descending from this GUI.\n\t * @returns {this}\n\t */\n\tload( obj, recursive = true ) {\n\n\t\tif ( obj.controllers ) {\n\n\t\t\tthis.controllers.forEach( c => {\n\n\t\t\t\tif ( c instanceof FunctionController ) return;\n\n\t\t\t\tif ( c._name in obj.controllers ) {\n\t\t\t\t\tc.load( obj.controllers[ c._name ] );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t}\n\n\t\tif ( recursive && obj.folders ) {\n\n\t\t\tthis.folders.forEach( f => {\n\n\t\t\t\tif ( f._title in obj.folders ) {\n\t\t\t\t\tf.load( obj.folders[ f._title ] );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Returns an object mapping controller names to values. The object can be passed to `gui.load()` to\n\t * recall these values.\n\t * @example\n\t * {\n\t * \tcontrollers: {\n\t * \t\tprop1: 1,\n\t * \t\tprop2: 'value',\n\t * \t\t...\n\t * \t},\n\t * \tfolders: {\n\t * \t\tfolderName1: { controllers, folders },\n\t * \t\tfolderName2: { controllers, folders }\n\t * \t\t...\n\t * \t}\n\t * }\n\t *\n\t * @param {boolean} recursive Pass false to exclude folders descending from this GUI.\n\t * @returns {object}\n\t */\n\tsave( recursive = true ) {\n\n\t\tconst obj = {\n\t\t\tcontrollers: {},\n\t\t\tfolders: {}\n\t\t};\n\n\t\tthis.controllers.forEach( c => {\n\n\t\t\tif ( c instanceof FunctionController ) return;\n\n\t\t\tif ( c._name in obj.controllers ) {\n\t\t\t\tthrow new Error( `Cannot save GUI with duplicate property \"${c._name}\"` );\n\t\t\t}\n\n\t\t\tobj.controllers[ c._name ] = c.save();\n\n\t\t} );\n\n\t\tif ( recursive ) {\n\n\t\t\tthis.folders.forEach( f => {\n\n\t\t\t\tif ( f._title in obj.folders ) {\n\t\t\t\t\tthrow new Error( `Cannot save GUI with duplicate folder \"${f._title}\"` );\n\t\t\t\t}\n\n\t\t\t\tobj.folders[ f._title ] = f.save();\n\n\t\t\t} );\n\n\t\t}\n\n\t\treturn obj;\n\n\t}\n\n\t/**\n\t * Opens a GUI or folder. GUI and folders are open by default.\n\t * @param {boolean} open Pass false to close\n\t * @returns {this}\n\t * @example\n\t * gui.open(); // open\n\t * gui.open( false ); // close\n\t * gui.open( gui._closed ); // toggle\n\t */\n\topen( open = true ) {\n\n\t\tthis._closed = !open;\n\n\t\tthis.$title.setAttribute( 'aria-expanded', !this._closed );\n\t\tthis.domElement.classList.toggle( 'closed', this._closed );\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Closes the GUI.\n\t * @returns {this}\n\t */\n\tclose() {\n\t\treturn this.open( false );\n\t}\n\n\t/**\n\t * Shows the GUI after it's been hidden.\n\t * @param {boolean} show\n\t * @returns {this}\n\t * @example\n\t * gui.show();\n\t * gui.show( false ); // hide\n\t * gui.show( gui._hidden ); // toggle\n\t */\n\tshow( show = true ) {\n\n\t\tthis._hidden = !show;\n\n\t\tthis.domElement.style.display = this._hidden ? 'none' : '';\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Hides the GUI.\n\t * @returns {this}\n\t */\n\thide() {\n\t\treturn this.show( false );\n\t}\n\n\topenAnimated( open = true ) {\n\n\t\t// set state immediately\n\t\tthis._closed = !open;\n\n\t\tthis.$title.setAttribute( 'aria-expanded', !this._closed );\n\n\t\t// wait for next frame to measure $children\n\t\trequestAnimationFrame( () => {\n\n\t\t\t// explicitly set initial height for transition\n\t\t\tconst initialHeight = this.$children.clientHeight;\n\t\t\tthis.$children.style.height = initialHeight + 'px';\n\n\t\t\tthis.domElement.classList.add( 'transition' );\n\n\t\t\tconst onTransitionEnd = e => {\n\t\t\t\tif ( e.target !== this.$children ) return;\n\t\t\t\tthis.$children.style.height = '';\n\t\t\t\tthis.domElement.classList.remove( 'transition' );\n\t\t\t\tthis.$children.removeEventListener( 'transitionend', onTransitionEnd );\n\t\t\t};\n\n\t\t\tthis.$children.addEventListener( 'transitionend', onTransitionEnd );\n\n\t\t\t// todo: this is wrong if children's scrollHeight makes for a gui taller than maxHeight\n\t\t\tconst targetHeight = !open ? 0 : this.$children.scrollHeight;\n\n\t\t\tthis.domElement.classList.toggle( 'closed', !open );\n\n\t\t\trequestAnimationFrame( () => {\n\t\t\t\tthis.$children.style.height = targetHeight + 'px';\n\t\t\t} );\n\n\t\t} );\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Change the title of this GUI.\n\t * @param {string} title\n\t * @returns {this}\n\t */\n\ttitle( title ) {\n\t\t/**\n\t\t * Current title of the GUI. Use `gui.title( 'Title' )` to modify this value.\n\t\t * @type {string}\n\t\t */\n\t\tthis._title = title;\n\t\tthis.$title.innerHTML = title;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resets all controllers to their initial values.\n\t * @param {boolean} recursive Pass false to exclude folders descending from this GUI.\n\t * @returns {this}\n\t */\n\treset( recursive = true ) {\n\t\tconst controllers = recursive ? this.controllersRecursive() : this.controllers;\n\t\tcontrollers.forEach( c => c.reset() );\n\t\treturn this;\n\t}\n\n\t/**\n\t * Pass a function to be called whenever a controller in this GUI changes.\n\t * @param {function({object:object, property:string, value:any, controller:Controller})} callback\n\t * @returns {this}\n\t * @example\n\t * gui.onChange( event => {\n\t * \tevent.object // object that was modified\n\t * \tevent.property // string, name of property\n\t * \tevent.value // new value of controller\n\t * \tevent.controller // controller that was modified\n\t * } );\n\t */\n\tonChange( callback ) {\n\t\t/**\n\t\t * Used to access the function bound to `onChange` events. Don't modify this value\n\t\t * directly. Use the `gui.onChange( callback )` method instead.\n\t\t * @type {Function}\n\t\t */\n\t\tthis._onChange = callback;\n\t\treturn this;\n\t}\n\n\t_callOnChange( controller ) {\n\n\t\tif ( this.parent ) {\n\t\t\tthis.parent._callOnChange( controller );\n\t\t}\n\n\t\tif ( this._onChange !== undefined ) {\n\t\t\tthis._onChange.call( this, {\n\t\t\t\tobject: controller.object,\n\t\t\t\tproperty: controller.property,\n\t\t\t\tvalue: controller.getValue(),\n\t\t\t\tcontroller\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Pass a function to be called whenever a controller in this GUI has finished changing.\n\t * @param {function({object:object, property:string, value:any, controller:Controller})} callback\n\t * @returns {this}\n\t * @example\n\t * gui.onFinishChange( event => {\n\t * \tevent.object // object that was modified\n\t * \tevent.property // string, name of property\n\t * \tevent.value // new value of controller\n\t * \tevent.controller // controller that was modified\n\t * } );\n\t */\n\tonFinishChange( callback ) {\n\t\t/**\n\t\t * Used to access the function bound to `onFinishChange` events. Don't modify this value\n\t\t * directly. Use the `gui.onFinishChange( callback )` method instead.\n\t\t * @type {Function}\n\t\t */\n\t\tthis._onFinishChange = callback;\n\t\treturn this;\n\t}\n\n\t_callOnFinishChange( controller ) {\n\n\t\tif ( this.parent ) {\n\t\t\tthis.parent._callOnFinishChange( controller );\n\t\t}\n\n\t\tif ( this._onFinishChange !== undefined ) {\n\t\t\tthis._onFinishChange.call( this, {\n\t\t\t\tobject: controller.object,\n\t\t\t\tproperty: controller.property,\n\t\t\t\tvalue: controller.getValue(),\n\t\t\t\tcontroller\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all DOM elements and event listeners associated with this GUI\n\t */\n\tdestroy() {\n\n\t\tif ( this.parent ) {\n\t\t\tthis.parent.children.splice( this.parent.children.indexOf( this ), 1 );\n\t\t\tthis.parent.folders.splice( this.parent.folders.indexOf( this ), 1 );\n\t\t}\n\n\t\tif ( this.domElement.parentElement ) {\n\t\t\tthis.domElement.parentElement.removeChild( this.domElement );\n\t\t}\n\n\t\tArray.from( this.children ).forEach( c => c.destroy() );\n\n\t}\n\n\t/**\n\t * Returns an array of controllers contained by this GUI and its descendents.\n\t * @returns {Controller[]}\n\t */\n\tcontrollersRecursive() {\n\t\tlet controllers = Array.from( this.controllers );\n\t\tthis.folders.forEach( f => {\n\t\t\tcontrollers = controllers.concat( f.controllersRecursive() );\n\t\t} );\n\t\treturn controllers;\n\t}\n\n\t/**\n\t * Returns an array of folders contained by this GUI and its descendents.\n\t * @returns {GUI[]}\n\t */\n\tfoldersRecursive() {\n\t\tlet folders = Array.from( this.folders );\n\t\tthis.folders.forEach( f => {\n\t\t\tfolders = folders.concat( f.foldersRecursive() );\n\t\t} );\n\t\treturn folders;\n\t}\n\n}\n\nexport default GUI;\nexport { BooleanController, ColorController, Controller, FunctionController, GUI, NumberController, OptionController, StringController };\n","// stats.js - http://github.com/mrdoob/stats.js\n(function(f,e){\"object\"===typeof exports&&\"undefined\"!==typeof module?module.exports=e():\"function\"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;dg+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/\n1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement(\"canvas\");q.width=r;q.height=h;q.style.cssText=\"width:80px;height:48px\";var b=q.getContext(\"2d\");b.font=\"bold \"+9*a+\"px Helvetica,Arial,sans-serif\";b.textBaseline=\"top\";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);\nb.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+\" \"+e+\" (\"+g(c)+\"-\"+g(k)+\")\",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});\n","module.exports = new __parcel__URL__(\"../\" + require('./helpers/bundle-manifest').resolve(\"lWGOs\")).toString();"],"names":["parcelRequire","register","JSON","parse","$ilwiq","$443c013b983d0324$var$_changeEvent","type","$443c013b983d0324$var$_startEvent","$443c013b983d0324$var$_endEvent","$443c013b983d0324$export$8ff7788029dfdf52","EventDispatcher","constructor","object","domElement1","super","undefined","console","warn","document","error","this","domElement","style","touchAction","enabled","target","Vector3","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","Math","PI","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","panSpeed","screenSpacePanning","keyPanSpeed","autoRotate","autoRotateSpeed","keys","LEFT","UP","RIGHT","BOTTOM","mouseButtons","MOUSE","ROTATE","MIDDLE","DOLLY","PAN","touches","ONE","TOUCH","TWO","DOLLY_PAN","target0","clone","position0","position","zoom0","zoom","_domElementKeyEvents","getPolarAngle","spherical","phi","getAzimuthalAngle","theta","getDistance","distanceTo","listenToKeyEvents","addEventListener","onKeyDown","saveState","scope","copy","reset","updateProjectionMatrix","dispatchEvent","update","state","STATE","NONE","offset","quat","Quaternion","setFromUnitVectors","up","quatInverse","invert","lastPosition","lastQuaternion","twoPI","sub","applyQuaternion","setFromVector3","rotateLeft","sphericalDelta","min","max","isFinite","makeSafe","radius","scale","addScaledVector","panOffset","add","setFromSpherical","lookAt","multiplyScalar","set","zoomChanged","distanceToSquared","EPS","dot","quaternion","dispose","removeEventListener","onContextMenu","onPointerDown","onPointerCancel","onMouseWheel","onPointerMove","onPointerUp","TOUCH_ROTATE","TOUCH_PAN","TOUCH_DOLLY_PAN","TOUCH_DOLLY_ROTATE","Spherical","rotateStart","Vector2","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","pointers","pointerPositions","getZoomScale","pow","angle","rotateUp","panLeft","v","distance","objectMatrix","setFromMatrixColumn","panUp","crossVectors","pan","deltaX","deltaY","element","isPerspectiveCamera","targetDistance","length","tan","fov","clientHeight","matrix","isOrthographicCamera","right","left","clientWidth","top","bottom","dollyOut","dollyScale","dollyIn","handleMouseDownRotate","event","clientX","clientY","handleMouseDownPan","handleTouchStartRotate","pageX","pageY","x","y","handleTouchStartPan","handleTouchStartDolly","dx","dy","sqrt","handleTouchMoveRotate","getSecondPointerPosition","subVectors","handleTouchMovePan","handleTouchMoveDolly","setPointerCapture","pointerId","push","addPointer","pointerType","trackPointer","DOLLY_ROTATE","onTouchStart","mouseAction","button","handleMouseDownDolly","ctrlKey","metaKey","shiftKey","onMouseDown","handleTouchMoveDollyPan","handleTouchMoveDollyRotate","onTouchMove","handleMouseMoveRotate","handleMouseMoveDolly","handleMouseMovePan","onMouseMove","removePointer","releasePointerCapture","preventDefault","handleMouseWheel","needsUpdate","code","handleKeyDown","i","splice","pointer","passive","$6e44765c12ddb126$export$bd0bf19f25da8474","parent","property","className","widgetTag","_disabled","initialValue","getValue","createElement","classList","$name","nextNameID","id","$widget","$disable","appendChild","children","controllers","$children","_listenCallback","bind","name","_name","innerHTML","onChange","callback","_onChange","_callOnChange","call","_changed","onFinishChange","_onFinishChange","_callOnFinishChange","setValue","enable","disable","disabled","toggle","toggleAttribute","options","controller","destroy","step","listen","_listening","_listenCallbackID","cancelAnimationFrame","requestAnimationFrame","curValue","save","_listenPrevValue","updateDisplay","value","load","indexOf","removeChild","$6e44765c12ddb126$export$c6f57966aed3cc84","$input","setAttribute","checked","$6e44765c12ddb126$var$normalizeColorString","string","match","result","parseInt","toString","padStart","$6e44765c12ddb126$var$STRING","isPrimitive","fromHexString","toHexString","$6e44765c12ddb126$var$INT","substring","$6e44765c12ddb126$var$ARRAY","Array","isArray","rgbScale","int","r","g","b","$6e44765c12ddb126$var$OBJECT","Object","$6e44765c12ddb126$var$FORMATS","$6e44765c12ddb126$export$3a401c49038ca28a","$text","$display","_format","find","format","_rgbScale","_initialValueHexString","_textFocused","_setValueFromHexString","tryParse","select","newValue","backgroundColor","$6e44765c12ddb126$export$2d7dcf9d07c8b352","$button","e","$6e44765c12ddb126$export$ee52b68072d314b9","_initInput","stepExplicit","_getImplicitStep","_min","_onUpdateMinMax","_max","explicit","_step","_stepExplicit","_hasSlider","percent","$fill","width","_inputFocused","increment","delta","parseFloat","isNaN","_snapClampSetValue","initClientX","initClientY","prevClientY","initValue","dragDelta","testingForVerticalDrag","abs","blur","_setDraggingStyle","onMouseUp","_arrowKeyMultiplier","window","_clamp","_normalizeMouseWheel","_initSlider","$slider","insertBefore","setValueFromX","rect","getBoundingClientRect","a","c","d","mouseMove","mouseUp","prevClientX","testingForScroll","beginTouchDrag","onTouchEnd","callOnFinishChange","wheelFinishChangeTimeout","_hasScrollBar","clearTimeout","setTimeout","active","axis","body","_hasMin","_hasMax","floor","wheelDelta","mult","altKey","_snap","round","toPrecision","root","scrollHeight","$6e44765c12ddb126$export$25f00c724c27c8b4","$select","_values","values","_names","forEach","$option","selectedIndex","remove","index","$6e44765c12ddb126$export$786d0ebe8f71368e","$6e44765c12ddb126$var$stylesInjected","$6e44765c12ddb126$export$983832d820c96993","autoPlace","container","title","injectStyles","touchStyles","folders","_closed","_hidden","$title","openAnimated","click","cssContent","injected","before","querySelector","head","$6e44765c12ddb126$var$_injectStyles","setProperty","stopPropagation","$1","addColor","addFolder","obj","recursive","f","_title","Error","open","close","show","display","hide","initialHeight","height","onTransitionEnd","targetHeight","controllersRecursive","parentElement","from","concat","foldersRecursive","f1","$6e44765c12ddb126$export$2e2bcd8739ae039","c1","dom","u","l","cssText","k","performance","Date","now","a1","Panel","h","self","memory","t","REVISION","addPanel","showPanel","begin","end","usedJSHeapSize","jsHeapSizeLimit","setMode","devicePixelRatio","h1","m","n","p","q","getContext","font","textBaseline","fillStyle","fillRect","fillText","globalAlpha","w","drawImage","$8d6448069697305c$exports","$eb2af5dd4c33aff6$exports","URL","resolve","import","meta","url","clock","Clock","stats","$parcel$interopDefault","innerWidth","innerHeight","garden","camera","gui","guiObject","progress","ar","report","log","renderer","info","render","generate","capture","async","canvas","setClearColor","resize","Promise","imageUrl","toDataURL","anchor","download","href","scene","Scene","PerspectiveCamera","WebGLRenderer","antialias","alpha","preserveDrawingBuffer","setPixelRatio","setSize","controls","$fJaKA","default","domeView","Views","GeometryView","modelUrl","maxBloomRadius","minBloomRadius","minSurfaceOffset","maxSurfaceOffset","textureScale","views","animate","aspect"],"version":3,"file":"index.06fb0362.js.map"}