@xviewer.js/debug 1.0.3 → 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/main.cjs
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var three = require('three');
|
|
4
|
+
var Addons = require('three/examples/jsm/Addons');
|
|
5
|
+
var TextureUtils = require('three/examples/jsm/utils/WebGLTextureUtils');
|
|
4
6
|
var core = require('@xviewer.js/core');
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var TextureUtils__namespace = /*#__PURE__*/_interopNamespaceDefault(TextureUtils);
|
|
7
26
|
|
|
8
|
-
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}";
|
|
27
|
+
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}}
|
|
28
|
+
|
|
29
|
+
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";
|
|
9
30
|
n(css,{});
|
|
10
31
|
|
|
11
32
|
class Controller {
|
|
@@ -319,13 +340,7 @@ class OptionController extends Controller {
|
|
|
319
340
|
this.$select.setAttribute('aria-labelledby', this.$name.id);
|
|
320
341
|
this.$display = document.createElement('div');
|
|
321
342
|
this.$display.classList.add('display');
|
|
322
|
-
this.
|
|
323
|
-
this._names = Array.isArray(options) ? options : Object.keys(options);
|
|
324
|
-
this._names.forEach((name)=>{
|
|
325
|
-
const $option = document.createElement('option');
|
|
326
|
-
$option.innerHTML = name;
|
|
327
|
-
this.$select.appendChild($option);
|
|
328
|
-
});
|
|
343
|
+
this.options(options);
|
|
329
344
|
this.$select.addEventListener('change', ()=>{
|
|
330
345
|
this.setValue(this._values[this.$select.selectedIndex]);
|
|
331
346
|
this._callOnFinishChange();
|
|
@@ -883,10 +898,7 @@ class ColorController extends Controller {
|
|
|
883
898
|
return this;
|
|
884
899
|
}
|
|
885
900
|
constructor(parent, object, property, rgbScale){
|
|
886
|
-
super(parent, object, property, 'color');
|
|
887
|
-
this._textFocused = false;
|
|
888
|
-
this._initialValueHexString = "";
|
|
889
|
-
this._rgbScale = 1;
|
|
901
|
+
super(parent, object, property, 'color'), this._textFocused = false, this._initialValueHexString = "", this._rgbScale = 1;
|
|
890
902
|
this.$input = document.createElement('input');
|
|
891
903
|
this.$input.setAttribute('type', 'color');
|
|
892
904
|
this.$input.setAttribute('tabindex', "-1");
|
|
@@ -1042,13 +1054,7 @@ class UINumber extends UIElement {
|
|
|
1042
1054
|
return this;
|
|
1043
1055
|
}
|
|
1044
1056
|
constructor(value, min, max, step){
|
|
1045
|
-
super(document.createElement('input'));
|
|
1046
|
-
this.value = 0;
|
|
1047
|
-
this.min = -Infinity;
|
|
1048
|
-
this.max = Infinity;
|
|
1049
|
-
this.step = 1;
|
|
1050
|
-
this.nudge = 1;
|
|
1051
|
-
this.unit = "";
|
|
1057
|
+
super(document.createElement('input')), this.value = 0, this.min = -Infinity, this.max = Infinity, this.step = 1, this.nudge = 1, this.unit = "";
|
|
1052
1058
|
this.dom.style.cursor = 'ns-resize';
|
|
1053
1059
|
this.dom.value = '0.00';
|
|
1054
1060
|
this.min = min != null ? min : this.min;
|
|
@@ -1706,7 +1712,7 @@ class TextureController extends Controller {
|
|
|
1706
1712
|
canvas.title = texture.sourceFile || "";
|
|
1707
1713
|
canvas.height = canvas.width / image.width * image.height;
|
|
1708
1714
|
if (this.getImage) {
|
|
1709
|
-
const w = 256, h = 256 / image.width * image.height;
|
|
1715
|
+
const w = 256, h = Math.floor(256 / image.width * image.height);
|
|
1710
1716
|
context.drawImage(this.getImage(texture, w, h), 0, 0, w * 1.5, h * 1.5, 0, 0, canvas.width, canvas.height); //why 1.5 ?
|
|
1711
1717
|
}
|
|
1712
1718
|
} else {
|
|
@@ -1718,8 +1724,7 @@ class TextureController extends Controller {
|
|
|
1718
1724
|
return this;
|
|
1719
1725
|
}
|
|
1720
1726
|
constructor(parent, object, property){
|
|
1721
|
-
super(parent, object, property, "texture");
|
|
1722
|
-
this._autoRefresh = false;
|
|
1727
|
+
super(parent, object, property, "texture"), this._autoRefresh = false;
|
|
1723
1728
|
const group = this.$widget.appendChild(document.createElement("div"));
|
|
1724
1729
|
group.classList.add("group");
|
|
1725
1730
|
this.$canvas = group.appendChild(document.createElement("canvas"));
|
|
@@ -1738,6 +1743,486 @@ class TextureController extends Controller {
|
|
|
1738
1743
|
}
|
|
1739
1744
|
}
|
|
1740
1745
|
|
|
1746
|
+
class SceneTreeController extends Controller {
|
|
1747
|
+
_setupDOM() {
|
|
1748
|
+
// Hide the name element since we don't need it for scene tree
|
|
1749
|
+
this.$name.style.display = 'none';
|
|
1750
|
+
this.$treeContainer = document.createElement('div');
|
|
1751
|
+
this.$treeContainer.classList.add('scene-tree-container');
|
|
1752
|
+
this.$widget.appendChild(this.$treeContainer);
|
|
1753
|
+
}
|
|
1754
|
+
_createContextMenu() {
|
|
1755
|
+
this._contextMenu = document.createElement('div');
|
|
1756
|
+
this._contextMenu.classList.add('scene-tree-context-menu');
|
|
1757
|
+
this._contextMenu.style.display = 'none';
|
|
1758
|
+
const menuItems = [
|
|
1759
|
+
{
|
|
1760
|
+
label: 'Export',
|
|
1761
|
+
action: 'export'
|
|
1762
|
+
},
|
|
1763
|
+
{
|
|
1764
|
+
label: 'Copy',
|
|
1765
|
+
action: 'copy'
|
|
1766
|
+
},
|
|
1767
|
+
{
|
|
1768
|
+
label: 'Paste',
|
|
1769
|
+
action: 'paste'
|
|
1770
|
+
}
|
|
1771
|
+
];
|
|
1772
|
+
menuItems.forEach((item)=>{
|
|
1773
|
+
const menuItem = document.createElement('div');
|
|
1774
|
+
menuItem.classList.add('context-menu-item');
|
|
1775
|
+
menuItem.dataset.action = item.action;
|
|
1776
|
+
menuItem.textContent = item.label;
|
|
1777
|
+
menuItem.addEventListener('click', ()=>this._handleContextMenuAction(item.action));
|
|
1778
|
+
this._contextMenu.appendChild(menuItem);
|
|
1779
|
+
});
|
|
1780
|
+
document.body.appendChild(this._contextMenu);
|
|
1781
|
+
}
|
|
1782
|
+
_setupGlobalEventListeners() {
|
|
1783
|
+
// Hide context menu when clicking outside
|
|
1784
|
+
document.addEventListener('click', (e)=>{
|
|
1785
|
+
if (this._contextMenu && !this._contextMenu.contains(e.target)) {
|
|
1786
|
+
this._hideContextMenu();
|
|
1787
|
+
}
|
|
1788
|
+
});
|
|
1789
|
+
// Hide context menu on escape key
|
|
1790
|
+
document.addEventListener('keydown', (e)=>{
|
|
1791
|
+
if (e.key === 'Escape') {
|
|
1792
|
+
this._hideContextMenu();
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
_showContextMenu(x, y, target) {
|
|
1797
|
+
if (!this._contextMenu) return;
|
|
1798
|
+
this._contextMenuTarget = target;
|
|
1799
|
+
this._contextMenu.style.display = 'block';
|
|
1800
|
+
// Update paste menu item state based on clipboard
|
|
1801
|
+
this._updateContextMenuState();
|
|
1802
|
+
// Position the menu
|
|
1803
|
+
const rect = this._contextMenu.getBoundingClientRect();
|
|
1804
|
+
const viewportWidth = window.innerWidth;
|
|
1805
|
+
const viewportHeight = window.innerHeight;
|
|
1806
|
+
// Adjust position if menu would go off-screen
|
|
1807
|
+
let adjustedX = x;
|
|
1808
|
+
let adjustedY = y;
|
|
1809
|
+
if (x + rect.width > viewportWidth) {
|
|
1810
|
+
adjustedX = x - rect.width;
|
|
1811
|
+
}
|
|
1812
|
+
if (y + rect.height > viewportHeight) {
|
|
1813
|
+
adjustedY = y - rect.height;
|
|
1814
|
+
}
|
|
1815
|
+
this._contextMenu.style.left = `${adjustedX}px`;
|
|
1816
|
+
this._contextMenu.style.top = `${adjustedY}px`;
|
|
1817
|
+
}
|
|
1818
|
+
_updateContextMenuState() {
|
|
1819
|
+
if (!this._contextMenu) return;
|
|
1820
|
+
const pasteItem = this._contextMenu.querySelector('[data-action="paste"]');
|
|
1821
|
+
if (pasteItem) {
|
|
1822
|
+
if (this._clipboardData) {
|
|
1823
|
+
pasteItem.classList.remove('disabled');
|
|
1824
|
+
pasteItem.style.cursor = 'pointer';
|
|
1825
|
+
} else {
|
|
1826
|
+
pasteItem.classList.add('disabled');
|
|
1827
|
+
pasteItem.style.cursor = 'not-allowed';
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
_hideContextMenu() {
|
|
1832
|
+
if (this._contextMenu) {
|
|
1833
|
+
this._contextMenu.style.display = 'none';
|
|
1834
|
+
}
|
|
1835
|
+
this._contextMenuTarget = null;
|
|
1836
|
+
}
|
|
1837
|
+
_handleContextMenuAction(action) {
|
|
1838
|
+
if (!this._contextMenuTarget) return;
|
|
1839
|
+
switch(action){
|
|
1840
|
+
case 'export':
|
|
1841
|
+
this._exportObject(this._contextMenuTarget);
|
|
1842
|
+
break;
|
|
1843
|
+
case 'copy':
|
|
1844
|
+
this._copyObject(this._contextMenuTarget);
|
|
1845
|
+
break;
|
|
1846
|
+
case 'paste':
|
|
1847
|
+
if (this._clipboardData) {
|
|
1848
|
+
this._pasteObject(this._contextMenuTarget);
|
|
1849
|
+
}
|
|
1850
|
+
break;
|
|
1851
|
+
}
|
|
1852
|
+
this._hideContextMenu();
|
|
1853
|
+
}
|
|
1854
|
+
_exportObject(node) {
|
|
1855
|
+
try {
|
|
1856
|
+
new Addons.GLTFExporter().setTextureUtils(TextureUtils__namespace).parse(node.object, (result)=>{
|
|
1857
|
+
if (result instanceof ArrayBuffer) {
|
|
1858
|
+
const blob = new Blob([
|
|
1859
|
+
result
|
|
1860
|
+
], {
|
|
1861
|
+
type: 'application/octet-stream'
|
|
1862
|
+
});
|
|
1863
|
+
const url = URL.createObjectURL(blob);
|
|
1864
|
+
const link = document.createElement('a');
|
|
1865
|
+
link.href = url;
|
|
1866
|
+
link.download = `${node.name || node.type}.glb`;
|
|
1867
|
+
link.click();
|
|
1868
|
+
}
|
|
1869
|
+
}, (err)=>{
|
|
1870
|
+
console.log('An error happened during parsing', err);
|
|
1871
|
+
}, {
|
|
1872
|
+
trs: false,
|
|
1873
|
+
binary: true,
|
|
1874
|
+
maxTextureSize: 4096
|
|
1875
|
+
});
|
|
1876
|
+
console.log(`Exported object: ${node.name || node.type}`);
|
|
1877
|
+
} catch (error) {
|
|
1878
|
+
console.error('Failed to export object:', error);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
_copyObject(node) {
|
|
1882
|
+
try {
|
|
1883
|
+
const copyData = this._serializeObject(node.object);
|
|
1884
|
+
this._clipboardData = copyData;
|
|
1885
|
+
// Also copy to system clipboard if possible
|
|
1886
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
1887
|
+
navigator.clipboard.writeText(JSON.stringify(copyData, null, 2));
|
|
1888
|
+
}
|
|
1889
|
+
console.log(`Copied object: ${node.name || node.type}`);
|
|
1890
|
+
} catch (error) {
|
|
1891
|
+
console.error('Failed to copy object:', error);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
_pasteObject(targetNode) {
|
|
1895
|
+
if (!this._clipboardData) {
|
|
1896
|
+
console.warn('No object data in clipboard');
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
try {
|
|
1900
|
+
// Create a new object based on clipboard data
|
|
1901
|
+
const newObject = this._deserializeObject(this._clipboardData);
|
|
1902
|
+
if (newObject) {
|
|
1903
|
+
// Add to the target node's parent
|
|
1904
|
+
const parent = this._findParentNode(targetNode);
|
|
1905
|
+
if (parent) {
|
|
1906
|
+
parent.object.add(newObject);
|
|
1907
|
+
this.refresh();
|
|
1908
|
+
console.log(`Pasted object to: ${parent.name || parent.type}`);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
} catch (error) {
|
|
1912
|
+
console.error('Failed to paste object:', error);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
_serializeObject(obj) {
|
|
1916
|
+
const serialized = {
|
|
1917
|
+
type: obj.type,
|
|
1918
|
+
name: obj.name,
|
|
1919
|
+
uuid: obj.uuid,
|
|
1920
|
+
visible: obj.visible,
|
|
1921
|
+
position: obj.position.toArray(),
|
|
1922
|
+
rotation: obj.rotation.toArray(),
|
|
1923
|
+
scale: obj.scale.toArray(),
|
|
1924
|
+
userData: obj.userData
|
|
1925
|
+
};
|
|
1926
|
+
// Add children if any
|
|
1927
|
+
if (obj.children.length > 0) {
|
|
1928
|
+
serialized.children = obj.children.map((child)=>this._serializeObject(child));
|
|
1929
|
+
}
|
|
1930
|
+
return serialized;
|
|
1931
|
+
}
|
|
1932
|
+
_deserializeObject(data) {
|
|
1933
|
+
try {
|
|
1934
|
+
// This is a simplified deserialization
|
|
1935
|
+
// In a real implementation, you'd want to handle different object types properly
|
|
1936
|
+
const obj = new three.Object3D();
|
|
1937
|
+
obj.name = data.name || data.type;
|
|
1938
|
+
obj.visible = data.visible !== undefined ? data.visible : true;
|
|
1939
|
+
if (data.position) {
|
|
1940
|
+
obj.position.set(data.position[0], data.position[1], data.position[2]);
|
|
1941
|
+
}
|
|
1942
|
+
if (data.rotation) {
|
|
1943
|
+
obj.rotation.set(data.rotation[0], data.rotation[1], data.rotation[2]);
|
|
1944
|
+
}
|
|
1945
|
+
if (data.scale) {
|
|
1946
|
+
obj.scale.set(data.scale[0], data.scale[1], data.scale[2]);
|
|
1947
|
+
}
|
|
1948
|
+
if (data.userData) {
|
|
1949
|
+
obj.userData = {
|
|
1950
|
+
...data.userData
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
return obj;
|
|
1954
|
+
} catch (error) {
|
|
1955
|
+
console.error('Failed to deserialize object:', error);
|
|
1956
|
+
return null;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
_findParentNode(node) {
|
|
1960
|
+
const findParent = (current, target)=>{
|
|
1961
|
+
if (current.children.includes(target)) {
|
|
1962
|
+
return current;
|
|
1963
|
+
}
|
|
1964
|
+
for (const child of current.children){
|
|
1965
|
+
const result = findParent(child, target);
|
|
1966
|
+
if (result) return result;
|
|
1967
|
+
}
|
|
1968
|
+
return null;
|
|
1969
|
+
};
|
|
1970
|
+
return findParent(this._rootNode, node);
|
|
1971
|
+
}
|
|
1972
|
+
_buildSceneTree(scene) {
|
|
1973
|
+
const buildNode = (obj)=>{
|
|
1974
|
+
const children = [];
|
|
1975
|
+
for(let i = 0; i < obj.children.length; i++){
|
|
1976
|
+
children.push(buildNode(obj.children[i]));
|
|
1977
|
+
}
|
|
1978
|
+
return {
|
|
1979
|
+
object: obj,
|
|
1980
|
+
name: obj.name || obj.type,
|
|
1981
|
+
type: obj.type,
|
|
1982
|
+
visible: obj.visible,
|
|
1983
|
+
children: children,
|
|
1984
|
+
expanded: false
|
|
1985
|
+
};
|
|
1986
|
+
};
|
|
1987
|
+
return buildNode(scene);
|
|
1988
|
+
}
|
|
1989
|
+
_renderTree() {
|
|
1990
|
+
this.$treeContainer.innerHTML = '';
|
|
1991
|
+
this._visibleNodeCount = 0; // Reset counter for each render
|
|
1992
|
+
this._renderNode(this._rootNode, 0);
|
|
1993
|
+
}
|
|
1994
|
+
_renderNode(node, depth) {
|
|
1995
|
+
const nodeElement = document.createElement('div');
|
|
1996
|
+
nodeElement.classList.add('scene-tree-node');
|
|
1997
|
+
// Remove marginLeft from the node itself to keep background full width
|
|
1998
|
+
// Add alternating background colors using theme colors
|
|
1999
|
+
// Use a simple counter that increments for each visible node
|
|
2000
|
+
const isEvenRow = this._visibleNodeCount % 2 === 0;
|
|
2001
|
+
nodeElement.classList.add(isEvenRow ? 'even-row' : 'odd-row');
|
|
2002
|
+
this._visibleNodeCount++;
|
|
2003
|
+
// Create a content wrapper for indentation
|
|
2004
|
+
const contentWrapper = document.createElement('div');
|
|
2005
|
+
contentWrapper.style.marginLeft = `${depth * 7}px`;
|
|
2006
|
+
contentWrapper.style.display = 'flex';
|
|
2007
|
+
contentWrapper.style.alignItems = 'center';
|
|
2008
|
+
contentWrapper.style.width = '100%';
|
|
2009
|
+
// Expand/collapse button
|
|
2010
|
+
if (node.children.length > 0) {
|
|
2011
|
+
const expandBtn = document.createElement('span');
|
|
2012
|
+
expandBtn.classList.add('expand-btn');
|
|
2013
|
+
expandBtn.classList.add(node.expanded ? 'expanded' : 'collapsed');
|
|
2014
|
+
expandBtn.textContent = node.expanded ? '▾' : '▸';
|
|
2015
|
+
expandBtn.addEventListener('click', (e)=>{
|
|
2016
|
+
e.stopPropagation();
|
|
2017
|
+
node.expanded = !node.expanded;
|
|
2018
|
+
this._renderTree();
|
|
2019
|
+
});
|
|
2020
|
+
contentWrapper.appendChild(expandBtn);
|
|
2021
|
+
}
|
|
2022
|
+
// Node name and type
|
|
2023
|
+
const nodeInfo = document.createElement('span');
|
|
2024
|
+
nodeInfo.textContent = `${node.name} (${node.type})`;
|
|
2025
|
+
nodeInfo.classList.add('node-info');
|
|
2026
|
+
contentWrapper.appendChild(nodeInfo);
|
|
2027
|
+
// Visibility toggle (moved after node name)
|
|
2028
|
+
const visibilityBtn = document.createElement('span');
|
|
2029
|
+
visibilityBtn.classList.add('visibility-btn');
|
|
2030
|
+
visibilityBtn.classList.add(node.visible ? 'visible' : 'hidden');
|
|
2031
|
+
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>';
|
|
2032
|
+
visibilityBtn.addEventListener('click', (e)=>{
|
|
2033
|
+
e.stopPropagation();
|
|
2034
|
+
node.object.visible = !node.object.visible;
|
|
2035
|
+
node.visible = node.object.visible;
|
|
2036
|
+
this._renderTree();
|
|
2037
|
+
});
|
|
2038
|
+
contentWrapper.appendChild(visibilityBtn);
|
|
2039
|
+
// Add content wrapper to node
|
|
2040
|
+
nodeElement.appendChild(contentWrapper);
|
|
2041
|
+
// Selection indicator
|
|
2042
|
+
if (this._selectedObject === node.object) {
|
|
2043
|
+
nodeElement.classList.add('selected');
|
|
2044
|
+
}
|
|
2045
|
+
// Click to select
|
|
2046
|
+
nodeElement.addEventListener('click', ()=>{
|
|
2047
|
+
this._selectObject(node.object);
|
|
2048
|
+
});
|
|
2049
|
+
// Right-click for context menu
|
|
2050
|
+
nodeElement.addEventListener('contextmenu', (e)=>{
|
|
2051
|
+
e.preventDefault();
|
|
2052
|
+
e.stopPropagation();
|
|
2053
|
+
this._showContextMenu(e.clientX, e.clientY, node);
|
|
2054
|
+
});
|
|
2055
|
+
this.$treeContainer.appendChild(nodeElement);
|
|
2056
|
+
// Render children if expanded
|
|
2057
|
+
if (node.expanded) {
|
|
2058
|
+
node.children.forEach((child)=>{
|
|
2059
|
+
this._renderNode(child, depth + 1);
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
_selectObject(object) {
|
|
2064
|
+
this._selectedObject = object;
|
|
2065
|
+
this._renderTree();
|
|
2066
|
+
if (this._onObjectSelect) {
|
|
2067
|
+
this._onObjectSelect(object);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
onObjectSelect(callback) {
|
|
2071
|
+
this._onObjectSelect = callback;
|
|
2072
|
+
return this;
|
|
2073
|
+
}
|
|
2074
|
+
refresh() {
|
|
2075
|
+
this._rootNode = this._buildSceneTree(this._scene);
|
|
2076
|
+
this._renderTree();
|
|
2077
|
+
}
|
|
2078
|
+
getSelectedObject() {
|
|
2079
|
+
return this._selectedObject;
|
|
2080
|
+
}
|
|
2081
|
+
expandAll() {
|
|
2082
|
+
const expandNode = (node)=>{
|
|
2083
|
+
node.expanded = true;
|
|
2084
|
+
node.children.forEach(expandNode);
|
|
2085
|
+
};
|
|
2086
|
+
expandNode(this._rootNode);
|
|
2087
|
+
this._renderTree();
|
|
2088
|
+
}
|
|
2089
|
+
collapseAll() {
|
|
2090
|
+
const collapseNode = (node)=>{
|
|
2091
|
+
node.expanded = false;
|
|
2092
|
+
node.children.forEach(collapseNode);
|
|
2093
|
+
};
|
|
2094
|
+
collapseNode(this._rootNode);
|
|
2095
|
+
this._renderTree();
|
|
2096
|
+
}
|
|
2097
|
+
update() {
|
|
2098
|
+
// Always update visibility states (lightweight operation)
|
|
2099
|
+
this._updateVisibilityStates(this._rootNode);
|
|
2100
|
+
// Only check for structural changes periodically to avoid performance issues
|
|
2101
|
+
if (this._autoUpdate && this._shouldCheckForChanges()) {
|
|
2102
|
+
this._checkForStructuralChanges();
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
_shouldCheckForChanges() {
|
|
2106
|
+
const now = performance.now();
|
|
2107
|
+
if (now - this._lastUpdateTime > this._updateInterval) {
|
|
2108
|
+
this._lastUpdateTime = now;
|
|
2109
|
+
return true;
|
|
2110
|
+
}
|
|
2111
|
+
return false;
|
|
2112
|
+
}
|
|
2113
|
+
setAutoUpdate(enabled) {
|
|
2114
|
+
this._autoUpdate = enabled;
|
|
2115
|
+
}
|
|
2116
|
+
setUpdateInterval(intervalMs) {
|
|
2117
|
+
this._updateInterval = intervalMs;
|
|
2118
|
+
}
|
|
2119
|
+
getUpdateInterval() {
|
|
2120
|
+
return this._updateInterval;
|
|
2121
|
+
}
|
|
2122
|
+
getAutoUpdate() {
|
|
2123
|
+
return this._autoUpdate;
|
|
2124
|
+
}
|
|
2125
|
+
forceUpdate() {
|
|
2126
|
+
this._rootNode = this._buildSceneTree(this._scene);
|
|
2127
|
+
this._renderTree();
|
|
2128
|
+
}
|
|
2129
|
+
_checkForStructuralChanges() {
|
|
2130
|
+
// Use lightweight change detection instead of rebuilding the entire tree
|
|
2131
|
+
if (this._hasSceneStructureChanged()) {
|
|
2132
|
+
this._rebuildSceneTree();
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
_hasSceneStructureChanged() {
|
|
2136
|
+
// Quick check for common changes without rebuilding the tree
|
|
2137
|
+
return this._checkObjectCount() || this._checkObjectReferences();
|
|
2138
|
+
}
|
|
2139
|
+
_checkObjectCount() {
|
|
2140
|
+
// Check if the total number of objects has changed
|
|
2141
|
+
const currentCount = this._countObjects(this._scene);
|
|
2142
|
+
if (currentCount !== this._cachedObjectCount) {
|
|
2143
|
+
this._cachedObjectCount = currentCount;
|
|
2144
|
+
return true;
|
|
2145
|
+
}
|
|
2146
|
+
return false;
|
|
2147
|
+
}
|
|
2148
|
+
_checkObjectReferences() {
|
|
2149
|
+
// Check if any object references have changed (objects added/removed)
|
|
2150
|
+
return this._scene.children.length !== this._rootNode.children.length || this._hasChildrenChanged(this._scene, this._rootNode);
|
|
2151
|
+
}
|
|
2152
|
+
_hasChildrenChanged(sceneObj, treeNode) {
|
|
2153
|
+
if (sceneObj.children.length !== treeNode.children.length) return true;
|
|
2154
|
+
for(let i = 0; i < sceneObj.children.length; i++){
|
|
2155
|
+
const sceneChild = sceneObj.children[i];
|
|
2156
|
+
const treeChild = treeNode.children[i];
|
|
2157
|
+
if (sceneChild !== treeChild.object) return true;
|
|
2158
|
+
if (this._hasChildrenChanged(sceneChild, treeChild)) return true;
|
|
2159
|
+
}
|
|
2160
|
+
return false;
|
|
2161
|
+
}
|
|
2162
|
+
_countObjects(obj) {
|
|
2163
|
+
let count = 1;
|
|
2164
|
+
for(let i = 0; i < obj.children.length; i++){
|
|
2165
|
+
count += this._countObjects(obj.children[i]);
|
|
2166
|
+
}
|
|
2167
|
+
return count;
|
|
2168
|
+
}
|
|
2169
|
+
_rebuildSceneTree() {
|
|
2170
|
+
// Only rebuild when necessary
|
|
2171
|
+
const currentStructure = this._buildSceneTree(this._scene);
|
|
2172
|
+
this._preserveExpandedStates(this._rootNode, currentStructure);
|
|
2173
|
+
this._rootNode = currentStructure;
|
|
2174
|
+
this._cachedObjectCount = this._countObjects(this._scene);
|
|
2175
|
+
this._renderTree();
|
|
2176
|
+
}
|
|
2177
|
+
_hasStructureChanged(oldNode, newNode) {
|
|
2178
|
+
if (oldNode.children.length !== newNode.children.length) return true;
|
|
2179
|
+
if (oldNode.object !== newNode.object) return true;
|
|
2180
|
+
for(let i = 0; i < oldNode.children.length; i++){
|
|
2181
|
+
if (this._hasStructureChanged(oldNode.children[i], newNode.children[i])) {
|
|
2182
|
+
return true;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
return false;
|
|
2186
|
+
}
|
|
2187
|
+
_preserveExpandedStates(oldNode, newNode) {
|
|
2188
|
+
// Try to preserve expanded states by matching object references
|
|
2189
|
+
if (oldNode.object === newNode.object) {
|
|
2190
|
+
newNode.expanded = oldNode.expanded;
|
|
2191
|
+
}
|
|
2192
|
+
for(let i = 0; i < Math.min(oldNode.children.length, newNode.children.length); i++){
|
|
2193
|
+
this._preserveExpandedStates(oldNode.children[i], newNode.children[i]);
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
_updateVisibilityStates(node) {
|
|
2197
|
+
node.visible = node.object.visible;
|
|
2198
|
+
node.children.forEach((child)=>this._updateVisibilityStates(child));
|
|
2199
|
+
}
|
|
2200
|
+
destroy() {
|
|
2201
|
+
super.destroy();
|
|
2202
|
+
this._onObjectSelect = null;
|
|
2203
|
+
// Clean up context menu
|
|
2204
|
+
if (this._contextMenu && this._contextMenu.parentNode) {
|
|
2205
|
+
this._contextMenu.parentNode.removeChild(this._contextMenu);
|
|
2206
|
+
}
|
|
2207
|
+
this._contextMenu = null;
|
|
2208
|
+
this._contextMenuTarget = null;
|
|
2209
|
+
this._clipboardData = null;
|
|
2210
|
+
}
|
|
2211
|
+
constructor(parent, scene){
|
|
2212
|
+
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
|
|
2213
|
+
, this._visibleNodeCount = 0 // Counter for alternating background colors
|
|
2214
|
+
, // Context menu properties
|
|
2215
|
+
this._contextMenu = null, this._contextMenuTarget = null, this._clipboardData = null;
|
|
2216
|
+
this._scene = scene;
|
|
2217
|
+
this._rootNode = this._buildSceneTree(scene);
|
|
2218
|
+
this._cachedObjectCount = this._countObjects(scene);
|
|
2219
|
+
this._setupDOM();
|
|
2220
|
+
this._createContextMenu();
|
|
2221
|
+
this._renderTree();
|
|
2222
|
+
this._setupGlobalEventListeners();
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
|
|
1741
2226
|
class GUI {
|
|
1742
2227
|
/**
|
|
1743
2228
|
* Adds a controller to the GUI, inferring controller type using the `typeof` operator.
|
|
@@ -1812,6 +2297,13 @@ class GUI {
|
|
|
1812
2297
|
addCurve(object, property) {
|
|
1813
2298
|
return new CurveController(this, object, property);
|
|
1814
2299
|
}
|
|
2300
|
+
/**
|
|
2301
|
+
* Adds a scene tree controller to display Three.js scene hierarchy.
|
|
2302
|
+
* @param {Scene} scene The Three.js scene to display
|
|
2303
|
+
* @returns {SceneTreeController}
|
|
2304
|
+
*/ addSceneTree(scene) {
|
|
2305
|
+
return new SceneTreeController(this, scene);
|
|
2306
|
+
}
|
|
1815
2307
|
/**
|
|
1816
2308
|
* Adds a folder to the GUI, which is just another GUI. This method returns
|
|
1817
2309
|
* the nested GUI so you can add controllers to it.
|
|
@@ -1821,8 +2313,6 @@ class GUI {
|
|
|
1821
2313
|
* folder.add( position, 'y' );
|
|
1822
2314
|
* folder.add( position, 'z' );
|
|
1823
2315
|
*
|
|
1824
|
-
* @param {string} title Name to display in the folder's title bar.
|
|
1825
|
-
* @param {string} id Id
|
|
1826
2316
|
* @returns {GUI}
|
|
1827
2317
|
*/ addFolder(title, id = title) {
|
|
1828
2318
|
const folder = new GUI({
|
|
@@ -2118,6 +2608,25 @@ class GUI {
|
|
|
2118
2608
|
child.update();
|
|
2119
2609
|
}
|
|
2120
2610
|
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Sets this folder as active and deactivates all other folders
|
|
2613
|
+
*/ setActive() {
|
|
2614
|
+
// Only root GUI can manage active states
|
|
2615
|
+
if (!this.parent) return;
|
|
2616
|
+
// Remove active class from ALL folders in the entire GUI tree using DOM query
|
|
2617
|
+
const allActiveFolders = document.querySelectorAll('.lil-gui.active');
|
|
2618
|
+
allActiveFolders.forEach((folder)=>{
|
|
2619
|
+
folder.classList.remove('active');
|
|
2620
|
+
});
|
|
2621
|
+
// Add active class to this folder
|
|
2622
|
+
this.domElement.classList.add('active');
|
|
2623
|
+
}
|
|
2624
|
+
/**
|
|
2625
|
+
* Gets the currently active folder
|
|
2626
|
+
*/ getActiveFolder() {
|
|
2627
|
+
if (!this.parent) return null;
|
|
2628
|
+
return this.parent.folders.find((folder)=>folder.domElement.classList.contains('active')) || null;
|
|
2629
|
+
}
|
|
2121
2630
|
constructor({ parent, container, width, autoPlace = parent === undefined, title = 'Controls', id = title, closeFolders = false, touchStyles = true } = {}){
|
|
2122
2631
|
this.children = [];
|
|
2123
2632
|
this.controllers = [];
|
|
@@ -2139,6 +2648,8 @@ class GUI {
|
|
|
2139
2648
|
this.$title.setAttribute('aria-expanded', "true");
|
|
2140
2649
|
this.$title.setAttribute('tabindex', "0");
|
|
2141
2650
|
this.$title.addEventListener('click', ()=>{
|
|
2651
|
+
// Set this folder as active and deactivate others
|
|
2652
|
+
this.setActive();
|
|
2142
2653
|
this.openAnimated(this._closed);
|
|
2143
2654
|
});
|
|
2144
2655
|
this.$title.addEventListener('keydown', (e)=>{
|
|
@@ -2197,7 +2708,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
2197
2708
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2198
2709
|
PERFORMANCE OF THIS SOFTWARE.
|
|
2199
2710
|
***************************************************************************** */
|
|
2200
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
2711
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
2201
2712
|
|
|
2202
2713
|
|
|
2203
2714
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -2353,67 +2864,74 @@ __decorate([
|
|
|
2353
2864
|
core.property
|
|
2354
2865
|
], ViewerHelper.prototype, "targetFrameRate", null);
|
|
2355
2866
|
|
|
2356
|
-
|
|
2867
|
+
const vert_Sprite = `
|
|
2868
|
+
uniform vec4 u_transform;
|
|
2869
|
+
uniform vec4 u_resolution;
|
|
2870
|
+
varying vec2 v_uv;
|
|
2871
|
+
|
|
2872
|
+
void main() {
|
|
2873
|
+
vec2 pos = u_transform.xy + u_transform.zw * 0.5 + position.xy * u_transform.zw;
|
|
2874
|
+
vec2 ndc = pos * u_resolution.zw * 2. - 1.;
|
|
2875
|
+
gl_Position = vec4(ndc, 0., 1.);
|
|
2876
|
+
v_uv = uv;
|
|
2877
|
+
}
|
|
2878
|
+
`;
|
|
2879
|
+
const frag_Sprite = `
|
|
2880
|
+
uniform sampler2D u_texture;
|
|
2881
|
+
varying vec2 v_uv;
|
|
2882
|
+
|
|
2883
|
+
void main() {
|
|
2884
|
+
gl_FragColor = texture2D(u_texture, v_uv);
|
|
2885
|
+
}
|
|
2886
|
+
`;
|
|
2887
|
+
class Inspector extends core.Component {
|
|
2357
2888
|
onLoad() {
|
|
2358
2889
|
const { width, height } = this.viewer;
|
|
2359
|
-
this.
|
|
2360
|
-
this.
|
|
2890
|
+
this._spriteUniforms.u_resolution.value.set(width, height, 1 / width, 1 / height);
|
|
2891
|
+
this._sprite = new three.Mesh(new three.PlaneGeometry(1, 1, 1, 1), new three.ShaderMaterial({
|
|
2892
|
+
side: three.DoubleSide,
|
|
2893
|
+
vertexShader: vert_Sprite,
|
|
2894
|
+
fragmentShader: frag_Sprite,
|
|
2895
|
+
uniforms: this._spriteUniforms
|
|
2896
|
+
}));
|
|
2897
|
+
this._sprite.frustumCulled = false;
|
|
2898
|
+
this._camera.viewport = new three.Vector4(0, 0, 256, 256);
|
|
2361
2899
|
this._gui = new GUI({
|
|
2362
2900
|
width: 310,
|
|
2363
2901
|
title: "Inspector"
|
|
2364
2902
|
}).close();
|
|
2903
|
+
this._tree = this._gui.addSceneTree(this.viewer.scene);
|
|
2365
2904
|
this._gui.addFolder("Viewer").close().hide();
|
|
2366
2905
|
this._gui.addFolder("Component").close().hide();
|
|
2367
2906
|
this._gui.addFolder("Material").close().hide();
|
|
2368
2907
|
this._gui.addFolder("Other").close().hide();
|
|
2369
2908
|
this._inspect(new ViewerHelper(this.viewer));
|
|
2370
|
-
this._addSprite();
|
|
2371
2909
|
}
|
|
2372
2910
|
onDestroy() {
|
|
2911
|
+
if (this._tree) {
|
|
2912
|
+
this._tree.destroy();
|
|
2913
|
+
}
|
|
2373
2914
|
this._gui.destroy();
|
|
2374
2915
|
this._refCntMap.clear();
|
|
2375
2916
|
this._targetMap.clear();
|
|
2376
2917
|
}
|
|
2377
2918
|
update(dt) {
|
|
2378
2919
|
this._gui.update();
|
|
2920
|
+
if (this._tree) {
|
|
2921
|
+
this._tree.update();
|
|
2922
|
+
}
|
|
2379
2923
|
this._updateFolders();
|
|
2380
2924
|
}
|
|
2381
2925
|
resize(width, height) {
|
|
2382
|
-
this.
|
|
2383
|
-
this._camera.right = width;
|
|
2384
|
-
this._camera.top = height;
|
|
2385
|
-
this._camera.bottom = 0;
|
|
2386
|
-
this._camera.updateProjectionMatrix();
|
|
2387
|
-
}
|
|
2388
|
-
_addSprite() {
|
|
2389
|
-
const viewer = this.viewer;
|
|
2390
|
-
this._sprite = viewer.add(three.Sprite, {
|
|
2391
|
-
parent: this._scene,
|
|
2392
|
-
scale: new three.Vector3(256, 256, 1),
|
|
2393
|
-
position: new three.Vector3(viewer.width / 2, viewer.height / 2),
|
|
2394
|
-
visible: false
|
|
2395
|
-
});
|
|
2396
|
-
}
|
|
2397
|
-
_renderScene() {
|
|
2398
|
-
const { renderer } = this.viewer;
|
|
2399
|
-
const autoClearDepth = renderer.autoClearDepth;
|
|
2400
|
-
const autoClearColor = renderer.autoClearColor;
|
|
2401
|
-
renderer.autoClearDepth = true;
|
|
2402
|
-
renderer.autoClearColor = false;
|
|
2403
|
-
renderer.render(this._scene, this._camera);
|
|
2404
|
-
renderer.autoClearDepth = autoClearDepth;
|
|
2405
|
-
renderer.autoClearColor = autoClearColor;
|
|
2406
|
-
return renderer.domElement;
|
|
2926
|
+
this._spriteUniforms.u_resolution.value.set(width, height, 1 / width, 1 / height);
|
|
2407
2927
|
}
|
|
2408
2928
|
_renderSprite(texture, w, h) {
|
|
2409
|
-
this.
|
|
2410
|
-
this.
|
|
2411
|
-
this.
|
|
2412
|
-
this.
|
|
2413
|
-
this.
|
|
2414
|
-
|
|
2415
|
-
this._sprite.visible = false;
|
|
2416
|
-
return dom;
|
|
2929
|
+
const resolution = this._spriteUniforms.u_resolution.value;
|
|
2930
|
+
this._camera.viewport.set(0, resolution.y - h, w, h);
|
|
2931
|
+
this._spriteUniforms.u_transform.value.set(0, resolution.y - h, w, h);
|
|
2932
|
+
this._spriteUniforms.u_texture.value = texture;
|
|
2933
|
+
this.viewer.render(null, this._sprite, this._camera, 0, 0);
|
|
2934
|
+
return this.viewer.canvas;
|
|
2417
2935
|
}
|
|
2418
2936
|
_updateFolders() {
|
|
2419
2937
|
const refCntMap = this._refCntMap;
|
|
@@ -2422,8 +2940,14 @@ class Inspector extends core.Mount {
|
|
|
2422
2940
|
if (refCntMap.get(v) === undefined) refCntMap.set(v, 1);
|
|
2423
2941
|
};
|
|
2424
2942
|
refCntMap.forEach((_, k, map)=>map.set(k, -1));
|
|
2425
|
-
this.viewer
|
|
2426
|
-
|
|
2943
|
+
const { scene, componentManager } = this.viewer;
|
|
2944
|
+
scene.traverse((item)=>{
|
|
2945
|
+
if (item.material) {
|
|
2946
|
+
if (Array.isArray(item.material)) item.material.forEach(setState);
|
|
2947
|
+
else setState(item.material);
|
|
2948
|
+
}
|
|
2949
|
+
});
|
|
2950
|
+
componentManager.traverseComponents(setState);
|
|
2427
2951
|
refCntMap.forEach((v, k, map)=>{
|
|
2428
2952
|
if (v === 1) {
|
|
2429
2953
|
this._inspect(k);
|
|
@@ -2499,12 +3023,16 @@ class Inspector extends core.Mount {
|
|
|
2499
3023
|
this._addGUI(folder, this._getPropertiesList(value), target, k);
|
|
2500
3024
|
}
|
|
2501
3025
|
if (Array.isArray(value)) {
|
|
2502
|
-
|
|
2503
|
-
value.
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
3026
|
+
if (prop.flat) {
|
|
3027
|
+
value.forEach((v)=>this._addGUI(folder, this._getPropertiesList(v), v, v.constructor.name));
|
|
3028
|
+
} else {
|
|
3029
|
+
this._addGUI(folder, [
|
|
3030
|
+
value.map((_, i)=>[
|
|
3031
|
+
i.toString(),
|
|
3032
|
+
{}
|
|
3033
|
+
])
|
|
3034
|
+
], value, k);
|
|
3035
|
+
}
|
|
2508
3036
|
} else {
|
|
2509
3037
|
const type = typeof value;
|
|
2510
3038
|
let ins = null;
|
|
@@ -2542,11 +3070,20 @@ class Inspector extends core.Mount {
|
|
|
2542
3070
|
}
|
|
2543
3071
|
}
|
|
2544
3072
|
constructor(...args){
|
|
2545
|
-
super(...args)
|
|
2546
|
-
|
|
2547
|
-
|
|
3073
|
+
super(...args), this._camera = new three.Camera(), this._sprite = null, this._spriteUniforms = {
|
|
3074
|
+
u_texture: {
|
|
3075
|
+
value: null
|
|
3076
|
+
},
|
|
3077
|
+
u_transform: {
|
|
3078
|
+
value: new three.Vector4()
|
|
3079
|
+
},
|
|
3080
|
+
u_resolution: {
|
|
3081
|
+
value: new three.Vector4()
|
|
3082
|
+
}
|
|
3083
|
+
}, this._refCntMap = new Map(), this._targetMap = new Map();
|
|
2548
3084
|
}
|
|
2549
3085
|
}
|
|
3086
|
+
Inspector.viewport = new three.Vector4();
|
|
2550
3087
|
function targetName(target) {
|
|
2551
3088
|
return target.name || target.constructor.name || target.type;
|
|
2552
3089
|
}
|
|
@@ -2924,7 +3461,7 @@ var Stats$1 = function() {
|
|
|
2924
3461
|
};
|
|
2925
3462
|
};
|
|
2926
3463
|
|
|
2927
|
-
class Stats extends core.
|
|
3464
|
+
class Stats extends core.Component {
|
|
2928
3465
|
onLoad() {
|
|
2929
3466
|
this._stats.addPanel(this._dcPanel);
|
|
2930
3467
|
this._stats.addPanel(this._texPanel);
|
|
@@ -2945,36 +3482,10 @@ class Stats extends core.Mount {
|
|
|
2945
3482
|
this._stats.update();
|
|
2946
3483
|
}
|
|
2947
3484
|
constructor(...args){
|
|
2948
|
-
super(...args);
|
|
2949
|
-
this._stats = new Stats$1();
|
|
2950
|
-
this._dcPanel = new Panel('DC', '#ff8', '#221');
|
|
2951
|
-
this._triPanel = new Panel("TRI", '#ff8', '#221');
|
|
2952
|
-
this._texPanel = new Panel('TEX', '#ff8', '#221');
|
|
2953
|
-
this._prgPanel = new Panel('PRG', '#ff8', '#221');
|
|
2954
|
-
}
|
|
2955
|
-
}
|
|
2956
|
-
|
|
2957
|
-
class BoxProjectionHelper extends core.Mount {
|
|
2958
|
-
onLoad() {
|
|
2959
|
-
this._box3 = new three.Box3();
|
|
2960
|
-
this._target = this.viewer.mount(core.BoxProjection);
|
|
2961
|
-
this._helper = this.viewer.add(new three.Box3Helper(this._box3));
|
|
2962
|
-
}
|
|
2963
|
-
onEnable() {
|
|
2964
|
-
this._helper.visible = true;
|
|
2965
|
-
}
|
|
2966
|
-
onDisable() {
|
|
2967
|
-
this._helper.visible = false;
|
|
2968
|
-
}
|
|
2969
|
-
update(dt) {
|
|
2970
|
-
const { center, boxMin, boxMax } = this._target;
|
|
2971
|
-
this._box3.min.copy(center).add(boxMin);
|
|
2972
|
-
this._box3.max.copy(center).add(boxMax);
|
|
2973
|
-
this._helper.updateMatrixWorld();
|
|
3485
|
+
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');
|
|
2974
3486
|
}
|
|
2975
3487
|
}
|
|
2976
3488
|
|
|
2977
|
-
exports.BoxProjectionHelper = BoxProjectionHelper;
|
|
2978
3489
|
exports.GUI = GUI;
|
|
2979
3490
|
exports.Inspector = Inspector;
|
|
2980
3491
|
exports.Stats = Stats;
|