@xviewer.js/debug 1.0.4-alpha.0 → 1.0.4-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -1
- package/dist/assets/index-DeOiC-Xv.css +545 -0
- package/dist/main.cjs +613 -102
- package/dist/main.cjs.map +1 -1
- package/dist/module.js +597 -104
- package/dist/module.js.map +1 -1
- package/package.json +5 -2
- package/types/Inspector.d.ts +7 -6
- package/types/Stats.d.ts +2 -2
- package/types/gui/GUI.d.ts +16 -3
- package/types/gui/controllers/SceneTreeController.d.ts +67 -0
- package/types/gui/controllers/SceneTreeController.example.d.ts +12 -0
- package/types/gui/utils/getColorFormat.d.ts +2 -2
- package/types/helpers/BoxProjectionHelper.d.ts +10 -0
- package/types/helpers/ViewerHelper.d.ts +30 -0
- package/types/index.d.ts +0 -1
package/dist/module.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Texture, Material, MeshBasicMaterial, MeshStandardMaterial, MeshPhysicalMaterial,
|
|
2
|
-
import {
|
|
1
|
+
import { Object3D, Texture, Vector4, Material, MeshBasicMaterial, MeshStandardMaterial, MeshPhysicalMaterial, Mesh, PlaneGeometry, ShaderMaterial, DoubleSide, Camera } from 'three';
|
|
2
|
+
import { GLTFExporter } from 'three/examples/jsm/Addons';
|
|
3
|
+
import * as TextureUtils from 'three/examples/jsm/utils/WebGLTextureUtils';
|
|
4
|
+
import { property, ObjectInstance, Component, PropertyManager } from '@xviewer.js/core';
|
|
3
5
|
|
|
4
|
-
var e=[],t=[];function n(n,r){if(n&&"undefined"!=typeof document){var a,s
|
|
6
|
+
var e=[],t=[];function n(n,r){if(n&&"undefined"!=typeof document){var a,s=true===r.prepend?"prepend":"append",d=true===r.singleTag,i="string"==typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(d){var u=e.indexOf(i);-1===u&&(u=e.push(i)-1,t[u]={}),a=t[u]&&t[u][s]?t[u][s]:t[u][s]=c();}else a=c();65279===n.charCodeAt(0)&&(n=n.substring(1)),a.styleSheet?a.styleSheet.cssText+=n:a.appendChild(document.createTextNode(n));}function c(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var a="prepend"===s?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}
|
|
5
7
|
|
|
6
|
-
var css = "@charset \"UTF-8\";\n.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,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Arial,\n sans-serif;\n --font-family-mono: Menlo,\n Monaco,\n Consolas,\n \"Droid Sans Mono\",\n monospace;\n --padding: 4px;\n --spacing: 4px;\n --widget-height: 20px;\n --title-height: calc(var(--widget-height) + var(--spacing) * 1.25);\n --name-width: 40%;\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, .lil-gui.allow-touch-styles .lil-gui {\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, .lil-gui.force-touch-styles .lil-gui {\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 rgba(255, 255, 255, 0.6);\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.lil-gui .controller.texture canvas {\n width: 100%;\n border-radius: var(--widget-border-radius);\n}\n.lil-gui .controller.texture .group {\n display: flex;\n position: relative;\n width: 100%;\n}\n.lil-gui .controller.texture .info {\n position: absolute;\n display: flex;\n gap: 11px;\n}\n.lil-gui .controller.texture .label {\n position: absolute;\n background-color: rgba(0, 0, 0, 0.6745098039);\n display: \"flex\";\n padding: 2px;\n border-radius: var(--widget-border-radius);\n}\n.lil-gui .controller.texture .block {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 2px;\n width: var(--font-size);\n height: var(--font-size);\n border-radius: var(--font-size);\n background-color: white;\n cursor: pointer;\n}\n.lil-gui .controller.texture .block.select {\n background-color: var(--string-color);\n}\n.lil-gui .controller.image img {\n width: 100%;\n}\n.lil-gui .controller.image canvas {\n width: 100%;\n}\n.lil-gui .controller.vector input {\n color: var(--number-color);\n}\n.lil-gui .controller.vector .fill {\n height: 100%;\n margin-left: var(--spacing);\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 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.curve-editor {\n display: flex;\n flex-direction: column;\n gap: 5px;\n background-color: #303030;\n outline: 1px solid #000000;\n padding: 5px;\n width: 100%;\n}\n.curve-editor .button-medium {\n background-color: #545454;\n min-width: var(--widget-height);\n min-height: var(--widget-height);\n height: 100%;\n outline: 1px solid #3c3c3c;\n display: flex;\n justify-content: center;\n align-items: center;\n color: #fff;\n font-size: var(--input-font-size, 11px);\n}\n.curve-editor .button-medium.selected {\n background-color: #4772b3;\n pointer-events: none;\n}\n.curve-editor .button-medium:hover {\n background-color: #656565;\n cursor: default;\n}\n.curve-editor .curve-top {\n display: flex;\n width: 100%;\n}\n.curve-editor .curve-panel {\n width: 100%;\n height: 90px;\n outline: 1px solid #646464;\n}\n.curve-editor .curve-point-panel {\n display: flex;\n align-items: center;\n width: 100%;\n height: var(--widget-height);\n}\n.curve-editor .curve-point-panel input {\n background-color: #545454;\n height: 100%;\n width: 100%;\n color: #fff;\n border: 0;\n outline: 1px solid #3c3c3c;\n text-align: center;\n font-size: var(--input-font-size, 11px);\n}";
|
|
8
|
+
var css = "/* lil-gui CSS - Main entry point */\n\n/* Import all CSS modules */\n/* Base styles and CSS variables for lil-gui */\n/* Font face for icons */\n@font-face {\n\tfont-family: 'lil-gui';\n\tsrc: 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/* CSS Variables - Unified Theme */\n:root {\n\t/* Colors */\n\t--bg-primary: #2a2a2a;\n\t--bg-secondary: #1e1e1e;\n\t--bg-tertiary: #323232;\n\t--bg-widget: #3c3c3c;\n\t--bg-hover: #4a4a4a;\n\t--bg-focus: #4d90fe;\n\t--bg-active: #4d90fe;\n\t--bg-selected: #185fbd;\n\n\t--text-primary: #d9d9d9;\n\t--text-muted: #a0a0a0;\n\t--text-number: #d9d9d9;\n\t--text-string: #a2db3c;\n\t--text-warning: #ff8c00;\n\t--text-error: #ff6b6b;\n\t--text-success: #4caf50;\n\n\t/* Typography */\n\t--font-size: 12px;\n\t--font-size-input: 12px;\n\t--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;\n\t--font-family-mono: Menlo, Monaco, Consolas, 'Droid Sans Mono', monospace;\n\n\t/* Layout */\n\t--padding: 4px;\n\t--spacing: 4px;\n\t--widget-height: 20px;\n\t--title-height: 25px;\n\t--name-width: 40%;\n\t--border-radius: 2px;\n\n\t/* Components */\n\t--slider-knob-width: 2px;\n\t--slider-input-width: 27%;\n\t--color-input-width: 27%;\n\t--slider-input-min-width: 45px;\n\t--color-input-min-width: 65px;\n\t--folder-indent: 7px;\n\t--checkbox-size: 15px;\n\t--scrollbar-width: 5px;\n\n\t/* Effects */\n\t--text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);\n\t--text-shadow-light: 0 1px 1px rgba(0, 0, 0, 0.6);\n}\n/* Touch device overrides */\n@media (pointer: coarse) {\n\t:root {\n\t\t--widget-height: 28px;\n\t\t--padding: 6px;\n\t\t--spacing: 6px;\n\t\t--font-size: 13px;\n\t\t--font-size-input: 16px;\n\t\t--folder-indent: 10px;\n\t\t--scrollbar-width: 7px;\n\t\t--slider-input-min-width: 50px;\n\t\t--color-input-min-width: 65px;\n\t}\n}\n/* Base styles */\n.lil-gui {\n\tfont-family: var(--font-family);\n\tfont-size: var(--font-size);\n\tline-height: 1;\n\tfont-weight: normal;\n\tfont-style: normal;\n\ttext-align: left;\n\tbackground-color: var(--bg-primary);\n\tcolor: var(--text-primary);\n\tuser-select: none;\n\t-webkit-user-select: none;\n\ttouch-action: manipulation;\n\ttext-shadow: var(--text-shadow);\n}\n.lil-gui,\n.lil-gui * {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tborder-radius: var(--border-radius);\n\tpadding: 1px 0;\n}\n/* Root container */\n.lil-gui.root {\n\twidth: var(--width, 245px);\n\tdisplay: flex;\n\tflex-direction: column;\n}\n.lil-gui.root>.title {\n\tbackground: var(--bg-secondary);\n\tcolor: var(--text-primary);\n\tmargin: 1px 2px;\n}\n.lil-gui.root>.children {\n\toverflow-x: hidden;\n\toverflow-y: auto;\n\tpadding: 0 2px 0;\n\tmargin: 0;\n}\n/* Scrollbar styles */\n.lil-gui.root>.children::-webkit-scrollbar,\n.scene-tree-container::-webkit-scrollbar {\n\twidth: var(--scrollbar-width);\n\theight: var(--scrollbar-width);\n\tbackground: var(--bg-primary);\n}\n.lil-gui.root>.children::-webkit-scrollbar-thumb,\n.scene-tree-container::-webkit-scrollbar-thumb {\n\tborder-radius: var(--scrollbar-width);\n\tbackground: var(--bg-focus);\n}\n.scene-tree-container::-webkit-scrollbar-thumb:hover {\n\tbackground: var(--text-primary);\n}\n/* Auto placement */\n.lil-gui.autoPlace {\n\tmax-height: 100%;\n\tposition: fixed;\n\ttop: 0;\n\tright: 15px;\n\tz-index: 1001;\n}\n/* Title styles */\n.lil-gui .title {\n\theight: var(--title-height);\n\tline-height: calc(var(--title-height) - 4px);\n\tfont-weight: normal;\n\tfont-size: var(--font-size);\n\tpadding: 0 var(--padding);\n\t-webkit-tap-highlight-color: transparent;\n\tcursor: pointer;\n\toutline: none;\n\ttext-decoration-skip: objects;\n\ttext-shadow: var(--text-shadow);\n}\n.lil-gui .title:before {\n\tfont-family: 'lil-gui';\n\tcontent: '▾';\n\tpadding-right: 2px;\n\tdisplay: inline-block;\n}\n/* Title states */\n.lil-gui .title:hover,\n.lil-gui .title:focus,\n.lil-gui .title:active {\n\tbackground: var(--bg-hover);\n\ttext-decoration: none;\n}\n.lil-gui .title:active {\n\topacity: 0.75;\n}\n/* Closed state */\n.lil-gui.closed>.title:before {\n\tcontent: '▸';\n}\n.lil-gui.closed>.children {\n\ttransform: translateY(-7px);\n\topacity: 0;\n}\n.lil-gui.closed:not(.transition)>.children {\n\tdisplay: none;\n}\n/* Transition state */\n.lil-gui.transition>.children {\n\ttransition: height 300ms, opacity 300ms, transform 300ms;\n\ttransition-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);\n\toverflow: hidden;\n\tpointer-events: none;\n}\n/* Empty children */\n.lil-gui .children:empty:before {\n\tcontent: 'Empty';\n\tpadding: 0 var(--padding);\n\tmargin: var(--spacing) 0;\n\tdisplay: block;\n\theight: var(--widget-height);\n\tfont-style: italic;\n\tline-height: var(--widget-height);\n\topacity: 0.5;\n}\n/* Dragging state */\n.lil-gui-dragging .lil-gui {\n\t--bg-hover: var(--bg-widget);\n}\n.lil-gui-dragging * {\n\tcursor: ew-resize !important;\n}\n.lil-gui-dragging.lil-gui-vertical * {\n\tcursor: ns-resize !important;\n}\n/* Controller styles for lil-gui */\n/* Base controller */\n.lil-gui .controller {\n\tdisplay: flex;\n\talign-items: center;\n\tpadding: 0 var(--padding);\n\tmargin: 0;\n}\n.lil-gui .controller.disabled {\n\topacity: 0.5;\n\tpointer-events: none !important;\n}\n.lil-gui .controller > .name {\n\tmin-width: var(--name-width);\n\tflex-shrink: 0;\n\twhite-space: pre;\n\tpadding-right: var(--spacing);\n\tline-height: var(--widget-height);\n\ttext-shadow: var(--text-shadow-light);\n}\n.lil-gui .controller .widget {\n\tposition: relative;\n\tdisplay: flex;\n\talign-items: center;\n\twidth: 100%;\n\tmin-height: var(--widget-height);\n}\n/* String controller */\n.lil-gui .controller.string input {\n\tcolor: var(--text-string);\n}\n/* Boolean controller */\n.lil-gui .controller.boolean .widget {\n\tcursor: pointer;\n}\n/* Color controller */\n.lil-gui .controller.color .display {\n\twidth: 100%;\n\theight: var(--widget-height);\n\tborder-radius: var(--border-radius);\n\tposition: relative;\n}\n.lil-gui .controller.color .display:hover:before {\n\tcontent: ' ';\n\tdisplay: block;\n\tposition: absolute;\n\tborder-radius: var(--border-radius);\n\tborder: 1px solid #fff9;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n}\n.lil-gui .controller.color input[type='color'] {\n\topacity: 0;\n\twidth: 100%;\n\theight: 100%;\n\tcursor: pointer;\n}\n.lil-gui .controller.color input[type='text'] {\n\tmargin-left: var(--spacing);\n\tfont-family: var(--font-family-mono);\n\tmin-width: var(--color-input-min-width);\n\twidth: var(--color-input-width);\n\tflex-shrink: 0;\n}\n/* Option controller */\n.lil-gui .controller.option select {\n\topacity: 0;\n\tposition: absolute;\n\twidth: 100%;\n\tmax-width: 100%;\n}\n.lil-gui .controller.option .display {\n\tposition: relative;\n\tpointer-events: none;\n\tborder-radius: var(--border-radius);\n\theight: var(--widget-height);\n\tline-height: var(--widget-height);\n\tmax-width: 100%;\n\toverflow: hidden;\n\tword-break: break-all;\n\tpadding-left: 0.55em;\n\tpadding-right: 1.75em;\n\tbackground: var(--bg-widget);\n\ttext-shadow: var(--text-shadow);\n}\n.lil-gui .controller.option .display.focus,\n.lil-gui .controller.option .display.active {\n\tbackground: var(--bg-focus);\n}\n.lil-gui .controller.option .display:after {\n\tfont-family: 'lil-gui';\n\tcontent: '↕';\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tpadding-right: 0.375em;\n}\n.lil-gui .controller.option .widget,\n.lil-gui .controller.option select {\n\tcursor: pointer;\n}\n.lil-gui .controller.option .widget:hover .display {\n\tbackground: var(--bg-hover);\n}\n/* Number controller */\n.lil-gui .controller.number input {\n\tcolor: var(--text-number);\n}\n.lil-gui .controller.number.hasSlider input {\n\tmargin-left: var(--spacing);\n\twidth: var(--slider-input-width);\n\tmin-width: var(--slider-input-min-width);\n\tflex-shrink: 0;\n}\n.lil-gui .controller.number .slider {\n\twidth: 100%;\n\theight: var(--widget-height);\n\tbackground-color: var(--bg-widget);\n\tborder-radius: var(--border-radius);\n\tpadding-right: var(--slider-knob-width);\n\toverflow: hidden;\n\tcursor: ew-resize;\n\ttouch-action: pan-y;\n}\n.lil-gui .controller.number .slider:hover {\n\tbackground-color: var(--bg-hover);\n}\n.lil-gui .controller.number .slider.active {\n\tbackground-color: var(--bg-active);\n}\n.lil-gui .controller.number .slider.active .fill {\n\topacity: 0.95;\n}\n.lil-gui .controller.number .fill {\n\theight: 100%;\n\tborder-right: var(--slider-knob-width) solid var(--text-number);\n\tbox-sizing: content-box;\n}\n/* Texture controller */\n.lil-gui .controller.texture canvas {\n\twidth: 100%;\n\tborder-radius: var(--border-radius);\n}\n.lil-gui .controller.texture .group {\n\tdisplay: flex;\n\tposition: relative;\n\twidth: 100%;\n}\n.lil-gui .controller.texture .info {\n\tposition: absolute;\n\tdisplay: flex;\n\tgap: 11px;\n}\n.lil-gui .controller.texture .label {\n\tposition: absolute;\n\tbackground-color: #000000ac;\n\tdisplay: flex;\n\tpadding: 2px;\n\tborder-radius: var(--border-radius);\n}\n.lil-gui .controller.texture .block {\n\tposition: absolute;\n\tleft: 50%;\n\ttransform: translateX(-50%);\n\tmargin-top: 2px;\n\twidth: var(--font-size);\n\theight: var(--font-size);\n\tborder-radius: var(--font-size);\n\tbackground-color: white;\n\tcursor: pointer;\n}\n.lil-gui .controller.texture .block.select {\n\tbackground-color: var(--text-string);\n}\n/* Image controller */\n.lil-gui .controller.image img,\n.lil-gui .controller.image canvas {\n\twidth: 100%;\n}\n/* Vector controller */\n.lil-gui .controller.vector input {\n\tcolor: var(--text-number);\n}\n.lil-gui .controller.vector .fill {\n\theight: 100%;\n\tmargin-left: var(--spacing);\n\tbox-sizing: content-box;\n}\n/* Input and form control styles for lil-gui */\n/* Base input styles */\n.lil-gui input {\n\t-webkit-tap-highlight-color: transparent;\n\tborder: 0;\n\toutline: none;\n\tfont-family: var(--font-family);\n\tfont-size: var(--font-size-input);\n\tborder-radius: var(--border-radius);\n\theight: var(--widget-height);\n\tbackground: var(--bg-widget);\n\tcolor: var(--text-primary);\n\twidth: 100%;\n\ttext-shadow: var(--text-shadow-light);\n}\n.lil-gui input:hover {\n\tbackground: var(--bg-hover);\n}\n.lil-gui input:focus {\n\tbackground: var(--bg-focus);\n}\n.lil-gui input:disabled {\n\topacity: 1;\n}\n/* Text and number inputs */\n.lil-gui input[type='text'],\n.lil-gui input[type='number'] {\n\tpadding: 0 0 0 3px;\n}\n/* Hide number spinners */\n.lil-gui input::-webkit-outer-spin-button,\n.lil-gui input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.lil-gui input[type='number'] {\n\t-moz-appearance: textfield;\n}\n/* Checkbox */\n.lil-gui input[type='checkbox'] {\n\tappearance: none;\n\t-webkit-appearance: none;\n\theight: var(--checkbox-size);\n\twidth: var(--checkbox-size);\n\tborder-radius: var(--border-radius);\n\ttext-align: center;\n\tcursor: pointer;\n}\n.lil-gui input[type='checkbox']:checked:before {\n\tfont-family: 'lil-gui';\n\tcontent: '✓';\n\tfont-size: var(--checkbox-size);\n\tline-height: var(--checkbox-size);\n}\n.lil-gui input[type='checkbox']:focus {\n\tbox-shadow: inset 0 0 0 1px var(--bg-active);\n}\n/* Button */\n.lil-gui button {\n\t-webkit-tap-highlight-color: transparent;\n\toutline: none;\n\tcursor: pointer;\n\tfont-family: var(--font-family);\n\tfont-size: var(--font-size);\n\tcolor: var(--text-primary);\n\twidth: 100%;\n\theight: var(--widget-height);\n\ttext-transform: none;\n\tbackground: var(--bg-widget);\n\tborder-radius: var(--border-radius);\n\tborder: 1px solid var(--bg-widget);\n\ttext-align: center;\n\tline-height: calc(var(--widget-height) - 4px);\n\ttext-shadow: var(--text-shadow);\n}\n.lil-gui button:hover {\n\tbackground: var(--bg-hover);\n\tborder-color: var(--bg-hover);\n}\n.lil-gui button:focus {\n\tborder-color: var(--bg-active);\n}\n.lil-gui button:active {\n\tbackground: var(--bg-active);\n}\n/* Curve editor styles for lil-gui */\n.curve-editor {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 5px;\n\tbackground-color: var(--bg-tertiary);\n\toutline: 1px solid #000000;\n\tpadding: 5px;\n\twidth: 100%;\n}\n.curve-editor .button-medium {\n\tbackground-color: #545454;\n\tmin-width: var(--widget-height);\n\tmin-height: var(--widget-height);\n\theight: 100%;\n\toutline: 1px solid var(--bg-widget);\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n\tcolor: #fff;\n\tfont-size: var(--font-size-input);\n}\n.curve-editor .button-medium.selected {\n\tbackground-color: var(--bg-active);\n\tpointer-events: none;\n}\n.curve-editor .button-medium:hover {\n\tbackground-color: #656565;\n\tcursor: default;\n}\n.curve-editor .curve-top {\n\tdisplay: flex;\n\twidth: 100%;\n}\n.curve-editor .curve-panel {\n\twidth: 100%;\n\theight: 90px;\n\toutline: 1px solid #646464;\n}\n.curve-editor .curve-point-panel {\n\tdisplay: flex;\n\talign-items: center;\n\twidth: 100%;\n\theight: var(--widget-height);\n}\n.curve-editor .curve-point-panel input {\n\tbackground-color: #545454;\n\theight: 100%;\n\twidth: 100%;\n\tcolor: #fff;\n\tborder: 0;\n\toutline: 1px solid var(--bg-widget);\n\ttext-align: center;\n\tfont-size: var(--font-size-input);\n}\n/* Scene Tree Controller Styles */\n/* Base styles for scene tree */\n.scene-tree-container,\n.scene-tree-controller {\n\twidth: 100%;\n}\n.scene-tree-container {\n\theight: 100%;\n\toverflow-y: auto;\n\toverflow-x: hidden;\n\tposition: relative;\n\tpadding: 0;\n}\n.scene-tree-controller {\n\tfont-family: var(--font-family);\n\tfont-size: var(--font-size);\n\tmax-height: 300px;\n\toverflow-y: auto;\n\tborder: none;\n\tpadding: 0 !important;\n}\n/* Scene tree node */\n.scene-tree-controller .scene-tree-node {\n\ttransition: background-color 200ms ease;\n\tborder-radius: 0;\n\tpadding: 2px var(--padding);\n\tmargin: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tcursor: pointer;\n\tuser-select: none;\n\tmin-height: 24px;\n\twidth: 100%;\n\tbox-sizing: border-box;\n\tposition: relative;\n\theight: var(--title-height);\n\tline-height: calc(var(--title-height) - 4px);\n}\n/* Alternating background colors */\n.scene-tree-controller .scene-tree-node.even-row {\n\tbackground-color: var(--bg-primary);\n}\n.scene-tree-controller .scene-tree-node.odd-row {\n\tbackground-color: var(--bg-tertiary);\n}\n.scene-tree-controller .scene-tree-node:hover {\n\tbackground-color: var(--bg-hover);\n}\n.scene-tree-controller .scene-tree-node.selected {\n\tbackground-color: var(--bg-active);\n\tcolor: #ffffff;\n}\n/* Expand button */\n.scene-tree-controller .scene-tree-node .expand-btn {\n\tcursor: pointer;\n\tuser-select: none;\n\ttransition: all 300ms;\n\tdisplay: inline-block;\n\theight: 16px;\n\tflex-shrink: 0;\n\tfont-family: 'lil-gui';\n\tfont-size: var(--font-size);\n\tline-height: 1;\n\tcolor: var(--text-primary);\n\ttext-align: center;\n\topacity: 0.8;\n}\n.scene-tree-controller .scene-tree-node .expand-btn:hover {\n\topacity: 1;\n}\n/* Visibility button */\n.scene-tree-controller .scene-tree-node .visibility-btn {\n\tcursor: pointer;\n\tuser-select: none;\n\ttransition: all 300ms;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\theight: 16px;\n\tborder-radius: var(--border-radius);\n\tmargin-left: auto;\n\tflex-shrink: 0;\n\topacity: 0.8;\n}\n.scene-tree-controller .scene-tree-node .visibility-btn:hover {\n\tbackground-color: var(--bg-secondary);\n\topacity: 0.8;\n}\n.scene-tree-controller .scene-tree-node .visibility-btn svg {\n\twidth: 16px;\n\theight: 16px;\n\tfill: var(--text-primary);\n}\n.scene-tree-controller .scene-tree-node .visibility-btn.hidden svg {\n\topacity: 0.6;\n}\n.scene-tree-controller .scene-tree-node .visibility-btn:hover {\n\topacity: 1;\n}\n/* Node info */\n.scene-tree-controller .scene-tree-node .node-info {\n\tflex: 1;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--text-primary);\n\tfont-size: var(--font-size);\n\tmargin-right: var(--spacing);\n\tmin-width: 0;\n\tpadding-left: 0;\n\ttext-shadow: var(--text-shadow);\n}\n/* Context Menu Styles - Blender-inspired */\n.scene-tree-context-menu {\n\tposition: fixed;\n\tbackground: #202020;\n\tborder-radius: 2px;\n\tbox-shadow: 0 4px 20px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);\n\tz-index: 10000;\n\tmin-width: 100px;\n\tpadding: 4px;\n\tfont-family: var(--font-family);\n\tfont-size: var(--font-size);\n\tcolor: #e0e0e0;\n}\n.scene-tree-context-menu .context-menu-item {\n\theight: 20px;\n\tline-height: 20px;\n\tpadding: 0 16px;\n\tcursor: pointer;\n\tdisplay: flex;\n\talign-items: center;\n\tcolor: #e0e0e0;\n\ttransition: all 0.1s ease;\n\tuser-select: none;\n\t-webkit-tap-highlight-color: transparent;\n\toutline: none;\n\ttext-decoration-skip: objects;\n\tfont-weight: 400;\n\tborder-radius: 2px;\n}\n.scene-tree-context-menu .context-menu-item:hover {\n\tbackground: #3a3a3a;\n\tcolor: #ffffff;\n}\n.scene-tree-context-menu .context-menu-item:active {\n\tbackground: #4a4a4a;\n\tcolor: #ffffff;\n}\n/* Context menu separator */\n.scene-tree-context-menu .context-menu-separator {\n\theight: 1px;\n\tbackground-color: #404040;\n\tmargin: 4px 0;\n}\n/* Disabled state for paste when clipboard is empty */\n.scene-tree-context-menu .context-menu-item.disabled {\n\topacity: 0.4;\n\tcursor: not-allowed;\n\tcolor: #808080;\n}\n.scene-tree-context-menu .context-menu-item.disabled:hover,\n.scene-tree-context-menu .context-menu-item.disabled:focus,\n.scene-tree-context-menu .context-menu-item.disabled:active {\n\tbackground: transparent;\n\tcolor: #808080;\n}\n\n\n";
|
|
7
9
|
n(css,{});
|
|
8
10
|
|
|
9
11
|
class Controller {
|
|
@@ -317,13 +319,7 @@ class OptionController extends Controller {
|
|
|
317
319
|
this.$select.setAttribute('aria-labelledby', this.$name.id);
|
|
318
320
|
this.$display = document.createElement('div');
|
|
319
321
|
this.$display.classList.add('display');
|
|
320
|
-
this.
|
|
321
|
-
this._names = Array.isArray(options) ? options : Object.keys(options);
|
|
322
|
-
this._names.forEach((name)=>{
|
|
323
|
-
const $option = document.createElement('option');
|
|
324
|
-
$option.innerHTML = name;
|
|
325
|
-
this.$select.appendChild($option);
|
|
326
|
-
});
|
|
322
|
+
this.options(options);
|
|
327
323
|
this.$select.addEventListener('change', ()=>{
|
|
328
324
|
this.setValue(this._values[this.$select.selectedIndex]);
|
|
329
325
|
this._callOnFinishChange();
|
|
@@ -881,10 +877,7 @@ class ColorController extends Controller {
|
|
|
881
877
|
return this;
|
|
882
878
|
}
|
|
883
879
|
constructor(parent, object, property, rgbScale){
|
|
884
|
-
super(parent, object, property, 'color');
|
|
885
|
-
this._textFocused = false;
|
|
886
|
-
this._initialValueHexString = "";
|
|
887
|
-
this._rgbScale = 1;
|
|
880
|
+
super(parent, object, property, 'color'), this._textFocused = false, this._initialValueHexString = "", this._rgbScale = 1;
|
|
888
881
|
this.$input = document.createElement('input');
|
|
889
882
|
this.$input.setAttribute('type', 'color');
|
|
890
883
|
this.$input.setAttribute('tabindex', "-1");
|
|
@@ -1040,13 +1033,7 @@ class UINumber extends UIElement {
|
|
|
1040
1033
|
return this;
|
|
1041
1034
|
}
|
|
1042
1035
|
constructor(value, min, max, step){
|
|
1043
|
-
super(document.createElement('input'));
|
|
1044
|
-
this.value = 0;
|
|
1045
|
-
this.min = -Infinity;
|
|
1046
|
-
this.max = Infinity;
|
|
1047
|
-
this.step = 1;
|
|
1048
|
-
this.nudge = 1;
|
|
1049
|
-
this.unit = "";
|
|
1036
|
+
super(document.createElement('input')), this.value = 0, this.min = -Infinity, this.max = Infinity, this.step = 1, this.nudge = 1, this.unit = "";
|
|
1050
1037
|
this.dom.style.cursor = 'ns-resize';
|
|
1051
1038
|
this.dom.value = '0.00';
|
|
1052
1039
|
this.min = min != null ? min : this.min;
|
|
@@ -1704,7 +1691,7 @@ class TextureController extends Controller {
|
|
|
1704
1691
|
canvas.title = texture.sourceFile || "";
|
|
1705
1692
|
canvas.height = canvas.width / image.width * image.height;
|
|
1706
1693
|
if (this.getImage) {
|
|
1707
|
-
const w = 256, h = 256 / image.width * image.height;
|
|
1694
|
+
const w = 256, h = Math.floor(256 / image.width * image.height);
|
|
1708
1695
|
context.drawImage(this.getImage(texture, w, h), 0, 0, w * 1.5, h * 1.5, 0, 0, canvas.width, canvas.height); //why 1.5 ?
|
|
1709
1696
|
}
|
|
1710
1697
|
} else {
|
|
@@ -1716,8 +1703,7 @@ class TextureController extends Controller {
|
|
|
1716
1703
|
return this;
|
|
1717
1704
|
}
|
|
1718
1705
|
constructor(parent, object, property){
|
|
1719
|
-
super(parent, object, property, "texture");
|
|
1720
|
-
this._autoRefresh = false;
|
|
1706
|
+
super(parent, object, property, "texture"), this._autoRefresh = false;
|
|
1721
1707
|
const group = this.$widget.appendChild(document.createElement("div"));
|
|
1722
1708
|
group.classList.add("group");
|
|
1723
1709
|
this.$canvas = group.appendChild(document.createElement("canvas"));
|
|
@@ -1736,6 +1722,486 @@ class TextureController extends Controller {
|
|
|
1736
1722
|
}
|
|
1737
1723
|
}
|
|
1738
1724
|
|
|
1725
|
+
class SceneTreeController extends Controller {
|
|
1726
|
+
_setupDOM() {
|
|
1727
|
+
// Hide the name element since we don't need it for scene tree
|
|
1728
|
+
this.$name.style.display = 'none';
|
|
1729
|
+
this.$treeContainer = document.createElement('div');
|
|
1730
|
+
this.$treeContainer.classList.add('scene-tree-container');
|
|
1731
|
+
this.$widget.appendChild(this.$treeContainer);
|
|
1732
|
+
}
|
|
1733
|
+
_createContextMenu() {
|
|
1734
|
+
this._contextMenu = document.createElement('div');
|
|
1735
|
+
this._contextMenu.classList.add('scene-tree-context-menu');
|
|
1736
|
+
this._contextMenu.style.display = 'none';
|
|
1737
|
+
const menuItems = [
|
|
1738
|
+
{
|
|
1739
|
+
label: 'Export',
|
|
1740
|
+
action: 'export'
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
label: 'Copy',
|
|
1744
|
+
action: 'copy'
|
|
1745
|
+
},
|
|
1746
|
+
{
|
|
1747
|
+
label: 'Paste',
|
|
1748
|
+
action: 'paste'
|
|
1749
|
+
}
|
|
1750
|
+
];
|
|
1751
|
+
menuItems.forEach((item)=>{
|
|
1752
|
+
const menuItem = document.createElement('div');
|
|
1753
|
+
menuItem.classList.add('context-menu-item');
|
|
1754
|
+
menuItem.dataset.action = item.action;
|
|
1755
|
+
menuItem.textContent = item.label;
|
|
1756
|
+
menuItem.addEventListener('click', ()=>this._handleContextMenuAction(item.action));
|
|
1757
|
+
this._contextMenu.appendChild(menuItem);
|
|
1758
|
+
});
|
|
1759
|
+
document.body.appendChild(this._contextMenu);
|
|
1760
|
+
}
|
|
1761
|
+
_setupGlobalEventListeners() {
|
|
1762
|
+
// Hide context menu when clicking outside
|
|
1763
|
+
document.addEventListener('click', (e)=>{
|
|
1764
|
+
if (this._contextMenu && !this._contextMenu.contains(e.target)) {
|
|
1765
|
+
this._hideContextMenu();
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
// Hide context menu on escape key
|
|
1769
|
+
document.addEventListener('keydown', (e)=>{
|
|
1770
|
+
if (e.key === 'Escape') {
|
|
1771
|
+
this._hideContextMenu();
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
_showContextMenu(x, y, target) {
|
|
1776
|
+
if (!this._contextMenu) return;
|
|
1777
|
+
this._contextMenuTarget = target;
|
|
1778
|
+
this._contextMenu.style.display = 'block';
|
|
1779
|
+
// Update paste menu item state based on clipboard
|
|
1780
|
+
this._updateContextMenuState();
|
|
1781
|
+
// Position the menu
|
|
1782
|
+
const rect = this._contextMenu.getBoundingClientRect();
|
|
1783
|
+
const viewportWidth = window.innerWidth;
|
|
1784
|
+
const viewportHeight = window.innerHeight;
|
|
1785
|
+
// Adjust position if menu would go off-screen
|
|
1786
|
+
let adjustedX = x;
|
|
1787
|
+
let adjustedY = y;
|
|
1788
|
+
if (x + rect.width > viewportWidth) {
|
|
1789
|
+
adjustedX = x - rect.width;
|
|
1790
|
+
}
|
|
1791
|
+
if (y + rect.height > viewportHeight) {
|
|
1792
|
+
adjustedY = y - rect.height;
|
|
1793
|
+
}
|
|
1794
|
+
this._contextMenu.style.left = `${adjustedX}px`;
|
|
1795
|
+
this._contextMenu.style.top = `${adjustedY}px`;
|
|
1796
|
+
}
|
|
1797
|
+
_updateContextMenuState() {
|
|
1798
|
+
if (!this._contextMenu) return;
|
|
1799
|
+
const pasteItem = this._contextMenu.querySelector('[data-action="paste"]');
|
|
1800
|
+
if (pasteItem) {
|
|
1801
|
+
if (this._clipboardData) {
|
|
1802
|
+
pasteItem.classList.remove('disabled');
|
|
1803
|
+
pasteItem.style.cursor = 'pointer';
|
|
1804
|
+
} else {
|
|
1805
|
+
pasteItem.classList.add('disabled');
|
|
1806
|
+
pasteItem.style.cursor = 'not-allowed';
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
_hideContextMenu() {
|
|
1811
|
+
if (this._contextMenu) {
|
|
1812
|
+
this._contextMenu.style.display = 'none';
|
|
1813
|
+
}
|
|
1814
|
+
this._contextMenuTarget = null;
|
|
1815
|
+
}
|
|
1816
|
+
_handleContextMenuAction(action) {
|
|
1817
|
+
if (!this._contextMenuTarget) return;
|
|
1818
|
+
switch(action){
|
|
1819
|
+
case 'export':
|
|
1820
|
+
this._exportObject(this._contextMenuTarget);
|
|
1821
|
+
break;
|
|
1822
|
+
case 'copy':
|
|
1823
|
+
this._copyObject(this._contextMenuTarget);
|
|
1824
|
+
break;
|
|
1825
|
+
case 'paste':
|
|
1826
|
+
if (this._clipboardData) {
|
|
1827
|
+
this._pasteObject(this._contextMenuTarget);
|
|
1828
|
+
}
|
|
1829
|
+
break;
|
|
1830
|
+
}
|
|
1831
|
+
this._hideContextMenu();
|
|
1832
|
+
}
|
|
1833
|
+
_exportObject(node) {
|
|
1834
|
+
try {
|
|
1835
|
+
new GLTFExporter().setTextureUtils(TextureUtils).parse(node.object, (result)=>{
|
|
1836
|
+
if (result instanceof ArrayBuffer) {
|
|
1837
|
+
const blob = new Blob([
|
|
1838
|
+
result
|
|
1839
|
+
], {
|
|
1840
|
+
type: 'application/octet-stream'
|
|
1841
|
+
});
|
|
1842
|
+
const url = URL.createObjectURL(blob);
|
|
1843
|
+
const link = document.createElement('a');
|
|
1844
|
+
link.href = url;
|
|
1845
|
+
link.download = `${node.name || node.type}.glb`;
|
|
1846
|
+
link.click();
|
|
1847
|
+
}
|
|
1848
|
+
}, (err)=>{
|
|
1849
|
+
console.log('An error happened during parsing', err);
|
|
1850
|
+
}, {
|
|
1851
|
+
trs: false,
|
|
1852
|
+
binary: true,
|
|
1853
|
+
maxTextureSize: 4096
|
|
1854
|
+
});
|
|
1855
|
+
console.log(`Exported object: ${node.name || node.type}`);
|
|
1856
|
+
} catch (error) {
|
|
1857
|
+
console.error('Failed to export object:', error);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
_copyObject(node) {
|
|
1861
|
+
try {
|
|
1862
|
+
const copyData = this._serializeObject(node.object);
|
|
1863
|
+
this._clipboardData = copyData;
|
|
1864
|
+
// Also copy to system clipboard if possible
|
|
1865
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
1866
|
+
navigator.clipboard.writeText(JSON.stringify(copyData, null, 2));
|
|
1867
|
+
}
|
|
1868
|
+
console.log(`Copied object: ${node.name || node.type}`);
|
|
1869
|
+
} catch (error) {
|
|
1870
|
+
console.error('Failed to copy object:', error);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
_pasteObject(targetNode) {
|
|
1874
|
+
if (!this._clipboardData) {
|
|
1875
|
+
console.warn('No object data in clipboard');
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
try {
|
|
1879
|
+
// Create a new object based on clipboard data
|
|
1880
|
+
const newObject = this._deserializeObject(this._clipboardData);
|
|
1881
|
+
if (newObject) {
|
|
1882
|
+
// Add to the target node's parent
|
|
1883
|
+
const parent = this._findParentNode(targetNode);
|
|
1884
|
+
if (parent) {
|
|
1885
|
+
parent.object.add(newObject);
|
|
1886
|
+
this.refresh();
|
|
1887
|
+
console.log(`Pasted object to: ${parent.name || parent.type}`);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
} catch (error) {
|
|
1891
|
+
console.error('Failed to paste object:', error);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
_serializeObject(obj) {
|
|
1895
|
+
const serialized = {
|
|
1896
|
+
type: obj.type,
|
|
1897
|
+
name: obj.name,
|
|
1898
|
+
uuid: obj.uuid,
|
|
1899
|
+
visible: obj.visible,
|
|
1900
|
+
position: obj.position.toArray(),
|
|
1901
|
+
rotation: obj.rotation.toArray(),
|
|
1902
|
+
scale: obj.scale.toArray(),
|
|
1903
|
+
userData: obj.userData
|
|
1904
|
+
};
|
|
1905
|
+
// Add children if any
|
|
1906
|
+
if (obj.children.length > 0) {
|
|
1907
|
+
serialized.children = obj.children.map((child)=>this._serializeObject(child));
|
|
1908
|
+
}
|
|
1909
|
+
return serialized;
|
|
1910
|
+
}
|
|
1911
|
+
_deserializeObject(data) {
|
|
1912
|
+
try {
|
|
1913
|
+
// This is a simplified deserialization
|
|
1914
|
+
// In a real implementation, you'd want to handle different object types properly
|
|
1915
|
+
const obj = new Object3D();
|
|
1916
|
+
obj.name = data.name || data.type;
|
|
1917
|
+
obj.visible = data.visible !== undefined ? data.visible : true;
|
|
1918
|
+
if (data.position) {
|
|
1919
|
+
obj.position.set(data.position[0], data.position[1], data.position[2]);
|
|
1920
|
+
}
|
|
1921
|
+
if (data.rotation) {
|
|
1922
|
+
obj.rotation.set(data.rotation[0], data.rotation[1], data.rotation[2]);
|
|
1923
|
+
}
|
|
1924
|
+
if (data.scale) {
|
|
1925
|
+
obj.scale.set(data.scale[0], data.scale[1], data.scale[2]);
|
|
1926
|
+
}
|
|
1927
|
+
if (data.userData) {
|
|
1928
|
+
obj.userData = {
|
|
1929
|
+
...data.userData
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
return obj;
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
console.error('Failed to deserialize object:', error);
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
_findParentNode(node) {
|
|
1939
|
+
const findParent = (current, target)=>{
|
|
1940
|
+
if (current.children.includes(target)) {
|
|
1941
|
+
return current;
|
|
1942
|
+
}
|
|
1943
|
+
for (const child of current.children){
|
|
1944
|
+
const result = findParent(child, target);
|
|
1945
|
+
if (result) return result;
|
|
1946
|
+
}
|
|
1947
|
+
return null;
|
|
1948
|
+
};
|
|
1949
|
+
return findParent(this._rootNode, node);
|
|
1950
|
+
}
|
|
1951
|
+
_buildSceneTree(scene) {
|
|
1952
|
+
const buildNode = (obj)=>{
|
|
1953
|
+
const children = [];
|
|
1954
|
+
for(let i = 0; i < obj.children.length; i++){
|
|
1955
|
+
children.push(buildNode(obj.children[i]));
|
|
1956
|
+
}
|
|
1957
|
+
return {
|
|
1958
|
+
object: obj,
|
|
1959
|
+
name: obj.name || obj.type,
|
|
1960
|
+
type: obj.type,
|
|
1961
|
+
visible: obj.visible,
|
|
1962
|
+
children: children,
|
|
1963
|
+
expanded: false
|
|
1964
|
+
};
|
|
1965
|
+
};
|
|
1966
|
+
return buildNode(scene);
|
|
1967
|
+
}
|
|
1968
|
+
_renderTree() {
|
|
1969
|
+
this.$treeContainer.innerHTML = '';
|
|
1970
|
+
this._visibleNodeCount = 0; // Reset counter for each render
|
|
1971
|
+
this._renderNode(this._rootNode, 0);
|
|
1972
|
+
}
|
|
1973
|
+
_renderNode(node, depth) {
|
|
1974
|
+
const nodeElement = document.createElement('div');
|
|
1975
|
+
nodeElement.classList.add('scene-tree-node');
|
|
1976
|
+
// Remove marginLeft from the node itself to keep background full width
|
|
1977
|
+
// Add alternating background colors using theme colors
|
|
1978
|
+
// Use a simple counter that increments for each visible node
|
|
1979
|
+
const isEvenRow = this._visibleNodeCount % 2 === 0;
|
|
1980
|
+
nodeElement.classList.add(isEvenRow ? 'even-row' : 'odd-row');
|
|
1981
|
+
this._visibleNodeCount++;
|
|
1982
|
+
// Create a content wrapper for indentation
|
|
1983
|
+
const contentWrapper = document.createElement('div');
|
|
1984
|
+
contentWrapper.style.marginLeft = `${depth * 7}px`;
|
|
1985
|
+
contentWrapper.style.display = 'flex';
|
|
1986
|
+
contentWrapper.style.alignItems = 'center';
|
|
1987
|
+
contentWrapper.style.width = '100%';
|
|
1988
|
+
// Expand/collapse button
|
|
1989
|
+
if (node.children.length > 0) {
|
|
1990
|
+
const expandBtn = document.createElement('span');
|
|
1991
|
+
expandBtn.classList.add('expand-btn');
|
|
1992
|
+
expandBtn.classList.add(node.expanded ? 'expanded' : 'collapsed');
|
|
1993
|
+
expandBtn.textContent = node.expanded ? '▾' : '▸';
|
|
1994
|
+
expandBtn.addEventListener('click', (e)=>{
|
|
1995
|
+
e.stopPropagation();
|
|
1996
|
+
node.expanded = !node.expanded;
|
|
1997
|
+
this._renderTree();
|
|
1998
|
+
});
|
|
1999
|
+
contentWrapper.appendChild(expandBtn);
|
|
2000
|
+
}
|
|
2001
|
+
// Node name and type
|
|
2002
|
+
const nodeInfo = document.createElement('span');
|
|
2003
|
+
nodeInfo.textContent = `${node.name} (${node.type})`;
|
|
2004
|
+
nodeInfo.classList.add('node-info');
|
|
2005
|
+
contentWrapper.appendChild(nodeInfo);
|
|
2006
|
+
// Visibility toggle (moved after node name)
|
|
2007
|
+
const visibilityBtn = document.createElement('span');
|
|
2008
|
+
visibilityBtn.classList.add('visibility-btn');
|
|
2009
|
+
visibilityBtn.classList.add(node.visible ? 'visible' : 'hidden');
|
|
2010
|
+
visibilityBtn.innerHTML = node.visible ? '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>' : '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></svg>';
|
|
2011
|
+
visibilityBtn.addEventListener('click', (e)=>{
|
|
2012
|
+
e.stopPropagation();
|
|
2013
|
+
node.object.visible = !node.object.visible;
|
|
2014
|
+
node.visible = node.object.visible;
|
|
2015
|
+
this._renderTree();
|
|
2016
|
+
});
|
|
2017
|
+
contentWrapper.appendChild(visibilityBtn);
|
|
2018
|
+
// Add content wrapper to node
|
|
2019
|
+
nodeElement.appendChild(contentWrapper);
|
|
2020
|
+
// Selection indicator
|
|
2021
|
+
if (this._selectedObject === node.object) {
|
|
2022
|
+
nodeElement.classList.add('selected');
|
|
2023
|
+
}
|
|
2024
|
+
// Click to select
|
|
2025
|
+
nodeElement.addEventListener('click', ()=>{
|
|
2026
|
+
this._selectObject(node.object);
|
|
2027
|
+
});
|
|
2028
|
+
// Right-click for context menu
|
|
2029
|
+
nodeElement.addEventListener('contextmenu', (e)=>{
|
|
2030
|
+
e.preventDefault();
|
|
2031
|
+
e.stopPropagation();
|
|
2032
|
+
this._showContextMenu(e.clientX, e.clientY, node);
|
|
2033
|
+
});
|
|
2034
|
+
this.$treeContainer.appendChild(nodeElement);
|
|
2035
|
+
// Render children if expanded
|
|
2036
|
+
if (node.expanded) {
|
|
2037
|
+
node.children.forEach((child)=>{
|
|
2038
|
+
this._renderNode(child, depth + 1);
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
_selectObject(object) {
|
|
2043
|
+
this._selectedObject = object;
|
|
2044
|
+
this._renderTree();
|
|
2045
|
+
if (this._onObjectSelect) {
|
|
2046
|
+
this._onObjectSelect(object);
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
onObjectSelect(callback) {
|
|
2050
|
+
this._onObjectSelect = callback;
|
|
2051
|
+
return this;
|
|
2052
|
+
}
|
|
2053
|
+
refresh() {
|
|
2054
|
+
this._rootNode = this._buildSceneTree(this._scene);
|
|
2055
|
+
this._renderTree();
|
|
2056
|
+
}
|
|
2057
|
+
getSelectedObject() {
|
|
2058
|
+
return this._selectedObject;
|
|
2059
|
+
}
|
|
2060
|
+
expandAll() {
|
|
2061
|
+
const expandNode = (node)=>{
|
|
2062
|
+
node.expanded = true;
|
|
2063
|
+
node.children.forEach(expandNode);
|
|
2064
|
+
};
|
|
2065
|
+
expandNode(this._rootNode);
|
|
2066
|
+
this._renderTree();
|
|
2067
|
+
}
|
|
2068
|
+
collapseAll() {
|
|
2069
|
+
const collapseNode = (node)=>{
|
|
2070
|
+
node.expanded = false;
|
|
2071
|
+
node.children.forEach(collapseNode);
|
|
2072
|
+
};
|
|
2073
|
+
collapseNode(this._rootNode);
|
|
2074
|
+
this._renderTree();
|
|
2075
|
+
}
|
|
2076
|
+
update() {
|
|
2077
|
+
// Always update visibility states (lightweight operation)
|
|
2078
|
+
this._updateVisibilityStates(this._rootNode);
|
|
2079
|
+
// Only check for structural changes periodically to avoid performance issues
|
|
2080
|
+
if (this._autoUpdate && this._shouldCheckForChanges()) {
|
|
2081
|
+
this._checkForStructuralChanges();
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
_shouldCheckForChanges() {
|
|
2085
|
+
const now = performance.now();
|
|
2086
|
+
if (now - this._lastUpdateTime > this._updateInterval) {
|
|
2087
|
+
this._lastUpdateTime = now;
|
|
2088
|
+
return true;
|
|
2089
|
+
}
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
setAutoUpdate(enabled) {
|
|
2093
|
+
this._autoUpdate = enabled;
|
|
2094
|
+
}
|
|
2095
|
+
setUpdateInterval(intervalMs) {
|
|
2096
|
+
this._updateInterval = intervalMs;
|
|
2097
|
+
}
|
|
2098
|
+
getUpdateInterval() {
|
|
2099
|
+
return this._updateInterval;
|
|
2100
|
+
}
|
|
2101
|
+
getAutoUpdate() {
|
|
2102
|
+
return this._autoUpdate;
|
|
2103
|
+
}
|
|
2104
|
+
forceUpdate() {
|
|
2105
|
+
this._rootNode = this._buildSceneTree(this._scene);
|
|
2106
|
+
this._renderTree();
|
|
2107
|
+
}
|
|
2108
|
+
_checkForStructuralChanges() {
|
|
2109
|
+
// Use lightweight change detection instead of rebuilding the entire tree
|
|
2110
|
+
if (this._hasSceneStructureChanged()) {
|
|
2111
|
+
this._rebuildSceneTree();
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
_hasSceneStructureChanged() {
|
|
2115
|
+
// Quick check for common changes without rebuilding the tree
|
|
2116
|
+
return this._checkObjectCount() || this._checkObjectReferences();
|
|
2117
|
+
}
|
|
2118
|
+
_checkObjectCount() {
|
|
2119
|
+
// Check if the total number of objects has changed
|
|
2120
|
+
const currentCount = this._countObjects(this._scene);
|
|
2121
|
+
if (currentCount !== this._cachedObjectCount) {
|
|
2122
|
+
this._cachedObjectCount = currentCount;
|
|
2123
|
+
return true;
|
|
2124
|
+
}
|
|
2125
|
+
return false;
|
|
2126
|
+
}
|
|
2127
|
+
_checkObjectReferences() {
|
|
2128
|
+
// Check if any object references have changed (objects added/removed)
|
|
2129
|
+
return this._scene.children.length !== this._rootNode.children.length || this._hasChildrenChanged(this._scene, this._rootNode);
|
|
2130
|
+
}
|
|
2131
|
+
_hasChildrenChanged(sceneObj, treeNode) {
|
|
2132
|
+
if (sceneObj.children.length !== treeNode.children.length) return true;
|
|
2133
|
+
for(let i = 0; i < sceneObj.children.length; i++){
|
|
2134
|
+
const sceneChild = sceneObj.children[i];
|
|
2135
|
+
const treeChild = treeNode.children[i];
|
|
2136
|
+
if (sceneChild !== treeChild.object) return true;
|
|
2137
|
+
if (this._hasChildrenChanged(sceneChild, treeChild)) return true;
|
|
2138
|
+
}
|
|
2139
|
+
return false;
|
|
2140
|
+
}
|
|
2141
|
+
_countObjects(obj) {
|
|
2142
|
+
let count = 1;
|
|
2143
|
+
for(let i = 0; i < obj.children.length; i++){
|
|
2144
|
+
count += this._countObjects(obj.children[i]);
|
|
2145
|
+
}
|
|
2146
|
+
return count;
|
|
2147
|
+
}
|
|
2148
|
+
_rebuildSceneTree() {
|
|
2149
|
+
// Only rebuild when necessary
|
|
2150
|
+
const currentStructure = this._buildSceneTree(this._scene);
|
|
2151
|
+
this._preserveExpandedStates(this._rootNode, currentStructure);
|
|
2152
|
+
this._rootNode = currentStructure;
|
|
2153
|
+
this._cachedObjectCount = this._countObjects(this._scene);
|
|
2154
|
+
this._renderTree();
|
|
2155
|
+
}
|
|
2156
|
+
_hasStructureChanged(oldNode, newNode) {
|
|
2157
|
+
if (oldNode.children.length !== newNode.children.length) return true;
|
|
2158
|
+
if (oldNode.object !== newNode.object) return true;
|
|
2159
|
+
for(let i = 0; i < oldNode.children.length; i++){
|
|
2160
|
+
if (this._hasStructureChanged(oldNode.children[i], newNode.children[i])) {
|
|
2161
|
+
return true;
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
return false;
|
|
2165
|
+
}
|
|
2166
|
+
_preserveExpandedStates(oldNode, newNode) {
|
|
2167
|
+
// Try to preserve expanded states by matching object references
|
|
2168
|
+
if (oldNode.object === newNode.object) {
|
|
2169
|
+
newNode.expanded = oldNode.expanded;
|
|
2170
|
+
}
|
|
2171
|
+
for(let i = 0; i < Math.min(oldNode.children.length, newNode.children.length); i++){
|
|
2172
|
+
this._preserveExpandedStates(oldNode.children[i], newNode.children[i]);
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
_updateVisibilityStates(node) {
|
|
2176
|
+
node.visible = node.object.visible;
|
|
2177
|
+
node.children.forEach((child)=>this._updateVisibilityStates(child));
|
|
2178
|
+
}
|
|
2179
|
+
destroy() {
|
|
2180
|
+
super.destroy();
|
|
2181
|
+
this._onObjectSelect = null;
|
|
2182
|
+
// Clean up context menu
|
|
2183
|
+
if (this._contextMenu && this._contextMenu.parentNode) {
|
|
2184
|
+
this._contextMenu.parentNode.removeChild(this._contextMenu);
|
|
2185
|
+
}
|
|
2186
|
+
this._contextMenu = null;
|
|
2187
|
+
this._contextMenuTarget = null;
|
|
2188
|
+
this._clipboardData = null;
|
|
2189
|
+
}
|
|
2190
|
+
constructor(parent, scene){
|
|
2191
|
+
super(parent, scene, 'sceneTree', 'scene-tree-controller', 'div'), this._selectedObject = null, this._onObjectSelect = null, this._autoUpdate = true, this._cachedObjectCount = 0, this._lastUpdateTime = 0, this._updateInterval = 1000 // Only check for changes every 1 second
|
|
2192
|
+
, this._visibleNodeCount = 0 // Counter for alternating background colors
|
|
2193
|
+
, // Context menu properties
|
|
2194
|
+
this._contextMenu = null, this._contextMenuTarget = null, this._clipboardData = null;
|
|
2195
|
+
this._scene = scene;
|
|
2196
|
+
this._rootNode = this._buildSceneTree(scene);
|
|
2197
|
+
this._cachedObjectCount = this._countObjects(scene);
|
|
2198
|
+
this._setupDOM();
|
|
2199
|
+
this._createContextMenu();
|
|
2200
|
+
this._renderTree();
|
|
2201
|
+
this._setupGlobalEventListeners();
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
|
|
1739
2205
|
class GUI {
|
|
1740
2206
|
/**
|
|
1741
2207
|
* Adds a controller to the GUI, inferring controller type using the `typeof` operator.
|
|
@@ -1810,6 +2276,13 @@ class GUI {
|
|
|
1810
2276
|
addCurve(object, property) {
|
|
1811
2277
|
return new CurveController(this, object, property);
|
|
1812
2278
|
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Adds a scene tree controller to display Three.js scene hierarchy.
|
|
2281
|
+
* @param {Scene} scene The Three.js scene to display
|
|
2282
|
+
* @returns {SceneTreeController}
|
|
2283
|
+
*/ addSceneTree(scene) {
|
|
2284
|
+
return new SceneTreeController(this, scene);
|
|
2285
|
+
}
|
|
1813
2286
|
/**
|
|
1814
2287
|
* Adds a folder to the GUI, which is just another GUI. This method returns
|
|
1815
2288
|
* the nested GUI so you can add controllers to it.
|
|
@@ -1819,8 +2292,6 @@ class GUI {
|
|
|
1819
2292
|
* folder.add( position, 'y' );
|
|
1820
2293
|
* folder.add( position, 'z' );
|
|
1821
2294
|
*
|
|
1822
|
-
* @param {string} title Name to display in the folder's title bar.
|
|
1823
|
-
* @param {string} id Id
|
|
1824
2295
|
* @returns {GUI}
|
|
1825
2296
|
*/ addFolder(title, id = title) {
|
|
1826
2297
|
const folder = new GUI({
|
|
@@ -2116,6 +2587,25 @@ class GUI {
|
|
|
2116
2587
|
child.update();
|
|
2117
2588
|
}
|
|
2118
2589
|
}
|
|
2590
|
+
/**
|
|
2591
|
+
* Sets this folder as active and deactivates all other folders
|
|
2592
|
+
*/ setActive() {
|
|
2593
|
+
// Only root GUI can manage active states
|
|
2594
|
+
if (!this.parent) return;
|
|
2595
|
+
// Remove active class from ALL folders in the entire GUI tree using DOM query
|
|
2596
|
+
const allActiveFolders = document.querySelectorAll('.lil-gui.active');
|
|
2597
|
+
allActiveFolders.forEach((folder)=>{
|
|
2598
|
+
folder.classList.remove('active');
|
|
2599
|
+
});
|
|
2600
|
+
// Add active class to this folder
|
|
2601
|
+
this.domElement.classList.add('active');
|
|
2602
|
+
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Gets the currently active folder
|
|
2605
|
+
*/ getActiveFolder() {
|
|
2606
|
+
if (!this.parent) return null;
|
|
2607
|
+
return this.parent.folders.find((folder)=>folder.domElement.classList.contains('active')) || null;
|
|
2608
|
+
}
|
|
2119
2609
|
constructor({ parent, container, width, autoPlace = parent === undefined, title = 'Controls', id = title, closeFolders = false, touchStyles = true } = {}){
|
|
2120
2610
|
this.children = [];
|
|
2121
2611
|
this.controllers = [];
|
|
@@ -2137,6 +2627,8 @@ class GUI {
|
|
|
2137
2627
|
this.$title.setAttribute('aria-expanded', "true");
|
|
2138
2628
|
this.$title.setAttribute('tabindex', "0");
|
|
2139
2629
|
this.$title.addEventListener('click', ()=>{
|
|
2630
|
+
// Set this folder as active and deactivate others
|
|
2631
|
+
this.setActive();
|
|
2140
2632
|
this.openAnimated(this._closed);
|
|
2141
2633
|
});
|
|
2142
2634
|
this.$title.addEventListener('keydown', (e)=>{
|
|
@@ -2195,7 +2687,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
2195
2687
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2196
2688
|
PERFORMANCE OF THIS SOFTWARE.
|
|
2197
2689
|
***************************************************************************** */
|
|
2198
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
2690
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
2199
2691
|
|
|
2200
2692
|
|
|
2201
2693
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -2351,67 +2843,74 @@ __decorate([
|
|
|
2351
2843
|
property
|
|
2352
2844
|
], ViewerHelper.prototype, "targetFrameRate", null);
|
|
2353
2845
|
|
|
2354
|
-
|
|
2846
|
+
const vert_Sprite = `
|
|
2847
|
+
uniform vec4 u_transform;
|
|
2848
|
+
uniform vec4 u_resolution;
|
|
2849
|
+
varying vec2 v_uv;
|
|
2850
|
+
|
|
2851
|
+
void main() {
|
|
2852
|
+
vec2 pos = u_transform.xy + u_transform.zw * 0.5 + position.xy * u_transform.zw;
|
|
2853
|
+
vec2 ndc = pos * u_resolution.zw * 2. - 1.;
|
|
2854
|
+
gl_Position = vec4(ndc, 0., 1.);
|
|
2855
|
+
v_uv = uv;
|
|
2856
|
+
}
|
|
2857
|
+
`;
|
|
2858
|
+
const frag_Sprite = `
|
|
2859
|
+
uniform sampler2D u_texture;
|
|
2860
|
+
varying vec2 v_uv;
|
|
2861
|
+
|
|
2862
|
+
void main() {
|
|
2863
|
+
gl_FragColor = texture2D(u_texture, v_uv);
|
|
2864
|
+
}
|
|
2865
|
+
`;
|
|
2866
|
+
class Inspector extends Component {
|
|
2355
2867
|
onLoad() {
|
|
2356
2868
|
const { width, height } = this.viewer;
|
|
2357
|
-
this.
|
|
2358
|
-
this.
|
|
2869
|
+
this._spriteUniforms.u_resolution.value.set(width, height, 1 / width, 1 / height);
|
|
2870
|
+
this._sprite = new Mesh(new PlaneGeometry(1, 1, 1, 1), new ShaderMaterial({
|
|
2871
|
+
side: DoubleSide,
|
|
2872
|
+
vertexShader: vert_Sprite,
|
|
2873
|
+
fragmentShader: frag_Sprite,
|
|
2874
|
+
uniforms: this._spriteUniforms
|
|
2875
|
+
}));
|
|
2876
|
+
this._sprite.frustumCulled = false;
|
|
2877
|
+
this._camera.viewport = new Vector4(0, 0, 256, 256);
|
|
2359
2878
|
this._gui = new GUI({
|
|
2360
2879
|
width: 310,
|
|
2361
2880
|
title: "Inspector"
|
|
2362
2881
|
}).close();
|
|
2882
|
+
this._tree = this._gui.addSceneTree(this.viewer.scene);
|
|
2363
2883
|
this._gui.addFolder("Viewer").close().hide();
|
|
2364
2884
|
this._gui.addFolder("Component").close().hide();
|
|
2365
2885
|
this._gui.addFolder("Material").close().hide();
|
|
2366
2886
|
this._gui.addFolder("Other").close().hide();
|
|
2367
2887
|
this._inspect(new ViewerHelper(this.viewer));
|
|
2368
|
-
this._addSprite();
|
|
2369
2888
|
}
|
|
2370
2889
|
onDestroy() {
|
|
2890
|
+
if (this._tree) {
|
|
2891
|
+
this._tree.destroy();
|
|
2892
|
+
}
|
|
2371
2893
|
this._gui.destroy();
|
|
2372
2894
|
this._refCntMap.clear();
|
|
2373
2895
|
this._targetMap.clear();
|
|
2374
2896
|
}
|
|
2375
2897
|
update(dt) {
|
|
2376
2898
|
this._gui.update();
|
|
2899
|
+
if (this._tree) {
|
|
2900
|
+
this._tree.update();
|
|
2901
|
+
}
|
|
2377
2902
|
this._updateFolders();
|
|
2378
2903
|
}
|
|
2379
2904
|
resize(width, height) {
|
|
2380
|
-
this.
|
|
2381
|
-
this._camera.right = width;
|
|
2382
|
-
this._camera.top = height;
|
|
2383
|
-
this._camera.bottom = 0;
|
|
2384
|
-
this._camera.updateProjectionMatrix();
|
|
2385
|
-
}
|
|
2386
|
-
_addSprite() {
|
|
2387
|
-
const viewer = this.viewer;
|
|
2388
|
-
this._sprite = viewer.add(Sprite, {
|
|
2389
|
-
parent: this._scene,
|
|
2390
|
-
scale: new Vector3(256, 256, 1),
|
|
2391
|
-
position: new Vector3(viewer.width / 2, viewer.height / 2),
|
|
2392
|
-
visible: false
|
|
2393
|
-
});
|
|
2394
|
-
}
|
|
2395
|
-
_renderScene() {
|
|
2396
|
-
const { renderer } = this.viewer;
|
|
2397
|
-
const autoClearDepth = renderer.autoClearDepth;
|
|
2398
|
-
const autoClearColor = renderer.autoClearColor;
|
|
2399
|
-
renderer.autoClearDepth = true;
|
|
2400
|
-
renderer.autoClearColor = false;
|
|
2401
|
-
renderer.render(this._scene, this._camera);
|
|
2402
|
-
renderer.autoClearDepth = autoClearDepth;
|
|
2403
|
-
renderer.autoClearColor = autoClearColor;
|
|
2404
|
-
return renderer.domElement;
|
|
2905
|
+
this._spriteUniforms.u_resolution.value.set(width, height, 1 / width, 1 / height);
|
|
2405
2906
|
}
|
|
2406
2907
|
_renderSprite(texture, w, h) {
|
|
2407
|
-
this.
|
|
2408
|
-
this.
|
|
2409
|
-
this.
|
|
2410
|
-
this.
|
|
2411
|
-
this.
|
|
2412
|
-
|
|
2413
|
-
this._sprite.visible = false;
|
|
2414
|
-
return dom;
|
|
2908
|
+
const resolution = this._spriteUniforms.u_resolution.value;
|
|
2909
|
+
this._camera.viewport.set(0, resolution.y - h, w, h);
|
|
2910
|
+
this._spriteUniforms.u_transform.value.set(0, resolution.y - h, w, h);
|
|
2911
|
+
this._spriteUniforms.u_texture.value = texture;
|
|
2912
|
+
this.viewer.render(null, this._sprite, this._camera, 0, 0);
|
|
2913
|
+
return this.viewer.canvas;
|
|
2415
2914
|
}
|
|
2416
2915
|
_updateFolders() {
|
|
2417
2916
|
const refCntMap = this._refCntMap;
|
|
@@ -2420,8 +2919,14 @@ class Inspector extends Mount {
|
|
|
2420
2919
|
if (refCntMap.get(v) === undefined) refCntMap.set(v, 1);
|
|
2421
2920
|
};
|
|
2422
2921
|
refCntMap.forEach((_, k, map)=>map.set(k, -1));
|
|
2423
|
-
this.viewer
|
|
2424
|
-
|
|
2922
|
+
const { scene, componentManager } = this.viewer;
|
|
2923
|
+
scene.traverse((item)=>{
|
|
2924
|
+
if (item.material) {
|
|
2925
|
+
if (Array.isArray(item.material)) item.material.forEach(setState);
|
|
2926
|
+
else setState(item.material);
|
|
2927
|
+
}
|
|
2928
|
+
});
|
|
2929
|
+
componentManager.traverseComponents(setState);
|
|
2425
2930
|
refCntMap.forEach((v, k, map)=>{
|
|
2426
2931
|
if (v === 1) {
|
|
2427
2932
|
this._inspect(k);
|
|
@@ -2497,12 +3002,16 @@ class Inspector extends Mount {
|
|
|
2497
3002
|
this._addGUI(folder, this._getPropertiesList(value), target, k);
|
|
2498
3003
|
}
|
|
2499
3004
|
if (Array.isArray(value)) {
|
|
2500
|
-
|
|
2501
|
-
value.
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
3005
|
+
if (prop.flat) {
|
|
3006
|
+
value.forEach((v)=>this._addGUI(folder, this._getPropertiesList(v), v, v.constructor.name));
|
|
3007
|
+
} else {
|
|
3008
|
+
this._addGUI(folder, [
|
|
3009
|
+
value.map((_, i)=>[
|
|
3010
|
+
i.toString(),
|
|
3011
|
+
{}
|
|
3012
|
+
])
|
|
3013
|
+
], value, k);
|
|
3014
|
+
}
|
|
2506
3015
|
} else {
|
|
2507
3016
|
const type = typeof value;
|
|
2508
3017
|
let ins = null;
|
|
@@ -2540,11 +3049,20 @@ class Inspector extends Mount {
|
|
|
2540
3049
|
}
|
|
2541
3050
|
}
|
|
2542
3051
|
constructor(...args){
|
|
2543
|
-
super(...args)
|
|
2544
|
-
|
|
2545
|
-
|
|
3052
|
+
super(...args), this._camera = new Camera(), this._sprite = null, this._spriteUniforms = {
|
|
3053
|
+
u_texture: {
|
|
3054
|
+
value: null
|
|
3055
|
+
},
|
|
3056
|
+
u_transform: {
|
|
3057
|
+
value: new Vector4()
|
|
3058
|
+
},
|
|
3059
|
+
u_resolution: {
|
|
3060
|
+
value: new Vector4()
|
|
3061
|
+
}
|
|
3062
|
+
}, this._refCntMap = new Map(), this._targetMap = new Map();
|
|
2546
3063
|
}
|
|
2547
3064
|
}
|
|
3065
|
+
Inspector.viewport = new Vector4();
|
|
2548
3066
|
function targetName(target) {
|
|
2549
3067
|
return target.name || target.constructor.name || target.type;
|
|
2550
3068
|
}
|
|
@@ -2922,7 +3440,7 @@ var Stats$1 = function() {
|
|
|
2922
3440
|
};
|
|
2923
3441
|
};
|
|
2924
3442
|
|
|
2925
|
-
class Stats extends
|
|
3443
|
+
class Stats extends Component {
|
|
2926
3444
|
onLoad() {
|
|
2927
3445
|
this._stats.addPanel(this._dcPanel);
|
|
2928
3446
|
this._stats.addPanel(this._texPanel);
|
|
@@ -2943,34 +3461,9 @@ class Stats extends Mount {
|
|
|
2943
3461
|
this._stats.update();
|
|
2944
3462
|
}
|
|
2945
3463
|
constructor(...args){
|
|
2946
|
-
super(...args);
|
|
2947
|
-
this._stats = new Stats$1();
|
|
2948
|
-
this._dcPanel = new Panel('DC', '#ff8', '#221');
|
|
2949
|
-
this._triPanel = new Panel("TRI", '#ff8', '#221');
|
|
2950
|
-
this._texPanel = new Panel('TEX', '#ff8', '#221');
|
|
2951
|
-
this._prgPanel = new Panel('PRG', '#ff8', '#221');
|
|
2952
|
-
}
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
class BoxProjectionHelper extends Mount {
|
|
2956
|
-
onLoad() {
|
|
2957
|
-
this._box3 = new Box3();
|
|
2958
|
-
this._target = this.viewer.mount(BoxProjection);
|
|
2959
|
-
this._helper = this.viewer.add(new Box3Helper(this._box3));
|
|
2960
|
-
}
|
|
2961
|
-
onEnable() {
|
|
2962
|
-
this._helper.visible = true;
|
|
2963
|
-
}
|
|
2964
|
-
onDisable() {
|
|
2965
|
-
this._helper.visible = false;
|
|
2966
|
-
}
|
|
2967
|
-
update(dt) {
|
|
2968
|
-
const { center, boxMin, boxMax } = this._target;
|
|
2969
|
-
this._box3.min.copy(center).add(boxMin);
|
|
2970
|
-
this._box3.max.copy(center).add(boxMax);
|
|
2971
|
-
this._helper.updateMatrixWorld();
|
|
3464
|
+
super(...args), this._stats = new Stats$1(), this._dcPanel = new Panel('DC', '#ff8', '#221'), this._triPanel = new Panel("TRI", '#ff8', '#221'), this._texPanel = new Panel('TEX', '#ff8', '#221'), this._prgPanel = new Panel('PRG', '#ff8', '#221');
|
|
2972
3465
|
}
|
|
2973
3466
|
}
|
|
2974
3467
|
|
|
2975
|
-
export {
|
|
3468
|
+
export { GUI, Inspector, Stats };
|
|
2976
3469
|
//# sourceMappingURL=module.js.map
|