UNPKG

@zeainc/zea-ux

Version:
1 lines 141 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@zeainc/zea-engine"),t={name:"@zeainc/zea-ux",version:"4.9.0",description:"Zea UX",homepage:"https://github.com/ZeaInc/zea-ux#readme",author:"Zea Inc.",license:"MIT",repository:{type:"git",url:"git+ssh://git@github.com/ZeaInc/zea-ux.git"},bugs:{url:"https://github.com/ZeaInc/zea-ux/issues"},main:"dist/index.cjs.js",module:"dist/index.esm.js",browser:"dist/index.umd.js",umd:"dist/index.umd.js",exports:{".":{import:"./dist/index.esm.js",require:"./dist/index.cjs.js",types:"./dist/zea-ux.d.ts"}},types:"dist/zea-ux.d.ts",files:["dist/"],keywords:["Zea","UX"],scripts:{"build:tsc":"npx tsc","build:tsc:watch":"npx tsc --watch","clean:build":"rm -Rf dist/ buildcache","build:rollup":"rollup -c","build:rollup:watch":"rollup -w -c",build:"npm-run-all clean:build build:rollup",dev:"npm-run-all --parallel build:rollup:watch start:watch",start:"es-dev-server --app-index testing-e2e/index.html --open","start:watch":"es-dev-server --app-index testing-e2e/index.html --open --watch",release:"standard-version",dist:"yarn publish --access=public",docs:"adg --config adg.config.json","docs-w":"adg -w --config=adg.config.json","docs:serve":"docsify serve docs/",lint:"eslint src/",prepare:"yarn run build",test:"jest",generate:"plop","test:coverage":"jest --coverage","test:debug":"node --inspect ./node_modules/jest/bin/jest.js --runInBand --watch","test:watch":"jest --watch","test:e2e":"percy exec cypress run --browser chrome --headless","test:e2e:watch":"percy exec cypress open","to-cleanup":"rm -Rf dist/ node_modules/ yarn.lock","to-link-packages":"yarn link @zeainc/zea-engine"},devDependencies:{"@babel/preset-env":"^7.12.7","@percy/cypress":"^2.3.1","@rollup/plugin-commonjs":"^21.0.1","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.0.6","@rollup/plugin-terser":"0.4.4","@rollup/plugin-typescript":"^12.1.1","@zeainc/zea-collab":"^6.3.4","@zeainc/zea-engine":"4.17.0",canvas:"^2.6.1",copyfiles:"^2.4.1",cypress:"^5.6.0","docsify-cli":"^4.4.2",documentation:"^13.1.0","es-dev-server":"^1.60.1",eslint:"^7.14.0","eslint-config-google":"^0.14.0","eslint-config-prettier":"^6.15.0","eslint-plugin-prettier":"^3.2.0",husky:"^4.3.0","husky-run":"^0.0.0",jest:"^26.6.3","npm-run-all":"^4.1.5",plop:"^2.7.4",prettier:"^2.2.1",rollup:"^2.34.1","rollup-plugin-dts":"^4.2.3","standard-version":"^9.0.0","ts-node":"^10.4.0",tslib:"^2.3.1",typedoc:"^0.23.21","typedoc-plugin-markdown":"^3.13.6",typescript:"^5.6.3"},dependencies:{"dom-to-image":"^2.6.0",global:"^4.4.0","license-checker":"^25.0.1"},husky:{hooks:{"disabled=pre-commit":"npm test","disabled=pre-push":"npm test"}}};function a(t){return t instanceof e.ZeaMouseEvent||e.ZeaTouchEvent?t.pointerRay:t instanceof e.XRControllerEvent?t.controller.pointerRay:(console.warn("unhandled pointer event"),new e.Ray)}class i extends e.TreeItem{gizmoRay;activeController;captured=!1;colorParam=new e.ColorParameter("Color",new e.Color);highlightColorParam=new e.ColorParameter("HighlightColor",new e.Color(1,1,1));grabPos;holdPos;holdDist;value;delta;releasePos;constructor(e){super(e),this.addParameter(this.colorParam),this.addParameter(this.highlightColorParam)}highlight(){this.emit("highlight")}unhighlight(){this.emit("unhighlight")}getManipulationPlane(){const t=this.globalXfoParam.value;return new e.Ray(t.tr,t.ori.getZaxis())}onPointerEnter(e){this.highlight()}onPointerLeave(e){this.unhighlight()}onPointerDown(t){t.setCapture(this),t.stopPropagation(),this.captured=!0,t instanceof e.ZeaTouchEvent&&this.highlight(),t instanceof e.ZeaMouseEvent||t instanceof e.ZeaTouchEvent?this.handlePointerDown(t):t instanceof e.XRControllerEvent&&this.onXRControllerButtonDown(t)}onPointerMove(t){this.captured&&(t.stopPropagation(),t instanceof e.ZeaMouseEvent||t instanceof e.ZeaTouchEvent?this.handlePointerMove(t):t instanceof e.XRPoseEvent&&this.onXRPoseChanged(t)),t.preventDefault()}onPointerUp(t){t.stopPropagation(),this.captured&&(t.releaseCapture(),this.captured=!1,t instanceof e.ZeaTouchEvent&&this.unhighlight(),t instanceof e.ZeaMouseEvent||t instanceof e.ZeaTouchEvent?this.handlePointerUp(t):t instanceof e.XRControllerEvent&&this.onVRControllerButtonUp(t))}onPointerClick(e){e.stopPropagation()}onPointerDoubleClick(e){e.stopPropagation()}onWheel(e){}handlePointerDown(e){this.gizmoRay=this.getManipulationPlane();const t=a(e),i=t.intersectRayPlane(this.gizmoRay);this.grabPos=t.pointAtDist(i),this.onDragStart(e)}handlePointerMove(e){const t=a(e),i=t.intersectRayPlane(this.gizmoRay);this.holdPos=t.pointAtDist(i),this.onDrag(e)}handlePointerUp(e){const t=e.pointerRay;if(t){const e=t.intersectRayPlane(this.gizmoRay);this.releasePos=t.pointAtDist(e)}this.onDragEnd(e)}onXRControllerButtonDown(e){this.activeController=e.controller;const t=this.activeController.getTipXfo().clone(),a=this.getManipulationPlane(),i=t.tr.subtract(a.start),s=t.tr.subtract(a.dir.scale(i.dot(a.dir)));this.grabPos=s,this.onDragStart(e)}onXRPoseChanged(e){if(this.activeController){const t=this.activeController.getTipXfo(),a=this.getManipulationPlane(),i=t.tr.subtract(a.start),s=t.tr.subtract(a.dir.scale(i.dot(a.dir)));this.holdPos=s,this.onDrag(e)}}onVRControllerButtonUp(e){this.activeController==e.controller&&(this.activeController.getTipXfo(),this.onDragEnd(e),this.activeController=void 0)}onDragStart(e){console.warn("@Handle#onDragStart - Implement me!",e)}onDrag(e){console.warn("@Handle#onDrag - Implement me!",e)}onDragEnd(e){console.warn("@Handle#onDragEnd - Implement me!",e)}setTargetParam(e){console.warn("setTargetParam not implemented")}}class s extends i{grabDist;constructor(e){super(e)}handlePointerDown(e){this.gizmoRay=this.getManipulationPlane();const t=a(e).intersectRayVector(this.gizmoRay);this.grabDist=Array.isArray(t)?t[1]:t;const i=this.gizmoRay.pointAtDist(this.grabDist);this.grabPos=i,this.onDragStart(e)}handlePointerMove(e){const t=a(e).intersectRayVector(this.gizmoRay),i=Array.isArray(t)?t[1]:t;this.holdPos=this.gizmoRay.pointAtDist(i),this.holdDist=i,this.value=i,this.delta=i-this.grabDist,this.onDrag(e)}handlePointerUp(e){const t=a(e);if(t){const e=t.intersectRayVector(this.gizmoRay),a=Array.isArray(e)?e[1]:e,i=this.gizmoRay.pointAtDist(a);this.releasePos=i}this.onDragEnd(e)}onXRControllerButtonDown(e){this.gizmoRay=this.getManipulationPlane(),this.activeController=e.controller;const t=this.activeController.getTipXfo();this.grabDist=t.tr.subtract(this.gizmoRay.start).dot(this.gizmoRay.dir),this.grabPos=this.gizmoRay.start.add(this.gizmoRay.dir.scale(this.grabDist)),this.onDragStart(e)}onXRPoseChanged(e){const t=this.activeController.getTipXfo().tr.subtract(this.gizmoRay.start).dot(this.gizmoRay.dir);this.holdPos=this.gizmoRay.start.add(this.gizmoRay.dir.scale(t)),this.value=t,this.delta=t-this.grabDist,this.onDrag(e)}onVRControllerButtonUp(e){this.activeController==e.controller&&(this.onDragEnd(),this.activeController=void 0)}}const o=e=>{e.undo();for(let t=e.secondaryChanges.length-1;t>=0;t--)o(e.secondaryChanges[t])},n=e=>{e.redo();for(let t=0;t<e.secondaryChanges.length;t++)n(e.secondaryChanges[t])};class r extends e.EventEmitter{__undoStack=[];__redoStack=[];__currChange=null;constructor(){super(),this.currChangeUpdated=this.currChangeUpdated.bind(this)}flush(){for(const e of this.__undoStack)e.destroy();this.__undoStack=[];for(const e of this.__redoStack)e.destroy();this.__redoStack=[],this.__currChange&&(this.__currChange.off("updated",this.currChangeUpdated),this.__currChange=null)}addChange(e){this.__currChange&&this.__currChange.off&&this.__currChange.off("updated",this.currChangeUpdated),this.__undoStack.push(e),this.__currChange=e,this.__currChange.on&&this.__currChange.on("updated",this.currChangeUpdated);for(const e of this.__redoStack)e.destroy();this.__redoStack=[],this.emit("changeAdded",{change:e})}getCurrentChange(){return this.__currChange}currChangeUpdated(e){this.emit("changeUpdated",e)}undo(e=!0){if(this.__undoStack.length>0){this.__currChange&&(this.__currChange.off("updated",this.currChangeUpdated),this.__currChange=null);const t=this.__undoStack.pop();o(t),e&&(this.__redoStack.push(t),this.emit("changeUndone",{change:t}))}}cancel(){if(this.__currChange){this.__currChange.off("updated",this.currChangeUpdated),this.__currChange=null;const e=this.__undoStack.pop();o(e)}}redo(){if(this.__redoStack.length>0){const e=this.__redoStack.pop();n(e),this.__undoStack.push(e),this.emit("changeRedone",{change:e})}}constructChange(t){return e.Registry.constructClass(t)}static isChangeClassRegistered(t){try{e.Registry.getClassName(Object.getPrototypeOf(t).constructor);return!0}catch(e){return!1}}static getChangeClassName(t){return e.Registry.getClassName(Object.getPrototypeOf(t).constructor)}static registerChange(t,a){e.Registry.register(t,a)}static getInstance(){return l||(l=new r),l}}let l;class h extends e.EventEmitter{name;secondaryChanges=[];suppressPrimaryChange=!1;closed=!1;constructor(e){super(),this.name=e||r.getChangeClassName(this)}addSecondaryChange(e){const t=this.secondaryChanges.length;return this.secondaryChanges.push(e),e.setPrimaryChange(this),t}setPrimaryChange(e){}undo(){}redo(){}update(e){throw new Error("Implement me")}toJSON(e){return{name:this.name,className:this.getClassName(),secondaryChanges:this.secondaryChanges.map((t=>t.toJSON(e)))}}fromJSON(e,t){this.name=e.name,e.secondaryChanges.forEach((e=>{const a=r.getInstance().constructChange(e.className);a.fromJSON(e,t),this.addSecondaryChange(a)}))}destroy(){}}r.registerChange("Change",h);class c extends h{param;nextValue;prevValue;supressed=!1;constructor(e,t){super(e?e.getName()+" Changed":"ParameterValueChange"),e&&(this.prevValue=e.value,this.param=e,null!=t&&(this.nextValue=t,this.param.value=this.nextValue))}undo(){this.param&&!this.suppressPrimaryChange&&(this.param.value=this.prevValue)}redo(){this.param&&!this.suppressPrimaryChange&&(this.param.value=this.nextValue)}update(e){this.param&&(this.nextValue=e.value,this.supressed||(this.param.value=this.nextValue),this.emit("updated",e))}toJSON(e){const t=super.toJSON(e);return t.paramPath=this.param.getPath(),null!=this.nextValue&&(this.nextValue.toJSON?t.value=this.nextValue.toJSON():t.value=this.nextValue),t}fromJSON(t,a){super.fromJSON(t,a);const i=a.appData.scene.getRoot().resolvePath(t.paramPath,1);i&&i instanceof e.Parameter?(this.param=i,this.prevValue=this.param.value,this.prevValue.clone?this.nextValue=this.prevValue.clone():this.nextValue=this.prevValue,null!=t.value&&(this.nextValue.fromJSON?this.nextValue.fromJSON(t.value):this.nextValue=t.value),this.supressed||(this.param.value=this.nextValue)):console.warn("resolvePath is unable to resolve",t.paramPath)}}r.registerChange("ParameterValueChange",c);class d extends e.Material{baseColorParam=new e.MaterialColorParam("BaseColor",new e.Color(1,1,.5));maintainScreenSizeParam=new e.NumberParameter("MaintainScreenSize",0);overlayParam=new e.NumberParameter("Overlay",0,[0,1]);constructor(e){super(e),this.__shaderName="HandleShader",this.addParameter(this.baseColorParam),this.addParameter(this.maintainScreenSizeParam),this.addParameter(this.overlayParam)}}e.Registry.register("HandleMaterial",d);class m extends e.GLShader{constructor(e){super(e),this.setShaderStage("VERTEX_SHADER",'\nprecision highp float;\n\nattribute vec3 positions;\n#ifdef ENABLE_TEXTURES\nattribute vec2 texCoords;\n#endif\n\n<%include file="GLSLUtils.glsl"/>\n<%include file="stack-gl/transpose.glsl"/>\n<%include file="drawItemId.glsl"/>\n<%include file="drawItemTexture.glsl"/>\n<%include file="modelMatrix.glsl"/>\n<%include file="materialparams.glsl"/>\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform lowp int isOrthographic;\nuniform vec4 viewportFrustum;\n\n\n/* VS Outputs */\nvarying float v_drawItemId;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\n\nvoid main(void) {\n int drawItemId = getDrawItemId();\n v_drawItemId = float(drawItemId);\n v_geomItemData = getInstanceData(drawItemId);\n\n //////////////////////////////////////////////\n // Material\n vec2 materialCoords = v_geomItemData.zw;\n vec4 materialValue1 = getMaterialValue(materialCoords, 1);\n int maintainScreenSize = int(materialValue1.x + 0.5);\n float overlay = materialValue1.y;\n\n //////////////////////////////////////////////\n // Matrix\n \n mat4 modelMatrix = getModelMatrix(drawItemId);\n if (maintainScreenSize != 0) {\n // Remove the scale from the model matrix.\n vec3 row0 = normalize(vec3(modelMatrix[0][0], modelMatrix[0][1], modelMatrix[0][2]));\n vec3 row1 = normalize(vec3(modelMatrix[1][0], modelMatrix[1][1], modelMatrix[1][2]));\n vec3 row2 = normalize(vec3(modelMatrix[2][0], modelMatrix[2][1], modelMatrix[2][2]));\n modelMatrix = mat4(\n row0.x, row0.y, row0.z, 0.0,\n row1.x, row1.y, row1.z, 0.0,\n row2.x, row2.y, row2.z, 0.0,\n modelMatrix[3][0], modelMatrix[3][1], modelMatrix[3][2], 1.0\n );\n }\n mat4 modelViewMatrix = viewMatrix * modelMatrix;\n if (maintainScreenSize != 0) {\n if (isOrthographic > 0){\n // At a distance of 1, we should match the orthographic and perspective sizes.\n // Calculate the size of the handle in perpective projection at 1 meter.\n // With a 24mm camera, the Fov is 46.4 degrees, or 0.8098327729253689 radians.\n // (0.81 / 2.0) * focalDist * 2.0\n // The frustum height at 1m is 0.81.\n float sc = viewportFrustum.y / 0.8098327;\n mat4 scmat = mat4(\n sc, 0.0, 0.0, 0.0,\n 0.0, sc, 0.0, 0.0,\n 0.0, 0.0, sc, 0.0,\n 0.0, 0.0, 0.0, 1.0\n );\n modelViewMatrix = modelViewMatrix * scmat;\n } else {\n float dist = modelViewMatrix[3][2];\n float sc = abs(dist); // Note: items in front of the camera will have a negative value here.\n mat4 scmat = mat4(\n sc, 0.0, 0.0, 0.0,\n 0.0, sc, 0.0, 0.0,\n 0.0, 0.0, sc, 0.0,\n 0.0, 0.0, 0.0, 1.0\n );\n modelViewMatrix = modelViewMatrix * scmat;\n }\n }\n\n vec4 viewPos = modelViewMatrix * vec4(positions, 1.0);\n gl_Position = projectionMatrix * viewPos;\n\n if(overlay > 0.0){\n gl_Position.z = mix(gl_Position.z, -gl_Position.w, overlay);\n }\n\n v_viewPos = viewPos.xyz;\n v_textureCoord = texCoords;\n v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n}\n'),this.setShaderStage("FRAGMENT_SHADER",'\nprecision highp float;\n\n<%include file="GLSLUtils.glsl"/>\n<%include file="math/constants.glsl"/>\n<%include file="drawItemTexture.glsl"/>\n<%include file="stack-gl/gamma.glsl"/>\n<%include file="materialparams.glsl"/>\n\n\n#if defined(DRAW_COLOR)\n\nuniform color BaseColor;\n\n#ifdef ENABLE_TEXTURES\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\n#endif\n\n#elif defined(DRAW_GEOMDATA)\n\nuniform lowp int isOrthographic;\nimport \'surfaceGeomData.glsl\'\n\n#elif defined(DRAW_HIGHLIGHT)\n\n#ifdef ENABLE_FLOAT_TEXTURES\nvec4 getHighlightColor(int id) {\n return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 4);\n}\n#else // ENABLE_FLOAT_TEXTURES\n\nuniform vec4 highlightColor;\n\nvec4 getHighlightColor() {\n return highlightColor;\n}\n\n#endif // ENABLE_FLOAT_TEXTURES\n\n#endif // DRAW_HIGHLIGHT\n\n/* VS Outputs */\nvarying float v_drawItemId;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\n\n\n#ifdef ENABLE_ES3\n out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n vec4 fragColor;\n#endif\n\n int drawItemId = int(v_drawItemId + 0.5);\n\n //////////////////////////////////////////////\n // Color\n#if defined(DRAW_COLOR)\n\n vec2 materialCoords = v_geomItemData.zw;\n vec4 baseColor = toLinear(getMaterialValue(materialCoords, 0));\n\n fragColor = baseColor;\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n fragColor.rgb = toGamma(fragColor.rgb);\n#endif\n\n //////////////////////////////////////////////\n // GeomData\n#elif defined(DRAW_GEOMDATA)\n\n fragColor = setFragColor_geomData(v_viewPos, floatGeomBuffer, passId, v_drawItemId, isOrthographic);\n //////////////////////////////////////////////\n // Highlight\n#elif defined(DRAW_HIGHLIGHT)\n \n fragColor = getHighlightColor(drawItemId);\n\n#endif // DRAW_HIGHLIGHT\n\n\n#ifndef ENABLE_ES3\n gl_FragColor = fragColor;\n#endif\n}\n')}static getPackedMaterialData(e){const t=new Float32Array(8),a=e.getParameter("BaseColor").value;return t[0]=a.r,t[1]=a.g,t[2]=a.b,t[3]=a.a,t[4]=e.getParameter("MaintainScreenSize").value,t[5]=e.getParameter("Overlay").value,t}static isOverlay(){return!0}static getMaterialTemplate(){return u}}const u=new d("HandleShader_template");e.Registry.register("HandleShader",m);const g=(e,t)=>{e.update();const a=e.positions;for(let e=0;e<a.getCount();e++){const i=a.getValue(e),s=t.transformVec3(i);a.setValue(e,s)}};class p extends h{supressed=!1;treeItems=[];baseXfo;localXfos=[];prevValues=[];newValues=[];constructor(e,t){if(super("SelectionXfoChange"),!e||!t)return;this.treeItems=e,this.baseXfo=t;const a=t.inverse();this.treeItems.forEach((e=>{this.localXfos.push(a.multiply(e.globalXfoParam.value)),this.prevValues.push(e.globalXfoParam.value),this.newValues.push(e.globalXfoParam.value)}))}setDeltaXfo(e){const t=this.baseXfo.clone();t.tr=e.tr.add(t.tr),t.ori=e.ori.multiply(t.ori),t.sc=e.sc.multiply(t.sc),this.prevValues.forEach(((e,a)=>{const i=t.multiply(this.localXfos[a]);this.newValues[a]=i,this.treeItems[a].globalXfoParam.value=this.newValues[a].clone()})),this.emit("updated",{newValues:[...this.newValues]})}setDone(){this.emit("done")}undo(){this.treeItems.forEach(((e,t)=>{e.globalXfoParam.value=this.prevValues[t]}))}redo(){this.treeItems.forEach(((e,t)=>{e.globalXfoParam.value=this.newValues[t]}))}update(e){this.newValues=e.newValues,this.supressed||this.treeItems.forEach(((e,t)=>{e.globalXfoParam.value=this.newValues[t]})),this.emit("updated",e)}toJSON(e){const t=super.toJSON(e);return t.treeItems=[],t.prevValues=[],t.newValues=[],t.baseXfo=this.baseXfo.toJSON(),t.supressed=this.supressed,this.treeItems.forEach(((e,a)=>{t.treeItems[a]=this.treeItems[a].getPath(),t.prevValues[a]=this.prevValues[a].toJSON(),t.newValues[a]=this.newValues[a].toJSON()})),t}fromJSON(t,a){super.fromJSON(t,a),this.baseXfo||(this.baseXfo=new e.Xfo),this.baseXfo.fromJSON(t.baseXfo);const i=this.baseXfo.inverse();t.treeItems.forEach(((s,o)=>{this.treeItems[o]=a.appData.scene.getRoot().resolvePath(s),this.localXfos.push(i.multiply(this.treeItems[o].globalXfoParam.value)),this.prevValues[o]||(this.prevValues[o]=new e.Xfo),this.prevValues[o].fromJSON(t.prevValues[o]),this.newValues[o]||(this.newValues[o]=new e.Xfo),this.newValues[o].fromJSON(t.newValues[o])}))}}r.registerChange("SelectionXfoChange",p);class f extends h{__selectionManager;__prevSelection;__newSelection;constructor(e,t,a){super("SelectionChange"),e&&t&&a&&(this.__selectionManager=e,this.__prevSelection=t,this.__newSelection=a)}undo(){this.__selectionManager.setSelection(this.__prevSelection,!1)}redo(){this.__selectionManager.setSelection(this.__newSelection,!1)}toJSON(e){const t=super.toJSON(e),a=[];for(const e of this.__newSelection)a.push(e.getPath());return t.itemPaths=a,t}fromJSON(e,t){super.fromJSON(e,t),this.__selectionManager=t.appData.selectionManager,this.__prevSelection=new Set(this.__selectionManager.getSelection());const a=t.appData.scene.getRoot(),i=new Set;for(const t of e.itemPaths)i.add(a.resolvePath(t,1));this.__newSelection=i,this.__selectionManager.setSelection(this.__newSelection,!1)}}r.registerChange("SelectionChange",f);class v extends h{selection;state;constructor(e,t){super("Selection Visibility Change"),e&&"boolean"==typeof t&&(this.selection=e,this.state=t,this._changeItemsVisibility(this.state))}undo(){this._changeItemsVisibility(!this.state)}redo(){this._changeItemsVisibility(this.state)}_changeItemsVisibility(e){for(const t of this.selection)t.getParameter("Visible").value=e}}r.registerChange("ToggleSelectionVisibility",v);class P extends h{treeItem;owner;prevSelection;selectionManager;treeItemIndex;constructor(e,t,a){e?(super(e.getName()+" Added"),this.treeItem=e,this.owner=t,this.selectionManager=a,this.prevSelection=new Set(this.selectionManager.getSelection()),this.treeItemIndex=this.owner.getChildIndex(this.owner.addChild(this.treeItem)),this.selectionManager.setSelection(new Set([this.treeItem]),!1)):super()}undo(){if(this.treeItem instanceof e.Operator){this.treeItem.detach()}else this.treeItem instanceof e.TreeItem&&this.treeItem.traverse((t=>{if(t instanceof e.Operator){t.detach()}}),!1);this.owner.removeChild(this.treeItemIndex),this.selectionManager&&this.selectionManager.setSelection(this.prevSelection,!1)}redo(){if(this.treeItem instanceof e.Operator){this.treeItem.reattach()}else this.treeItem instanceof e.TreeItem&&this.treeItem.traverse((t=>{if(t instanceof e.Operator){t.reattach()}}),!1);this.owner.addChild(this.treeItem),this.selectionManager&&this.selectionManager.setSelection(new Set([this.treeItem]),!1)}toJSON(e){const t=super.toJSON(e);return t.treeItem=this.treeItem.toJSON(e),t.treeItemPath=this.treeItem.getPath(),t.treeItemIndex=this.treeItemIndex,t}fromJSON(t,a){super.fromJSON(t,a);const i=e.Registry.constructClass(t.treeItem.type);i?(this.name=t.name,this.treeItem=i,this.treeItem.fromJSON(t.treeItem,a),this.treeItemIndex=this.owner.getChildIndex(this.owner.addChild(this.treeItem))):console.warn("resolvePath is unable to construct",t.treeItem)}destroy(){}}r.registerChange("TreeItemAddChange",P);class I extends h{treeItem;oldOwner;oldOwnerIndex;newOwner;constructor(e,t){e?(super(e.getName()+" Moved"),this.treeItem=e,this.oldOwner=this.treeItem.getOwner(),this.oldOwnerIndex=this.oldOwner.getChildIndex(this.treeItem),this.newOwner=t,this.newOwner.addChild(this.treeItem,!0)):super()}undo(){this.oldOwner.insertChild(this.treeItem,this.oldOwnerIndex,!0)}redo(){this.newOwner.addChild(this.treeItem,!0)}toJSON(e){const t=super.toJSON(e);return t.treeItemPath=this.treeItem.getPath(),t.newOwnerPath=this.newOwner.getPath(),t}fromJSON(e,t){if(!t||!t.scene)return;super.fromJSON(e,t);const a=t.scene.getRoot().resolvePath(e.treeItemPath,1);if(!a)return void console.warn("resolvePath is unable to resolve",e.treeItemPath);const i=t.scene.getRoot().resolvePath(e.newOwnerPath,1);i?(this.name=e.name,this.treeItem=a,this.newOwner=i,this.oldOwner=this.treeItem.getOwner(),this.oldOwnerIndex=this.oldOwner.getChildIndex(this.treeItem),this.newOwner.addChild(this.treeItem,!0)):console.warn("resolvePath is unable to resolve",e.newOwnerPath)}}r.registerChange("TreeItemMoveChange",I);class C extends h{items=[];itemOwners=[];itemPaths=[];itemIndices=[];constructor(e,t){if(super(),e){this.items=e;const a=new Set(t?.selectionManager?.getSelection()),i=[];this.items.forEach((e=>{const t=e.getOwner(),s=t.getChildIndex(e);i.push(e.getName()),this.itemOwners.push(t),this.itemPaths.push(e.getPath()),this.itemIndices.push(s),a.has(e)&&a.delete(e),e.traverse((e=>{a.has(e)&&a.delete(e)}),!1),t.removeChild(s)})),t?.selectionManager&&t.selectionManager.setSelection(a,!0,this),this.name=i+" Deleted"}}undo(){this.items.forEach(((e,t)=>{this.itemOwners[t].insertChild(e,this.itemIndices[t],!1,!1)}))}redo(){this.items.forEach(((e,t)=>{this.itemOwners[t].removeChild(this.itemIndices[t])}))}toJSON(e){const t=super.toJSON(e);return t.itemPaths=this.itemPaths,t.itemIndices=this.itemIndices,t}fromJSON(e,t){super.fromJSON(e,t);const a=t.appData.scene.getRoot();e.itemPaths.forEach((e=>{const t=a.resolvePath(e,1);if(!t)return void console.warn("resolvePath is unable to resolve",e);const i=t.getOwner(),s=i.getChildIndex(t);this.itemOwners.push(i),this.itemPaths.push(t.getPath()),this.itemIndices.push(s),i.removeChild(s)}))}}r.registerChange("TreeItemsRemoveChange",C);class w extends s{handleMat;baseXfo;change;param;selectionGroup;constructor(t,a=.1,i=.003,s=new e.Color){super(t),this.colorParam.value=s,this.handleMat=new d("handle"),this.handleMat.baseColorParam.value=s,this.handleMat.maintainScreenSizeParam.value=1,this.handleMat.overlayParam.value=.9;const o=new e.Cylinder(i,a,64);o.baseZAtZeroParam.value=!0;const n=new e.Cone(8*i,16*i,64,!0),r=new e.GeomItem("handle",o,this.handleMat),l=new e.GeomItem("tip",n,this.handleMat),h=new e.Xfo;h.tr.set(0,0,a),g(n,h),this.colorParam.on("valueChanged",(()=>{this.handleMat.baseColorParam.value=this.colorParam.value})),this.addChild(r),this.addChild(l)}highlight(){super.highlight(),this.handleMat.baseColorParam.value=this.highlightColorParam.value}unhighlight(){super.unhighlight(),this.handleMat.baseColorParam.value=this.colorParam.value}setSelectionGroup(e){this.selectionGroup=e}setTargetParam(e){this.param=e}getTargetParam(){return this.param?this.param:this.globalXfoParam}onDragStart(e){const t=this.getTargetParam();if(this.baseXfo=t.value,this.selectionGroup){const e=this.selectionGroup.getItems();this.change=new p(Array.from(e),this.globalXfoParam.value),r.getInstance().addChange(this.change)}else this.change=new c(t),r.getInstance().addChange(this.change)}onDrag(t){const a=this.holdPos.subtract(this.grabPos);if(this.change instanceof p){const t=new e.Xfo(a);this.change.setDeltaXfo(t)}else{const e=this.baseXfo.clone();e.tr.addInPlace(a),this.change.update({value:e})}}onDragEnd(e){this.change instanceof p&&this.change.setDone(),this.change=null}}class b extends i{param;radiusParam;baseXfo;handleXfo;snapIncrementAngle=22.5;enableAngleSnapping=!1;handleToTargetXfo;vec0;change;handleMat;handle;selectionGroup;constructor(t,a,i,s=.5*Math.PI,o=new e.Color(1,1,0)){super(t),this.radiusParam=new e.NumberParameter("Radius",a),this.colorParam.value=o,this.addParameter(this.radiusParam),this.handleMat=new d("handle"),this.handleMat.baseColorParam.value=o,this.handleMat.maintainScreenSizeParam.value=1,this.handleMat.overlayParam.value=.9;const n=new e.Torus(i,a,64,s);this.handle=new e.GeomItem("handle",n,this.handleMat),this.radiusParam.on("valueChanged",(()=>{a=this.radiusParam.value,n.outerRadiusParam.value=a,n.innerRadiusParam.value=.02*a})),this.colorParam.on("valueChanged",(()=>{this.handleMat.baseColorParam.value=this.colorParam.value})),this.addChild(this.handle)}highlight(){super.highlight(),this.handleMat.baseColorParam.value=this.highlightColorParam.value}unhighlight(){super.unhighlight(),this.handleMat.baseColorParam.value=this.colorParam.value}setSelectionGroup(e){this.selectionGroup=e}setTargetParam(e){this.param=e}getTargetParam(){return this.param?this.param:this.globalXfoParam}onDragStart(e){if(this.highlight(),this.baseXfo=this.globalXfoParam.value.clone(),this.vec0=this.grabPos.subtract(this.baseXfo.tr),this.vec0.normalizeInPlace(),this.selectionGroup){const e=this.selectionGroup.getItems();this.change=new p(Array.from(e),this.baseXfo),r.getInstance().addChange(this.change)}else{const e=this.baseXfo.inverse(),t=this.getTargetParam();this.handleToTargetXfo=e.multiply(t.value),this.change=new c(t),r.getInstance().addChange(this.change)}}onDrag(t){const a=this.holdPos.subtract(this.baseXfo.tr);a.normalizeInPlace();let i=this.vec0.angleTo(a);if(this.vec0.cross(a).dot(this.baseXfo.ori.getZaxis())<0&&(i=-i),t instanceof e.ZeaMouseEvent&&t.shiftKey||this.enableAngleSnapping){const t=e.MathFunctions.degToRad(this.snapIncrementAngle);i=Math.floor(i/t)*t}const s=new e.Xfo;if(s.ori.setFromAxisAndAngle(this.baseXfo.ori.getZaxis(),i),this.change instanceof p)this.change.setDeltaXfo(s);else{const e=this.baseXfo.clone();e.ori=s.ori.multiply(e.ori);const t=e.multiply(this.handleToTargetXfo);this.change.update({value:t})}}onDragEnd(e){this.change instanceof p&&this.change.setDone(),this.change=null}}class y extends i{param;fullXfoManipulationInVR;grabOffset;baseXfo;change;selectionGroup;constructor(e){super(e),this.fullXfoManipulationInVR=!0}setSelectionGroup(e){this.selectionGroup=e}setTargetParam(e){this.param=e}getTargetParam(){return this.param?this.param:this.globalXfoParam}onDragStart(e){this.grabPos=this.grabPos;const t=this.getTargetParam();if(this.baseXfo=t.value,this.selectionGroup){const e=this.selectionGroup.getItems();this.change=new p(Array.from(e),this.globalXfoParam.value),r.getInstance().addChange(this.change)}else this.change=new c(t),r.getInstance().addChange(this.change)}onDrag(t){const a=this.holdPos.subtract(this.grabPos);if(this.change instanceof p){const t=new e.Xfo(a);this.change.setDeltaXfo(t)}else{const e=this.baseXfo.clone();e.tr.addInPlace(a),this.change.update({value:e})}}onDragEnd(e){this.change instanceof p&&this.change.setDone(),this.change=null}onXRControllerButtonDown(e){if(this.fullXfoManipulationInVR){this.activeController=e.controller;const t=this.activeController.getTipXfo(),a=this.globalXfoParam.value;this.grabOffset=t.inverse().multiply(a)}else super.onXRControllerButtonDown(e)}onXRPoseChanged(e){if(this.fullXfoManipulationInVR){const e=this.activeController.getTipXfo().multiply(this.grabOffset);if(this.change)this.change.update({value:e});else{this.getTargetParam().value=e}}else super.onXRPoseChanged(e)}onVRControllerButtonUp(e){this.fullXfoManipulationInVR?this.change=null:super.onVRControllerButtonUp(e)}}class X extends y{sizeParam;handle;handleMat;constructor(t,a,i,s=new e.Color){super(t),this.sizeParam=new e.NumberParameter("Size",a),this.addParameter(this.sizeParam),this.colorParam.value=s,this.handleMat=new d("handle"),this.handleMat.baseColorParam.value=s,this.handleMat.maintainScreenSizeParam.value=1,this.handleMat.overlayParam.value=.9;const o=new e.Cuboid(a,a,.02*a),n=new e.Xfo;n.tr=i,g(o,n),this.handle=new e.GeomItem("handle",o,this.handleMat),this.sizeParam.on("valueChanged",(()=>{a=this.sizeParam.value,o.sizeXParam.value=a,o.sizeYParam.value=a,o.sizeZParam.value=.02*a})),this.colorParam.on("valueChanged",(()=>{this.handleMat.baseColorParam.value=this.colorParam.value})),this.addChild(this.handle)}highlight(){super.highlight(),this.handleMat.baseColorParam.value=this.highlightColorParam.value}unhighlight(){super.unhighlight(),this.handleMat.baseColorParam.value=this.colorParam.value}}class x extends e.TreeItem{param;highlightColorParam=new e.ColorParameter("HighlightColor",new e.Color(1,1,1));constructor(t=.1,a=.001){super("XfoHandle"),this.highlightColorParam.on("valueChanged",(()=>{const e=this.highlightColorParam.value;this.traverse((t=>{t instanceof i&&(t.highlightColorParam.value=e)}))})),this.addParameter(this.highlightColorParam);const s=new e.TreeItem("Translate");this.addChild(s);const o=new e.Color(1,.1,.1),n=new e.Color("#32CD32"),r=new e.Color("#1E90FF");o.a=1,n.a=1,r.a=1;{const i=new w("linearX",t,a,o),n=new e.Xfo;n.ori.setFromAxisAndAngle(new e.Vec3(0,1,0),.5*Math.PI),i.localXfoParam.value=n,s.addChild(i)}{const i=new w("linearY",t,a,n),o=new e.Xfo;o.ori.setFromAxisAndAngle(new e.Vec3(1,0,0),-.5*Math.PI),i.localXfoParam.value=o,s.addChild(i)}{const e=new w("linearZ",t,a,r);s.addChild(e)}const l=.25*t;{const t=new X("planarXY",l,new e.Vec3(.85*l,.85*l,0),r),a=new e.Xfo;t.localXfoParam.value=a,s.addChild(t)}{const t=new X("planarYZ",l,new e.Vec3(-.85*l,.85*l,0),o),a=new e.Xfo;a.ori.setFromAxisAndAngle(new e.Vec3(0,1,0),.5*Math.PI),t.localXfoParam.value=a,s.addChild(t)}{const t=new X("planarXZ",l,new e.Vec3(.85*l,.85*l,0),n),a=new e.Xfo;a.ori.setFromAxisAndAngle(new e.Vec3(1,0,0),.5*Math.PI),t.localXfoParam.value=a,s.addChild(t)}const h=new e.TreeItem("Rotate");this.addChild(h);{const i=new b("rotationX",.75*t,a,.5*Math.PI,o),s=new e.Xfo;s.ori.setFromEulerAngles(new e.EulerAngles(-.5*Math.PI,-.5*Math.PI,0)),i.localXfoParam.value=s,h.addChild(i)}{const i=new b("rotationY",.75*t,a,.5*Math.PI,n),s=new e.Xfo;s.ori.setFromAxisAndAngle(new e.Vec3(1,0,0),-.5*Math.PI),i.localXfoParam.value=s,h.addChild(i)}{const i=new b("rotationZ",.75*t,a,.5*Math.PI,r),s=new e.Xfo;s.ori.setFromAxisAndAngle(new e.Vec3(0,0,1),.5*Math.PI),i.localXfoParam.value=s,h.addChild(i)}}showHandles(e){e?this.setVisible(!0):this.setVisible(!1)}setTargetParam(e){this.param=e,this.traverse((t=>{(t instanceof w||t instanceof X||t instanceof b)&&t.setTargetParam(e)}))}setSelectionGroup(e){this.traverse((t=>{(t instanceof w||t instanceof X||t instanceof b)&&t.setSelectionGroup(e)}))}}class M extends e.Operator{currGroupXfo;xfoModeInput=new e.NumberOperatorInput("InitialXfoMode");xfoOutput=new e.XfoOperatorOutput("GroupGlobalXfo");constructor(t,a){super(),this.addInput(this.xfoModeInput).setParam(t),this.addOutput(this.xfoOutput).setParam(a),this.currGroupXfo=new e.Xfo}addItem(t){const a=new e.XfoOperatorInput("MemberGlobalXfo"+this.getNumInputs());a.setParam(t.globalXfoParam),this.addInput(a),this.setDirty()}removeItem(e){const t=e.globalXfoParam;for(let e=1;e<this.getNumInputs();e++){const a=this.getInputByIndex(e);if(a.getParam()==t)return this.removeInput(a),void this.setDirty()}throw new Error("Item not found in SelectionGroupXfoOperator")}backPropagateValue(e){const t=this.currGroupXfo.inverse(),a=e.multiply(t);a.ori.normalizeInPlace(),this.currGroupXfo=a.multiply(this.currGroupXfo);for(let e=1;e<this.getNumInputs();e++){const t=this.getInputByIndex(e),i=t.getValue(),s=a.multiply(i);t.setValue(s)}}evaluate(){if(this.currGroupXfo=new e.Xfo,1==this.getNumInputs())return void this.xfoOutput.setClean(this.currGroupXfo);const t=this.xfoModeInput.param.value;if(t!=e.KinematicGroup.INITIAL_XFO_MODES.manual){if(t==e.KinematicGroup.INITIAL_XFO_MODES.first){const e=this.getInputByIndex(1).getValue();this.currGroupXfo.tr=e.tr.clone(),this.currGroupXfo.ori=e.ori.clone()}else if(t==e.KinematicGroup.INITIAL_XFO_MODES.average){this.currGroupXfo.ori.set(0,0,0,0);let e=0;for(let t=1;t<this.getNumInputs();t++){const a=this.getInputByIndex(t).getValue();this.currGroupXfo.tr.addInPlace(a.tr),0==e&&this.currGroupXfo.ori.addInPlace(a.ori),e++}this.currGroupXfo.tr.scaleInPlace(1/e)}else{if(t!=e.KinematicGroup.INITIAL_XFO_MODES.globalOri)throw new Error("Invalid KinematicGroup.INITIAL_XFO_MODES.");{let e=0;for(let t=1;t<this.getNumInputs();t++){const a=this.getInputByIndex(t).getValue();this.currGroupXfo.tr.addInPlace(a.tr),e++}this.currGroupXfo.tr.scaleInPlace(1/e)}}this.currGroupXfo.ori.normalizeInPlace(),this.xfoOutput.setClean(this.currGroupXfo)}else this.currGroupXfo=this.xfoOutput.getParam().value.clone()}}const S={disabled:0,manual:1,first:2,average:3,globalOri:4};class T extends e.SelectionSet{initialXfoModeParam=new e.MultiChoiceParameter("InitialXfoMode",S.average,["manual","first","average","global"]);selectionGroupXfoOp;constructor(t){super();const a=t.selectionOutlineColor?t.selectionOutlineColor:new e.Color(3/255,227/255,172/255,.1);this.highlightColorParam.value=a,this.itemsParam.setFilterFn((t=>t instanceof e.BaseItem)),this.addParameter(this.initialXfoModeParam),this.selectionGroupXfoOp=new M(this.initialXfoModeParam,this.globalXfoParam)}static get INITIAL_XFO_MODES(){return S}clone(e){const t=new T;return t.copyFrom(this,e),t}bindItem(e,t){const a=this.highlightColorParam.value;a.a=this.highlightFillParam.value,e.addHighlight("selected"+this.getId(),a,!0),this.selectionGroupXfoOp.addItem(e)}unbindItem(e,t){e.removeHighlight("selected"+this.getId(),!0),this.selectionGroupXfoOp.removeItem(e)}}class A extends e.EventEmitter{appData;leadSelection=void 0;selectionGroup;xfoHandle;xfoHandleVisible;renderer;pickFilter;pickCB;constructor(t,a={}){super(),this.appData=t,this.selectionGroup=new T(a),!0===a.enableXfoHandles&&(this.xfoHandle=new x,this.xfoHandle.setSelectionGroup(this.selectionGroup),this.xfoHandle.setVisible(!1),this.xfoHandle.highlightColorParam.value=new e.Color(1,1,0),this.xfoHandleVisible=!0,this.selectionGroup.addChild(this.xfoHandle)),this.appData.renderer&&this.setRenderer(this.appData.renderer)}setRenderer(e){this.renderer!=e?(this.renderer=e,this.renderer.addTreeItem(this.selectionGroup)):console.warn("Renderer already set on SelectionManager")}setXfoMode(e){this.xfoHandle&&(this.selectionGroup.initialXfoModeParam.value=e)}showHandles(e){this.xfoHandleVisible=e}updateHandleVisibility(){if(!this.xfoHandle)return;const e=this.selectionGroup.getItems(),t=Array.from(e).length>0;this.xfoHandle.setVisible(t&&this.xfoHandleVisible),this.renderer.requestRedraw()}getSelection(){return this.selectionGroup.getItems()}setSelection(e,t=!0,a){const i=new Set(this.selectionGroup.getItems()),s=new Set(i);for(const t of e)i.has(t)||(t.setSelected(!0),i.add(t));for(const t of i)e.has(t)||(t.setSelected(!1),i.delete(t));if(this.selectionGroup.setItems(i),i.size>0?this.setLeadSelection(i.values().next().value):this.setLeadSelection(),this.updateHandleVisibility(),t){const e=new f(this,s,i);a?a.addSecondaryChange(e):r.getInstance().addChange(e)}this.emit("selectionChanged",{prevSelection:s,selection:i})}setLeadSelection(e){this.leadSelection!=e&&(this.leadSelection=e,this.emit("leadSelectionChanged",{treeItem:e}))}toggleItemSelection(e,t=!0,a=!0,i){const s=new Set(this.selectionGroup.getItems()),o=new Set(s);if(t&&(1!=s.size||!s.has(e))){let t=!0;if(s.has(e)){let a=1;e.traverse((e=>{s.has(e)&&a++})),t=a!=s.size}t&&(Array.from(s).forEach((e=>{e.setSelected(!1)})),s.clear())}let n;if(s.has(e)?(e.setSelected(!1),s.delete(e),n=!1):(e.setSelected(!0),s.add(e),n=!0),this.selectionGroup.setItems(s),n&&1===s.size?this.setLeadSelection(e):n||(1===s.size?this.setLeadSelection(s.values().next().value):0===s.size&&this.setLeadSelection()),a){const e=new f(this,o,s);i?i.addSecondaryChange(e):r.getInstance().addChange(e)}this.updateHandleVisibility(),this.emit("selectionChanged",{prevSelection:o,selection:s})}clearSelection(e=!0,t){const a=new Set(this.selectionGroup.getItems());if(0==a.size)return;let i;e&&(i=new Set(a));for(const e of a)e.setSelected(!1);if(a.clear(),this.selectionGroup.setItems(a),this.setLeadSelection(),this.updateHandleVisibility(),e){const e=new f(this,i,a);t?t.addSecondaryChange(e):r.getInstance().addChange(e)}this.emit("selectionChanged",{selection:a,prevSelection:i})}selectItems(e,t=!0,a=!0,i){const s=new Set(this.selectionGroup.getItems()),o=new Set(s);t&&s.clear();for(const t of e)s.has(t)||(t.setSelected(!0),s.add(t));if(this.selectionGroup.setItems(s),1===s.size?this.setLeadSelection(s.values().next().value):0===s.size&&this.setLeadSelection(),this.updateHandleVisibility(),a){const e=new f(this,o,s);i?i.addSecondaryChange(e):r.getInstance().addChange(e)}this.emit("selectionChanged",{prevSelection:o,selection:s})}deselectItems(e,t=!0,a){const i=new Set(this.selectionGroup.getItems()),s=new Set(i);for(const t of e)i.has(t)&&(t.setSelected(!1),i.delete(t));if(this.selectionGroup.setItems(i),1===i.size?this.setLeadSelection(i.values().next().value):0===i.size&&this.setLeadSelection(),this.updateHandleVisibility(),t){const e=new f(this,s,i);a?a.addSecondaryChange(e):r.getInstance().addChange(e)}this.emit("selectionChanged",{prevSelection:s,selection:i})}startPickingMode(e,t){this.pickCB=e,this.pickFilter=t}pickingModeActive(){return!!this.pickCB&&!!this.pickFilter}endPickingMode(){this.pickCB=void 0}pick(e){if(this.pickCB)if(Array.isArray(e))e.forEach((e=>{const t=this.pickFilter?this.pickFilter(e):e;t&&this.pickCB(t)}));else{const t=this.pickFilter?this.pickFilter(e):e;t&&this.pickCB(t)}}}class D extends e.BaseTool{appData;dragging;selectionManager;selectionRectXfo;rectItem;pointerDownPos;selectionRect;selectionRectMat;selectionFilterFn=null;constructor(t){super(),t||console.error("App data not provided to tool"),this.appData=t,this.dragging=!1,t.selectionManager||console.error("`SelectionTool` requires `SelectionManager` to be provided in the `appData` object"),this.selectionManager=t.selectionManager,this.selectionRect=new e.Rect(1,1),this.selectionRectMat=new e.ScreenSpaceMaterial("marker"),this.selectionRectMat.baseColorParam.value=new e.Color("#03E3AC"),this.selectionRectXfo=new e.Xfo,this.selectionRectXfo.sc.set(0,0,0),this.rectItem=new e.GeomItem("selectionRect",this.selectionRect,this.selectionRectMat),this.rectItem.visibleParam.value=!1,this.rectItem.pickableParam.value=!1,this.appData.renderer.addTreeItem(this.rectItem)}activateTool(){super.activateTool()}deactivateTool(){super.deactivateTool(),this.selectionRectXfo.sc.set(0,0,0),this.rectItem.globalXfoParam.value=this.selectionRectXfo,this.rectItem.visibleParam.value=!1}setSelectionManager(e){this.selectionManager=e}setSelectionFilter(e){this.selectionFilterFn=e}resizeRect(t,a){const i=t.getWidth(),s=t.getHeight(),o=new e.Vec2(1/i*2,1/s*2),n=a.multiply(o);this.selectionRectXfo.sc.set(Math.abs(n.x),Math.abs(n.y),1);const r=this.pointerDownPos.subtract(a.scale(.5)).multiply(o).subtract(new e.Vec2(1,1));this.selectionRectXfo.tr.x=r.x,this.selectionRectXfo.tr.y=-r.y,this.rectItem.globalXfoParam.value=this.selectionRectXfo}onPointerDoublePress(e){}onPointerDown(t){this.dragging?(this.selectionRectXfo.sc.set(0,0,0),this.rectItem.globalXfoParam.value=this.selectionRectXfo,this.rectItem.visibleParam.value=!1,this.pointerDownPos=void 0,this.dragging=!1,t.stopPropagation()):(t instanceof e.ZeaTouchEvent||t instanceof e.ZeaMouseEvent&&0==t.button)&&(this.pointerDownPos=t.pointerPos.scale(window.devicePixelRatio),this.dragging=!1,t.stopPropagation())}onPointerMove(t){if(t instanceof e.ZeaMouseEvent||t instanceof e.ZeaTouchEvent)if(this.pointerDownPos){const e=t.pointerPos.scale(window.devicePixelRatio),a=this.pointerDownPos.subtract(e);a.length()>4&&(this.dragging=!0,this.rectItem.visibleParam.value=!0,this.resizeRect(t.viewport,a)),t.stopPropagation()}else this.selectionManager.pickingModeActive()&&(t.intersectionData?this.selectionManager.pickFilter(t.intersectionData.geomItem):this.selectionManager.pickFilter(null));else console.warn("not handling VR")}onPointerUp(t){if((t instanceof e.ZeaMouseEvent||t instanceof e.ZeaTouchEvent)&&this.pointerDownPos){if(this.dragging){this.dragging=!1,this.rectItem.visibleParam.value=!1;const a=t.pointerPos.scale(window.devicePixelRatio),s=new e.Vec2(Math.min(this.pointerDownPos.x,a.x),Math.min(this.pointerDownPos.y,a.y)),o=new e.Vec2(Math.max(this.pointerDownPos.x,a.x),Math.max(this.pointerDownPos.y,a.y)),n=t.viewport;let r=Array.from(n.getGeomItemsInRect(s,o));if(r=r.filter((e=>e!=this.rectItem&&!(e.parent instanceof i))),this.selectionFilterFn){const e=[];r.forEach((t=>{const a=this.selectionFilterFn(t);a&&e.push(a)})),r=e}if(!this.selectionManager)throw"Please set the Selection Manager on the Selection Tool before using it.";if(this.selectionManager.pickingModeActive())this.selectionManager.pick(r);else{const e=new Set(r);t.shiftKey?this.selectionManager.deselectItems(e):this.selectionManager.selectItems(e,!t.ctrlKey),this.selectionRectXfo.sc.set(0,0,0),this.rectItem.globalXfoParam.value=this.selectionRectXfo}}else{const e=t.viewport,a=t.pointerPos,s=e.getGeomDataAtPos(a,void 0);if(null==s||s.geomItem.getOwner()instanceof i)this.selectionManager.clearSelection();else{let e=s.geomItem;if(this.selectionFilterFn&&(e=this.selectionFilterFn(e)),e)if(this.selectionManager.pickingModeActive())this.selectionManager.pick(e);else if(t.shiftKey){const t=new Set;t.add(e),this.selectionManager.deselectItems(t)}else this.selectionManager.toggleItemSelection(e,!t.ctrlKey)}}this.pointerDownPos=void 0,t.stopPropagation()}}onXRControllerButtonDown(e){if(1==e.button){if(!this.selectionManager)throw"Please set the Selection Manager on the Selection Tool before using it.";const t=e.controller.getGeomItemAtTip();null==t||t.geomItem.getOwner()instanceof i||(this.selectionManager.toggleItemSelection(t.geomItem),e.stopPropagation())}}}const R=new e.Lines;R.setNumVertices(2),R.setNumSegments(1),R.setSegmentVertexIndices(0,0,1);const V=R.getVertexAttribute("positions");V.setValue(0,new e.Vec3(0,0,0)),V.setValue(1,new e.Vec3(0,0,1)),R.setBoundingBoxDirty();const E=new e.LinesMaterial("line");E.baseColorParam.value=new e.Color(.2,1,.2);class O extends e.BaseTool{appData;vrViewport;prevCursor;pointerController;pointerThickness=.002;pointerColor=new e.Color(1,.2,.2);geom;material;defaultRaycastDist=0;raycastDist=20;bindControllerId;pointerGeomItems=[];constructor(t){super(),this.appData=t,this.appData.renderer.getXRViewport().then((t=>{t instanceof e.VRViewport&&(this.vrViewport=t)}))}activateTool(){super.activateTool(),this.displayPointers()}deactivateTool(){super.deactivateTool(),this.removePointers()}displayPointers(){this.appData&&this.appData.renderer&&(this.prevCursor=this.appData.renderer.getGLCanvas().style.cursor,this.appData.renderer.getGLCanvas().style.cursor="crosshair"),this.pointerThickness>0?(!this.geom||this.geom instanceof e.Cylinder)&&(this.geom=new e.Cylinder(this.pointerThickness,1,6,2,!0,!0),this.material=new e.FlatSurfaceMaterial("line"),this.material.overlayParam.value=.5):(this.geom=R,this.material=new e.LinesMaterial("line"),this.material.overlayParam.value=.5),this.material.baseColorParam.value=this.pointerColor;const t=t=>{if(this.pointerGeomItems[t.id])return;this.defaultRaycastDist=t.raycastDist,t.raycastDist=this.raycastDist;const a=new e.GeomItem("PointerRay",this.geom,this.material);a.pickableParam.value=!1;const i=new e.Xfo;i.sc.set(1,1,this.raycastDist/t.getTipXfo().sc.z),a.localXfoParam.value=i,t.tipItem.addChild(a,!1),this.pointerGeomItems[t.id]=a,this.appData.session&&this.appData.session.pub("poseChanged",{interfaceType:"VR",showPointer:{controllerId:t.id,thickness:this.pointerThickness,xfo:i,color:this.pointerColor}})};if(this.pointerController)t(this.pointerController);else if(this.vrViewport){for(const e of this.vrViewport.controllers)t(e);this.bindControllerId=this.vrViewport.on("controllerAdded",(e=>t(e.controller)))}}removePointers(){this.appData&&this.appData.renderer&&(this.appData.renderer.getGLCanvas().style.cursor=this.prevCursor);const e=e=>{this.pointerGeomItems[e.id]&&(e.tipItem.removeChildByHandle(this.pointerGeomItems[e.id]),e.raycastDist=this.defaultRaycastDist,this.pointerGeomItems[e.id]=null)};if(this.pointerController)e(this.pointerController);else if(this.vrViewport){for(const t of this.vrViewport.controllers)e(t);this.vrViewport.removeListenerById("controllerAdded",this.bindControllerId)}}setPointerLength(e,t){const a=this.pointerGeomItems[t.id];if(a){const i=a.localXfoParam.value;i.sc.set(1,1,e/t.getTipXfo().sc.z),a.localXfoParam.value=i,this.appData.session&&this.appData.session.pub("poseChanged",{interfaceType:"VR",updatePointer:{controllerId:t.id,xfo:i}})}}checkPointerIntersection(e){const t=e.getGeomItemAtTip();t?this.setPointerLength(t.dist,e):this.setPointerLength(this.raycastDist,e)}onPointerMove(t){t instanceof e.XRPoseEvent&&(this.pointerController?this.checkPointerIntersection(this.pointerController):t.controllers.forEach((e=>{this.pointerGeomItems[e.id]&&this.checkPointerIntersection(e)})),t.stopPropagation())}}const k=function(){return{escape:function(e){return e.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1")},parseExtension:e,mimeType:function(t){const a=e(t).toLowerCase();return function(){const e="application/font-woff",t="image/jpeg";return{woff:e,woff2:e,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:t,jpeg:t,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml"}}()[a]||""},dataAsUrl:function(e,t){return"data:"+t+";base64,"+e},isDataUrl:function(e){return-1!==e.search(/^(data:)/)},canvasToBlob:function(e){return e.toBlob?new Promise((function(t){e.toBlob(t)})):function(e){return new Promise((function(t){const a=window.atob(e.toDataURL().split(",")[1]),i=a.length,s=new Uint8Array(i);for(let e=0;e<i;e++)s[e]=a.charCodeAt(e);t(new Blob([s],{type:"image/png"}))}))}(e)},resolveUrl:function(e,t){const a=document.implementation.createHTMLDocument(),i=a.createElement("base");a.head.appendChild(i);const s=a.createElement("a");return a.body.appendChild(s),i.href=t,s.href=e,s.href},getAndEncode:function(e){const t=3e4;F.impl.options.cacheBust&&(e+=(/\?/.test(e)?"&":"?")+(new Date).getTime());return new Promise((function(a){const i=new XMLHttpRequest;let s;if(i.onreadystatechange=o,i.ontimeout=n,i.responseType="blob",i.timeout=t,i.open("GET",e,!0),i.send(),F.impl.options.imagePlaceholder){const e=F.impl.options.imagePlaceholder.split(/,/);e&&e[1]&&(s=e[1])}function o(){if(4!==i.readyState)return;if(200!==i.status)return void(s?a(s):r("cannot fetch resource: "+e+", status: "+i.status));const t=new FileReader;t.onloadend=function(){if("string"==typeof t.result){const e=t.result.split(/,/)[1];a(e)}else console.warn("encoder.result is not of string type")},t.readAsDataURL(i.response)}function n(){s?a(s):r("timeout of "+t+"ms occured while fetching resource: "+e)}function r(e){console.error(e),a("")}}))},uid:function(){let e=0;return function(){return"u"+t()+e++;function t(){return("0000"+(Math.random()*Math.pow(36,4)|0).toString(36)).slice(-4)}}}(),delay:function(e){return function(t){return new Promise((function(a){setTimeout((function(){a(t)}),e)}))}},asArray:function(e){const t=[],a=e.length;for(let i=0;i<a;i++)t.push(e[i]);return t},escapeXhtml:function(e){return e.replace(/#/g,"%23").replace(/\n/g,"%0A")},makeImage:function(e){return new Promise((function(t,a){const i=new Image;i.onload=function(){t(i)},i.onerror=a,i.src=e}))},width:function(e){const a=t(e,"border-left-width"),i=t(e,"border-right-width");return e.scrollWidth+a+i},height:function(e){const a=t(e,"border-top-width"),i=t(e,"border-bottom-width");return e.scrollHeight+a+i}};function e(e){const t=/\.([^\.\/]*?)$/g.exec(e);return t?t[1]:""}function t(e,t){const a=window.getComputedStyle(e).getPropertyValue(t);return parseFloat(a.replace("px",""))}}(),G=function(){const e=/url\(['"]?([^'"]+?)['"]?\)/g;return{inlineAll:function(e,s,o){return n()?Promise.resolve(e):Promise.resolve(e).then(a).then((function(t){let a=Promise.resolve(e);return t.forEach((function(e){a=a.then((function(t){return i(t,e,s,o)}))})),a}));function n(){return!t(e)}},shouldProcess:t,impl:{readUrls:a,inline:i}};function t(t){return-1!==t.search(e)}function a(t){const a=[];let i;for(;null!==(i=e.exec(t));)a.push(i[1]);return a.filter((function(e){return!k.isDataUrl(e)}))}function i(e,t,a,i){return Promise.resolve(t).then((function(e){return a?k.resolveUrl(e,a):e})).then(i||k.getAndE