From 6c088e2ac1688fc91c7e44cdc00226626ff10363 Mon Sep 17 00:00:00 2001 From: flash555588 Date: Sun, 12 Jul 2026 23:28:52 +0800 Subject: [PATCH] Release 0.7.6 --- CHANGELOG.md | 4 ++++ README.md | 15 ++++++--------- docs/README.md | 1 + docs/development-handoff.md | 4 ++-- docs/release-notes/0.7.6.md | 32 ++++++++++++++++++++++++++++++++ main.js | 2 +- manifest.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/render/babylon/scene.ts | 12 ++++++------ versions.json | 2 +- 11 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 docs/release-notes/0.7.6.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f694c8..fc5d388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 0.7.6 - 2026-07-12 + +- Review: use `window.requestAnimationFrame()` and `window.cancelAnimationFrame()` for Babylon preview frame scheduling so Obsidian source review accepts the timer calls. + ## 0.7.5 - 2026-07-12 - Stability: gate conversion-backed direct file views behind an explicit Load model action even when Obsidian restores them through `onLoadFile`, preventing STEP/STP workspace restore loops from freezing the vault. diff --git a/README.md b/README.md index f6e9249..2fc1077 100644 --- a/README.md +++ b/README.md @@ -89,23 +89,20 @@ ## Current Release -`0.7.5` upgrades the Slice and measurement workflows across Babylon.js and Three.js previews. Slice now uses a stable world-horizontal `0°` reset, editable position and X/Y/Z rotation fields, a model-covering cutting board, synchronized plane-local ruler/gizmo controls, and linked interaction rules that prevent conflicts with focus, measurement, disassembly, and camera orbit. +`0.7.6` is a source-review patch for the `0.7.5` Slice and measurement release. It preserves the `0.7.5` interaction behavior while using the review-approved global window animation-frame APIs throughout the Babylon preview. Release highlights: -- Defines Slice `0°` as the world-horizontal XZ plane and resets it through the model's world-bounds center at `50%`. -- Adds editable Slice position and X/Y/Z rotation inputs synchronized with the in-scene cutting board, ruler, move handle, and rotation rings. -- Stabilizes Babylon.js and Three.js Slice dragging with a fixed gesture frame, centered pivot, camera-inertia isolation, snap hysteresis, and frame-coalesced updates. -- Sizes the cutting board beyond all projected model corners and updates clipping planes in place to avoid flicker while moving. -- Measures the whole model by default; only an explicitly focused component narrows the measurement target. -- Coordinates Slice, measurement, focus, and disassembly as linked exclusive modes while preserving camera orbit and view overlays. +- Replaces Babylon preview `activeWindow.requestAnimationFrame()` with `window.requestAnimationFrame()` as required by Obsidian source review. +- Uses the matching `window.cancelAnimationFrame()` API for Babylon focus and Slice frame cancellation. +- Keeps the `0.7.5` world-horizontal Slice reset, numeric position/rotation controls, centered rotation pivot, adaptive cutting board, measurement scope, and linked interaction rules unchanged. - Babylon.js compatibility mode remains the default for single-model previews, with Three.js still available as an explicit opt-in route. - Converted GLB outputs from STEP/FBX/3MF/DAE/etc. can use a configurable Three.js fast path with silent Babylon fallback. - Auxiliary conversion side files can be stored in a user-selected folder instead of only under the Obsidian config directory. - Direct file view, `3dgrid`, measurement, camera zoom, and large-model loading paths have tighter performance and stability behavior. - README warnings now call out STEP/CAD conversion limits, external converter risk, large-model resource pressure, generated side files, renderer-route differences, mobile limits, and optional remote-draft privacy. -See [docs/release-notes/0.7.5.md](docs/release-notes/0.7.5.md), [docs/release-notes/0.7.1.md](docs/release-notes/0.7.1.md), and [CHANGELOG.md](CHANGELOG.md) for the full release history. +See [docs/release-notes/0.7.6.md](docs/release-notes/0.7.6.md), [docs/release-notes/0.7.5.md](docs/release-notes/0.7.5.md), and [CHANGELOG.md](CHANGELOG.md) for the full release history. --- @@ -654,7 +651,7 @@ ai-model-workbench/ ### Release Publishing -Releases are published by the GitHub Actions `Release` workflow. Push a tag that matches `manifest.json`, for example `0.7.5`, or run the workflow manually. The workflow uploads only `main.js`, `manifest.json`, and `styles.css`, removes unsupported release assets, verifies asset sizes and SHA-256 hashes, includes versioned release notes when available, and generates GitHub artifact attestations for the published files. After a release is published, run `npm run verify:obsidian -- --release-tag 0.7.5` to install the assets downloaded from GitHub into the temporary Obsidian vault. +Releases are published by the GitHub Actions `Release` workflow. Push a tag that matches `manifest.json`, for example `0.7.6`, or run the workflow manually. The workflow uploads only `main.js`, `manifest.json`, and `styles.css`, removes unsupported release assets, verifies asset sizes and SHA-256 hashes, includes versioned release notes when available, and generates GitHub artifact attestations for the published files. After a release is published, run `npm run verify:obsidian -- --release-tag 0.7.6` to install the assets downloaded from GitHub into the temporary Obsidian vault. ### Release Token Safety diff --git a/docs/README.md b/docs/README.md index c57bd28..f157e41 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,6 +45,7 @@ Use this page to choose the right document before changing code. - `../CHANGELOG.md` - current unreleased and release history. - `release-notes/0.6.0-plus.md` - user-facing rolling update log for the `0.6.0+` release line. +- `release-notes/0.7.6.md` - GitHub release notes for the Babylon timer source-review patch. - `release-notes/0.7.5.md` - GitHub release notes for the Slice and measurement interaction release. - `release-notes/0.7.1.md` - GitHub release notes for the `0.7.1` source-review patch. - `release-notes/0.7.0.md` - GitHub release notes for the `0.7.0` compatibility release. diff --git a/docs/development-handoff.md b/docs/development-handoff.md index d1d6cc5..e9205bd 100644 --- a/docs/development-handoff.md +++ b/docs/development-handoff.md @@ -8,7 +8,7 @@ README, implementation, verification scripts, and release/security docs. AI Model Workbench is an Obsidian plugin that renders 3D model files inside a vault, adds 3D annotations/bookmarks, and generates linked knowledge notes from model evidence. -The current package version is `0.7.5`. +The current package version is `0.7.6`. Important runtime files: @@ -240,7 +240,7 @@ npm run verify:preview -- --model "models/resource-fixtures/grouped-parts/groupe ## Current Follow-Up Direction -Short-term product direction after `0.7.5`: +Short-term product direction after `0.7.6`: - Keep tightening auto part registration and cross-model part reuse feedback. - Keep improving direct workbench UX without prematurely moving all workbench routes. diff --git a/docs/release-notes/0.7.6.md b/docs/release-notes/0.7.6.md new file mode 100644 index 0000000..eb4e5ed --- /dev/null +++ b/docs/release-notes/0.7.6.md @@ -0,0 +1,32 @@ +# AI Model Workbench 0.7.6 + +`0.7.6` is a source-review patch for the `0.7.5` Slice and measurement +interaction release. + +## Changes + +- Replaced Babylon preview `activeWindow.requestAnimationFrame()` with + `window.requestAnimationFrame()` to satisfy Obsidian's timer API source-review + rule. +- Replaced the related Babylon focus and Slice frame cancellations with + `window.cancelAnimationFrame()` for consistent scheduling and cleanup. +- Rebuilt the packaged plugin assets with the review-approved calls. + +## Behavior + +- Slice, measurement, focus, disassembly, annotation, and camera behavior are + unchanged from `0.7.5`. +- Babylon.js compatibility mode remains the default single-model route. +- Three.js opt-in routing, Converted GLB fast-path behavior, and Babylon fallback + remain unchanged. +- No settings or persisted-data migration is introduced. + +## Verification + +- `npm run lint` +- `npm run typecheck` +- `npm test` +- `npm run verify:preview` +- `npm run build` +- `npm run verify:release` +- `npm run verify:obsidian -- --clean` diff --git a/main.js b/main.js index cd98c27..1a8f5a7 100644 --- a/main.js +++ b/main.js @@ -23813,7 +23813,7 @@ gl_FragColor=color; #define CUSTOM_FRAGMENT_MAIN_END }`;x.ShadersStore[E1]||(x.ShadersStore[E1]=u$);HSe={name:E1,shader:u$}});var p$,h$,My,XSe,YSe,m$,A1,g$=y(()=>{na();qi();Pp();He();Wo();Sp();KD();ls();CO();$t();Si();Yu();rd();SO();Ll();wt();Object.defineProperty(ai.prototype,"forceShowBoundingBoxes",{get:function(){return this._forceShowBoundingBoxes||!1},set:function(n){this._forceShowBoundingBoxes=n,n&&this.getBoundingBoxRenderer()},enumerable:!0,configurable:!0});ai.prototype.getBoundingBoxRenderer=function(){return this._boundingBoxRenderer||(this._boundingBoxRenderer=new A1(this)),this._boundingBoxRenderer};Object.defineProperty(Ir.prototype,"showBoundingBox",{get:function(){return this._showBoundingBox||!1},set:function(n){this._showBoundingBox=n,n&&this.getScene().getBoundingBoxRenderer()},enumerable:!0,configurable:!0});p$=Q.Identity(),h$=new Q,My=new b,XSe=new b,YSe=p$.asArray(),m$=new ld(My,My),A1=class{get shaderLanguage(){return this._shaderLanguage}constructor(e){this.name=tt.NAME_BOUNDINGBOXRENDERER,this.frontColor=new he(1,1,1),this.backColor=new he(.1,.1,.1),this.showBackLines=!0,this.onBeforeBoxRenderingObservable=new re,this.onAfterBoxRenderingObservable=new re,this.onResourcesReadyObservable=new re,this.enabled=!0,this._shaderLanguage=0,this.renderList=new Qi(32),this._vertexBuffers={},this._fillIndexBuffer=null,this._fillIndexData=null,this._matrixBuffer=null,this._matrices=null,this._useInstances=!1,this._drawWrapperFront=null,this._drawWrapperBack=null,this.scene=e,this.scene.getEngine().isWebGPU&&(this._shaderLanguage=1),e._addComponent(this),this._uniformBufferFront=new xr(this.scene.getEngine(),void 0,void 0,"BoundingBoxRendererFront",!0),this._buildUniformLayout(this._uniformBufferFront),this._uniformBufferBack=new xr(this.scene.getEngine(),void 0,void 0,"BoundingBoxRendererBack",!0),this._buildUniformLayout(this._uniformBufferBack)}_buildUniformLayout(e){e.addUniform("color",4),e.addUniform("world",16),e.addUniform("viewProjection",16),e.addUniform("viewProjectionR",16),e.create()}register(){this.scene._beforeEvaluateActiveMeshStage.registerStep(tt.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER,this,this.reset),this.scene._preActiveMeshStage.registerStep(tt.STEP_PREACTIVEMESH_BOUNDINGBOXRENDERER,this,this._preActiveMesh),this.scene._evaluateSubMeshStage.registerStep(tt.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER,this,this._evaluateSubMesh),this.scene._afterRenderingGroupDrawStage.registerStep(tt.STEP_AFTERRENDERINGGROUPDRAW_BOUNDINGBOXRENDERER,this,this.render)}async whenReadyAsync(e=16,t=3e4){return this._prepareResources(),await new Promise(i=>{Pl(()=>this._colorShader.isReady(),()=>{i()},(r,s)=>{s?(te.Error("BoundingBoxRenderer: Timeout while waiting for the renderer to be ready."),r&&te.Error(r)):(te.Error("BoundingBoxRenderer: An unexpected error occurred while waiting for the renderer to be ready."),r&&(te.Error(r),r.stack&&te.Error(r.stack)))},e,t)})}_evaluateSubMesh(e,t){if(e.showSubMeshesBoundingBox){let i=t.getBoundingInfo();i!=null&&(i.boundingBox._tag=e.renderingGroupId,this.renderList.push(i.boundingBox))}}_preActiveMesh(e){if(e.showBoundingBox||this.scene.forceShowBoundingBoxes){let t=e.getBoundingInfo();t.boundingBox._tag=e.renderingGroupId,this.renderList.push(t.boundingBox)}}_prepareResources(){if(this._colorShader)return;this._colorShader=new tl("colorShader",this.scene,"boundingBoxRenderer",{attributes:[D.PositionKind,"world0","world1","world2","world3"],uniforms:["world","viewProjection","viewProjectionR","color"],uniformBuffers:["BoundingBoxRenderer"],shaderLanguage:this._shaderLanguage,extraInitializationsAsync:async()=>{this._shaderLanguage===1?await Promise.all([Promise.resolve().then(()=>(d1(),f1)),Promise.resolve().then(()=>(m1(),h1))]):await Promise.all([Promise.resolve().then(()=>(v1(),_1)),Promise.resolve().then(()=>(T1(),S1))])}},!1),this._colorShader.setDefine("INSTANCES",this._useInstances),this._colorShader.doNotSerialize=!0,this._colorShader.reservedDataStore={hidden:!0},this._colorShaderForOcclusionQuery=new tl("colorShaderOccQuery",this.scene,"boundingBoxRenderer",{attributes:[D.PositionKind],uniforms:["world","viewProjection","viewProjectionR","color"],uniformBuffers:["BoundingBoxRenderer"],shaderLanguage:this._shaderLanguage,extraInitializationsAsync:async()=>{this._shaderLanguage===1?await Promise.all([Promise.resolve().then(()=>(d1(),f1)),Promise.resolve().then(()=>(m1(),h1))]):await Promise.all([Promise.resolve().then(()=>(v1(),_1)),Promise.resolve().then(()=>(T1(),S1))])}},!0),this._colorShaderForOcclusionQuery.doNotSerialize=!0,this._colorShaderForOcclusionQuery.reservedDataStore={hidden:!0};let e=this.scene.getEngine(),t=Ab({size:1});this._vertexBuffers[D.PositionKind]=new D(e,t.positions,D.PositionKind,!1),this._createIndexBuffer(),this._fillIndexData=t.indices,this.onResourcesReadyObservable.notifyObservers(this)}_createIndexBuffer(){let e=this.scene.getEngine();this._indexBuffer=e.createIndexBuffer([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,7,1,6,2,5,3,4])}rebuild(){let e=this._vertexBuffers[D.PositionKind];e&&e._rebuild(),this._createIndexBuffer(),this._matrixBuffer&&this._matrixBuffer._rebuild()}reset(){this.renderList.reset()}render(e){var r,s;if(this.renderList.length===0||!this.enabled)return;if(this._useInstances){this._renderInstanced(e);return}if(this._prepareResources(),!this._colorShader.isReady())return;let t=this.scene.getEngine();t.setDepthWrite(!1);let i=this.scene.getTransformMatrix();for(let a=0;ar*2)&&(i=new Float32Array(r),this._matrices=i),this.onBeforeBoxRenderingObservable.notifyObservers(m$);let s=0,a=this.scene.floatingOriginOffset;for(let _=0;_{"use strict";He();bN();$t();Xo();g$();xs();FE();yP();Wd=class Wd{constructor(e,t,i,r,s){this.meshToPart=new Map;this.occlusionDirection=b.Zero();this.occlusionRay=new on(b.Zero(),b.Zero(),1);this.lastOccluded=!1;this.selected=null;this.partPointerActive=!1;this.activePointerId=null;this.scene=e,this.camera=t,this.meshes=r,this.parts=qSe(i,r,s);for(let a of this.parts)for(let o of a.meshes)this.meshToPart.set(o.uniqueId,a);this.setBoundingBoxColor(Wd.BBOX_VISIBLE)}getParts(){return this.parts}getPartId(e){return e.id}isDisposed(e){return ZSe(e.node)||e.meshes.every(t=>t.isDisposed())}captureTransform(e){var t,i;return{parent:e.node.parent,position:e.node.position.clone(),rotation:e.node.rotation.clone(),rotationQuaternion:(i=(t=e.node.rotationQuaternion)==null?void 0:t.clone())!=null?i:null,scaling:e.node.scaling.clone()}}restoreTransform(e,t){var i,r;e.node.setParent(t.parent),e.node.position.copyFrom(t.position),e.node.rotation.copyFrom(t.rotation),e.node.rotationQuaternion=(r=(i=t.rotationQuaternion)==null?void 0:i.clone())!=null?r:null,e.node.scaling.copyFrom(t.scaling),e.node.computeWorldMatrix(!0);for(let s of e.meshes)s.computeWorldMatrix(!0)}subscribe(e){let t=this.scene.getEngine().getRenderingCanvas();t==null||t.classList.add("ai3d-disassembly-active");let i=this.scene.onPointerObservable.add(s=>{var o,l,c,f;let a=s.event;if(a.isPrimary!==!1){if(s.type===ot.POINTERDOWN){if(a.button!==0)return;let d=(l=(o=s.pickInfo)==null?void 0:o.pickedMesh)!=null?l:null;if(this.partPointerActive=!!this.resolvePart(d),this.partPointerActive){a.preventDefault(),a.stopPropagation(),this.activePointerId=a.pointerId;try{(c=t==null?void 0:t.setPointerCapture)==null||c.call(t,a.pointerId)}catch(u){}this.camera.detachControl()}e.onPointerDown(d,a)}else if(s.type===ot.POINTERMOVE){if(this.activePointerId!==null&&a.pointerId!==this.activePointerId)return;this.partPointerActive&&(a.preventDefault(),a.stopPropagation()),e.onPointerMove(a)}else if(s.type===ot.POINTERUP){if(this.activePointerId!==null&&a.pointerId!==this.activePointerId)return;if(this.partPointerActive&&(a.preventDefault(),a.stopPropagation()),e.onPointerUp(a),this.activePointerId!==null&&((f=t==null?void 0:t.hasPointerCapture)!=null&&f.call(t,this.activePointerId)))try{t.releasePointerCapture(this.activePointerId)}catch(d){}this.partPointerActive=!1,this.activePointerId=null,this.camera.attachControl(this.scene.getEngine().getRenderingCanvas(),!0)}}}),r=this.scene.onAfterRenderCameraObservable.add(s=>{s===this.camera&&e.onRender()});return()=>{var s;if(this.scene.onPointerObservable.remove(i),this.scene.onAfterRenderCameraObservable.remove(r),t==null||t.classList.remove("ai3d-disassembly-active","ai3d-disassembly-dragging"),this.activePointerId!==null&&((s=t==null?void 0:t.hasPointerCapture)!=null&&s.call(t,this.activePointerId)))try{t.releasePointerCapture(this.activePointerId)}catch(a){}this.partPointerActive=!1,this.activePointerId=null,this.camera.attachControl(t,!0)}}resolvePart(e){var t;return KSe(e)?this.parts.includes(e)?e:null:!e||typeof e!="object"?null:(t=this.meshToPart.get(e.uniqueId))!=null?t:null}setSelected(e){if(this.selected)for(let t of this.selected.meshes)t.isDisposed()||(t.showBoundingBox=!1);if(this.selected=e,this.lastOccluded=!1,this.setBoundingBoxColor(Wd.BBOX_VISIBLE),this.selected&&!this.isDisposed(this.selected))for(let t of this.selected.meshes)t.isDisposed()||(t.showBoundingBox=!0)}beginDrag(e,t){var o,l,c;let i=this.getPointOnDragPlane(e,t);if(!i)return null;t.preventDefault(),t.stopPropagation(),(o=this.scene.getEngine().getRenderingCanvas())==null||o.classList.add("ai3d-disassembly-dragging"),e.node.setParent(null),e.node.computeWorldMatrix(!0);for(let f of e.meshes)f.computeWorldMatrix(!0);t.shiftKey&&!e.node.rotationQuaternion&&(e.node.rotationQuaternion=je.FromEulerVector(e.node.rotation),e.node.rotation.set(0,0,0));let r=x1(e),s=Um(ct(i),ct(this.camera.getForwardRay().direction));if(!s)return null;let a={part:e,mode:t.shiftKey?"rotate":"move",plane:s,startPoint:i,startPosition:e.node.position.clone(),startRotationQuaternion:(c=(l=e.node.rotationQuaternion)==null?void 0:l.clone())!=null?c:null,pivot:r,pointerX:t.clientX,pointerY:t.clientY};return this.camera.detachControl(),a}updateDrag(e,t){if(t.preventDefault(),t.stopPropagation(),e.mode==="rotate"){this.updateRotation(e,t);return}let i=this.getRayPlanePoint(t,e.plane);if(!i)return;let r=i.subtract(e.startPoint);e.part.node.position=e.startPosition.add(r),e.part.node.computeWorldMatrix(!0);for(let s of e.part.meshes)s.computeWorldMatrix(!0)}endDrag(e){var t;(t=this.scene.getEngine().getRenderingCanvas())==null||t.classList.remove("ai3d-disassembly-dragging"),this.camera.attachControl(this.scene.getEngine().getRenderingCanvas(),!0)}updateSelectionOcclusion(e){let t=x1(e),i=this.camera.position,r=kf(ct(i),ct(t));if(!r)return;let s=this.occlusionDirection;s.set(r.direction.x,r.direction.y,r.direction.z),this.occlusionRay.origin=i,this.occlusionRay.direction=s,this.occlusionRay.length=r.distance;let a=this.scene.pickWithRay(this.occlusionRay),o=!!(a!=null&&a.hit)&&Gf(a.distance,r.distance,r.epsilon);o!==this.lastOccluded&&(this.lastOccluded=o,this.setBoundingBoxColor(o?Wd.BBOX_OCCLUDED:Wd.BBOX_VISIBLE))}setBoundingBoxColor(e){var i,r;let t=(r=(i=this.scene).getBoundingBoxRenderer)==null?void 0:r.call(i);t&&(t.frontColor=e,t.backColor=e)}updateRotation(e,t){if(!e.startRotationQuaternion)return;let i=t.clientX-e.pointerX,r=t.clientY-e.pointerY,s=WA({startPosition:ct(e.startPosition),pivot:ct(e.pivot),startRotationQuaternion:zA(e.startRotationQuaternion),yawAxis:ct(this.camera.getDirection(b.Up()).normalize()),pitchAxis:ct(this.camera.getDirection(b.Right()).normalize()),deltaX:i,deltaY:r,sensitivity:.01});if(s){e.part.node.position=new b(s.position.x,s.position.y,s.position.z),e.part.node.rotationQuaternion=new je(s.rotationQuaternion.x,s.rotationQuaternion.y,s.rotationQuaternion.z,s.rotationQuaternion.w),e.part.node.rotation.set(0,0,0),e.part.node.computeWorldMatrix(!0);for(let a of e.part.meshes)a.computeWorldMatrix(!0)}}getPointOnDragPlane(e,t){var s;let i=x1(e),r=Um(ct(i),ct(this.camera.getForwardRay().direction));return r&&(s=this.getRayPlanePoint(t,r))!=null?s:i}getRayPlanePoint(e,t){let i=this.scene.getEngine().getRenderingCanvas();if(!i)return null;let r=i.getBoundingClientRect(),s=e.clientX-r.left,a=e.clientY-r.top,o=this.scene.createPickingRay(s,a,Q.Identity(),this.camera),l=kA({origin:ct(o.origin),direction:ct(o.direction)},t);return l?new b(l.x,l.y,l.z):null}};Wd.BBOX_VISIBLE=new he(.25,.7,1),Wd.BBOX_OCCLUDED=new he(.1,.25,.4);R1=Wd});var C$={};Be(C$,{BabylonModelPreview:()=>Iy,createBabylonModelPreview:()=>_Te});function b$(n,e,t){let i=t.x-e.x,r=t.y-e.y,s=i*i+r*r;if(s<=Number.EPSILON)return Math.hypot(n.x-e.x,n.y-e.y);let a=Math.max(0,Math.min(1,((n.x-e.x)*i+(n.y-e.y)*r)/s));return Math.hypot(n.x-(e.x+i*a),n.y-(e.y+r*a))}function fTe(n){let e=n.getClassName();return e==="DirectionalLight"||e==="PointLight"||e==="SpotLight"}function b1(n){return n.getClassName()==="GaussianSplattingMesh"}function dTe(n){return!!n&&typeof n=="object"&&"getBoundingInfo"in n}function M$(n){return n instanceof ii}function hf(n){return typeof n.isDisposed=="function"?n.isDisposed():!1}function xg(n,e){let t=n;for(;t;){if(t===e)return!0;t=t.parent}return!1}function M1(n,e=[]){for(let t of n)t.isDisposed()||t.dispose(!0,!0);for(let t of e)t.isDisposed()||t.dispose(!1,!0)}function go(n){return new b(n.x,n.y,n.z)}function y$(n){return Number.isFinite(n)?Math.max(0,Math.min(n,1)):0}function I$(n){let e=new We("measure-marker-mat",n);return e.diffuseColor=UE.clone(),e.emissiveColor=UE.clone(),e.specularColor=new he(0,0,0),e.disableLighting=!0,e.alpha=.48,e}function BE(n,e){let t=n.material;t&&(t.diffuseColor=e.clone(),t.emissiveColor=e.clone())}function uTe(n){let e=n.replace(/\s+#.*$/,"").trim();if(e.startsWith('"')){let t=e.indexOf('"',1);if(t>1)return e.slice(1,t)}return e}function hTe(n){let e=n.trim().split(/\s+/),t=e.findIndex(i=>!i.startsWith("-")&&!/^[-+]?\d*\.?\d+$/.test(i));return e.slice(Math.max(0,t)).join(" ").replace(/^"|"$/g,"")}function mTe(n){var t,i;let e=(i=(t=n.split(".").pop())==null?void 0:t.toLowerCase())!=null?i:"png";return e==="jpg"||e==="jpeg"?"image/jpeg":e==="png"?"image/png":e==="bmp"?"image/bmp":e==="tga"?"image/x-tga":e==="webp"?"image/webp":`image/${e}`}function pTe(n,e,t){let i=Qs(e),r=i.replace(/\.[^.]+$/,""),s=gn(t),a=[Nn(n,e),Nn(n,i)];if(s)for(let o of E$)a.push(Nn(n,`${s}.${o}`));for(let o of E$){let l=`${r}.${o}`;l!==i&&a.push(Nn(n,l))}return a}function gTe(n){return Number.isFinite(n)?n.toPrecision(10):String(n)}function _Te(n){return new Iy(n)}var yy,E$,QSe,$Se,JSe,S$,UE,eTe,tTe,T$,iTe,rTe,nTe,sTe,aTe,A$,x$,R$,oTe,lTe,cTe,Ga,Iy,P$=y(()=>{"use strict";zD();na();Eb();Sb();d4();u4();uO();He();Gu();$t();ki();cd();QO();vr();qi();lf();QY();bN();OM();l9();tO();ug();OE();OE();zF();WF();bQ();i$();FA();Ma();As();r$();v$();FE();Lo();HA();hP();iv();xs();qA();ev();sv();bP();yy=null,E$=["jpg","jpeg","png","bmp","tga","webp","tif","tiff"],QSe=/^\s*(map_Kd|map_Ka|map_Ks|map_Ns|map_d|map_bump|bump|disp|decal)\s+(.+)/i,$Se=.242,JSe=320,S$=new he(.97,.98,.99),UE=new he(.97,.98,.99),eTe=new he(.96,.62,.04),tTe=new he(1,1,1),T$=new he(.9,.91,.92),iTe=new he(.22,.74,.97),rTe=new he(.58,.77,.99),nTe=new he(.88,.95,1),sTe=new he(.96,.62,.04),aTe=new he(.99,.83,.3),A$=new he(.94,.27,.27),x$=new he(.13,.77,.37),R$=new he(.23,.51,.96),oTe=new he(.97,.98,.99),lTe=new he(.98,.8,.08),cTe=.32;Ga=class Ga{constructor(e){this.rootMesh=null;this.loadedMeshes=[];this.loadedTransformNodes=[];this.cachedRenderableMeshes=null;this.cachedRenderableRoot=null;this.loadedExt="";this.rendering=!1;this.contextLost=!1;this.viewportVisible=!0;this.viewportObserver=null;this.cleanupPicking=null;this.configLights=[];this.shadowGenerator=null;this.groundMesh=null;this.gridMesh=null;this.axisMeshes=[];this.autoRotateBehavior=null;this.sliceAutoRotatePaused=!1;this.wireframeEnabled=!1;this.sliceActive=!1;this.sliceNormal=new b(Dr.x,Dr.y,Dr.z);this.slicePlaneX=new b(1,0,0);this.slicePlaneY=new b(0,0,-1);this.sliceCenter=null;this.sliceReferenceNormal=new b(Dr.x,Dr.y,Dr.z);this.sliceOffset=Il;this.sliceInteractionMode=Xf;this.sliceThickness=Hm;this.slicePlane=null;this.sliceOverlayPlanes=[];this.sliceOverlayLines=[];this.sliceOverlayLabels=[];this.sliceRotationLabel=null;this.sliceRotationLabelText="";this.sliceDragState=null;this.pendingSliceMove=null;this.sliceMoveFrame=0;this.sliceObservers=new Set;this.sliceOriginalMaterialClipping=new Map;this.gizmo=null;this.gizmoEnabled=!1;this.disassembly=null;this.focusSelectionEnabled=!1;this.focusedNode=null;this.originalMeshVisibility=new Map;this.bboxMesh=null;this.bboxEnabled=!1;this.currentQuality="high";this.renderScale=1;this.resourceWarnings=[];this.gltfComponentMetadata=new Map;this.animPlaying=!1;this.initialCamera={alpha:Math.PI/4,beta:Math.PI/3,radius:5,target:b.Zero()};this.focusWorldPointFrame=0;this._lastPickResult={mesh:null,pickedPoint:null,screenX:0,screenY:0};this._onPickCallbacks=[];this.measurementActive=!1;this.measurementScale={x:1,y:1,z:1};this.measurementBaseRootScaling=new b(1,1,1);this.measurementBaseBounds=null;this.measurementUnit="mm";this.measurementSegments=[];this.measurementMarkers=[];this.measurementMarkerPoints=[];this.measurementTargetNode=null;this.measurementTargetMeshes=[];this.measurementSnapInputCache=null;this.measurementSnapInputCacheTargetId=null;this.measurementSnapInputCacheSignature=null;this.measurementSnapKind=null;this.measurementObservers=new Set;this.pendingPoint=null;this.pendingMarker=null;this.hoveredMarkerIndex=-1;this.lastPointerClient={x:0,y:0,altKey:!1};this.previewLine=null;this.cameraZoomObservers=new Set;this.handlePointerDown=e=>{e.button!==0||e.isPrimary===!1||this.sliceActive&&this.beginSliceDrag(e)};this.handlePointerUp=e=>{e.button!==0||e.isPrimary===!1||this.endSliceDrag(e)};this.handlePointerMove=e=>{if(this.lastPointerClient={x:e.clientX,y:e.clientY,altKey:e.altKey},this.updateSliceDrag(e)||!this.measurementActive||(this.pendingPoint&&this.updatePreviewLine(),this.measurementMarkers.length===0))return;let t=this.engine.getRenderingCanvas();if(!t)return;let i=t.getBoundingClientRect(),r=e.clientX-i.left,s=e.clientY-i.top,a=this.scene.pick(r,s,l=>this.measurementMarkers.includes(l)),o=a.hit?this.measurementMarkers.indexOf(a.pickedMesh):-1;if(o!==this.hoveredMarkerIndex){if(this.hoveredMarkerIndex>=0&&this.hoveredMarkerIndex=0&&o{this.endSliceDrag(e,!0)};this.handlePointerCaptureLost=e=>{this.endSliceDrag(e,!0)};this.preventCanvasWheelScroll=e=>{e.preventDefault(),e.stopPropagation()};this.handleMeasurementModifierKey=e=>{e.key==="Alt"&&this.updateMeasurementModifierAltKey(e.type==="keydown")};this.handleMeasurementModifierBlur=()=>{this.updateMeasurementModifierAltKey(!1),this.endSliceDrag(null,!0)};this.handleViewportIntersection=e=>{let t=e.some(i=>i.isIntersecting);t!==this.viewportVisible&&(this.viewportVisible=t,t?this.startRenderLoop():this.rendering&&(this.engine.stopRenderLoop(),this.rendering=!1))};this.handleContextLost=e=>{e.preventDefault(),this.contextLost=!0,this.rendering&&(this.engine.stopRenderLoop(),this.rendering=!1)};this.handleContextRestored=()=>{this.contextLost=!1,this.engine.resize(),this.startRenderLoop()};this.engine=new ze(e,!0,{preserveDrawingBuffer:!0}),this.scene=new ai(this.engine),this.scene.clearColor=new ht(.12,.12,.14,1),this.scene.setRenderingAutoClearDepthStencil(2,!0,!0,!0),this.camera=new Mi("cam",Math.PI/4,Math.PI/3,5,b.Zero(),this.scene),this.camera.attachControl(e,!0),this.camera.lowerRadiusLimit=.1,this.camera.wheelPrecision=45,this.camera.onViewMatrixChangedObservable.add(()=>{this.measurementSegments.length>0&&this.updateMeasurementOverlayPositions(),this.notifyCameraZoomChanged()}),e.addEventListener("wheel",this.preventCanvasWheelScroll,{passive:!1}),e.addEventListener("pointerdown",this.handlePointerDown,!0),e.addEventListener("pointerup",this.handlePointerUp,!0),e.addEventListener("pointermove",this.handlePointerMove,!0),e.addEventListener("pointercancel",this.handlePointerCancel,!0),e.addEventListener("lostpointercapture",this.handlePointerCaptureLost,!0),e.addEventListener("webglcontextlost",this.handleContextLost),e.addEventListener("webglcontextrestored",this.handleContextRestored),window.addEventListener("keydown",this.handleMeasurementModifierKey),window.addEventListener("keyup",this.handleMeasurementModifierKey),window.addEventListener("blur",this.handleMeasurementModifierBlur),this.scene.ambientColor=new he(.3,.3,.3);let t=new Fa("default-light",new b(0,1,.5),this.scene);t.intensity=1.2,this.resizeObs=new ResizeObserver(()=>this.engine.resize()),this.resizeObs.observe(e),typeof IntersectionObserver!="undefined"&&(this.viewportObserver=new IntersectionObserver(this.handleViewportIntersection,{root:null,threshold:[0,.01]}),this.viewportObserver.observe(e)),window.requestAnimationFrame(()=>this.engine.resize())}canRender(){let e=this.engine.getRenderingCanvas();return!!(e!=null&&e.isConnected)&&e.clientWidth>0&&e.clientHeight>0}getCameraZoomRange(){if(!this.rootMesh)return null;let e=this.camera.radius,t=this.camera.lowerRadiusLimit,i=this.camera.upperRadiusLimit,r=typeof t=="number"&&Number.isFinite(t)&&t>0?t:Math.max(e*.08,1e-5),s=typeof i=="number"&&Number.isFinite(i)&&i>r?i:Math.max(e*8,r*10);return{current:Math.max(r,Math.min(e,s)),min:r,max:s}}notifyCameraZoomChanged(){if(this.cameraZoomObservers.size===0)return;let e=this.getCameraZoomState();for(let t of this.cameraZoomObservers)t(e)}ensureDisassemblyController(){return this.rootMesh?(this.disassembly||(this.disassembly=_$(this.scene,this.camera,this.rootMesh,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata)),this.disassembly):null}isDisassemblyActive(){var e,t;return(t=(e=this.disassembly)==null?void 0:e.isEnabled())!=null?t:!1}async loadModel(e,t,i,r,s){var g,p,_,v;xi(s),await DE(),xi(s),this.rootMesh&&((g=this.engine.getRenderingCanvas())==null||g.classList.remove("ai3d-slice-active","ai3d-slice-dragging","ai3d-slice-rotate"),this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),M1(this.loadedMeshes,this.loadedTransformNodes),this.rootMesh=null,this.notifyCameraZoomChanged()),this.invalidateMeshCache(),this.loadedMeshes=[],this.loadedTransformNodes=[],this.disposeMeasurementOverlays(!0),this.resetMeasurementCalibrationState(),(p=this.disassembly)==null||p.dispose(),this.disassembly=null,this.clearFocusedMesh(),this.originalMeshVisibility.clear();let a=t.toLowerCase().replace(".","");this.loadedExt=a,this.resourceWarnings=[],xi(s),this.gltfComponentMetadata=xQ(e,a);let o=this.scene,c=(_={glb:".glb",gltf:".gltf",stl:".stl",obj:".obj",splat:".splat",ply:".ply"}[a])!=null?_:`.${a}`;xi(s);let f=`data:application/octet-stream;base64,${Iu(e)}`;xi(s);let d=E=>{try{xi(s)}catch(S){throw M1(E.meshes,E.transformNodes),S}this.loadedMeshes=E.meshes,this.loadedTransformNodes=E.transformNodes,E.meshes.length>0&&(this.rootMesh=E.meshes[0])},u=()=>{try{xi(s)}catch(E){throw M1(this.loadedMeshes,this.loadedTransformNodes),this.loadedMeshes=[],this.loadedTransformNodes=[],this.rootMesh=null,this.invalidateMeshCache(),this.notifyCameraZoomChanged(),E}};if(a==="obj"&&i&&r){yy&&await yy,xi(s);let E;yy=new Promise(S=>{E=S});try{let{OBJFileLoader:S}=await Promise.resolve().then(()=>(GF(),fQ)),T=S.prototype;typeof T._loadMTL!="function"&&console.warn("[AI3D] OBJFileLoader._loadMTL not found \u2014 MTL vault resolution disabled");let A=T._loadMTL,M=new TextDecoder().decode(new Uint8Array(e)).match(/mtllib\s+(.+)/),I=null;if(M&&i&&r){let L=uTe(M[1]),w=J_(r),G=Nn(w,L);try{let O=await i(G);xi(s);let B=new TextDecoder().decode(new Uint8Array(O)).split(` `);for(let K=0;KK!=="");if(!V.some(K=>/^\s*Kd\s+/i.test(K))){let K=V.findIndex(J=>/^\s*newmtl\s+/i.test(J));V.splice(K>=0?K+1:0,0,"Kd 0.80 0.80 0.80")}I=V.join(` -`)}catch(O){if(Vf(O))throw O;this.resourceWarnings.push(`OBJ material library not found: ${G}`)}}T._loadMTL=function(L,w,G){let O=I!=null?I:"";G(O)};let C=await TE(f,o,{meshNames:"",pluginExtension:c});d(C),T._loadMTL=A}catch(S){throw Vf(S)||console.error("[AI3D] OBJ load error:",S),S}finally{E(),yy=null}}else if(a==="stl"){let E=mQ(o,e);try{xi(s)}catch(S){throw E==null||E.dispose(!1,!0),S}this.rootMesh=E,this.rootMesh&&(this.loadedMeshes=[this.rootMesh])}else if(a==="ply"){let E=gQ(o,e);try{xi(s)}catch(S){throw E==null||E.dispose(!1,!0),S}this.rootMesh=E,this.rootMesh&&(this.loadedMeshes=[this.rootMesh])}else{let E=await TE(f,o,{meshNames:"",pluginExtension:c});d(E)}if(u(),!this.rootMesh)throw new Error("No mesh found in model file");let h=this.getRenderableBounds(this.rootMesh);this.captureMeasurementBaseState(this.rootMesh,h);for(let E of this.getRenderableMeshes(this.rootMesh))E.material&&(E.material.backFaceCulling=!1);this.syncSliceClipping(),this.notifySliceChanged();let m=tv(h);return this.camera.target=go(m.target),this.camera.radius=m.radius,this.camera.lowerRadiusLimit=m.lowerRadiusLimit,this.camera.upperRadiusLimit=m.upperRadiusLimit,this.camera.minZ=m.near,this.camera.maxZ=m.far,this.initialCamera={alpha:this.camera.alpha,beta:this.camera.beta,radius:this.camera.radius,target:this.camera.target.clone()},this.notifyCameraZoomChanged(),this.startRenderLoop(),this.engine.resize(),(v=this.cleanupPicking)==null||v.call(this),this.cleanupPicking=t$(this.scene,E=>{var A,R,M;if(this.sliceActive||this.isDisassemblyActive())return;let S=E.mesh&&this.rootMesh?wE(this.rootMesh,E.mesh,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata):null,T={mesh:S,pickedPoint:E.pickedPoint,screenX:E.screenX,screenY:E.screenY,modifiers:E.modifiers};if(this.lastPointerClient={x:E.screenX,y:E.screenY,altKey:((A=E.modifiers)==null?void 0:A.altKey)===!0},this._lastPickResult=T,this.measurementActive){if(((R=E.modifiers)==null?void 0:R.altKey)===!0){if(!E.pickedPoint)return;this.setMeasurementSnapKind("free"),this.addMeasurementPoint(go(E.pickedPoint));return}if(!this.measurementTargetNode){S&&this.setMeasurementTargetNode(S);return}let I=this.getMeasurementTargetPickPoint(E.mesh,E.pickedPoint);if(!I){this.setMeasurementSnapKind(null);return}this.addMeasurementPoint(this.resolveMeasurementPickPoint(I,!1));return}this.focusSelectionEnabled&&(S?this.setFocusedNode(S):(M=this.cleanupPicking)==null||M.clearHighlight()),this._onPickCallbacks.forEach(I=>I(T))},()=>!this.focusSelectionEnabled&&!this.measurementActive&&!this.sliceActive,E=>this.resolvePickHighlightMeshes(E)),this.ensureDisassemblyController(),this.createModelSummary(this.rootMesh)}applyConfig(e){e.camera&&this.applyCameraConfig(e.camera),e.lights&&this.applyLightConfig(e.lights),e.scene&&this.applySceneConfig(e.scene),e.stl&&this.loadedExt==="stl"&&(e.stl.color&&this.setSTLColor(e.stl.color),e.stl.wireframe!==void 0&&this.setWireframe(e.stl.wireframe))}applyCameraConfig(e){var i;let t=this.engine.getRenderingCanvas();if(t){if(e.mode==="orthographic"){let r=this.camera.radius,s=t.clientWidth/t.clientHeight,a=(i=e.zoom)!=null?i:1,o=r/a;this.camera.mode=1,this.camera.orthoLeft=-o*s,this.camera.orthoRight=o*s,this.camera.orthoTop=o,this.camera.orthoBottom=-o}else this.camera.mode=0,e.fov&&(this.camera.fov=e.fov*Math.PI/180);if(e.position){let[r,s,a]=e.position;this.camera.setPosition(new b(r,s,a))}if(e.lookAt){let[r,s,a]=e.lookAt;this.camera.setTarget(new b(r,s,a))}e.near!==void 0&&(this.camera.minZ=e.near),e.far!==void 0&&(this.camera.maxZ=e.far),this.notifyCameraZoomChanged()}}applyLightConfig(e){var i;for(let r of this.configLights)r.dispose();this.configLights=[],(i=this.shadowGenerator)==null||i.dispose(),this.shadowGenerator=null;let t=this.scene.getLightByName("default-light");t&&t.dispose();for(let r of e){let s=this.createLight(r);s&&this.configLights.push(s)}}createLight(e){var r,s;let t=e.color?he.FromHexString(e.color):he.White(),i=(r=e.intensity)!=null?r:1;switch(e.type){case"hemisphere":{let a=e.groundColor?he.FromHexString(e.groundColor):new he(.2,.2,.2),o=new Fa("hemi",new b(0,1,0),this.scene);return o.diffuse=t,o.groundColor=a,o.intensity=i,o}case"directional":{let a=e.position?new b(...e.position).normalize():new b(-1,-2,-1).normalize(),o=new ca("dir",a,this.scene);return o.diffuse=t,o.intensity=i,e.castShadow&&this.rootMesh&&this.setupShadow(o),o}case"point":{let a=e.position?new b(...e.position):new b(0,5,0),o=new Sd("point",a,this.scene);return o.diffuse=t,o.intensity=i,e.decay!==void 0&&(o.decay=e.decay),o}case"spot":{let a=e.position?new b(...e.position):new b(0,5,0),l=(e.target?new b(...e.target):b.Zero()).subtract(a).normalize(),c=e.angle?e.angle*Math.PI/180:Math.PI/4,f=(s=e.penumbra)!=null?s:.5,d=new Zr("spot",a,l,c,f,this.scene);return d.diffuse=t,d.intensity=i,e.decay!==void 0&&(d.decay=e.decay),e.castShadow&&this.rootMesh&&this.setupShadow(d),d}case"attachToCam":{let a=new Sd("cam-light",b.Zero(),this.scene);return a.diffuse=t,a.intensity=i,a.parent=this.camera,a}default:return null}}setupShadow(e){if(!this.rootMesh)return;if(!fTe(e)){console.warn("[AI3D] Light type does not support shadows:",e.name);return}let t=new zi(1024,e);t.useBlurExponentialShadowMap=!0,t.blurKernel=32;for(let i of this.getRenderableMeshes(this.rootMesh))t.addShadowCaster(i),i.receiveShadows=!0;this.shadowGenerator=t}applySceneConfig(e){var t,i;if(e.background!==void 0){let r=ht.FromColor3(he.FromHexString(e.background),e.transparent?0:1);this.scene.clearColor=r}e.autoRotate===!0?this.autoRotateBehavior?this.autoRotateBehavior.idleRotationSpeed=(i=e.autoRotateSpeed)!=null?i:.5:(this.autoRotateBehavior=new qp,this.autoRotateBehavior.idleRotationSpeed=(t=e.autoRotateSpeed)!=null?t:.5,this.autoRotateBehavior.idleRotationWaitTime=1e3,this.autoRotateBehavior.idleRotationSpinupTime=500,this.sliceDragState?this.sliceAutoRotatePaused=!0:this.camera.addBehavior(this.autoRotateBehavior)):e.autoRotate===!1&&this.autoRotateBehavior&&(this.sliceAutoRotatePaused||this.camera.removeBehavior(this.autoRotateBehavior),this.autoRotateBehavior=null,this.sliceAutoRotatePaused=!1),e.groundShadow&&this.rootMesh&&this.createGround(),e.grid&&this.createGrid(),e.axis&&this.createAxis()}createGround(){if(!this.rootMesh||this.groundMesh)return;let e=this.getRenderableBounds(this.rootMesh),t=Ui(e),i=Math.max(t.x,t.z)*3,r=e.min.y;this.groundMesh=Pn.CreateGround("ground",{width:i,height:i},this.scene),this.groundMesh.position.y=r;let s=new We("ground-mat",this.scene);s.diffuseColor=new he(.15,.15,.15),s.specularColor=he.Black(),s.alpha=.5,this.groundMesh.material=s,this.groundMesh.receiveShadows=!0}createGrid(){if(!this.rootMesh||this.gridMesh)return;let e=this.getRenderableBounds(this.rootMesh),t=Ui(e),i=Math.max(t.x,t.z)*2,r=e.min.y-.01;this.gridMesh=Pn.CreateGround("grid",{width:i,height:i,subdivisions:20},this.scene),this.gridMesh.position.y=r;let s=new We("grid-mat",this.scene);s.wireframe=!0,s.diffuseColor=new he(.3,.3,.3),s.emissiveColor=new he(.1,.1,.1),this.gridMesh.material=s}createAxis(){if(!this.rootMesh||this.axisMeshes.length>0)return;let e=this.getRenderableBounds(this.rootMesh),t=aV(e)*1.5,i=go(e.min),r=Rs(e)*.01,s=[["x",he.Red(),new b(t,0,0)],["y",he.Green(),new b(0,t,0)],["z",he.Blue(),new b(0,0,t)]];for(let[a,o,l]of s){let c=Pn.CreateTube(`axis-${a}`,{path:[i,i.add(l)],radius:r,tessellation:8},this.scene),f=new We(`axis-${a}-mat`,this.scene);f.emissiveColor=o,f.diffuseColor=he.Black(),c.material=f,this.axisMeshes.push(c)}}setSTLColor(e){if(!this.rootMesh)return;let t=he.FromHexString(e);for(let i of this.getRenderableMeshes(this.rootMesh))if(i.material&&i.material.name==="stl-mat"){let r=i.material;r.diffuseColor=t,r.emissiveColor=t.scale(.1)}}setWireframe(e){this.rootMesh&&(b1(this.rootMesh)||(this.wireframeEnabled=e,this.scene.forceWireframe=e))}toggleWireframe(){return this.setWireframe(!this.wireframeEnabled),this.wireframeEnabled}hasAnimations(){return this.scene.animationGroups.length>0}toggleAnimation(){let e=this.scene.animationGroups;if(e.length===0)return!1;this.animPlaying=!this.animPlaying;for(let t of e)this.animPlaying?t.play(!0):t.pause();return this.animPlaying}toggleMeasurement(){var t;if(this.measurementActive)return this.deactivateMeasurementMode(),!1;this.isDisassemblyActive()&&this.disableDisassemblyAndReset(),this.deactivateSliceMode();let e=this.getCurrentMeasurementTargetNode();return(t=this.cleanupPicking)==null||t.clearHighlight(),this.clearFocusedMesh(),this.focusSelectionEnabled&&(this.focusSelectionEnabled=!1),this.measurementActive=!0,this.setMeasurementTargetNode(e,!1),Wf(this.engine.getRenderingCanvas(),this.measurementActive),this.notifyMeasurementsChanged(),this.measurementActive}isMeasurementActive(){return this.measurementActive}clearMeasurements(){this.disposeMeasurementOverlays(!1)}cancelMeasurement(){let e=!!this.pendingPoint;this.cancelPendingMeasurement(),e&&this.notifyMeasurementsChanged()}deactivateMeasurementMode(){return this.measurementActive?(this.measurementActive=!1,Wf(this.engine.getRenderingCanvas(),!1),this.setMeasurementTargetNode(null,!1),this.cancelPendingMeasurement(),this.notifyMeasurementsChanged(),!0):!1}disposeMeasurementOverlays(e){e&&(this.measurementActive=!1,Wf(this.engine.getRenderingCanvas(),!1),this.setMeasurementTargetNode(null,!1)),this.cancelPendingMeasurement(!1);for(let t of this.measurementSegments)t.line.dispose(!1,!0),t.label.dispose(!1,!0);this.measurementSegments=[];for(let t of this.measurementMarkers)t.dispose(!1,!0);this.measurementMarkers=[],this.measurementMarkerPoints=[],this.setMeasurementSnapKind(null,!1),this.notifyMeasurementsChanged()}setMeasurementScale(e){this.measurementScale=Ms(e),this.invalidateMeasurementSnapInputCache(),this.applyMeasurementModelScale(),this.sliceActive&&(this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping()),this.updateMeasurementOverlayPositions(),this.updateMeasurementLabels(),this.notifyMeasurementsChanged()}getMeasurementScale(){return{...this.measurementScale}}setMeasurementUnit(e){this.measurementUnit=rv(e),this.updateMeasurementLabels(),this.notifyMeasurementsChanged()}getMeasurementUnit(){return this.measurementUnit}getMeasurementBounds(){var t;if(!this.rootMesh)return null;let e=(t=this.measurementBaseBounds)!=null?t:this.getRenderableBounds(this.rootMesh);return e?{x:e.max.x-e.min.x,y:e.max.y-e.min.y,z:e.max.z-e.min.z}:null}getMeasurementRecords(){return this.createMeasurementRecords()}getMeasurementState(){return fx({active:this.measurementActive,pending:!!this.pendingPoint,records:this.createMeasurementRecords(),unit:this.measurementUnit,scale:this.getMeasurementScale(),bounds:this.getMeasurementBounds(),targetLocked:!!this.measurementTargetNode,targetName:this.getMeasurementTargetName(),targetScope:this.measurementTargetNode===this.rootMesh?"model":"part",snapKind:this.measurementSnapKind})}exportMeasurements(){return hx(this.createMeasurementRecords())}observeMeasurements(e){return this.measurementObservers.add(e),e(),()=>{this.measurementObservers.delete(e)}}updateMeasurementLabels(){var t;if(this.measurementSegments.length===0)return;let e=this.getMeasurementMarkerSize()*3.2;for(let i of this.measurementSegments){this.updateMeasurementLineGeometry(i);let r=Wm(this.createMeasurementReading(i.start,i.end));i.label.dispose(!1,!0);let s=this.createBabylonMeasurementDraftingLayout(i.start,i.end),a=(t=s==null?void 0:s.labelPosition)!=null?t:b.Center(this.toMeasurementDisplayPoint(i.start),this.toMeasurementDisplayPoint(i.end));i.label=this.createMeasurementLabelMesh(r,a,e)}}captureMeasurementBaseState(e,t){this.measurementBaseRootScaling=e.scaling.clone(),this.measurementBaseBounds=t?Za(t.min,t.max):null,this.measurementScale={x:1,y:1,z:1}}resetMeasurementCalibrationState(){this.measurementScale={x:1,y:1,z:1},this.measurementBaseRootScaling=new b(1,1,1),this.measurementBaseBounds=null,this.measurementMarkerPoints=[],this.invalidateMeasurementSnapInputCache()}applyMeasurementModelScale(){if(!this.rootMesh)return;let e=Ms(this.measurementScale);this.rootMesh.scaling=new b(this.measurementBaseRootScaling.x*e.x,this.measurementBaseRootScaling.y*e.y,this.measurementBaseRootScaling.z*e.z),this.rootMesh.computeWorldMatrix(!0);for(let t of this.loadedMeshes)t.computeWorldMatrix(!0);this.invalidateMeshCache(),this.rebuildScaledSceneHelpers(),this.refitCameraToModel(),this.startRenderLoop()}rebuildScaledSceneHelpers(){var s,a,o;let e=!!this.bboxMesh,t=!!this.groundMesh,i=!!this.gridMesh,r=this.axisMeshes.length>0;(s=this.bboxMesh)==null||s.dispose(),this.bboxMesh=null,(a=this.groundMesh)==null||a.dispose(),this.groundMesh=null,(o=this.gridMesh)==null||o.dispose(),this.gridMesh=null;for(let l of this.axisMeshes)l.dispose();if(this.axisMeshes=[],e&&this.rootMesh){let l=this.getRenderableBounds(this.rootMesh),c=go(mr(l)),f=go(Ui(l));this.bboxMesh=Pn.CreateBox("bbox",{width:f.x,height:f.y,depth:f.z},this.scene),this.bboxMesh.position=c;let d=new We("bbox-mat",this.scene);d.wireframe=!0,d.emissiveColor=new he(1,1,0),d.disableLighting=!0,d.alpha=.6,this.bboxMesh.material=d}t&&this.createGround(),i&&this.createGrid(),r&&this.createAxis()}refitCameraToModel(){if(!this.rootMesh)return;let e=tv(this.getRenderableBounds(this.rootMesh));this.camera.target=go(e.target),this.camera.radius=e.radius,this.camera.lowerRadiusLimit=e.lowerRadiusLimit,this.camera.upperRadiusLimit=e.upperRadiusLimit,this.camera.minZ=e.near,this.camera.maxZ=e.far,this.initialCamera={alpha:this.camera.alpha,beta:this.camera.beta,radius:this.camera.radius,target:this.camera.target.clone()},this.notifyCameraZoomChanged()}getMeasurementPivot(){var e,t;return(t=(e=this.rootMesh)==null?void 0:e.getAbsolutePosition().clone())!=null?t:b.Zero()}toMeasurementDisplayPoint(e){let t=rx(e,this.getMeasurementPivot(),this.measurementScale);return new b(t.x,t.y,t.z)}toMeasurementBasePoint(e){let t=nx(e,this.getMeasurementPivot(),this.measurementScale);return new b(t.x,t.y,t.z)}updateMeasurementOverlayPositions(){for(let e=0;e{this.cameraZoomObservers.delete(e)}}getPerformanceSnapshot(){return{backend:"babylon",renderScale:Number((1/this.engine.getHardwareScalingLevel()).toFixed(2)),quality:this.currentQuality,meshCount:this.rootMesh?this.getRenderableMeshes(this.rootMesh).length:0}}toggleBoundingBox(){var e;if(this.bboxEnabled=!this.bboxEnabled,this.bboxEnabled){if(!this.rootMesh)return this.bboxEnabled;this.bboxMesh&&this.bboxMesh.dispose();let t=this.getRenderableBounds(this.rootMesh),i=go(mr(t)),r=go(Ui(t));this.bboxMesh=Pn.CreateBox("bbox",{width:r.x,height:r.y,depth:r.z},this.scene),this.bboxMesh.position=i;let s=new We("bbox-mat",this.scene);s.wireframe=!0,s.emissiveColor=new he(1,1,0),s.disableLighting=!0,s.alpha=.6,this.bboxMesh.material=s}else(e=this.bboxMesh)==null||e.dispose(),this.bboxMesh=null;return this.bboxEnabled}toggleSlice(){var e;return this.sliceActive?(this.deactivateSliceMode(),!1):(this.disableDisassemblyAndReset(),this.deactivateMeasurementMode(),this.focusSelectionEnabled&&(this.focusSelectionEnabled=!1,this.clearFocusedMesh(),(e=this.cleanupPicking)==null||e.clearHighlight()),this.alignSlicePlaneToWorld(),this.sliceInteractionMode=Xf,this.sliceActive=!0,this.syncSliceClipping(),this.notifySliceChanged(),this.sliceActive)}isSliceActive(){return this.sliceActive}setSlicePlane(e,t=this.sliceOffset){let i=wo(e);return this.sliceNormal.set(i.x,i.y,i.z),this.rebuildSlicePlaneAxes(),this.sliceOffset=Ia(t),this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceOffset(e){return this.sliceOffset=Ia(e),this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceRotation(e){var a,o;let t=this.rootMesh?this.getRenderableBounds(this.rootMesh):null,i=this.getSliceRange(),r=(o=(a=this.sliceCenter)==null?void 0:a.clone())!=null?o:i?new b(i.point.x,i.point.y,i.point.z):null,s=gx(e);return this.slicePlaneX.set(s.x.x,s.x.y,s.x.z),this.slicePlaneY.set(s.y.x,s.y.y,s.y.z),this.sliceNormal.set(s.z.x,s.z.y,s.z.z),r?(this.sliceCenter=r,this.sliceOffset=Xm(t,s.z,ct(r))):this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceInteractionMode(e){let t=ov(e);return t===this.sliceInteractionMode?this.getSliceState():(this.endSliceDrag(null,!0),this.sliceInteractionMode=t,this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState())}resetSlicePlane(){return this.alignSlicePlaneToWorld(),this.sliceOffset=Il,this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceAxis(e){let t=av(e);return this.setSlicePlane({x:t==="x"?1:0,y:t==="y"?1:0,z:t==="z"?1:0})}setSlicePosition(e){return this.setSliceOffset(e)}setSliceThickness(e){return this.sliceThickness=lv(e),this.notifySliceChanged(),this.getSliceState()}getSliceState(){let e=px(this.sliceActive,ct(this.sliceNormal),this.sliceOffset,this.rootMesh?this.getRenderableBounds(this.rootMesh):null,!!this.sliceDragState,this.sliceThickness,this.sliceInteractionMode,ct(this.sliceReferenceNormal)),t=this.getSliceRange(),i=_x({x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)});return t?{...e,rotationDegrees:i,offset:t.offset,position:t.offset,point:{...t.point}}:{...e,rotationDegrees:i}}observeSlice(e){return this.sliceObservers.add(e),e(),()=>{this.sliceObservers.delete(e)}}toggleFocusSelection(){let e=!this.focusSelectionEnabled;return e&&this.isDisassemblyActive()&&this.disableDisassemblyAndReset(),e&&(this.deactivateMeasurementMode(),this.deactivateSliceMode()),this.focusSelectionEnabled=e,this.focusSelectionEnabled?this._lastPickResult.mesh&&this.setFocusedNode(this._lastPickResult.mesh):this.clearFocusedMesh(),this.focusSelectionEnabled}isFocusSelectionEnabled(){return this.focusSelectionEnabled}toggleDisassembly(){let e=this.ensureDisassemblyController();if(!e)return!1;let t=!e.isEnabled();t&&(this.focusSelectionEnabled=!1,this.clearFocusedMesh(),this.deactivateMeasurementMode(),this.deactivateSliceMode());let i=e.setEnabled(t);return i||e.reset(),i}resetDisassembly(){var e;(e=this.disassembly)==null||e.reset()}disableDisassemblyAndReset(){var e;this.isDisassemblyActive()&&((e=this.disassembly)==null||e.setEnabled(!1),this.resetDisassembly())}isDisassemblyEnabled(){return this.isDisassemblyActive()}setExplode(e,t){this.rootMesh&&RQ(this.rootMesh,e,t,this.loadedMeshes)}resetExplode(){this.rootMesh&&jF(this.rootMesh,this.loadedMeshes)}resetView(){this.rootMesh&&jF(this.rootMesh,this.loadedMeshes),this.resetDisassembly(),this.clearFocusedMesh(),this.camera.mode=0,this.camera.alpha=this.initialCamera.alpha,this.camera.beta=this.initialCamera.beta,this.camera.radius=this.initialCamera.radius,this.camera.target=this.initialCamera.target.clone(),this.startRenderLoop(),this.notifyCameraZoomChanged()}exportModelInfo(e){if(!this.rootMesh)return"";let t=this.getRenderableMeshes(this.rootMesh),i=b1(this.rootMesh),r=this.createModelSummary(this.rootMesh),s=e&&Qs(e)||r.rootName;return jA({title:s,format:this.loadedExt.toUpperCase(),summary:r,meshBreakdown:t.map(a=>SQ(a,{isSplat:i})),materialNames:t.map(a=>{var o;return(o=a.material)==null?void 0:o.name})})}getModelEvidence(){if(!this.rootMesh)return null;let e=this.getRenderableMeshes(this.rootMesh),t=AQ(e,this.loadedTransformNodes,this.gltfComponentMetadata);return JA({summary:this.createModelSummary(this.rootMesh),renderableMeshes:e,groupedPartCandidates:t,createMeshPart:i=>XF(i,this.gltfComponentMetadata),getMeshMaterialNames:i=>{var r;return[(r=i.material)==null?void 0:r.name]},resourceWarnings:this.resourceWarnings})}getSelectedPartInfo(){var t;if(!this.rootMesh)return null;let e=(t=this.focusedNode)!=null?t:M$(this._lastPickResult.mesh)?this._lastPickResult.mesh:null;return!e||hf(e)?null:YF(e,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata)}exportSelectedPartInfo(){let e=this.getSelectedPartInfo();return e?ZA(e):""}getPickWorldPoint(e){return e.pickedPoint&&typeof e.pickedPoint=="object"?ct(e.pickedPoint):this.rootMesh&&M$(e.mesh)?YF(e.mesh,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata).center:null}focusWorldPoint(e){let t=new b(e.x,e.y,e.z),i=this.camera.target.clone(),r=performance.now();this.focusWorldPointFrame&&(activeWindow.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0);let s=a=>{let o=Math.min(1,Math.max(0,(a-r)/JSe)),l=o<.5?4*o*o*o:1-Math.pow(-2*o+2,3)/2;if(this.camera.target=b.Lerp(i,t,l),o<1&&!this.scene.isDisposed){this.focusWorldPointFrame=window.requestAnimationFrame(s);return}this.focusWorldPointFrame=0};this.focusWorldPointFrame=window.requestAnimationFrame(s)}getAnnotationCameraStateKey(){return $A([{value:this.camera.alpha,digits:3},{value:this.camera.beta,digits:3},{value:this.camera.radius,digits:3},{value:this.camera.target.x,digits:2},{value:this.camera.target.y,digits:2},{value:this.camera.target.z,digits:2}])}projectAnnotationWorldPoint(e,t){let i=this.engine.getRenderingCanvas();if(!i||this.scene.isDisposed)return!1;let r=this.engine.getRenderWidth(),s=this.engine.getRenderHeight();if(r===0||s===0||i.clientWidth===0||i.clientHeight===0)return!1;let a=Ga.annotationWorldPoint;return a.set(e.x,e.y,e.z),b.ProjectToRef(a,Ga.annotationIdentity,this.scene.getTransformMatrix(),this.camera.viewport.toGlobal(r,s),Ga.annotationProjection),mV(Ga.annotationProjection,r,s,i,t)}isAnnotationWorldPointOccluded(e){if(this.scene.isDisposed)return!1;let t=kf(ct(this.camera.position),e);if(!t)return!1;let i=Ga.annotationDirection,r=Ga.annotationRay;i.set(t.direction.x,t.direction.y,t.direction.z),r.origin=this.camera.position,r.direction=i,r.length=t.distance;let s=this.scene.pickWithRay(r);return!!(s!=null&&s.hit)&&Gf(s.distance,t.distance,t.epsilon)}getAnnotationProvider(){let e=this.engine.getRenderingCanvas();if(!e)throw new Error("Preview canvas is unavailable");return QA({canvas:e,observeRender:t=>{let i=this.scene.onAfterRenderCameraObservable.add(r=>{r===this.camera&&t()});return{remove:()=>this.scene.onAfterRenderCameraObservable.remove(i)}},getCameraStateKey:()=>this.getAnnotationCameraStateKey(),projectWorldPoint:(t,i)=>this.projectAnnotationWorldPoint(t,i),isWorldPointOccluded:t=>this.isAnnotationWorldPointOccluded(t)})}getCanvas(){return this.engine.getRenderingCanvas()}getLastPickResult(){return this._lastPickResult}onPick(e){return this._onPickCallbacks.push(e),()=>{this._onPickCallbacks=this._onPickCallbacks.filter(t=>t!==e)}}setRenderQuality(e,t=this.renderScale){this.currentQuality=e,this.renderScale=Math.max(.25,Math.min(t,2));let i={low:2,medium:1.33,high:1},r=Rr()?1.5:1,s=i[e]*r/this.renderScale;if(this.engine.setHardwareScalingLevel(s),this.shadowGenerator){let a={low:0,medium:16,high:32};this.shadowGenerator.blurKernel=a[e],e==="low"?(this.shadowGenerator.useBlurExponentialShadowMap=!1,this.shadowGenerator.useExponentialShadowMap=!0):(this.shadowGenerator.useBlurExponentialShadowMap=!0,this.shadowGenerator.useExponentialShadowMap=!1)}}destroy(){var t,i,r,s,a,o,l,c;this.engine.stopRenderLoop(),this.focusWorldPointFrame&&(activeWindow.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0),this._onPickCallbacks=[],this.cameraZoomObservers.clear(),this.sliceObservers.clear(),(t=this.cleanupPicking)==null||t.call(this),this.cleanupPicking=null,(i=this.gizmo)==null||i.dispose(),this.gizmo=null,(r=this.disassembly)==null||r.dispose(),this.disassembly=null,this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.disposeMeasurementOverlays(!0),this.measurementObservers.clear(),this.clearFocusedMesh(),this.originalMeshVisibility.clear(),(s=this.bboxMesh)==null||s.dispose(),this.bboxMesh=null,this.camera.detachControl();let e=this.engine.getRenderingCanvas();e==null||e.classList.remove("ai3d-slice-active","ai3d-slice-dragging","ai3d-slice-rotate"),e==null||e.removeEventListener("wheel",this.preventCanvasWheelScroll),e==null||e.removeEventListener("pointerdown",this.handlePointerDown,!0),e==null||e.removeEventListener("pointerup",this.handlePointerUp,!0),e==null||e.removeEventListener("pointermove",this.handlePointerMove,!0),e==null||e.removeEventListener("pointercancel",this.handlePointerCancel,!0),e==null||e.removeEventListener("lostpointercapture",this.handlePointerCaptureLost,!0),e==null||e.removeEventListener("webglcontextlost",this.handleContextLost),e==null||e.removeEventListener("webglcontextrestored",this.handleContextRestored),window.removeEventListener("keydown",this.handleMeasurementModifierKey),window.removeEventListener("keyup",this.handleMeasurementModifierKey),window.removeEventListener("blur",this.handleMeasurementModifierBlur),(a=this.viewportObserver)==null||a.disconnect(),this.viewportObserver=null,this.resizeObs.disconnect(),this.sliceMoveFrame&&(activeWindow.cancelAnimationFrame(this.sliceMoveFrame),this.sliceMoveFrame=0),this.pendingSliceMove=null,this.invalidateMeshCache(),this.rootMesh=null,this.loadedMeshes=[],this.loadedTransformNodes=[],this.autoRotateBehavior&&(this.camera.removeBehavior(this.autoRotateBehavior),this.autoRotateBehavior=null);for(let f of this.configLights)f.dispose();this.configLights=[],(o=this.shadowGenerator)==null||o.dispose(),this.shadowGenerator=null,(l=this.groundMesh)==null||l.dispose(),this.groundMesh=null,(c=this.gridMesh)==null||c.dispose(),this.gridMesh=null;for(let f of this.axisMeshes)f.dispose();this.axisMeshes=[],this.scene.dispose(),this.engine.dispose()}startRenderLoop(){this.rendering||!this.viewportVisible||this.contextLost||(this.rendering=!0,this.engine.runRenderLoop(()=>{if(!this.canRender()||!this.viewportVisible||this.contextLost){this.engine.stopRenderLoop(),this.rendering=!1;return}this.scene.render(),this.gizmo&&this.gizmoEnabled&&(this.gizmo.syncWith(this.camera),this.gizmo.render())}))}getRenderableMeshes(e){if(this.cachedRenderableMeshes&&this.cachedRenderableRoot===e)return this.cachedRenderableMeshes;let t=Eh(e,this.loadedMeshes);return this.cachedRenderableMeshes=t,this.cachedRenderableRoot=e,t}getRenderableBounds(e){return hy(e,this.loadedMeshes)}getSliceRange(){let e=Du(this.rootMesh?this.getRenderableBounds(this.rootMesh):null,{normal:ct(this.sliceNormal),offset:this.sliceOffset});if(!e||!this.sliceCenter)return e;let t=b.Dot(this.sliceCenter,this.sliceNormal),i=Ia((t-e.min)/e.span);return this.sliceOffset=i,{...e,offset:i,distance:t,point:ct(this.sliceCenter)}}setSliceCenterFromOffset(e){if(!this.rootMesh)return;let t=Du(this.getRenderableBounds(this.rootMesh),{normal:ct(this.sliceNormal),offset:e});t&&(this.sliceCenter=new b(t.point.x,t.point.y,t.point.z))}alignSlicePlaneToWorld(){this.sliceNormal.set(Dr.x,Dr.y,Dr.z),this.rebuildSlicePlaneAxes(new b(1,0,0)),this.sliceReferenceNormal.copyFrom(this.sliceNormal),this.sliceCenter=null,this.setSliceCenterFromOffset(this.sliceOffset)}rebuildSlicePlaneAxes(e=this.slicePlaneX){let t=this.sliceNormal.clone().normalize(),i=e.clone().subtract(t.scale(b.Dot(e,t)));i.lengthSquared()<=1e-6&&(i.copyFrom(Math.abs(t.y)<.92?new b(0,1,0):new b(1,0,0)),i.subtractInPlace(t.scale(b.Dot(i,t)))),i.normalize(),this.slicePlaneX.copyFrom(i),b.CrossToRef(t,i,this.slicePlaneY),this.slicePlaneY.normalize()}deactivateSliceMode(){return!this.sliceActive&&!this.sliceDragState?!1:(this.endSliceDrag(null,!0),this.sliceActive=!1,this.syncSliceClipping(),this.notifySliceChanged(),!0)}beginSliceDrag(e){if(!this.rootMesh||!this.sliceActive)return!1;let t=this.getSlicePointerTarget(e);if(!t)return!1;let i=this.engine.getRenderingCanvas();if(!i)return!1;let r=i.getBoundingClientRect(),s=t.mode;this.sliceInteractionMode=s;let a={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,mode:s,moved:!1};if(s==="rotate"){let o=this.getSliceRange();if(!o)return!1;let l=this.getSlicePointerPolar(e,t.axis);if(!l)return!1;this.sliceDragState={...a,mode:s,axis:t.axis,startNormal:ct(this.sliceNormal),anchorPoint:{...o.point},rotationAxis:ct(t.axis==="x"?this.slicePlaneX:t.axis==="y"?this.slicePlaneY:this.sliceNormal),startPlaneX:ct(this.slicePlaneX),startPlaneY:ct(this.slicePlaneY),screenTangent:t.screenTangent,radiansPerPixel:t.radiansPerPixel,rotationRadians:0,startPointerAngle:l.angle,currentPointerAngle:l.angle,snapMode:Ym(l.radiusRatio),useScreenRotation:Ex(l.rayPlaneAlignment),labelPoint:t.labelPoint}}else this.sliceDragState={...a,mode:s,startOffset:this.sliceOffset,screenAxis:this.getSliceScreenAxis(),pixelsToOffset:1/Math.max(Math.min(r.width,r.height)*.72,1)};this.syncSliceClipping(),i.classList.add("ai3d-slice-dragging"),this.stabilizeCameraForSliceDrag(),this.camera.detachControl();try{i.setPointerCapture(e.pointerId)}catch(o){}return e.preventDefault(),e.stopImmediatePropagation(),this.notifySliceChanged(),this.startRenderLoop(),!0}getSlicePointerPolar(e,t,i,r){let s=this.engine.getRenderingCanvas(),a=this.getSliceRange();if(!s||!this.rootMesh||!a)return null;let o=s.getBoundingClientRect();if(o.width<=0||o.height<=0)return null;let l=this.scene.createPickingRay(e.clientX-o.left,e.clientY-o.top,Q.Identity(),this.camera),c=r!=null?r:a.point,f=new b(c.x,c.y,c.z),d=i?{x:new b(i.x.x,i.x.y,i.x.z),y:new b(i.y.x,i.y.y,i.y.z),z:new b(i.z.x,i.z.y,i.z.z)}:{x:this.slicePlaneX,y:this.slicePlaneY,z:this.sliceNormal},u=(t==="x"?d.x:t==="y"?d.y:d.z).clone().normalize(),h=(t==="x"?d.y:t==="y"?d.z:d.x).clone().normalize(),m=(t==="x"?d.z:t==="y"?d.x:d.y).clone().normalize(),g=b.Dot(u,l.direction);if(Math.abs(g)<=1e-6)return null;let p=b.Dot(f.subtract(l.origin),u)/g,v=l.origin.add(l.direction.scale(p)).subtract(f),E=this.getRenderableBounds(this.rootMesh),S=Math.max(Rs(E)*.62,a.span*.16,Number.EPSILON);return{angle:Math.atan2(b.Dot(v,m),b.Dot(v,h)),radiusRatio:v.length()/S,rayPlaneAlignment:Math.abs(g)}}getSlicePointerTarget(e){if(e.altKey||!this.rootMesh)return null;let t=this.engine.getRenderingCanvas(),i=this.getSliceRange();if(!t||!i)return null;let r=this.getRenderableBounds(this.rootMesh),s=t.getBoundingClientRect(),a=this.engine.getRenderWidth(),o=this.engine.getRenderHeight();if(s.width<=0||s.height<=0||a<=0||o<=0)return null;let l=this.camera.viewport.toGlobal(a,o),c=p=>{let _=b.Project(new b(p.x,p.y,p.z),Q.Identity(),this.scene.getTransformMatrix(),l);return{x:s.left+_.x/a*s.width,y:s.top+_.y/o*s.height}},f={x:e.clientX,y:e.clientY},d=e.pointerType==="touch"?28:14,u=c(i.point);if(Math.hypot(f.x-u.x,f.y-u.y)<=d*1.35)return{mode:"move"};let h=Km(r,i,64,{x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)});if(h.moveGuide.some(([p,_])=>{let v=c(p),E=c(_);return b$(f,v,E)<=d}))return{mode:"move"};let m=null,g=Number.POSITIVE_INFINITY;for(let p of["x","y","z"]){let _=h.rotationRings[p].map(([E,S])=>[c(E),c(S)]),v=_.reduce((E,[S,T])=>E+Math.hypot(T.x-S.x,T.y-S.y),0);for(let[E,S]of _){let T=b$(f,E,S);if(T>d||T>=g)continue;let A=Math.hypot(S.x-E.x,S.y-E.y);A<=Number.EPSILON||(g=T,m={mode:"rotate",axis:p,screenTangent:{x:(S.x-E.x)/A,y:(S.y-E.y)/A},radiansPerPixel:Math.PI*2/Math.max(v,80),labelPoint:{...i.point}})}}return m}updateSliceDrag(e){let t=this.sliceDragState;return!t||t.pointerId!==e.pointerId?!1:(e.preventDefault(),e.stopImmediatePropagation(),this.pendingSliceMove={pointerId:e.pointerId,clientX:e.clientX,clientY:e.clientY},this.sliceMoveFrame||(this.sliceMoveFrame=activeWindow.requestAnimationFrame(()=>{this.sliceMoveFrame=0,this.flushSliceDragUpdate()})),!0)}flushSliceDragUpdate(){this.sliceMoveFrame&&(activeWindow.cancelAnimationFrame(this.sliceMoveFrame),this.sliceMoveFrame=0);let e=this.pendingSliceMove;this.pendingSliceMove=null;let t=this.sliceDragState;if(!e||!t||t.pointerId!==e.pointerId)return;let i=e.clientX-t.startX,r=e.clientY-t.startY;if(t.moved=t.moved||Math.hypot(i,r)>2,t.mode==="rotate"){let o=this.getSlicePointerPolar(e,t.axis,{x:t.startPlaneX,y:t.startPlaneY,z:t.startNormal},t.anchorPoint);if(!o)return;let l=(i*t.screenTangent.x+r*t.screenTangent.y)*t.radiansPerPixel,c=cv(t.useScreenRotation?l:o.angle-t.startPointerAngle);t.useScreenRotation||(t.snapMode=Ym(o.radiusRatio,t.snapMode)),t.rotationRadians=vx(c,t.snapMode),t.currentPointerAngle=t.startPointerAngle+t.rotationRadians;let f=Yf(t.startNormal,t.rotationAxis,t.rotationRadians),d=Yf(t.startPlaneX,t.rotationAxis,t.rotationRadians),u=Yf(t.startPlaneY,t.rotationAxis,t.rotationRadians),h=b.DistanceSquared(this.sliceNormal,new b(f.x,f.y,f.z)),m=b.DistanceSquared(this.slicePlaneX,new b(d.x,d.y,d.z))+b.DistanceSquared(this.slicePlaneY,new b(u.x,u.y,u.z));if(h<=1e-6&&m<=1e-6)return;if(h>1e-6){let g=this.rootMesh?this.getRenderableBounds(this.rootMesh):null;this.sliceNormal.set(f.x,f.y,f.z),this.sliceCenter=new b(t.anchorPoint.x,t.anchorPoint.y,t.anchorPoint.z),this.sliceOffset=Xm(g,f,t.anchorPoint)}this.slicePlaneX.set(d.x,d.y,d.z),this.slicePlaneY.set(u.x,u.y,u.z),this.syncSliceClipping(),this.notifySliceChanged();return}let s=i*t.screenAxis.x+r*t.screenAxis.y,a=Ia(t.startOffset+s*t.pixelsToOffset);Math.abs(a-this.sliceOffset)<=5e-4||(this.sliceOffset=a,this.setSliceCenterFromOffset(a),this.syncSliceClipping(),this.notifySliceChanged())}endSliceDrag(e,t=!1){let i=this.sliceDragState;if(!i||e&&i.pointerId!==e.pointerId)return!1;this.flushSliceDragUpdate();let r=this.engine.getRenderingCanvas();if(this.sliceDragState=null,r==null||r.classList.remove("ai3d-slice-dragging"),this.syncSliceClipping(),this.camera.attachControl(r,!0),this.resumeCameraAfterSliceDrag(),e&&r){try{r.releasePointerCapture(e.pointerId)}catch(s){}e.preventDefault(),e.stopImmediatePropagation()}return(!t||i.moved)&&this.notifySliceChanged(),this.startRenderLoop(),!0}stabilizeCameraForSliceDrag(){this.focusWorldPointFrame&&(activeWindow.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0),this.camera.inertialAlphaOffset=0,this.camera.inertialBetaOffset=0,this.camera.inertialRadiusOffset=0,this.camera.inertialPanningX=0,this.camera.inertialPanningY=0,this.autoRotateBehavior&&!this.sliceAutoRotatePaused&&(this.camera.removeBehavior(this.autoRotateBehavior),this.sliceAutoRotatePaused=!0)}resumeCameraAfterSliceDrag(){!this.autoRotateBehavior||!this.sliceAutoRotatePaused||(this.camera.addBehavior(this.autoRotateBehavior),this.sliceAutoRotatePaused=!1)}getSliceScreenAxis(){let e=this.getSliceRange();if(!this.rootMesh||!e)return{x:0,y:-1};let t=this.getRenderableBounds(this.rootMesh),i=this.engine.getRenderingCanvas();if(!i)return{x:0,y:-1};let r=Math.max(Rs(t),e.span*.25,Number.EPSILON),s=new b(e.point.x,e.point.y,e.point.z),a=s.add(new b(e.normal.x,e.normal.y,e.normal.z).normalize().scale(r*.35)),o=this.engine.getRenderWidth(),l=this.engine.getRenderHeight();if(o===0||l===0||i.clientWidth===0||i.clientHeight===0)return{x:0,y:-1};let c=this.camera.viewport.toGlobal(o,l),f=b.Project(s,Q.Identity(),this.scene.getTransformMatrix(),c),d=b.Project(a,Q.Identity(),this.scene.getTransformMatrix(),c),u={x:d.x-f.x,y:d.y-f.y},h=Math.hypot(u.x,u.y);return!Number.isFinite(h)||h<=1e-6?{x:0,y:-1}:{x:u.x/h,y:u.y/h}}updateBabylonSlicePlane(e){let t=Tx(e,"babylon");if(!(t!=null&&t.length))return null;let i=t[0];return this.slicePlane?(this.slicePlane.normal.set(i.normal.x,i.normal.y,i.normal.z),this.slicePlane.d=i.constant):this.slicePlane=new Da(i.normal.x,i.normal.y,i.normal.z,i.constant),this.slicePlane}syncSliceClipping(){let e=this.engine.getRenderingCanvas();if(e==null||e.classList.toggle("ai3d-slice-active",this.sliceActive),e==null||e.classList.toggle("ai3d-slice-rotate",this.sliceActive&&this.sliceInteractionMode==="rotate"),!this.rootMesh||!this.sliceActive){this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.slicePlane=null,e==null||e.classList.remove("ai3d-slice-dragging"),e==null||e.classList.remove("ai3d-slice-rotate"),this.startRenderLoop();return}let t=this.getSliceRange(),i=this.updateBabylonSlicePlane(t);if(!i){this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.startRenderLoop();return}this.syncSliceOverlay(t);let r=new Set;for(let s of this.getRenderableMeshes(this.rootMesh)){let a=s.material;if(!a)continue;r.add(a.uniqueId);let o=!this.sliceOriginalMaterialClipping.has(a.uniqueId);o&&this.sliceOriginalMaterialClipping.set(a.uniqueId,{material:a,clipPlane:a.clipPlane,clipPlane2:a.clipPlane2}),(o||a.clipPlane!==i)&&(a.clipPlane=i,a.markDirty(!0))}for(let[s,a]of Array.from(this.sliceOriginalMaterialClipping.entries()))r.has(s)||(a.material.clipPlane=a.clipPlane,a.material.clipPlane2=a.clipPlane2,a.material.markDirty(!0),this.sliceOriginalMaterialClipping.delete(s));this.startRenderLoop()}restoreSliceMaterialClipping(){for(let e of this.sliceOriginalMaterialClipping.values())e.material.clipPlane=e.clipPlane,e.material.clipPlane2=e.clipPlane2,e.material.markDirty(!0);this.sliceOriginalMaterialClipping.clear()}syncSliceOverlay(e){var w,G,O,N,B,V;this.disposeSliceOverlay(!1,!0);let t=this.rootMesh?this.getRenderableBounds(this.rootMesh):null;if(!t||!e)return;let i={x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)},r=Sx(t,e,.12,i),s=this.createSliceOverlayPlane(r),a=this.sliceInteractionMode==="rotate"?aTe:rTe,o=this.createSliceOverlayLines(r.segments,a),l=this.createSliceOverlayLines(this.createSliceNormalGuide(t,e),nTe),c=((w=this.sliceDragState)==null?void 0:w.mode)==="rotate"?{[this.sliceDragState.axis]:this.sliceDragState.currentPointerAngle}:void 0,f=((G=this.sliceDragState)==null?void 0:G.mode)==="rotate"?{x:this.sliceDragState.startPlaneX,y:this.sliceDragState.startPlaneY,z:this.sliceDragState.startNormal}:i,d=Km(t,e,64,f,c),u=((O=this.sliceDragState)==null?void 0:O.mode)==="rotate"?this.sliceDragState.axis:null,h=((N=this.sliceDragState)==null?void 0:N.mode)==="move",m=(q,K)=>({color:u===q?oTe:K,alpha:u?u===q?.98:0:h?.1:.34,tickAlpha:u?u===q?.82:0:h?.04:.14}),g=m("x",A$),p=m("y",x$),_=m("z",R$),v=this.createSliceOverlayLines(d.rotationRings.x,g.color,g.alpha),E=this.createSliceOverlayLines(d.rotationRings.y,p.color,p.alpha),S=this.createSliceOverlayLines(d.rotationRings.z,_.color,_.alpha),T=this.createSliceOverlayLines(d.rotationTicks.x,g.color,g.tickAlpha),A=this.createSliceOverlayLines(d.rotationTicks.y,p.color,p.tickAlpha),R=this.createSliceOverlayLines(d.rotationTicks.z,_.color,_.tickAlpha),M=this.createSliceOverlayLines(d.moveGuide,lTe,u?.22:.96),I=u==="x"?A$:u==="y"?x$:R$,C=u?this.createSliceOverlayLines(d.rotationArcs[u],I,1):null,L=u?this.createSliceOverlayLines(d.rotationArrowheads[u],I,1):null;if(this.sliceOverlayPlanes.push(s),this.sliceOverlayLines.push(o,l,v,E,S,T,A,R,M),u&&C&&L){this.sliceOverlayLines.push(C,L);let q=this.sliceDragState;if((q==null?void 0:q.mode)==="rotate"){let K=(q.currentPointerAngle*180/Math.PI%360+360)%360,J=d.rotationArcs[u],Y=(V=(B=J[J.length-1])==null?void 0:B[1])!=null?V:q.labelPoint;this.updateSliceRotationLabel(`${u.toUpperCase()}: ${K.toFixed(1)}\xB0`,new b(Y.x,Y.y,Y.z),this.getMeasurementMarkerSize()*2.5)}}else this.disposeSliceRotationLabel()}createSliceOverlayPlane(e){let t=new $("ai3d-slice-plane",this.scene),i=e.corners,r=[i[0].x,i[0].y,i[0].z,i[1].x,i[1].y,i[1].z,i[2].x,i[2].y,i[2].z,i[3].x,i[3].y,i[3].z],s=[0,1,2,0,2,3],a=[];Ie.ComputeNormals(r,s,a);let o=new Ie;o.positions=r,o.indices=s,o.normals=a,o.applyToMesh(t);let l=new We("slice-plane-mat",this.scene),c=this.sliceInteractionMode==="rotate"?sTe:iTe;return l.diffuseColor=c.clone(),l.emissiveColor=c.scale(.75),l.specularColor=new he(0,0,0),l.alpha=cTe,l.backFaceCulling=!1,l.disableLighting=!0,l.zOffset=-2,t.material=l,t.isPickable=!1,t.renderingGroupId=2,t}createSliceOverlayLines(e,t,i=.88){let r=Pn.CreateLineSystem("ai3d-slice-frame",{lines:e.map(([s,a])=>[new b(s.x,s.y,s.z),new b(a.x,a.y,a.z)]),updatable:!1},this.scene);return r.color=t.clone(),r.alpha=i,r.isPickable=!1,r.renderingGroupId=2,r}createSliceNormalGuide(e,t){var o;let i=Math.max(Rs(e),t.span*.25,Number.EPSILON),r=(o=wn(t.normal))!=null?o:Dr,s=t.point,a={x:s.x+r.x*i*.26,y:s.y+r.y*i*.26,z:s.z+r.z*i*.26};return[[s,a]]}disposeSliceOverlay(e=!0,t=!1){for(let i of this.sliceOverlayPlanes)i.dispose(!1,!0);for(let i of this.sliceOverlayLines)i.dispose(!1,!0);for(let i of this.sliceOverlayLabels)i.dispose(!1,!0);this.sliceOverlayPlanes=[],this.sliceOverlayLines=[],this.sliceOverlayLabels=[],t||this.disposeSliceRotationLabel(),e&&this.startRenderLoop()}updateSliceRotationLabel(e,t,i){if(!this.sliceRotationLabel){this.sliceRotationLabel=this.createMeasurementLabelMesh({primary:e,secondary:""},t,i),this.sliceRotationLabelText=e;return}if(this.sliceRotationLabel.position.copyFrom(t),e===this.sliceRotationLabelText)return;let r=this.sliceRotationLabel.material,s=r instanceof We&&r.diffuseTexture instanceof EE?r.diffuseTexture:null;if(!s){this.disposeSliceRotationLabel(),this.updateSliceRotationLabel(e,t,i);return}let a=s.getContext();nv(a,{primary:e,secondary:""},Oo.width,Oo.height),s.update(),this.sliceRotationLabelText=e}disposeSliceRotationLabel(){var e;(e=this.sliceRotationLabel)==null||e.dispose(!1,!0),this.sliceRotationLabel=null,this.sliceRotationLabelText=""}notifySliceChanged(){for(let e of this.sliceObservers)e()}invalidateMeshCache(){this.cachedRenderableMeshes=null,this.cachedRenderableRoot=null}resolvePickHighlightMeshes(e){if(!this.rootMesh)return[e];let t=this.getRenderableMeshes(this.rootMesh),i=wE(this.rootMesh,e,t,this.gltfComponentMetadata),r=t.filter(s=>xg(s,i));return r.length>0?r:[e]}setFocusedNode(e){if(!this.rootMesh)return;let t=e?this.findSelectableNode(e):null;if(!t||hf(t)){this.clearFocusedMesh();return}if(this.focusedNode===t)return;let i=this.getRenderableMeshes(this.rootMesh),r=i.filter(a=>xg(a,t));if(r.length===0){this.clearFocusedMesh();return}let s=new Set(r);for(let a of i){this.originalMeshVisibility.has(a.uniqueId)||this.originalMeshVisibility.set(a.uniqueId,a.visibility);let o=s.has(a);a.visibility=o?1:$Se,a.renderOutline=o,a.outlineColor=new he(.18,.76,1),a.outlineWidth=o?.045:0}this.focusedNode=t}clearFocusedMesh(){if(!this.rootMesh){this.focusedNode=null;return}for(let e of this.getRenderableMeshes(this.rootMesh)){let t=this.originalMeshVisibility.get(e.uniqueId);t!==void 0&&(e.visibility=t),e.renderOutline=!1,e.outlineWidth=0}this.originalMeshVisibility.clear(),this.focusedNode=null,this.applyMeasurementTargetVisual(this.measurementTargetMeshes)}findSelectableNode(e){if(!this.rootMesh)return null;let t=this.getRenderableMeshes(this.rootMesh);if(t.includes(e)||t.some(r=>xg(r,e)))return e;if(!dTe(e))return null;let i=e.parent;for(;i&&"uniqueId"in i;){let r=i;if(t.includes(r)||t.some(s=>xg(s,r)))return r;i=i.parent}return null}getCurrentMeasurementTargetNode(){return this.focusSelectionEnabled&&this.focusedNode&&!hf(this.focusedNode)?this.findSelectableNode(this.focusedNode):this.rootMesh&&!this.rootMesh.isDisposed()?this.rootMesh:null}setMeasurementTargetNode(e,t=!0){this.clearMeasurementTargetVisual(!1),this.invalidateMeasurementSnapInputCache();let i=e&&!hf(e)?this.findSelectableNode(e):null;if(!i||hf(i)){this.measurementTargetNode=null,this.measurementTargetMeshes=[],this.setMeasurementSnapKind(null,!1),t&&this.notifyMeasurementsChanged();return}let r=this.getMeasurementTargetMeshes(i);if(r.length===0){this.measurementTargetNode=null,this.measurementTargetMeshes=[],this.setMeasurementSnapKind(null,!1),t&&this.notifyMeasurementsChanged();return}this.measurementTargetNode=i,this.measurementTargetMeshes=r,this.setMeasurementSnapKind(null,!1),this.applyMeasurementTargetVisual(r),this.scene.render(),t&&this.notifyMeasurementsChanged()}clearMeasurementTargetVisual(e=!0){for(let t of this.measurementTargetMeshes)t.isDisposed()||(t.renderOutline=!1,t.outlineWidth=0);this.measurementTargetMeshes=[],e&&!this.scene.isDisposed&&this.scene.render()}applyMeasurementTargetVisual(e){if(!(!this.measurementActive||e.length===0))for(let t of e)t.isDisposed()||(t.renderOutline=!0,t.outlineColor=new he(.38,.65,.98),t.outlineWidth=.045)}setMeasurementSnapKind(e,t=!0){this.measurementSnapKind!==e&&(this.measurementSnapKind=e,t&&this.notifyMeasurementsChanged())}updateMeasurementModifierAltKey(e){this.lastPointerClient.altKey!==e&&(this.lastPointerClient={...this.lastPointerClient,altKey:e},this.measurementActive&&this.pendingPoint&&this.updatePreviewLine())}invalidateMeasurementSnapInputCache(){this.measurementSnapInputCache=null,this.measurementSnapInputCacheTargetId=null,this.measurementSnapInputCacheSignature=null}getMeasurementTargetName(){let e=this.measurementTargetNode;return!e||hf(e)?null:Gd(e,e.name||`node-${e.uniqueId}`)}getMeasurementTargetBounds(){if(!this.rootMesh||!this.measurementTargetNode||hf(this.measurementTargetNode))return null;let e=this.findSelectableNode(this.measurementTargetNode);if(!e)return null;this.measurementTargetNode=e;let t=this.getRenderableMeshes(this.rootMesh).filter(i=>xg(i,e));return Ql(t)}resolveMeasurementPickPoint(e,t){if(t)return this.setMeasurementSnapKind("free"),e;let i=this.createMeasurementGeometrySnapInput();if(!i)return this.setMeasurementSnapKind("free"),e;let r=sx(this.toMeasurementPoint(e),i);return r?(this.setMeasurementSnapKind(r.kind),go(r.point)):(this.setMeasurementSnapKind("free"),e)}createMeasurementGeometrySnapInput(){var f;let e=this.measurementTargetNode;if(!this.rootMesh||!e||hf(e))return null;let t=this.getMeasurementTargetMeshes(e);if(t.length===0)return null;let i=this.createMeasurementSnapInputSignature(t);if(this.measurementSnapInputCache&&this.measurementSnapInputCacheTargetId===e.uniqueId&&this.measurementSnapInputCacheSignature===i)return this.measurementSnapInputCache;let r=[],s=[],a=`babylon:${e.uniqueId}`;for(let d of t){if(d.isDisposed())continue;let u=d.getVerticesData(D.PositionKind);if(!u||u.length<3)continue;let h=d.computeWorldMatrix(!0),m=[],g=Math.floor(u.length/3);for(let _=0;_{var r;let i="geometry"in t&&t.geometry?(r=t.geometry.uniqueId)!=null?r:"geometry":"none";return[t.uniqueId,i,t.getTotalVertices(),t.getTotalIndices(),t.computeWorldMatrix(!0).asArray().map(gTe).join(",")].join(":")}).join("|")}getMeasurementTargetMeshes(e=this.measurementTargetNode){return!this.rootMesh||!e||hf(e)?[]:this.getRenderableMeshes(this.rootMesh).filter(t=>!t.isDisposed()&&xg(t,e))}getMeasurementTargetPickPoint(e,t){return!e||e.isDisposed()||!t?null:this.measurementTargetMeshes.includes(e)?t.clone():null}pickFrontmostMeasurementTargetPoint(e,t){let i=this.engine.getRenderingCanvas();if(!i||this.measurementTargetMeshes.length===0)return null;let r=i.getBoundingClientRect(),s=e-r.left,a=t-r.top,o=this.scene.pick(s,a,l=>l!==this.previewLine&&!this.measurementMarkers.includes(l));return o!=null&&o.hit?this.getMeasurementTargetPickPoint(o.pickedMesh,o.pickedPoint):null}createBabylonMeasurementDraftingLayout(e,t){var l,c,f;let i=this.toMeasurementDisplayPoint(e),r=this.toMeasurementDisplayPoint(t),s=this.getMeasurementMarkerSize(),a=(f=(c=(l=this.camera.upVector)==null?void 0:l.clone)==null?void 0:c.call(l))!=null?f:new b(0,1,0);a.normalize();let o=cx(this.toMeasurementPoint(i),this.toMeasurementPoint(r),{viewPosition:this.toMeasurementPoint(this.camera.position),viewUp:this.toMeasurementPoint(a),offset:s*4.2,extensionGap:s*.55,extensionOvershoot:s*.8,arrowLength:s*2.35,arrowWidth:s*.78,labelGap:s*1.05});return o?{lineSegments:o.lineSegments.map(([d,u])=>[go(d),go(u)]),labelPosition:go(o.labelPoint)}:null}getMeasurementMarkerSize(){if(!this.rootMesh)return .02;let e=this.getRenderableBounds(this.rootMesh);return e?Math.max(e.max.x-e.min.x,e.max.y-e.min.y,e.max.z-e.min.z,.001)*.018:.02}cancelPendingMeasurement(e=!0){var r,s;let t=this.pendingMarker,i=(s=(r=this.pendingPoint)==null?void 0:r.clone())!=null?s:null;if(this.pendingPoint=null,this.pendingMarker=null,this.hoveredMarkerIndex=-1,i&&this.setMeasurementSnapKind(null,!1),this.removePreviewLine(),t&&i&&!this.isMeasurementPointUsed(i)){let a=this.measurementMarkers.indexOf(t);a>=0&&(this.measurementMarkers.splice(a,1),this.measurementMarkerPoints.splice(a,1)),t.dispose(!1,!0)}else t&&(t.scaling.setAll(1),BE(t,UE));e&&this.scene.render()}isMeasurementPointUsed(e){return this.measurementSegments.some(t=>b.Distance(t.start,e)<1e-4||b.Distance(t.end,e)<1e-4)}findNearestMarkerIndex(e){let t=this.getMeasurementMarkerSize()*2.5,i=this.toMeasurementDisplayPoint(e);for(let r=0;r=0?this.measurementMarkerPoints[i].clone():t;if(this.pendingPoint){if(b.Distance(r,this.pendingPoint)<1e-4)return;if(i<0){let s=this.getMeasurementMarkerSize(),a=Pn.CreateSphere("measure-marker",{diameter:s*.76,segments:12},this.scene);a.position=this.toMeasurementDisplayPoint(r),a.isPickable=!1,a.material=I$(this.scene),a.renderingGroupId=2,this.measurementMarkers.push(a),this.measurementMarkerPoints.push(r.clone())}this.createMeasurementSegment(this.pendingPoint,r),this.pendingMarker&&(this.pendingMarker.scaling.setAll(1),BE(this.pendingMarker,UE)),this.pendingPoint=null,this.pendingMarker=null,this.removePreviewLine()}else{if(i<0){let s=this.getMeasurementMarkerSize(),a=Pn.CreateSphere("measure-marker",{diameter:s*.76,segments:12},this.scene);a.position=this.toMeasurementDisplayPoint(r),a.isPickable=!1,a.material=I$(this.scene),a.renderingGroupId=2,this.measurementMarkers.push(a),this.measurementMarkerPoints.push(r.clone()),this.pendingMarker=a}else this.pendingMarker=this.measurementMarkers[i];this.pendingMarker.scaling.setAll(1.6),BE(this.pendingMarker,eTe),this.pendingPoint=r,this.ensurePreviewLine()}this.notifyMeasurementsChanged()}createMeasurementSegment(e,t){var f,d;let i=this.toMeasurementDisplayPoint(e),r=this.toMeasurementDisplayPoint(t),s=this.createBabylonMeasurementDraftingLayout(e,t),a=Pn.CreateLineSystem("measure-line",{lines:(f=s==null?void 0:s.lineSegments)!=null?f:[[i,r]]},this.scene);a.color=S$.clone(),a.alpha=1,a.isPickable=!1,a.renderingGroupId=2;let o=Wm(this.createMeasurementReading(e,t)),l=(d=s==null?void 0:s.labelPosition)!=null?d:b.Center(i,r),c=this.createMeasurementLabelMesh(o,l,this.getMeasurementMarkerSize()*3.2);this.measurementSegments.push({start:e.clone(),end:t.clone(),line:a,label:c})}createMeasurementLabelMesh(e,t,i){let r=Pn.CreatePlane("measure-label",{width:i*3.7,height:i*1.08},this.scene);r.position=t,r.billboardMode=$.BILLBOARDMODE_ALL,r.isPickable=!1,r.renderingGroupId=2;let s=new EE("measure-label-tex",{...Oo},this.scene);s.hasAlpha=!0;let a=s.getContext();nv(a,e,Oo.width,Oo.height),s.update();let o=new We("measure-label-mat",this.scene);return o.diffuseTexture=s,o.emissiveColor=new he(1,1,1),o.disableLighting=!0,o.disableDepthWrite=!0,o.opacityTexture=s,o.useAlphaFromDiffuseTexture=!0,r.material=o,r}ensurePreviewLine(){this.previewLine||(this.previewLine=Pn.CreateLineSystem("measure-preview",{lines:Array.from({length:7},()=>[b.Zero(),b.Zero()]),updatable:!0},this.scene),this.previewLine.color=T$.clone(),this.previewLine.alpha=.82,this.previewLine.isPickable=!1,this.previewLine.renderingGroupId=2)}updatePreviewLine(){var l;if(!this.pendingPoint||!this.previewLine||!this.rootMesh)return;let e=this.toMeasurementDisplayPoint(this.pendingPoint),t=this.engine.getRenderingCanvas();if(!t)return;let i=t.getBoundingClientRect(),r=this.lastPointerClient.x-i.left,s=this.lastPointerClient.y-i.top,a=null;if(this.lastPointerClient.altKey){this.setMeasurementSnapKind("free");let c=this.scene.pick(r,s,f=>f!==this.previewLine&&!this.measurementMarkers.includes(f));a=c.hit&&c.pickedPoint?this.resolveMeasurementPickPoint(c.pickedPoint,!0):e.add(this.scene.createPickingRay(r,s,Q.Identity(),this.camera).direction.scale(5))}else{let c=this.pickFrontmostMeasurementTargetPoint(this.lastPointerClient.x,this.lastPointerClient.y);c?a=this.resolveMeasurementPickPoint(c,!1):this.setMeasurementSnapKind(null)}let o=a?this.createBabylonMeasurementDraftingLayout(this.pendingPoint,this.toMeasurementBasePoint(a)):null;this.previewLine=Pn.CreateLineSystem("measure-preview",{lines:(l=o==null?void 0:o.lineSegments)!=null?l:[[e,e]],instance:this.previewLine},this.scene),this.previewLine.color=T$.clone(),this.previewLine.alpha=.82,this.previewLine.isPickable=!1,this.previewLine.renderingGroupId=2}removePreviewLine(){this.previewLine&&(this.previewLine.dispose(),this.previewLine=null)}createMeasurementReading(e,t){return ux(this.toMeasurementPoint(e),this.toMeasurementPoint(t),this.measurementScale,this.measurementUnit)}createMeasurementRecords(){return this.measurementSegments.map((e,t)=>({index:t+1,start:this.toMeasurementPoint(e.start),end:this.toMeasurementPoint(e.end),reading:this.createMeasurementReading(e.start,e.end)}))}toMeasurementPoint(e){return{x:e.x,y:e.y,z:e.z}}createModelSummary(e){let t=this.getRenderableMeshes(e),i=b1(e),r=t.reduce((s,a)=>s+kd(a),0);return my(e.name,this.getRenderableBounds(e),t,{splatCount:i?r:void 0,resourceWarnings:this.resourceWarnings})}};Ga.annotationIdentity=Q.Identity(),Ga.annotationWorldPoint=b.Zero(),Ga.annotationProjection=b.Zero(),Ga.annotationDirection=b.Zero(),Ga.annotationRay=new on(b.Zero(),b.Zero(),1);Iy=Ga});async function L$(n,e){if(Bh(e).backend==="three"){let{createThreeModelPreview:r}=await Promise.resolve().then(()=>($V(),QV));return r(n)}let{createBabylonModelPreview:i}=await Promise.resolve().then(()=>(P$(),C$));return i(n)}var D$=y(()=>{"use strict";_S()});var N$={};Be(N$,{createBabylonGridRenderer:()=>ETe});function vTe(n){return n.replace(/\|/g,"\\|").replace(/\r?\n/g," ")}function y1(n){return new b(n.x,n.y,n.z)}function O$(n){return Number.isFinite(n)?Math.max(0,Math.min(n,1)):0}function ETe(n){return new I1(n)}var Rg,I1,w$=y(()=>{"use strict";zD();na();Eb();Sb();He();$t();up();ug();cd();lf();OE();OE();FE();FA();Ma();Lo();HA();Rg=32;I1=class{constructor(e){this.cells=[];this.initialCameras=[];this.wireframeEnabled=!1;this.rendering=!1;this.dirty=!0;this.contextLost=!1;this.warmupFrame=null;this.renderScale=1;this.cameraZoomObservers=new Set;this.preventCanvasWheelScroll=e=>{e.preventDefault(),e.stopPropagation()};this.handleContextLost=e=>{e.preventDefault(),this.contextLost=!0,this.rendering&&(this.engine.stopRenderLoop(),this.rendering=!1)};this.handleContextRestored=()=>{this.contextLost=!1,this.engine.resize(),this.startRenderLoop(),this.markDirty(),this.scheduleWarmupFrames()};e.className="ai3d-canvas-full",e.addEventListener("wheel",this.preventCanvasWheelScroll,{passive:!1}),this.engine=new ze(e,!0,{preserveDrawingBuffer:!0}),e.addEventListener("webglcontextlost",this.handleContextLost),e.addEventListener("webglcontextrestored",this.handleContextRestored),this.scene=new ai(this.engine),this.scene.clearColor=new ht(.12,.12,.14,1),this.scene.autoClear=!1,new Fa("default-light",new b(0,1,.5),this.scene),this.resizeObs=new ResizeObserver(()=>{this.engine.resize(),this.markDirty()}),this.resizeObs.observe(e),window.requestAnimationFrame(()=>this.engine.resize())}canRender(){let e=this.engine.getRenderingCanvas();return!!(e!=null&&e.isConnected)&&e.clientWidth>0&&e.clientHeight>0}markDirty(){this.dirty=!0}getCameraZoomRange(e){let t=e.radius,i=e.lowerRadiusLimit,r=e.upperRadiusLimit,s=typeof i=="number"&&Number.isFinite(i)&&i>0?i:Math.max(t*.08,1e-5),a=typeof r=="number"&&Number.isFinite(r)&&r>s?r:Math.max(t*8,s*10);return{current:Math.max(s,Math.min(t,a)),min:s,max:a}}notifyCameraZoomChanged(){if(this.cameraZoomObservers.size===0)return;let e=this.getCameraZoomState();for(let t of this.cameraZoomObservers)t(e)}scheduleWarmupFrames(e=8){this.warmupFrame!==null&&window.cancelAnimationFrame(this.warmupFrame),this.warmupFrame=window.requestAnimationFrame(()=>{this.warmupFrame=null,!(!this.canRender()||this.contextLost)&&(this.markDirty(),e>1&&this.scheduleWarmupFrames(e-1))})}getCellBounds(e){let t=Ql(e);if(!t)throw new Error("Grid cell has no renderable meshes");return t}async loadModels(e,t,i){var d,u,h;await DE();let r=e.length>Rg?(console.warn(`[AI3D Grid] Capping ${e.length} models to ${Rg} (layerMask limit)`),e.slice(0,Rg)):e,s=(d=t.columns)!=null?d:Math.min(r.length,3),a=(u=t.gapX)!=null?u:.02,o=(h=t.gapY)!=null?h:.02,l=Math.ceil(r.length/s),c=(1-a*(s+1))/s,f=(1-o*(l+1))/l;for(let m=0;mRg?(console.warn(`[AI3D Preset] Capping ${e.placements.length} placements to ${Rg} (layerMask limit)`),e.placements.slice(0,Rg)):e.placements,r=[];for(let f=0;f0&&(u.push(...r[g]),h|=1<{this.markDirty(),this.notifyCameraZoomChanged()})),this.initialCameras.push({alpha:f.alpha,beta:f.beta,radius:f.radius,target:f.target.clone()}),f}async loadOne(e,t,i,r,s,a,o){var u,h;let l=await t(e.path),c=(h=(u=e.path.split(".").pop())==null?void 0:u.replace(".","").toLowerCase())!=null?h:"glb",{renderableMeshes:f}=await this.importMesh(e.path,l,o);if(c==="stl"&&e.color){let m=he.FromHexString(e.color);for(let g of f)g.material instanceof We&&g.material.name==="stl-mat"&&(g.material.diffuseColor=m)}if(c==="stl"&&e.wireframe!==void 0)for(let m of f)m.material instanceof We&&(m.material.wireframe=e.wireframe);let d=this.createCellCamera(f,o,i,r,s,a);this.cells.push({meshes:f,camera:d})}createCellCamera(e,t,i,r,s,a){let o=tv(this.getCellBounds(e)),l=new Mi(`cell-cam-${t}`,Math.PI/4,Math.PI/3,o.radius,y1(o.target),this.scene);l.fov=45*Math.PI/180,l.minZ=o.near,l.maxZ=o.far,l.lowerRadiusLimit=o.lowerRadiusLimit,l.upperRadiusLimit=o.upperRadiusLimit,l.wheelPrecision=45,l.viewport=new Go(i,r,s,a),l.layerMask=1<{this.markDirty(),this.notifyCameraZoomChanged()})),this.initialCameras.push({alpha:l.alpha,beta:l.beta,radius:l.radius,target:l.target.clone()}),l}renderFrame(){if(!this.canRender()||!this.dirty||this.contextLost)return;this.dirty=!1;let e=this.engine,t=this.scene;e.clear(t.clearColor,!0,!0);for(let i of this.cells){e.setViewport(i.camera.viewport);let r=i.camera.viewport,s=e.getRenderWidth(),a=e.getRenderHeight();e.enableScissor(r.x*s,r.y*a,r.width*s,r.height*a),t.activeCamera=i.camera,t.render(),e.disableScissor()}}startRenderLoop(){this.rendering||(this.rendering=!0,this.engine.runRenderLoop(()=>this.renderFrame()))}captureSnapshot(){let e=this.engine.getRenderingCanvas();return e?(this.renderFrame(),e.toDataURL("image/png")):null}getEngine(){return this.engine}getScene(){return this.scene}getCellCount(){return this.cells.length}getCanvas(){return this.engine.getRenderingCanvas()}getPrimaryCamera(){var e,t;return(t=(e=this.cells[0])==null?void 0:e.camera)!=null?t:null}setRenderScale(e){let t=Math.max(.25,Math.min(e,2));this.renderScale=t;let i=Rr()?1.5:1;return this.engine.setHardwareScalingLevel(i/t),this.getRenderScale()}getRenderScale(){return Number(this.renderScale.toFixed(2))}getCameraZoomState(){var s;let e=(s=this.cells[0])==null?void 0:s.camera;if(!e)return null;let t=this.getCameraZoomRange(e),i=(t.max-t.current)/(t.max-t.min),r=O$(i);return{value:r,percentage:Math.round(r*100)}}setCameraZoom(e){if(this.cells.length===0)return null;let t=O$(e);for(let i of this.cells){let r=this.getCameraZoomRange(i.camera);i.camera.radius=r.max-t*(r.max-r.min)}return this.markDirty(),this.startRenderLoop(),this.notifyCameraZoomChanged(),this.getCameraZoomState()}observeCameraZoom(e){return this.cameraZoomObservers.add(e),e(this.getCameraZoomState()),()=>{this.cameraZoomObservers.delete(e)}}resetView(){for(let e=0;e{var A,R,M;if(this.sliceActive||this.isDisassemblyActive())return;let S=E.mesh&&this.rootMesh?wE(this.rootMesh,E.mesh,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata):null,T={mesh:S,pickedPoint:E.pickedPoint,screenX:E.screenX,screenY:E.screenY,modifiers:E.modifiers};if(this.lastPointerClient={x:E.screenX,y:E.screenY,altKey:((A=E.modifiers)==null?void 0:A.altKey)===!0},this._lastPickResult=T,this.measurementActive){if(((R=E.modifiers)==null?void 0:R.altKey)===!0){if(!E.pickedPoint)return;this.setMeasurementSnapKind("free"),this.addMeasurementPoint(go(E.pickedPoint));return}if(!this.measurementTargetNode){S&&this.setMeasurementTargetNode(S);return}let I=this.getMeasurementTargetPickPoint(E.mesh,E.pickedPoint);if(!I){this.setMeasurementSnapKind(null);return}this.addMeasurementPoint(this.resolveMeasurementPickPoint(I,!1));return}this.focusSelectionEnabled&&(S?this.setFocusedNode(S):(M=this.cleanupPicking)==null||M.clearHighlight()),this._onPickCallbacks.forEach(I=>I(T))},()=>!this.focusSelectionEnabled&&!this.measurementActive&&!this.sliceActive,E=>this.resolvePickHighlightMeshes(E)),this.ensureDisassemblyController(),this.createModelSummary(this.rootMesh)}applyConfig(e){e.camera&&this.applyCameraConfig(e.camera),e.lights&&this.applyLightConfig(e.lights),e.scene&&this.applySceneConfig(e.scene),e.stl&&this.loadedExt==="stl"&&(e.stl.color&&this.setSTLColor(e.stl.color),e.stl.wireframe!==void 0&&this.setWireframe(e.stl.wireframe))}applyCameraConfig(e){var i;let t=this.engine.getRenderingCanvas();if(t){if(e.mode==="orthographic"){let r=this.camera.radius,s=t.clientWidth/t.clientHeight,a=(i=e.zoom)!=null?i:1,o=r/a;this.camera.mode=1,this.camera.orthoLeft=-o*s,this.camera.orthoRight=o*s,this.camera.orthoTop=o,this.camera.orthoBottom=-o}else this.camera.mode=0,e.fov&&(this.camera.fov=e.fov*Math.PI/180);if(e.position){let[r,s,a]=e.position;this.camera.setPosition(new b(r,s,a))}if(e.lookAt){let[r,s,a]=e.lookAt;this.camera.setTarget(new b(r,s,a))}e.near!==void 0&&(this.camera.minZ=e.near),e.far!==void 0&&(this.camera.maxZ=e.far),this.notifyCameraZoomChanged()}}applyLightConfig(e){var i;for(let r of this.configLights)r.dispose();this.configLights=[],(i=this.shadowGenerator)==null||i.dispose(),this.shadowGenerator=null;let t=this.scene.getLightByName("default-light");t&&t.dispose();for(let r of e){let s=this.createLight(r);s&&this.configLights.push(s)}}createLight(e){var r,s;let t=e.color?he.FromHexString(e.color):he.White(),i=(r=e.intensity)!=null?r:1;switch(e.type){case"hemisphere":{let a=e.groundColor?he.FromHexString(e.groundColor):new he(.2,.2,.2),o=new Fa("hemi",new b(0,1,0),this.scene);return o.diffuse=t,o.groundColor=a,o.intensity=i,o}case"directional":{let a=e.position?new b(...e.position).normalize():new b(-1,-2,-1).normalize(),o=new ca("dir",a,this.scene);return o.diffuse=t,o.intensity=i,e.castShadow&&this.rootMesh&&this.setupShadow(o),o}case"point":{let a=e.position?new b(...e.position):new b(0,5,0),o=new Sd("point",a,this.scene);return o.diffuse=t,o.intensity=i,e.decay!==void 0&&(o.decay=e.decay),o}case"spot":{let a=e.position?new b(...e.position):new b(0,5,0),l=(e.target?new b(...e.target):b.Zero()).subtract(a).normalize(),c=e.angle?e.angle*Math.PI/180:Math.PI/4,f=(s=e.penumbra)!=null?s:.5,d=new Zr("spot",a,l,c,f,this.scene);return d.diffuse=t,d.intensity=i,e.decay!==void 0&&(d.decay=e.decay),e.castShadow&&this.rootMesh&&this.setupShadow(d),d}case"attachToCam":{let a=new Sd("cam-light",b.Zero(),this.scene);return a.diffuse=t,a.intensity=i,a.parent=this.camera,a}default:return null}}setupShadow(e){if(!this.rootMesh)return;if(!fTe(e)){console.warn("[AI3D] Light type does not support shadows:",e.name);return}let t=new zi(1024,e);t.useBlurExponentialShadowMap=!0,t.blurKernel=32;for(let i of this.getRenderableMeshes(this.rootMesh))t.addShadowCaster(i),i.receiveShadows=!0;this.shadowGenerator=t}applySceneConfig(e){var t,i;if(e.background!==void 0){let r=ht.FromColor3(he.FromHexString(e.background),e.transparent?0:1);this.scene.clearColor=r}e.autoRotate===!0?this.autoRotateBehavior?this.autoRotateBehavior.idleRotationSpeed=(i=e.autoRotateSpeed)!=null?i:.5:(this.autoRotateBehavior=new qp,this.autoRotateBehavior.idleRotationSpeed=(t=e.autoRotateSpeed)!=null?t:.5,this.autoRotateBehavior.idleRotationWaitTime=1e3,this.autoRotateBehavior.idleRotationSpinupTime=500,this.sliceDragState?this.sliceAutoRotatePaused=!0:this.camera.addBehavior(this.autoRotateBehavior)):e.autoRotate===!1&&this.autoRotateBehavior&&(this.sliceAutoRotatePaused||this.camera.removeBehavior(this.autoRotateBehavior),this.autoRotateBehavior=null,this.sliceAutoRotatePaused=!1),e.groundShadow&&this.rootMesh&&this.createGround(),e.grid&&this.createGrid(),e.axis&&this.createAxis()}createGround(){if(!this.rootMesh||this.groundMesh)return;let e=this.getRenderableBounds(this.rootMesh),t=Ui(e),i=Math.max(t.x,t.z)*3,r=e.min.y;this.groundMesh=Pn.CreateGround("ground",{width:i,height:i},this.scene),this.groundMesh.position.y=r;let s=new We("ground-mat",this.scene);s.diffuseColor=new he(.15,.15,.15),s.specularColor=he.Black(),s.alpha=.5,this.groundMesh.material=s,this.groundMesh.receiveShadows=!0}createGrid(){if(!this.rootMesh||this.gridMesh)return;let e=this.getRenderableBounds(this.rootMesh),t=Ui(e),i=Math.max(t.x,t.z)*2,r=e.min.y-.01;this.gridMesh=Pn.CreateGround("grid",{width:i,height:i,subdivisions:20},this.scene),this.gridMesh.position.y=r;let s=new We("grid-mat",this.scene);s.wireframe=!0,s.diffuseColor=new he(.3,.3,.3),s.emissiveColor=new he(.1,.1,.1),this.gridMesh.material=s}createAxis(){if(!this.rootMesh||this.axisMeshes.length>0)return;let e=this.getRenderableBounds(this.rootMesh),t=aV(e)*1.5,i=go(e.min),r=Rs(e)*.01,s=[["x",he.Red(),new b(t,0,0)],["y",he.Green(),new b(0,t,0)],["z",he.Blue(),new b(0,0,t)]];for(let[a,o,l]of s){let c=Pn.CreateTube(`axis-${a}`,{path:[i,i.add(l)],radius:r,tessellation:8},this.scene),f=new We(`axis-${a}-mat`,this.scene);f.emissiveColor=o,f.diffuseColor=he.Black(),c.material=f,this.axisMeshes.push(c)}}setSTLColor(e){if(!this.rootMesh)return;let t=he.FromHexString(e);for(let i of this.getRenderableMeshes(this.rootMesh))if(i.material&&i.material.name==="stl-mat"){let r=i.material;r.diffuseColor=t,r.emissiveColor=t.scale(.1)}}setWireframe(e){this.rootMesh&&(b1(this.rootMesh)||(this.wireframeEnabled=e,this.scene.forceWireframe=e))}toggleWireframe(){return this.setWireframe(!this.wireframeEnabled),this.wireframeEnabled}hasAnimations(){return this.scene.animationGroups.length>0}toggleAnimation(){let e=this.scene.animationGroups;if(e.length===0)return!1;this.animPlaying=!this.animPlaying;for(let t of e)this.animPlaying?t.play(!0):t.pause();return this.animPlaying}toggleMeasurement(){var t;if(this.measurementActive)return this.deactivateMeasurementMode(),!1;this.isDisassemblyActive()&&this.disableDisassemblyAndReset(),this.deactivateSliceMode();let e=this.getCurrentMeasurementTargetNode();return(t=this.cleanupPicking)==null||t.clearHighlight(),this.clearFocusedMesh(),this.focusSelectionEnabled&&(this.focusSelectionEnabled=!1),this.measurementActive=!0,this.setMeasurementTargetNode(e,!1),Wf(this.engine.getRenderingCanvas(),this.measurementActive),this.notifyMeasurementsChanged(),this.measurementActive}isMeasurementActive(){return this.measurementActive}clearMeasurements(){this.disposeMeasurementOverlays(!1)}cancelMeasurement(){let e=!!this.pendingPoint;this.cancelPendingMeasurement(),e&&this.notifyMeasurementsChanged()}deactivateMeasurementMode(){return this.measurementActive?(this.measurementActive=!1,Wf(this.engine.getRenderingCanvas(),!1),this.setMeasurementTargetNode(null,!1),this.cancelPendingMeasurement(),this.notifyMeasurementsChanged(),!0):!1}disposeMeasurementOverlays(e){e&&(this.measurementActive=!1,Wf(this.engine.getRenderingCanvas(),!1),this.setMeasurementTargetNode(null,!1)),this.cancelPendingMeasurement(!1);for(let t of this.measurementSegments)t.line.dispose(!1,!0),t.label.dispose(!1,!0);this.measurementSegments=[];for(let t of this.measurementMarkers)t.dispose(!1,!0);this.measurementMarkers=[],this.measurementMarkerPoints=[],this.setMeasurementSnapKind(null,!1),this.notifyMeasurementsChanged()}setMeasurementScale(e){this.measurementScale=Ms(e),this.invalidateMeasurementSnapInputCache(),this.applyMeasurementModelScale(),this.sliceActive&&(this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping()),this.updateMeasurementOverlayPositions(),this.updateMeasurementLabels(),this.notifyMeasurementsChanged()}getMeasurementScale(){return{...this.measurementScale}}setMeasurementUnit(e){this.measurementUnit=rv(e),this.updateMeasurementLabels(),this.notifyMeasurementsChanged()}getMeasurementUnit(){return this.measurementUnit}getMeasurementBounds(){var t;if(!this.rootMesh)return null;let e=(t=this.measurementBaseBounds)!=null?t:this.getRenderableBounds(this.rootMesh);return e?{x:e.max.x-e.min.x,y:e.max.y-e.min.y,z:e.max.z-e.min.z}:null}getMeasurementRecords(){return this.createMeasurementRecords()}getMeasurementState(){return fx({active:this.measurementActive,pending:!!this.pendingPoint,records:this.createMeasurementRecords(),unit:this.measurementUnit,scale:this.getMeasurementScale(),bounds:this.getMeasurementBounds(),targetLocked:!!this.measurementTargetNode,targetName:this.getMeasurementTargetName(),targetScope:this.measurementTargetNode===this.rootMesh?"model":"part",snapKind:this.measurementSnapKind})}exportMeasurements(){return hx(this.createMeasurementRecords())}observeMeasurements(e){return this.measurementObservers.add(e),e(),()=>{this.measurementObservers.delete(e)}}updateMeasurementLabels(){var t;if(this.measurementSegments.length===0)return;let e=this.getMeasurementMarkerSize()*3.2;for(let i of this.measurementSegments){this.updateMeasurementLineGeometry(i);let r=Wm(this.createMeasurementReading(i.start,i.end));i.label.dispose(!1,!0);let s=this.createBabylonMeasurementDraftingLayout(i.start,i.end),a=(t=s==null?void 0:s.labelPosition)!=null?t:b.Center(this.toMeasurementDisplayPoint(i.start),this.toMeasurementDisplayPoint(i.end));i.label=this.createMeasurementLabelMesh(r,a,e)}}captureMeasurementBaseState(e,t){this.measurementBaseRootScaling=e.scaling.clone(),this.measurementBaseBounds=t?Za(t.min,t.max):null,this.measurementScale={x:1,y:1,z:1}}resetMeasurementCalibrationState(){this.measurementScale={x:1,y:1,z:1},this.measurementBaseRootScaling=new b(1,1,1),this.measurementBaseBounds=null,this.measurementMarkerPoints=[],this.invalidateMeasurementSnapInputCache()}applyMeasurementModelScale(){if(!this.rootMesh)return;let e=Ms(this.measurementScale);this.rootMesh.scaling=new b(this.measurementBaseRootScaling.x*e.x,this.measurementBaseRootScaling.y*e.y,this.measurementBaseRootScaling.z*e.z),this.rootMesh.computeWorldMatrix(!0);for(let t of this.loadedMeshes)t.computeWorldMatrix(!0);this.invalidateMeshCache(),this.rebuildScaledSceneHelpers(),this.refitCameraToModel(),this.startRenderLoop()}rebuildScaledSceneHelpers(){var s,a,o;let e=!!this.bboxMesh,t=!!this.groundMesh,i=!!this.gridMesh,r=this.axisMeshes.length>0;(s=this.bboxMesh)==null||s.dispose(),this.bboxMesh=null,(a=this.groundMesh)==null||a.dispose(),this.groundMesh=null,(o=this.gridMesh)==null||o.dispose(),this.gridMesh=null;for(let l of this.axisMeshes)l.dispose();if(this.axisMeshes=[],e&&this.rootMesh){let l=this.getRenderableBounds(this.rootMesh),c=go(mr(l)),f=go(Ui(l));this.bboxMesh=Pn.CreateBox("bbox",{width:f.x,height:f.y,depth:f.z},this.scene),this.bboxMesh.position=c;let d=new We("bbox-mat",this.scene);d.wireframe=!0,d.emissiveColor=new he(1,1,0),d.disableLighting=!0,d.alpha=.6,this.bboxMesh.material=d}t&&this.createGround(),i&&this.createGrid(),r&&this.createAxis()}refitCameraToModel(){if(!this.rootMesh)return;let e=tv(this.getRenderableBounds(this.rootMesh));this.camera.target=go(e.target),this.camera.radius=e.radius,this.camera.lowerRadiusLimit=e.lowerRadiusLimit,this.camera.upperRadiusLimit=e.upperRadiusLimit,this.camera.minZ=e.near,this.camera.maxZ=e.far,this.initialCamera={alpha:this.camera.alpha,beta:this.camera.beta,radius:this.camera.radius,target:this.camera.target.clone()},this.notifyCameraZoomChanged()}getMeasurementPivot(){var e,t;return(t=(e=this.rootMesh)==null?void 0:e.getAbsolutePosition().clone())!=null?t:b.Zero()}toMeasurementDisplayPoint(e){let t=rx(e,this.getMeasurementPivot(),this.measurementScale);return new b(t.x,t.y,t.z)}toMeasurementBasePoint(e){let t=nx(e,this.getMeasurementPivot(),this.measurementScale);return new b(t.x,t.y,t.z)}updateMeasurementOverlayPositions(){for(let e=0;e{this.cameraZoomObservers.delete(e)}}getPerformanceSnapshot(){return{backend:"babylon",renderScale:Number((1/this.engine.getHardwareScalingLevel()).toFixed(2)),quality:this.currentQuality,meshCount:this.rootMesh?this.getRenderableMeshes(this.rootMesh).length:0}}toggleBoundingBox(){var e;if(this.bboxEnabled=!this.bboxEnabled,this.bboxEnabled){if(!this.rootMesh)return this.bboxEnabled;this.bboxMesh&&this.bboxMesh.dispose();let t=this.getRenderableBounds(this.rootMesh),i=go(mr(t)),r=go(Ui(t));this.bboxMesh=Pn.CreateBox("bbox",{width:r.x,height:r.y,depth:r.z},this.scene),this.bboxMesh.position=i;let s=new We("bbox-mat",this.scene);s.wireframe=!0,s.emissiveColor=new he(1,1,0),s.disableLighting=!0,s.alpha=.6,this.bboxMesh.material=s}else(e=this.bboxMesh)==null||e.dispose(),this.bboxMesh=null;return this.bboxEnabled}toggleSlice(){var e;return this.sliceActive?(this.deactivateSliceMode(),!1):(this.disableDisassemblyAndReset(),this.deactivateMeasurementMode(),this.focusSelectionEnabled&&(this.focusSelectionEnabled=!1,this.clearFocusedMesh(),(e=this.cleanupPicking)==null||e.clearHighlight()),this.alignSlicePlaneToWorld(),this.sliceInteractionMode=Xf,this.sliceActive=!0,this.syncSliceClipping(),this.notifySliceChanged(),this.sliceActive)}isSliceActive(){return this.sliceActive}setSlicePlane(e,t=this.sliceOffset){let i=wo(e);return this.sliceNormal.set(i.x,i.y,i.z),this.rebuildSlicePlaneAxes(),this.sliceOffset=Ia(t),this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceOffset(e){return this.sliceOffset=Ia(e),this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceRotation(e){var a,o;let t=this.rootMesh?this.getRenderableBounds(this.rootMesh):null,i=this.getSliceRange(),r=(o=(a=this.sliceCenter)==null?void 0:a.clone())!=null?o:i?new b(i.point.x,i.point.y,i.point.z):null,s=gx(e);return this.slicePlaneX.set(s.x.x,s.x.y,s.x.z),this.slicePlaneY.set(s.y.x,s.y.y,s.y.z),this.sliceNormal.set(s.z.x,s.z.y,s.z.z),r?(this.sliceCenter=r,this.sliceOffset=Xm(t,s.z,ct(r))):this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceInteractionMode(e){let t=ov(e);return t===this.sliceInteractionMode?this.getSliceState():(this.endSliceDrag(null,!0),this.sliceInteractionMode=t,this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState())}resetSlicePlane(){return this.alignSlicePlaneToWorld(),this.sliceOffset=Il,this.setSliceCenterFromOffset(this.sliceOffset),this.syncSliceClipping(),this.notifySliceChanged(),this.getSliceState()}setSliceAxis(e){let t=av(e);return this.setSlicePlane({x:t==="x"?1:0,y:t==="y"?1:0,z:t==="z"?1:0})}setSlicePosition(e){return this.setSliceOffset(e)}setSliceThickness(e){return this.sliceThickness=lv(e),this.notifySliceChanged(),this.getSliceState()}getSliceState(){let e=px(this.sliceActive,ct(this.sliceNormal),this.sliceOffset,this.rootMesh?this.getRenderableBounds(this.rootMesh):null,!!this.sliceDragState,this.sliceThickness,this.sliceInteractionMode,ct(this.sliceReferenceNormal)),t=this.getSliceRange(),i=_x({x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)});return t?{...e,rotationDegrees:i,offset:t.offset,position:t.offset,point:{...t.point}}:{...e,rotationDegrees:i}}observeSlice(e){return this.sliceObservers.add(e),e(),()=>{this.sliceObservers.delete(e)}}toggleFocusSelection(){let e=!this.focusSelectionEnabled;return e&&this.isDisassemblyActive()&&this.disableDisassemblyAndReset(),e&&(this.deactivateMeasurementMode(),this.deactivateSliceMode()),this.focusSelectionEnabled=e,this.focusSelectionEnabled?this._lastPickResult.mesh&&this.setFocusedNode(this._lastPickResult.mesh):this.clearFocusedMesh(),this.focusSelectionEnabled}isFocusSelectionEnabled(){return this.focusSelectionEnabled}toggleDisassembly(){let e=this.ensureDisassemblyController();if(!e)return!1;let t=!e.isEnabled();t&&(this.focusSelectionEnabled=!1,this.clearFocusedMesh(),this.deactivateMeasurementMode(),this.deactivateSliceMode());let i=e.setEnabled(t);return i||e.reset(),i}resetDisassembly(){var e;(e=this.disassembly)==null||e.reset()}disableDisassemblyAndReset(){var e;this.isDisassemblyActive()&&((e=this.disassembly)==null||e.setEnabled(!1),this.resetDisassembly())}isDisassemblyEnabled(){return this.isDisassemblyActive()}setExplode(e,t){this.rootMesh&&RQ(this.rootMesh,e,t,this.loadedMeshes)}resetExplode(){this.rootMesh&&jF(this.rootMesh,this.loadedMeshes)}resetView(){this.rootMesh&&jF(this.rootMesh,this.loadedMeshes),this.resetDisassembly(),this.clearFocusedMesh(),this.camera.mode=0,this.camera.alpha=this.initialCamera.alpha,this.camera.beta=this.initialCamera.beta,this.camera.radius=this.initialCamera.radius,this.camera.target=this.initialCamera.target.clone(),this.startRenderLoop(),this.notifyCameraZoomChanged()}exportModelInfo(e){if(!this.rootMesh)return"";let t=this.getRenderableMeshes(this.rootMesh),i=b1(this.rootMesh),r=this.createModelSummary(this.rootMesh),s=e&&Qs(e)||r.rootName;return jA({title:s,format:this.loadedExt.toUpperCase(),summary:r,meshBreakdown:t.map(a=>SQ(a,{isSplat:i})),materialNames:t.map(a=>{var o;return(o=a.material)==null?void 0:o.name})})}getModelEvidence(){if(!this.rootMesh)return null;let e=this.getRenderableMeshes(this.rootMesh),t=AQ(e,this.loadedTransformNodes,this.gltfComponentMetadata);return JA({summary:this.createModelSummary(this.rootMesh),renderableMeshes:e,groupedPartCandidates:t,createMeshPart:i=>XF(i,this.gltfComponentMetadata),getMeshMaterialNames:i=>{var r;return[(r=i.material)==null?void 0:r.name]},resourceWarnings:this.resourceWarnings})}getSelectedPartInfo(){var t;if(!this.rootMesh)return null;let e=(t=this.focusedNode)!=null?t:M$(this._lastPickResult.mesh)?this._lastPickResult.mesh:null;return!e||hf(e)?null:YF(e,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata)}exportSelectedPartInfo(){let e=this.getSelectedPartInfo();return e?ZA(e):""}getPickWorldPoint(e){return e.pickedPoint&&typeof e.pickedPoint=="object"?ct(e.pickedPoint):this.rootMesh&&M$(e.mesh)?YF(e.mesh,this.getRenderableMeshes(this.rootMesh),this.gltfComponentMetadata).center:null}focusWorldPoint(e){let t=new b(e.x,e.y,e.z),i=this.camera.target.clone(),r=performance.now();this.focusWorldPointFrame&&(window.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0);let s=a=>{let o=Math.min(1,Math.max(0,(a-r)/JSe)),l=o<.5?4*o*o*o:1-Math.pow(-2*o+2,3)/2;if(this.camera.target=b.Lerp(i,t,l),o<1&&!this.scene.isDisposed){this.focusWorldPointFrame=window.requestAnimationFrame(s);return}this.focusWorldPointFrame=0};this.focusWorldPointFrame=window.requestAnimationFrame(s)}getAnnotationCameraStateKey(){return $A([{value:this.camera.alpha,digits:3},{value:this.camera.beta,digits:3},{value:this.camera.radius,digits:3},{value:this.camera.target.x,digits:2},{value:this.camera.target.y,digits:2},{value:this.camera.target.z,digits:2}])}projectAnnotationWorldPoint(e,t){let i=this.engine.getRenderingCanvas();if(!i||this.scene.isDisposed)return!1;let r=this.engine.getRenderWidth(),s=this.engine.getRenderHeight();if(r===0||s===0||i.clientWidth===0||i.clientHeight===0)return!1;let a=Ga.annotationWorldPoint;return a.set(e.x,e.y,e.z),b.ProjectToRef(a,Ga.annotationIdentity,this.scene.getTransformMatrix(),this.camera.viewport.toGlobal(r,s),Ga.annotationProjection),mV(Ga.annotationProjection,r,s,i,t)}isAnnotationWorldPointOccluded(e){if(this.scene.isDisposed)return!1;let t=kf(ct(this.camera.position),e);if(!t)return!1;let i=Ga.annotationDirection,r=Ga.annotationRay;i.set(t.direction.x,t.direction.y,t.direction.z),r.origin=this.camera.position,r.direction=i,r.length=t.distance;let s=this.scene.pickWithRay(r);return!!(s!=null&&s.hit)&&Gf(s.distance,t.distance,t.epsilon)}getAnnotationProvider(){let e=this.engine.getRenderingCanvas();if(!e)throw new Error("Preview canvas is unavailable");return QA({canvas:e,observeRender:t=>{let i=this.scene.onAfterRenderCameraObservable.add(r=>{r===this.camera&&t()});return{remove:()=>this.scene.onAfterRenderCameraObservable.remove(i)}},getCameraStateKey:()=>this.getAnnotationCameraStateKey(),projectWorldPoint:(t,i)=>this.projectAnnotationWorldPoint(t,i),isWorldPointOccluded:t=>this.isAnnotationWorldPointOccluded(t)})}getCanvas(){return this.engine.getRenderingCanvas()}getLastPickResult(){return this._lastPickResult}onPick(e){return this._onPickCallbacks.push(e),()=>{this._onPickCallbacks=this._onPickCallbacks.filter(t=>t!==e)}}setRenderQuality(e,t=this.renderScale){this.currentQuality=e,this.renderScale=Math.max(.25,Math.min(t,2));let i={low:2,medium:1.33,high:1},r=Rr()?1.5:1,s=i[e]*r/this.renderScale;if(this.engine.setHardwareScalingLevel(s),this.shadowGenerator){let a={low:0,medium:16,high:32};this.shadowGenerator.blurKernel=a[e],e==="low"?(this.shadowGenerator.useBlurExponentialShadowMap=!1,this.shadowGenerator.useExponentialShadowMap=!0):(this.shadowGenerator.useBlurExponentialShadowMap=!0,this.shadowGenerator.useExponentialShadowMap=!1)}}destroy(){var t,i,r,s,a,o,l,c;this.engine.stopRenderLoop(),this.focusWorldPointFrame&&(window.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0),this._onPickCallbacks=[],this.cameraZoomObservers.clear(),this.sliceObservers.clear(),(t=this.cleanupPicking)==null||t.call(this),this.cleanupPicking=null,(i=this.gizmo)==null||i.dispose(),this.gizmo=null,(r=this.disassembly)==null||r.dispose(),this.disassembly=null,this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.disposeMeasurementOverlays(!0),this.measurementObservers.clear(),this.clearFocusedMesh(),this.originalMeshVisibility.clear(),(s=this.bboxMesh)==null||s.dispose(),this.bboxMesh=null,this.camera.detachControl();let e=this.engine.getRenderingCanvas();e==null||e.classList.remove("ai3d-slice-active","ai3d-slice-dragging","ai3d-slice-rotate"),e==null||e.removeEventListener("wheel",this.preventCanvasWheelScroll),e==null||e.removeEventListener("pointerdown",this.handlePointerDown,!0),e==null||e.removeEventListener("pointerup",this.handlePointerUp,!0),e==null||e.removeEventListener("pointermove",this.handlePointerMove,!0),e==null||e.removeEventListener("pointercancel",this.handlePointerCancel,!0),e==null||e.removeEventListener("lostpointercapture",this.handlePointerCaptureLost,!0),e==null||e.removeEventListener("webglcontextlost",this.handleContextLost),e==null||e.removeEventListener("webglcontextrestored",this.handleContextRestored),window.removeEventListener("keydown",this.handleMeasurementModifierKey),window.removeEventListener("keyup",this.handleMeasurementModifierKey),window.removeEventListener("blur",this.handleMeasurementModifierBlur),(a=this.viewportObserver)==null||a.disconnect(),this.viewportObserver=null,this.resizeObs.disconnect(),this.sliceMoveFrame&&(window.cancelAnimationFrame(this.sliceMoveFrame),this.sliceMoveFrame=0),this.pendingSliceMove=null,this.invalidateMeshCache(),this.rootMesh=null,this.loadedMeshes=[],this.loadedTransformNodes=[],this.autoRotateBehavior&&(this.camera.removeBehavior(this.autoRotateBehavior),this.autoRotateBehavior=null);for(let f of this.configLights)f.dispose();this.configLights=[],(o=this.shadowGenerator)==null||o.dispose(),this.shadowGenerator=null,(l=this.groundMesh)==null||l.dispose(),this.groundMesh=null,(c=this.gridMesh)==null||c.dispose(),this.gridMesh=null;for(let f of this.axisMeshes)f.dispose();this.axisMeshes=[],this.scene.dispose(),this.engine.dispose()}startRenderLoop(){this.rendering||!this.viewportVisible||this.contextLost||(this.rendering=!0,this.engine.runRenderLoop(()=>{if(!this.canRender()||!this.viewportVisible||this.contextLost){this.engine.stopRenderLoop(),this.rendering=!1;return}this.scene.render(),this.gizmo&&this.gizmoEnabled&&(this.gizmo.syncWith(this.camera),this.gizmo.render())}))}getRenderableMeshes(e){if(this.cachedRenderableMeshes&&this.cachedRenderableRoot===e)return this.cachedRenderableMeshes;let t=Eh(e,this.loadedMeshes);return this.cachedRenderableMeshes=t,this.cachedRenderableRoot=e,t}getRenderableBounds(e){return hy(e,this.loadedMeshes)}getSliceRange(){let e=Du(this.rootMesh?this.getRenderableBounds(this.rootMesh):null,{normal:ct(this.sliceNormal),offset:this.sliceOffset});if(!e||!this.sliceCenter)return e;let t=b.Dot(this.sliceCenter,this.sliceNormal),i=Ia((t-e.min)/e.span);return this.sliceOffset=i,{...e,offset:i,distance:t,point:ct(this.sliceCenter)}}setSliceCenterFromOffset(e){if(!this.rootMesh)return;let t=Du(this.getRenderableBounds(this.rootMesh),{normal:ct(this.sliceNormal),offset:e});t&&(this.sliceCenter=new b(t.point.x,t.point.y,t.point.z))}alignSlicePlaneToWorld(){this.sliceNormal.set(Dr.x,Dr.y,Dr.z),this.rebuildSlicePlaneAxes(new b(1,0,0)),this.sliceReferenceNormal.copyFrom(this.sliceNormal),this.sliceCenter=null,this.setSliceCenterFromOffset(this.sliceOffset)}rebuildSlicePlaneAxes(e=this.slicePlaneX){let t=this.sliceNormal.clone().normalize(),i=e.clone().subtract(t.scale(b.Dot(e,t)));i.lengthSquared()<=1e-6&&(i.copyFrom(Math.abs(t.y)<.92?new b(0,1,0):new b(1,0,0)),i.subtractInPlace(t.scale(b.Dot(i,t)))),i.normalize(),this.slicePlaneX.copyFrom(i),b.CrossToRef(t,i,this.slicePlaneY),this.slicePlaneY.normalize()}deactivateSliceMode(){return!this.sliceActive&&!this.sliceDragState?!1:(this.endSliceDrag(null,!0),this.sliceActive=!1,this.syncSliceClipping(),this.notifySliceChanged(),!0)}beginSliceDrag(e){if(!this.rootMesh||!this.sliceActive)return!1;let t=this.getSlicePointerTarget(e);if(!t)return!1;let i=this.engine.getRenderingCanvas();if(!i)return!1;let r=i.getBoundingClientRect(),s=t.mode;this.sliceInteractionMode=s;let a={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,mode:s,moved:!1};if(s==="rotate"){let o=this.getSliceRange();if(!o)return!1;let l=this.getSlicePointerPolar(e,t.axis);if(!l)return!1;this.sliceDragState={...a,mode:s,axis:t.axis,startNormal:ct(this.sliceNormal),anchorPoint:{...o.point},rotationAxis:ct(t.axis==="x"?this.slicePlaneX:t.axis==="y"?this.slicePlaneY:this.sliceNormal),startPlaneX:ct(this.slicePlaneX),startPlaneY:ct(this.slicePlaneY),screenTangent:t.screenTangent,radiansPerPixel:t.radiansPerPixel,rotationRadians:0,startPointerAngle:l.angle,currentPointerAngle:l.angle,snapMode:Ym(l.radiusRatio),useScreenRotation:Ex(l.rayPlaneAlignment),labelPoint:t.labelPoint}}else this.sliceDragState={...a,mode:s,startOffset:this.sliceOffset,screenAxis:this.getSliceScreenAxis(),pixelsToOffset:1/Math.max(Math.min(r.width,r.height)*.72,1)};this.syncSliceClipping(),i.classList.add("ai3d-slice-dragging"),this.stabilizeCameraForSliceDrag(),this.camera.detachControl();try{i.setPointerCapture(e.pointerId)}catch(o){}return e.preventDefault(),e.stopImmediatePropagation(),this.notifySliceChanged(),this.startRenderLoop(),!0}getSlicePointerPolar(e,t,i,r){let s=this.engine.getRenderingCanvas(),a=this.getSliceRange();if(!s||!this.rootMesh||!a)return null;let o=s.getBoundingClientRect();if(o.width<=0||o.height<=0)return null;let l=this.scene.createPickingRay(e.clientX-o.left,e.clientY-o.top,Q.Identity(),this.camera),c=r!=null?r:a.point,f=new b(c.x,c.y,c.z),d=i?{x:new b(i.x.x,i.x.y,i.x.z),y:new b(i.y.x,i.y.y,i.y.z),z:new b(i.z.x,i.z.y,i.z.z)}:{x:this.slicePlaneX,y:this.slicePlaneY,z:this.sliceNormal},u=(t==="x"?d.x:t==="y"?d.y:d.z).clone().normalize(),h=(t==="x"?d.y:t==="y"?d.z:d.x).clone().normalize(),m=(t==="x"?d.z:t==="y"?d.x:d.y).clone().normalize(),g=b.Dot(u,l.direction);if(Math.abs(g)<=1e-6)return null;let p=b.Dot(f.subtract(l.origin),u)/g,v=l.origin.add(l.direction.scale(p)).subtract(f),E=this.getRenderableBounds(this.rootMesh),S=Math.max(Rs(E)*.62,a.span*.16,Number.EPSILON);return{angle:Math.atan2(b.Dot(v,m),b.Dot(v,h)),radiusRatio:v.length()/S,rayPlaneAlignment:Math.abs(g)}}getSlicePointerTarget(e){if(e.altKey||!this.rootMesh)return null;let t=this.engine.getRenderingCanvas(),i=this.getSliceRange();if(!t||!i)return null;let r=this.getRenderableBounds(this.rootMesh),s=t.getBoundingClientRect(),a=this.engine.getRenderWidth(),o=this.engine.getRenderHeight();if(s.width<=0||s.height<=0||a<=0||o<=0)return null;let l=this.camera.viewport.toGlobal(a,o),c=p=>{let _=b.Project(new b(p.x,p.y,p.z),Q.Identity(),this.scene.getTransformMatrix(),l);return{x:s.left+_.x/a*s.width,y:s.top+_.y/o*s.height}},f={x:e.clientX,y:e.clientY},d=e.pointerType==="touch"?28:14,u=c(i.point);if(Math.hypot(f.x-u.x,f.y-u.y)<=d*1.35)return{mode:"move"};let h=Km(r,i,64,{x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)});if(h.moveGuide.some(([p,_])=>{let v=c(p),E=c(_);return b$(f,v,E)<=d}))return{mode:"move"};let m=null,g=Number.POSITIVE_INFINITY;for(let p of["x","y","z"]){let _=h.rotationRings[p].map(([E,S])=>[c(E),c(S)]),v=_.reduce((E,[S,T])=>E+Math.hypot(T.x-S.x,T.y-S.y),0);for(let[E,S]of _){let T=b$(f,E,S);if(T>d||T>=g)continue;let A=Math.hypot(S.x-E.x,S.y-E.y);A<=Number.EPSILON||(g=T,m={mode:"rotate",axis:p,screenTangent:{x:(S.x-E.x)/A,y:(S.y-E.y)/A},radiansPerPixel:Math.PI*2/Math.max(v,80),labelPoint:{...i.point}})}}return m}updateSliceDrag(e){let t=this.sliceDragState;return!t||t.pointerId!==e.pointerId?!1:(e.preventDefault(),e.stopImmediatePropagation(),this.pendingSliceMove={pointerId:e.pointerId,clientX:e.clientX,clientY:e.clientY},this.sliceMoveFrame||(this.sliceMoveFrame=window.requestAnimationFrame(()=>{this.sliceMoveFrame=0,this.flushSliceDragUpdate()})),!0)}flushSliceDragUpdate(){this.sliceMoveFrame&&(window.cancelAnimationFrame(this.sliceMoveFrame),this.sliceMoveFrame=0);let e=this.pendingSliceMove;this.pendingSliceMove=null;let t=this.sliceDragState;if(!e||!t||t.pointerId!==e.pointerId)return;let i=e.clientX-t.startX,r=e.clientY-t.startY;if(t.moved=t.moved||Math.hypot(i,r)>2,t.mode==="rotate"){let o=this.getSlicePointerPolar(e,t.axis,{x:t.startPlaneX,y:t.startPlaneY,z:t.startNormal},t.anchorPoint);if(!o)return;let l=(i*t.screenTangent.x+r*t.screenTangent.y)*t.radiansPerPixel,c=cv(t.useScreenRotation?l:o.angle-t.startPointerAngle);t.useScreenRotation||(t.snapMode=Ym(o.radiusRatio,t.snapMode)),t.rotationRadians=vx(c,t.snapMode),t.currentPointerAngle=t.startPointerAngle+t.rotationRadians;let f=Yf(t.startNormal,t.rotationAxis,t.rotationRadians),d=Yf(t.startPlaneX,t.rotationAxis,t.rotationRadians),u=Yf(t.startPlaneY,t.rotationAxis,t.rotationRadians),h=b.DistanceSquared(this.sliceNormal,new b(f.x,f.y,f.z)),m=b.DistanceSquared(this.slicePlaneX,new b(d.x,d.y,d.z))+b.DistanceSquared(this.slicePlaneY,new b(u.x,u.y,u.z));if(h<=1e-6&&m<=1e-6)return;if(h>1e-6){let g=this.rootMesh?this.getRenderableBounds(this.rootMesh):null;this.sliceNormal.set(f.x,f.y,f.z),this.sliceCenter=new b(t.anchorPoint.x,t.anchorPoint.y,t.anchorPoint.z),this.sliceOffset=Xm(g,f,t.anchorPoint)}this.slicePlaneX.set(d.x,d.y,d.z),this.slicePlaneY.set(u.x,u.y,u.z),this.syncSliceClipping(),this.notifySliceChanged();return}let s=i*t.screenAxis.x+r*t.screenAxis.y,a=Ia(t.startOffset+s*t.pixelsToOffset);Math.abs(a-this.sliceOffset)<=5e-4||(this.sliceOffset=a,this.setSliceCenterFromOffset(a),this.syncSliceClipping(),this.notifySliceChanged())}endSliceDrag(e,t=!1){let i=this.sliceDragState;if(!i||e&&i.pointerId!==e.pointerId)return!1;this.flushSliceDragUpdate();let r=this.engine.getRenderingCanvas();if(this.sliceDragState=null,r==null||r.classList.remove("ai3d-slice-dragging"),this.syncSliceClipping(),this.camera.attachControl(r,!0),this.resumeCameraAfterSliceDrag(),e&&r){try{r.releasePointerCapture(e.pointerId)}catch(s){}e.preventDefault(),e.stopImmediatePropagation()}return(!t||i.moved)&&this.notifySliceChanged(),this.startRenderLoop(),!0}stabilizeCameraForSliceDrag(){this.focusWorldPointFrame&&(window.cancelAnimationFrame(this.focusWorldPointFrame),this.focusWorldPointFrame=0),this.camera.inertialAlphaOffset=0,this.camera.inertialBetaOffset=0,this.camera.inertialRadiusOffset=0,this.camera.inertialPanningX=0,this.camera.inertialPanningY=0,this.autoRotateBehavior&&!this.sliceAutoRotatePaused&&(this.camera.removeBehavior(this.autoRotateBehavior),this.sliceAutoRotatePaused=!0)}resumeCameraAfterSliceDrag(){!this.autoRotateBehavior||!this.sliceAutoRotatePaused||(this.camera.addBehavior(this.autoRotateBehavior),this.sliceAutoRotatePaused=!1)}getSliceScreenAxis(){let e=this.getSliceRange();if(!this.rootMesh||!e)return{x:0,y:-1};let t=this.getRenderableBounds(this.rootMesh),i=this.engine.getRenderingCanvas();if(!i)return{x:0,y:-1};let r=Math.max(Rs(t),e.span*.25,Number.EPSILON),s=new b(e.point.x,e.point.y,e.point.z),a=s.add(new b(e.normal.x,e.normal.y,e.normal.z).normalize().scale(r*.35)),o=this.engine.getRenderWidth(),l=this.engine.getRenderHeight();if(o===0||l===0||i.clientWidth===0||i.clientHeight===0)return{x:0,y:-1};let c=this.camera.viewport.toGlobal(o,l),f=b.Project(s,Q.Identity(),this.scene.getTransformMatrix(),c),d=b.Project(a,Q.Identity(),this.scene.getTransformMatrix(),c),u={x:d.x-f.x,y:d.y-f.y},h=Math.hypot(u.x,u.y);return!Number.isFinite(h)||h<=1e-6?{x:0,y:-1}:{x:u.x/h,y:u.y/h}}updateBabylonSlicePlane(e){let t=Tx(e,"babylon");if(!(t!=null&&t.length))return null;let i=t[0];return this.slicePlane?(this.slicePlane.normal.set(i.normal.x,i.normal.y,i.normal.z),this.slicePlane.d=i.constant):this.slicePlane=new Da(i.normal.x,i.normal.y,i.normal.z,i.constant),this.slicePlane}syncSliceClipping(){let e=this.engine.getRenderingCanvas();if(e==null||e.classList.toggle("ai3d-slice-active",this.sliceActive),e==null||e.classList.toggle("ai3d-slice-rotate",this.sliceActive&&this.sliceInteractionMode==="rotate"),!this.rootMesh||!this.sliceActive){this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.slicePlane=null,e==null||e.classList.remove("ai3d-slice-dragging"),e==null||e.classList.remove("ai3d-slice-rotate"),this.startRenderLoop();return}let t=this.getSliceRange(),i=this.updateBabylonSlicePlane(t);if(!i){this.restoreSliceMaterialClipping(),this.disposeSliceOverlay(!1),this.startRenderLoop();return}this.syncSliceOverlay(t);let r=new Set;for(let s of this.getRenderableMeshes(this.rootMesh)){let a=s.material;if(!a)continue;r.add(a.uniqueId);let o=!this.sliceOriginalMaterialClipping.has(a.uniqueId);o&&this.sliceOriginalMaterialClipping.set(a.uniqueId,{material:a,clipPlane:a.clipPlane,clipPlane2:a.clipPlane2}),(o||a.clipPlane!==i)&&(a.clipPlane=i,a.markDirty(!0))}for(let[s,a]of Array.from(this.sliceOriginalMaterialClipping.entries()))r.has(s)||(a.material.clipPlane=a.clipPlane,a.material.clipPlane2=a.clipPlane2,a.material.markDirty(!0),this.sliceOriginalMaterialClipping.delete(s));this.startRenderLoop()}restoreSliceMaterialClipping(){for(let e of this.sliceOriginalMaterialClipping.values())e.material.clipPlane=e.clipPlane,e.material.clipPlane2=e.clipPlane2,e.material.markDirty(!0);this.sliceOriginalMaterialClipping.clear()}syncSliceOverlay(e){var w,G,O,N,B,V;this.disposeSliceOverlay(!1,!0);let t=this.rootMesh?this.getRenderableBounds(this.rootMesh):null;if(!t||!e)return;let i={x:ct(this.slicePlaneX),y:ct(this.slicePlaneY),z:ct(this.sliceNormal)},r=Sx(t,e,.12,i),s=this.createSliceOverlayPlane(r),a=this.sliceInteractionMode==="rotate"?aTe:rTe,o=this.createSliceOverlayLines(r.segments,a),l=this.createSliceOverlayLines(this.createSliceNormalGuide(t,e),nTe),c=((w=this.sliceDragState)==null?void 0:w.mode)==="rotate"?{[this.sliceDragState.axis]:this.sliceDragState.currentPointerAngle}:void 0,f=((G=this.sliceDragState)==null?void 0:G.mode)==="rotate"?{x:this.sliceDragState.startPlaneX,y:this.sliceDragState.startPlaneY,z:this.sliceDragState.startNormal}:i,d=Km(t,e,64,f,c),u=((O=this.sliceDragState)==null?void 0:O.mode)==="rotate"?this.sliceDragState.axis:null,h=((N=this.sliceDragState)==null?void 0:N.mode)==="move",m=(q,K)=>({color:u===q?oTe:K,alpha:u?u===q?.98:0:h?.1:.34,tickAlpha:u?u===q?.82:0:h?.04:.14}),g=m("x",A$),p=m("y",x$),_=m("z",R$),v=this.createSliceOverlayLines(d.rotationRings.x,g.color,g.alpha),E=this.createSliceOverlayLines(d.rotationRings.y,p.color,p.alpha),S=this.createSliceOverlayLines(d.rotationRings.z,_.color,_.alpha),T=this.createSliceOverlayLines(d.rotationTicks.x,g.color,g.tickAlpha),A=this.createSliceOverlayLines(d.rotationTicks.y,p.color,p.tickAlpha),R=this.createSliceOverlayLines(d.rotationTicks.z,_.color,_.tickAlpha),M=this.createSliceOverlayLines(d.moveGuide,lTe,u?.22:.96),I=u==="x"?A$:u==="y"?x$:R$,C=u?this.createSliceOverlayLines(d.rotationArcs[u],I,1):null,L=u?this.createSliceOverlayLines(d.rotationArrowheads[u],I,1):null;if(this.sliceOverlayPlanes.push(s),this.sliceOverlayLines.push(o,l,v,E,S,T,A,R,M),u&&C&&L){this.sliceOverlayLines.push(C,L);let q=this.sliceDragState;if((q==null?void 0:q.mode)==="rotate"){let K=(q.currentPointerAngle*180/Math.PI%360+360)%360,J=d.rotationArcs[u],Y=(V=(B=J[J.length-1])==null?void 0:B[1])!=null?V:q.labelPoint;this.updateSliceRotationLabel(`${u.toUpperCase()}: ${K.toFixed(1)}\xB0`,new b(Y.x,Y.y,Y.z),this.getMeasurementMarkerSize()*2.5)}}else this.disposeSliceRotationLabel()}createSliceOverlayPlane(e){let t=new $("ai3d-slice-plane",this.scene),i=e.corners,r=[i[0].x,i[0].y,i[0].z,i[1].x,i[1].y,i[1].z,i[2].x,i[2].y,i[2].z,i[3].x,i[3].y,i[3].z],s=[0,1,2,0,2,3],a=[];Ie.ComputeNormals(r,s,a);let o=new Ie;o.positions=r,o.indices=s,o.normals=a,o.applyToMesh(t);let l=new We("slice-plane-mat",this.scene),c=this.sliceInteractionMode==="rotate"?sTe:iTe;return l.diffuseColor=c.clone(),l.emissiveColor=c.scale(.75),l.specularColor=new he(0,0,0),l.alpha=cTe,l.backFaceCulling=!1,l.disableLighting=!0,l.zOffset=-2,t.material=l,t.isPickable=!1,t.renderingGroupId=2,t}createSliceOverlayLines(e,t,i=.88){let r=Pn.CreateLineSystem("ai3d-slice-frame",{lines:e.map(([s,a])=>[new b(s.x,s.y,s.z),new b(a.x,a.y,a.z)]),updatable:!1},this.scene);return r.color=t.clone(),r.alpha=i,r.isPickable=!1,r.renderingGroupId=2,r}createSliceNormalGuide(e,t){var o;let i=Math.max(Rs(e),t.span*.25,Number.EPSILON),r=(o=wn(t.normal))!=null?o:Dr,s=t.point,a={x:s.x+r.x*i*.26,y:s.y+r.y*i*.26,z:s.z+r.z*i*.26};return[[s,a]]}disposeSliceOverlay(e=!0,t=!1){for(let i of this.sliceOverlayPlanes)i.dispose(!1,!0);for(let i of this.sliceOverlayLines)i.dispose(!1,!0);for(let i of this.sliceOverlayLabels)i.dispose(!1,!0);this.sliceOverlayPlanes=[],this.sliceOverlayLines=[],this.sliceOverlayLabels=[],t||this.disposeSliceRotationLabel(),e&&this.startRenderLoop()}updateSliceRotationLabel(e,t,i){if(!this.sliceRotationLabel){this.sliceRotationLabel=this.createMeasurementLabelMesh({primary:e,secondary:""},t,i),this.sliceRotationLabelText=e;return}if(this.sliceRotationLabel.position.copyFrom(t),e===this.sliceRotationLabelText)return;let r=this.sliceRotationLabel.material,s=r instanceof We&&r.diffuseTexture instanceof EE?r.diffuseTexture:null;if(!s){this.disposeSliceRotationLabel(),this.updateSliceRotationLabel(e,t,i);return}let a=s.getContext();nv(a,{primary:e,secondary:""},Oo.width,Oo.height),s.update(),this.sliceRotationLabelText=e}disposeSliceRotationLabel(){var e;(e=this.sliceRotationLabel)==null||e.dispose(!1,!0),this.sliceRotationLabel=null,this.sliceRotationLabelText=""}notifySliceChanged(){for(let e of this.sliceObservers)e()}invalidateMeshCache(){this.cachedRenderableMeshes=null,this.cachedRenderableRoot=null}resolvePickHighlightMeshes(e){if(!this.rootMesh)return[e];let t=this.getRenderableMeshes(this.rootMesh),i=wE(this.rootMesh,e,t,this.gltfComponentMetadata),r=t.filter(s=>xg(s,i));return r.length>0?r:[e]}setFocusedNode(e){if(!this.rootMesh)return;let t=e?this.findSelectableNode(e):null;if(!t||hf(t)){this.clearFocusedMesh();return}if(this.focusedNode===t)return;let i=this.getRenderableMeshes(this.rootMesh),r=i.filter(a=>xg(a,t));if(r.length===0){this.clearFocusedMesh();return}let s=new Set(r);for(let a of i){this.originalMeshVisibility.has(a.uniqueId)||this.originalMeshVisibility.set(a.uniqueId,a.visibility);let o=s.has(a);a.visibility=o?1:$Se,a.renderOutline=o,a.outlineColor=new he(.18,.76,1),a.outlineWidth=o?.045:0}this.focusedNode=t}clearFocusedMesh(){if(!this.rootMesh){this.focusedNode=null;return}for(let e of this.getRenderableMeshes(this.rootMesh)){let t=this.originalMeshVisibility.get(e.uniqueId);t!==void 0&&(e.visibility=t),e.renderOutline=!1,e.outlineWidth=0}this.originalMeshVisibility.clear(),this.focusedNode=null,this.applyMeasurementTargetVisual(this.measurementTargetMeshes)}findSelectableNode(e){if(!this.rootMesh)return null;let t=this.getRenderableMeshes(this.rootMesh);if(t.includes(e)||t.some(r=>xg(r,e)))return e;if(!dTe(e))return null;let i=e.parent;for(;i&&"uniqueId"in i;){let r=i;if(t.includes(r)||t.some(s=>xg(s,r)))return r;i=i.parent}return null}getCurrentMeasurementTargetNode(){return this.focusSelectionEnabled&&this.focusedNode&&!hf(this.focusedNode)?this.findSelectableNode(this.focusedNode):this.rootMesh&&!this.rootMesh.isDisposed()?this.rootMesh:null}setMeasurementTargetNode(e,t=!0){this.clearMeasurementTargetVisual(!1),this.invalidateMeasurementSnapInputCache();let i=e&&!hf(e)?this.findSelectableNode(e):null;if(!i||hf(i)){this.measurementTargetNode=null,this.measurementTargetMeshes=[],this.setMeasurementSnapKind(null,!1),t&&this.notifyMeasurementsChanged();return}let r=this.getMeasurementTargetMeshes(i);if(r.length===0){this.measurementTargetNode=null,this.measurementTargetMeshes=[],this.setMeasurementSnapKind(null,!1),t&&this.notifyMeasurementsChanged();return}this.measurementTargetNode=i,this.measurementTargetMeshes=r,this.setMeasurementSnapKind(null,!1),this.applyMeasurementTargetVisual(r),this.scene.render(),t&&this.notifyMeasurementsChanged()}clearMeasurementTargetVisual(e=!0){for(let t of this.measurementTargetMeshes)t.isDisposed()||(t.renderOutline=!1,t.outlineWidth=0);this.measurementTargetMeshes=[],e&&!this.scene.isDisposed&&this.scene.render()}applyMeasurementTargetVisual(e){if(!(!this.measurementActive||e.length===0))for(let t of e)t.isDisposed()||(t.renderOutline=!0,t.outlineColor=new he(.38,.65,.98),t.outlineWidth=.045)}setMeasurementSnapKind(e,t=!0){this.measurementSnapKind!==e&&(this.measurementSnapKind=e,t&&this.notifyMeasurementsChanged())}updateMeasurementModifierAltKey(e){this.lastPointerClient.altKey!==e&&(this.lastPointerClient={...this.lastPointerClient,altKey:e},this.measurementActive&&this.pendingPoint&&this.updatePreviewLine())}invalidateMeasurementSnapInputCache(){this.measurementSnapInputCache=null,this.measurementSnapInputCacheTargetId=null,this.measurementSnapInputCacheSignature=null}getMeasurementTargetName(){let e=this.measurementTargetNode;return!e||hf(e)?null:Gd(e,e.name||`node-${e.uniqueId}`)}getMeasurementTargetBounds(){if(!this.rootMesh||!this.measurementTargetNode||hf(this.measurementTargetNode))return null;let e=this.findSelectableNode(this.measurementTargetNode);if(!e)return null;this.measurementTargetNode=e;let t=this.getRenderableMeshes(this.rootMesh).filter(i=>xg(i,e));return Ql(t)}resolveMeasurementPickPoint(e,t){if(t)return this.setMeasurementSnapKind("free"),e;let i=this.createMeasurementGeometrySnapInput();if(!i)return this.setMeasurementSnapKind("free"),e;let r=sx(this.toMeasurementPoint(e),i);return r?(this.setMeasurementSnapKind(r.kind),go(r.point)):(this.setMeasurementSnapKind("free"),e)}createMeasurementGeometrySnapInput(){var f;let e=this.measurementTargetNode;if(!this.rootMesh||!e||hf(e))return null;let t=this.getMeasurementTargetMeshes(e);if(t.length===0)return null;let i=this.createMeasurementSnapInputSignature(t);if(this.measurementSnapInputCache&&this.measurementSnapInputCacheTargetId===e.uniqueId&&this.measurementSnapInputCacheSignature===i)return this.measurementSnapInputCache;let r=[],s=[],a=`babylon:${e.uniqueId}`;for(let d of t){if(d.isDisposed())continue;let u=d.getVerticesData(D.PositionKind);if(!u||u.length<3)continue;let h=d.computeWorldMatrix(!0),m=[],g=Math.floor(u.length/3);for(let _=0;_{var r;let i="geometry"in t&&t.geometry?(r=t.geometry.uniqueId)!=null?r:"geometry":"none";return[t.uniqueId,i,t.getTotalVertices(),t.getTotalIndices(),t.computeWorldMatrix(!0).asArray().map(gTe).join(",")].join(":")}).join("|")}getMeasurementTargetMeshes(e=this.measurementTargetNode){return!this.rootMesh||!e||hf(e)?[]:this.getRenderableMeshes(this.rootMesh).filter(t=>!t.isDisposed()&&xg(t,e))}getMeasurementTargetPickPoint(e,t){return!e||e.isDisposed()||!t?null:this.measurementTargetMeshes.includes(e)?t.clone():null}pickFrontmostMeasurementTargetPoint(e,t){let i=this.engine.getRenderingCanvas();if(!i||this.measurementTargetMeshes.length===0)return null;let r=i.getBoundingClientRect(),s=e-r.left,a=t-r.top,o=this.scene.pick(s,a,l=>l!==this.previewLine&&!this.measurementMarkers.includes(l));return o!=null&&o.hit?this.getMeasurementTargetPickPoint(o.pickedMesh,o.pickedPoint):null}createBabylonMeasurementDraftingLayout(e,t){var l,c,f;let i=this.toMeasurementDisplayPoint(e),r=this.toMeasurementDisplayPoint(t),s=this.getMeasurementMarkerSize(),a=(f=(c=(l=this.camera.upVector)==null?void 0:l.clone)==null?void 0:c.call(l))!=null?f:new b(0,1,0);a.normalize();let o=cx(this.toMeasurementPoint(i),this.toMeasurementPoint(r),{viewPosition:this.toMeasurementPoint(this.camera.position),viewUp:this.toMeasurementPoint(a),offset:s*4.2,extensionGap:s*.55,extensionOvershoot:s*.8,arrowLength:s*2.35,arrowWidth:s*.78,labelGap:s*1.05});return o?{lineSegments:o.lineSegments.map(([d,u])=>[go(d),go(u)]),labelPosition:go(o.labelPoint)}:null}getMeasurementMarkerSize(){if(!this.rootMesh)return .02;let e=this.getRenderableBounds(this.rootMesh);return e?Math.max(e.max.x-e.min.x,e.max.y-e.min.y,e.max.z-e.min.z,.001)*.018:.02}cancelPendingMeasurement(e=!0){var r,s;let t=this.pendingMarker,i=(s=(r=this.pendingPoint)==null?void 0:r.clone())!=null?s:null;if(this.pendingPoint=null,this.pendingMarker=null,this.hoveredMarkerIndex=-1,i&&this.setMeasurementSnapKind(null,!1),this.removePreviewLine(),t&&i&&!this.isMeasurementPointUsed(i)){let a=this.measurementMarkers.indexOf(t);a>=0&&(this.measurementMarkers.splice(a,1),this.measurementMarkerPoints.splice(a,1)),t.dispose(!1,!0)}else t&&(t.scaling.setAll(1),BE(t,UE));e&&this.scene.render()}isMeasurementPointUsed(e){return this.measurementSegments.some(t=>b.Distance(t.start,e)<1e-4||b.Distance(t.end,e)<1e-4)}findNearestMarkerIndex(e){let t=this.getMeasurementMarkerSize()*2.5,i=this.toMeasurementDisplayPoint(e);for(let r=0;r=0?this.measurementMarkerPoints[i].clone():t;if(this.pendingPoint){if(b.Distance(r,this.pendingPoint)<1e-4)return;if(i<0){let s=this.getMeasurementMarkerSize(),a=Pn.CreateSphere("measure-marker",{diameter:s*.76,segments:12},this.scene);a.position=this.toMeasurementDisplayPoint(r),a.isPickable=!1,a.material=I$(this.scene),a.renderingGroupId=2,this.measurementMarkers.push(a),this.measurementMarkerPoints.push(r.clone())}this.createMeasurementSegment(this.pendingPoint,r),this.pendingMarker&&(this.pendingMarker.scaling.setAll(1),BE(this.pendingMarker,UE)),this.pendingPoint=null,this.pendingMarker=null,this.removePreviewLine()}else{if(i<0){let s=this.getMeasurementMarkerSize(),a=Pn.CreateSphere("measure-marker",{diameter:s*.76,segments:12},this.scene);a.position=this.toMeasurementDisplayPoint(r),a.isPickable=!1,a.material=I$(this.scene),a.renderingGroupId=2,this.measurementMarkers.push(a),this.measurementMarkerPoints.push(r.clone()),this.pendingMarker=a}else this.pendingMarker=this.measurementMarkers[i];this.pendingMarker.scaling.setAll(1.6),BE(this.pendingMarker,eTe),this.pendingPoint=r,this.ensurePreviewLine()}this.notifyMeasurementsChanged()}createMeasurementSegment(e,t){var f,d;let i=this.toMeasurementDisplayPoint(e),r=this.toMeasurementDisplayPoint(t),s=this.createBabylonMeasurementDraftingLayout(e,t),a=Pn.CreateLineSystem("measure-line",{lines:(f=s==null?void 0:s.lineSegments)!=null?f:[[i,r]]},this.scene);a.color=S$.clone(),a.alpha=1,a.isPickable=!1,a.renderingGroupId=2;let o=Wm(this.createMeasurementReading(e,t)),l=(d=s==null?void 0:s.labelPosition)!=null?d:b.Center(i,r),c=this.createMeasurementLabelMesh(o,l,this.getMeasurementMarkerSize()*3.2);this.measurementSegments.push({start:e.clone(),end:t.clone(),line:a,label:c})}createMeasurementLabelMesh(e,t,i){let r=Pn.CreatePlane("measure-label",{width:i*3.7,height:i*1.08},this.scene);r.position=t,r.billboardMode=$.BILLBOARDMODE_ALL,r.isPickable=!1,r.renderingGroupId=2;let s=new EE("measure-label-tex",{...Oo},this.scene);s.hasAlpha=!0;let a=s.getContext();nv(a,e,Oo.width,Oo.height),s.update();let o=new We("measure-label-mat",this.scene);return o.diffuseTexture=s,o.emissiveColor=new he(1,1,1),o.disableLighting=!0,o.disableDepthWrite=!0,o.opacityTexture=s,o.useAlphaFromDiffuseTexture=!0,r.material=o,r}ensurePreviewLine(){this.previewLine||(this.previewLine=Pn.CreateLineSystem("measure-preview",{lines:Array.from({length:7},()=>[b.Zero(),b.Zero()]),updatable:!0},this.scene),this.previewLine.color=T$.clone(),this.previewLine.alpha=.82,this.previewLine.isPickable=!1,this.previewLine.renderingGroupId=2)}updatePreviewLine(){var l;if(!this.pendingPoint||!this.previewLine||!this.rootMesh)return;let e=this.toMeasurementDisplayPoint(this.pendingPoint),t=this.engine.getRenderingCanvas();if(!t)return;let i=t.getBoundingClientRect(),r=this.lastPointerClient.x-i.left,s=this.lastPointerClient.y-i.top,a=null;if(this.lastPointerClient.altKey){this.setMeasurementSnapKind("free");let c=this.scene.pick(r,s,f=>f!==this.previewLine&&!this.measurementMarkers.includes(f));a=c.hit&&c.pickedPoint?this.resolveMeasurementPickPoint(c.pickedPoint,!0):e.add(this.scene.createPickingRay(r,s,Q.Identity(),this.camera).direction.scale(5))}else{let c=this.pickFrontmostMeasurementTargetPoint(this.lastPointerClient.x,this.lastPointerClient.y);c?a=this.resolveMeasurementPickPoint(c,!1):this.setMeasurementSnapKind(null)}let o=a?this.createBabylonMeasurementDraftingLayout(this.pendingPoint,this.toMeasurementBasePoint(a)):null;this.previewLine=Pn.CreateLineSystem("measure-preview",{lines:(l=o==null?void 0:o.lineSegments)!=null?l:[[e,e]],instance:this.previewLine},this.scene),this.previewLine.color=T$.clone(),this.previewLine.alpha=.82,this.previewLine.isPickable=!1,this.previewLine.renderingGroupId=2}removePreviewLine(){this.previewLine&&(this.previewLine.dispose(),this.previewLine=null)}createMeasurementReading(e,t){return ux(this.toMeasurementPoint(e),this.toMeasurementPoint(t),this.measurementScale,this.measurementUnit)}createMeasurementRecords(){return this.measurementSegments.map((e,t)=>({index:t+1,start:this.toMeasurementPoint(e.start),end:this.toMeasurementPoint(e.end),reading:this.createMeasurementReading(e.start,e.end)}))}toMeasurementPoint(e){return{x:e.x,y:e.y,z:e.z}}createModelSummary(e){let t=this.getRenderableMeshes(e),i=b1(e),r=t.reduce((s,a)=>s+kd(a),0);return my(e.name,this.getRenderableBounds(e),t,{splatCount:i?r:void 0,resourceWarnings:this.resourceWarnings})}};Ga.annotationIdentity=Q.Identity(),Ga.annotationWorldPoint=b.Zero(),Ga.annotationProjection=b.Zero(),Ga.annotationDirection=b.Zero(),Ga.annotationRay=new on(b.Zero(),b.Zero(),1);Iy=Ga});async function L$(n,e){if(Bh(e).backend==="three"){let{createThreeModelPreview:r}=await Promise.resolve().then(()=>($V(),QV));return r(n)}let{createBabylonModelPreview:i}=await Promise.resolve().then(()=>(P$(),C$));return i(n)}var D$=y(()=>{"use strict";_S()});var N$={};Be(N$,{createBabylonGridRenderer:()=>ETe});function vTe(n){return n.replace(/\|/g,"\\|").replace(/\r?\n/g," ")}function y1(n){return new b(n.x,n.y,n.z)}function O$(n){return Number.isFinite(n)?Math.max(0,Math.min(n,1)):0}function ETe(n){return new I1(n)}var Rg,I1,w$=y(()=>{"use strict";zD();na();Eb();Sb();He();$t();up();ug();cd();lf();OE();OE();FE();FA();Ma();Lo();HA();Rg=32;I1=class{constructor(e){this.cells=[];this.initialCameras=[];this.wireframeEnabled=!1;this.rendering=!1;this.dirty=!0;this.contextLost=!1;this.warmupFrame=null;this.renderScale=1;this.cameraZoomObservers=new Set;this.preventCanvasWheelScroll=e=>{e.preventDefault(),e.stopPropagation()};this.handleContextLost=e=>{e.preventDefault(),this.contextLost=!0,this.rendering&&(this.engine.stopRenderLoop(),this.rendering=!1)};this.handleContextRestored=()=>{this.contextLost=!1,this.engine.resize(),this.startRenderLoop(),this.markDirty(),this.scheduleWarmupFrames()};e.className="ai3d-canvas-full",e.addEventListener("wheel",this.preventCanvasWheelScroll,{passive:!1}),this.engine=new ze(e,!0,{preserveDrawingBuffer:!0}),e.addEventListener("webglcontextlost",this.handleContextLost),e.addEventListener("webglcontextrestored",this.handleContextRestored),this.scene=new ai(this.engine),this.scene.clearColor=new ht(.12,.12,.14,1),this.scene.autoClear=!1,new Fa("default-light",new b(0,1,.5),this.scene),this.resizeObs=new ResizeObserver(()=>{this.engine.resize(),this.markDirty()}),this.resizeObs.observe(e),window.requestAnimationFrame(()=>this.engine.resize())}canRender(){let e=this.engine.getRenderingCanvas();return!!(e!=null&&e.isConnected)&&e.clientWidth>0&&e.clientHeight>0}markDirty(){this.dirty=!0}getCameraZoomRange(e){let t=e.radius,i=e.lowerRadiusLimit,r=e.upperRadiusLimit,s=typeof i=="number"&&Number.isFinite(i)&&i>0?i:Math.max(t*.08,1e-5),a=typeof r=="number"&&Number.isFinite(r)&&r>s?r:Math.max(t*8,s*10);return{current:Math.max(s,Math.min(t,a)),min:s,max:a}}notifyCameraZoomChanged(){if(this.cameraZoomObservers.size===0)return;let e=this.getCameraZoomState();for(let t of this.cameraZoomObservers)t(e)}scheduleWarmupFrames(e=8){this.warmupFrame!==null&&window.cancelAnimationFrame(this.warmupFrame),this.warmupFrame=window.requestAnimationFrame(()=>{this.warmupFrame=null,!(!this.canRender()||this.contextLost)&&(this.markDirty(),e>1&&this.scheduleWarmupFrames(e-1))})}getCellBounds(e){let t=Ql(e);if(!t)throw new Error("Grid cell has no renderable meshes");return t}async loadModels(e,t,i){var d,u,h;await DE();let r=e.length>Rg?(console.warn(`[AI3D Grid] Capping ${e.length} models to ${Rg} (layerMask limit)`),e.slice(0,Rg)):e,s=(d=t.columns)!=null?d:Math.min(r.length,3),a=(u=t.gapX)!=null?u:.02,o=(h=t.gapY)!=null?h:.02,l=Math.ceil(r.length/s),c=(1-a*(s+1))/s,f=(1-o*(l+1))/l;for(let m=0;mRg?(console.warn(`[AI3D Preset] Capping ${e.placements.length} placements to ${Rg} (layerMask limit)`),e.placements.slice(0,Rg)):e.placements,r=[];for(let f=0;f0&&(u.push(...r[g]),h|=1<{this.markDirty(),this.notifyCameraZoomChanged()})),this.initialCameras.push({alpha:f.alpha,beta:f.beta,radius:f.radius,target:f.target.clone()}),f}async loadOne(e,t,i,r,s,a,o){var u,h;let l=await t(e.path),c=(h=(u=e.path.split(".").pop())==null?void 0:u.replace(".","").toLowerCase())!=null?h:"glb",{renderableMeshes:f}=await this.importMesh(e.path,l,o);if(c==="stl"&&e.color){let m=he.FromHexString(e.color);for(let g of f)g.material instanceof We&&g.material.name==="stl-mat"&&(g.material.diffuseColor=m)}if(c==="stl"&&e.wireframe!==void 0)for(let m of f)m.material instanceof We&&(m.material.wireframe=e.wireframe);let d=this.createCellCamera(f,o,i,r,s,a);this.cells.push({meshes:f,camera:d})}createCellCamera(e,t,i,r,s,a){let o=tv(this.getCellBounds(e)),l=new Mi(`cell-cam-${t}`,Math.PI/4,Math.PI/3,o.radius,y1(o.target),this.scene);l.fov=45*Math.PI/180,l.minZ=o.near,l.maxZ=o.far,l.lowerRadiusLimit=o.lowerRadiusLimit,l.upperRadiusLimit=o.upperRadiusLimit,l.wheelPrecision=45,l.viewport=new Go(i,r,s,a),l.layerMask=1<{this.markDirty(),this.notifyCameraZoomChanged()})),this.initialCameras.push({alpha:l.alpha,beta:l.beta,radius:l.radius,target:l.target.clone()}),l}renderFrame(){if(!this.canRender()||!this.dirty||this.contextLost)return;this.dirty=!1;let e=this.engine,t=this.scene;e.clear(t.clearColor,!0,!0);for(let i of this.cells){e.setViewport(i.camera.viewport);let r=i.camera.viewport,s=e.getRenderWidth(),a=e.getRenderHeight();e.enableScissor(r.x*s,r.y*a,r.width*s,r.height*a),t.activeCamera=i.camera,t.render(),e.disableScissor()}}startRenderLoop(){this.rendering||(this.rendering=!0,this.engine.runRenderLoop(()=>this.renderFrame()))}captureSnapshot(){let e=this.engine.getRenderingCanvas();return e?(this.renderFrame(),e.toDataURL("image/png")):null}getEngine(){return this.engine}getScene(){return this.scene}getCellCount(){return this.cells.length}getCanvas(){return this.engine.getRenderingCanvas()}getPrimaryCamera(){var e,t;return(t=(e=this.cells[0])==null?void 0:e.camera)!=null?t:null}setRenderScale(e){let t=Math.max(.25,Math.min(e,2));this.renderScale=t;let i=Rr()?1.5:1;return this.engine.setHardwareScalingLevel(i/t),this.getRenderScale()}getRenderScale(){return Number(this.renderScale.toFixed(2))}getCameraZoomState(){var s;let e=(s=this.cells[0])==null?void 0:s.camera;if(!e)return null;let t=this.getCameraZoomRange(e),i=(t.max-t.current)/(t.max-t.min),r=O$(i);return{value:r,percentage:Math.round(r*100)}}setCameraZoom(e){if(this.cells.length===0)return null;let t=O$(e);for(let i of this.cells){let r=this.getCameraZoomRange(i.camera);i.camera.radius=r.max-t*(r.max-r.min)}return this.markDirty(),this.startRenderLoop(),this.notifyCameraZoomChanged(),this.getCameraZoomState()}observeCameraZoom(e){return this.cameraZoomObservers.add(e),e(this.getCameraZoomState()),()=>{this.cameraZoomObservers.delete(e)}}resetView(){for(let e=0;e(w$(),N$));return e(n)}var B$=y(()=>{"use strict"});var G$={};Be(G$,{createLoggedGridRenderer:()=>C1,createLoggedModelPreview:()=>bg,logGridPreviewSelection:()=>V$,logModelPreviewSelection:()=>U$});function U$(n,e,t){n.info("select preview backend",{...e,backend:t.backend,reason:t.reason,ext:t.ext,annotationMode:t.annotationMode,requireWorkbenchFeatures:t.requireWorkbenchFeatures,rendererRollout:t.rendererRollout})}async function bg(n,e,t,i){let r=Bh(i);return U$(n,e,r),{preview:await L$(t,i),route:r}}function V$(n,e,t){n.info("select preview backend",{...e,backend:t.backend,reason:t.reason})}async function C1(n,e,t){let i=uB();return V$(n,e,i),{renderer:await F$(t),route:i}}var Cy=y(()=>{"use strict";D$();B$();_S()});function P1(n){z$=n}function Py(n){return k$[n]>=k$[z$]}function Ly(){return new Date().toISOString()}function Dy(n){return n&&Object.keys(n).length>0?n:void 0}function er(n){let e=`[AI3D][${n}]`;return{debug(t,i){Py("debug")&&console.debug(e,Ly(),t,Dy(i))},info(t,i){Py("info")&&console.debug(e,Ly(),t,Dy(i))},warn(t,i){Py("warn")&&console.warn(e,Ly(),t,Dy(i))},error(t,i){Py("error")&&console.error(e,Ly(),t,Dy(i))}}}var k$,z$,zn=y(()=>{"use strict";k$={debug:10,info:20,warn:30,error:40},z$="warn"});var H$={};Be(H$,{supportsAnimationPreview:()=>Ny,supportsAnnotationPreview:()=>Oy,supportsBoundingBoxPreview:()=>Fy,supportsCameraZoomPreview:()=>By,supportsDisassemblyPreview:()=>Sh,supportsFocusSelectionPreview:()=>Th,supportsMeasurementPreview:()=>cn,supportsOrientationGizmoPreview:()=>VE,supportsRenderScalePreview:()=>GE,supportsSlicePreview:()=>Hd,supportsWireframePreview:()=>wy,supportsWorkbenchPreview:()=>W$});function Di(n,e){return!!n&&typeof n=="object"&&typeof n[e]=="function"}function Oy(n){return Di(n,"getAnnotationProvider")}function Ny(n){return Di(n,"hasAnimations")&&Di(n,"toggleAnimation")}function cn(n){return Di(n,"toggleMeasurement")&&Di(n,"isMeasurementActive")&&Di(n,"cancelMeasurement")&&Di(n,"clearMeasurements")&&Di(n,"setMeasurementScale")&&Di(n,"getMeasurementScale")&&Di(n,"setMeasurementUnit")&&Di(n,"getMeasurementUnit")&&Di(n,"getMeasurementBounds")&&Di(n,"getMeasurementRecords")&&Di(n,"getMeasurementState")&&Di(n,"updateMeasurementLabels")&&Di(n,"exportMeasurements")}function Hd(n){return Di(n,"toggleSlice")&&Di(n,"isSliceActive")&&Di(n,"setSlicePlane")&&Di(n,"setSliceOffset")&&Di(n,"setSliceRotation")&&Di(n,"resetSlicePlane")&&Di(n,"getSliceState")}function Sh(n){return Di(n,"toggleDisassembly")&&Di(n,"resetDisassembly")&&Di(n,"isDisassemblyEnabled")}function Th(n){return Di(n,"toggleFocusSelection")&&Di(n,"isFocusSelectionEnabled")}function wy(n){return Di(n,"toggleWireframe")}function VE(n){return Di(n,"toggleOrientationGizmo")}function Fy(n){return Di(n,"toggleBoundingBox")}function GE(n){return Di(n,"setRenderScale")}function By(n){return Di(n,"getCameraZoomState")&&Di(n,"setCameraZoom")}function W$(n){return Di(n,"setExplode")&&Di(n,"resetExplode")&&Di(n,"focusWorldPoint")}var Ah=y(()=>{"use strict"});function Uy(n,e){return Cu(n,e)}function X$(n){return Number.isFinite(n)?Math.max(0,Math.min(n,1)):0}function Vy(n,e){let t=Uy("div","ai3d-zoom-control is-hidden"),i=Uy("div","ai3d-zoom-track"),r=Uy("div","ai3d-zoom-fill"),s=Uy("input","ai3d-zoom-range");s.type="range",s.min="0",s.max="100",s.step="1",s.value="0",s.setAttribute("aria-label",H("helper.cameraZoomLabel")),s.setAttribute("aria-orientation","vertical"),i.appendChild(r),t.append(i,s),n.appendChild(t);let a=null,o=null,l=null,c=E=>{E.stopPropagation()};t.addEventListener("mousedown",c),t.addEventListener("click",c);function f(){let E=e();return By(E)?E:null}function d(E){if(!E){t.classList.add("is-hidden"),s.disabled=!0;return}let S=X$(E.value),T=Math.round(S*100);s.disabled=!1,s.value=String(T),t.style.setProperty("--ai3d-zoom-percent",`${T}%`);let A=Wi("helper.cameraZoomValue",{value:`${E.percentage}%`});s.setAttribute("aria-valuenow",String(T)),s.setAttribute("aria-valuetext",A),t.setAttribute("title",A),t.classList.remove("is-hidden")}function u(E){E!==a&&(o==null||o(),o=null,a=E,E!=null&&E.observeCameraZoom&&(o=E.observeCameraZoom(d)))}function h(){var S;let E=f();u(E),d((S=E==null?void 0:E.getCameraZoomState())!=null?S:null)}function m(){g(s.valueAsNumber/100)}function g(E){let S=a!=null?a:f();if(!S){h();return}u(S),d(S.setCameraZoom(X$(E)))}function p(E){let S=i.getBoundingClientRect();return S.height<=0?s.valueAsNumber/100:1-(E-S.top)/S.height}function _(E){E.preventDefault(),E.stopPropagation(),s.focus({preventScroll:!0}),g(p(E.clientY))}function v(E){var S;l===E.pointerId&&(E.preventDefault(),E.stopPropagation(),(S=t.hasPointerCapture)!=null&&S.call(t,E.pointerId)&&t.releasePointerCapture(E.pointerId),l=null,t.classList.remove("is-dragging"))}return s.addEventListener("input",m),t.addEventListener("pointerdown",E=>{var S;if(E.button!==0||s.disabled){E.stopPropagation();return}l=E.pointerId,(S=t.setPointerCapture)==null||S.call(t,E.pointerId),t.classList.add("is-dragging"),_(E)}),t.addEventListener("pointermove",E=>{l===E.pointerId&&_(E)}),t.addEventListener("pointerup",v),t.addEventListener("pointercancel",v),t.addEventListener("wheel",E=>{E.preventDefault(),E.stopPropagation();let S=E.deltaY<0?6:-6;s.value=String(Math.max(0,Math.min(100,s.valueAsNumber+S))),m()},{passive:!1}),h(),{sync:h,destroy(){o==null||o(),o=null,a=null,t.remove()}}}var L1=y(()=>{"use strict";xn();Ah();Fm()});function Y$(n){for(let e of STe)if(n[e])return e;return"idle"}function K$(n){return n!=="idle"}var STe,j$=y(()=>{"use strict";STe=["annotation","slice","measurement","disassembly","focus"]});function Br(n){let e=createSvg("svg");e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("width","16"),e.setAttribute("height","16");let t=new DOMParser().parseFromString(`${n}`,"image/svg+xml");for(let i of Array.from(t.documentElement.childNodes))e.appendChild(activeDocument.importNode(i,!0));return e}function Z$(n){var a,o;let[e,t]=n.split(","),i=(o=(a=e.match(/:(.*?);/))==null?void 0:a[1])!=null?o:"image/png",r=atob(t),s=new Uint8Array(r.length);for(let l=0;l{let s=Math.abs(i-e),a=Math.abs(Mg[t]-e);s{X.stopPropagation()};u.addEventListener("pointerdown",_),u.addEventListener("mousedown",_),u.addEventListener("click",_);let v=X=>{if(X.key!=="Escape"||X.defaultPrevented)return;let xe=X.target;if(xe instanceof Node&&!u.contains(xe)&&!e.contains(xe))return;let At=U();!At||!dx(At)||(Qe(),X.preventDefault(),X.stopPropagation())};u.addEventListener("keydown",v),e.addEventListener("keydown",v),f&&(u.classList.add("is-mobile"),Q$(e,!1));let E=Vy(e,i),S=null,T=null,A=null,R=null,M=!1,I="idle",C=X=>(X.classList.add("is-secondary"),X),L=(X,xe)=>{X.classList.toggle("ai3d-btn-active",xe),X.setAttribute("aria-pressed",String(xe))},w=()=>{for(let X of[h,m,g]){let xe=Array.from(X.querySelectorAll(".ai3d-inline-btn")).filter(st=>!st.classList.contains("is-hidden")),At=xe.length>0,kt=xe.some(st=>!st.classList.contains("is-secondary"));X.classList.toggle("is-hidden",!At),X.classList.toggle("has-primary-visible",kt)}},G=!1,O=!1,N=f?h.createEl("button",{cls:"ai3d-inline-btn ai3d-mobile-mode-btn",attr:{"aria-label":H("helper.enableInteractionLabel"),"aria-pressed":"false"}}):null;N==null||N.appendChild(Br(''));let B=(Hn=N==null?void 0:N.createSpan({cls:"ai3d-mobile-mode-btn-label"}))!=null?Hn:null,V=()=>{f&&N&&(Q$(e,G),L(N,G),B==null||B.setText(G?H("helper.scrollAction"):H("helper.interactAction")),N.setAttribute("aria-label",G?H("helper.disableInteractionLabel"):H("helper.enableInteractionLabel"))),L(Wt,O),u.classList.toggle("show-secondary",O),w()},q=X=>{G=X,V()};N==null||N.addEventListener("click",()=>{let X=!G;l==null||l(X),q(X),vi(N,X?H("helper.interactionOn"):H("helper.interactionOff"))});let K=(X,xe)=>{X.classList.toggle("is-hidden",!xe)},J=null,Y=X=>{switch(X){case"annotation":return H("helper.interactionModeAnnotation");case"focus":return H("helper.interactionModeFocus");case"disassembly":return H("helper.interactionModeDisassembly");case"measurement":return H("helper.interactionModeMeasurement");case"slice":return H("helper.interactionModeSlice");case"idle":return""}},j=(X,xe,At,kt)=>{let st=Y$({annotation:M,focus:!!(X!=null&&X.isFocusSelectionEnabled()),disassembly:!!(xe!=null&&xe.isDisassemblyEnabled()),measurement:!!(At!=null&&At.isMeasurementActive()),slice:!!(kt!=null&&kt.isSliceActive())});u.dataset.ai3dInteractionMode=st,e.dataset.ai3dInteractionMode=st,e.classList.toggle("ai3d-interaction-active",K$(st)),I!==st&&(e.classList.remove(`ai3d-interaction-${I}`),st!=="idle"&&e.classList.add(`ai3d-interaction-${st}`),I=st),p.textContent=Y(st),p.classList.toggle("is-hidden",st==="idle");let Qt=[["annotation",qe],["focus",we],["disassembly",dt],["measurement",Ti],["slice",Ve]];for(let[$r,Zi]of Qt)Zi.classList.toggle("ai3d-linked-inactive",st!=="idle"&&st!==$r)},ue=()=>{var Qt;let X=i(),xe=X&&Th(X)?X:null,At=X&&Sh(X)?X:null,kt=X&&cn(X)?X:null,st=X&&Hd(X)?X:null;L(we,!!(xe!=null&&xe.isFocusSelectionEnabled())),L(dt,!!(At!=null&&At.isDisassemblyEnabled())),L(Ti,!!(kt!=null&&kt.isMeasurementActive())),L(Ve,!!(st!=null&&st.isSliceActive())),L(qe,M),X&&VE(X)&&L(de,!!((Qt=X.isOrientationGizmoEnabled)!=null&&Qt.call(X))),j(xe,At,kt,st)},Ee=()=>{!M||!o||(M=o(),L(qe,M))},Ue=()=>{let X=i();X&&(Hd(X)&&X.isSliceActive()&&X.toggleSlice(),cn(X)&&X.isMeasurementActive()&&X.toggleMeasurement(),Sh(X)&&X.isDisassemblyEnabled()&&X.toggleDisassembly(),Th(X)&&X.isFocusSelectionEnabled()&&X.toggleFocusSelection())},se=()=>{let X=i(),xe=X&&Th(X)?X:null,At=X&&Sh(X)?X:null,kt=X&&Ny(X)?X:null,st=X&&GE(X)?X:null;X!==J&&(J=X,L(Le,!1),L(be,!1),L(ae,!1),ae.replaceChildren(Br('')),K(ve,!!(X!=null&&X.resetView)),K(ne,!!(X!=null&&X.exportModelInfo)),K(me,!!(X!=null&&X.exportSelectedPartInfo)),K(Le,!!X&&wy(X)),K(de,!!X&&VE(X)),K(be,!!X&&Fy(X)),K(we,!!xe),K(dt,!!At),K(Bt,!!st),K(Ve,!!X&&Hd(X)),K(ae,!!(kt!=null&&kt.hasAnimations()))),wi(st),K(Ti,!!X&&cn(X)),ue(),Qe(),$i(),w(),E.sync()},ve=h.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.resetViewLabel")}});Qr(ve,"reset-view"),ve.appendChild(Br('')),ve.addEventListener("click",()=>{let X=i();X!=null&&X.resetView&&(X.resetView(),se(),vi(ve,H("helper.resetViewDone")))});let ne=C(m.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.copyModelInfoLabel")}}));Qr(ne,"copy-model-info"),ne.appendChild(Br('')),ne.addEventListener("click",()=>{let X=i();if(X!=null&&X.exportModelInfo)try{let xe=X.exportModelInfo(r());if(!xe)return;navigator.clipboard.writeText(xe).then(()=>{vi(ne,H("helper.copied"))}).catch(()=>{vi(ne,H("helper.failed"))})}catch(xe){console.error("[AI3D] Export model info failed:",xe),vi(ne,H("helper.failed"))}});let me=C(m.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.copySelectedPartInfoLabel")}}));Qr(me,"copy-selected-part-info"),me.appendChild(Br('')),me.addEventListener("click",()=>{let X=i();if(X!=null&&X.exportSelectedPartInfo)try{let xe=X.exportSelectedPartInfo();if(!xe){vi(me,H("helper.noSelectedPart"));return}navigator.clipboard.writeText(xe).then(()=>{vi(me,H("helper.copied"))}).catch(()=>{vi(me,H("helper.failed"))})}catch(xe){console.error("[AI3D] Export selected part info failed:",xe),vi(me,H("helper.failed"))}});let Le=h.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.toggleWireframeLabel"),"aria-pressed":"false"}});Qr(Le,"toggle-wireframe"),Le.appendChild(Br('')),Le.addEventListener("click",()=>{let X=i();if(!(X!=null&&X.toggleWireframe))return;let xe=X.toggleWireframe();L(Le,xe),vi(Le,xe?H("helper.wireframeOn"):H("helper.wireframeOff"))});let de=h.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.toggleAxesLabel"),"aria-pressed":"false"}});Qr(de,"toggle-axes"),de.appendChild(Br('')),de.addEventListener("click",()=>{let X=i();if(!(X!=null&&X.toggleOrientationGizmo))return;let xe=X.toggleOrientationGizmo();L(de,xe),vi(de,xe?H("helper.axesOn"):H("helper.axesOff"))});let be=h.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.toggleBoundingBoxLabel"),"aria-pressed":"false"}});Qr(be,"toggle-bounding-box"),be.appendChild(Br('')),be.addEventListener("click",()=>{let X=i();if(!(X!=null&&X.toggleBoundingBox))return;let xe=X.toggleBoundingBox();L(be,xe),vi(be,xe?H("helper.boundingBoxOn"):H("helper.boundingBoxOff"))});let we=m.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.toggleFocusSelectionLabel"),"aria-pressed":"false"}});Qr(we,"toggle-focus"),we.appendChild(Br('')),we.addEventListener("click",()=>{let X=i();if(!X||!Th(X))return;X.isFocusSelectionEnabled()||Ee();let xe=X.toggleFocusSelection();se(),vi(we,xe?H("helper.focusSelectionOn"):H("helper.focusSelectionOff"))});let dt=m.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.toggleDisassemblyLabel"),"aria-pressed":"false"}});Qr(dt,"toggle-disassembly"),dt.appendChild(Br('')),dt.addEventListener("click",()=>{let X=i();if(!X||!Sh(X))return;X.isDisassemblyEnabled()||Ee();let xe=X.toggleDisassembly();se(),vi(dt,xe?H("helper.disassemblyOn"):H("helper.disassemblyOff"))});let Ve=m.createEl("button",{cls:"ai3d-inline-btn ai3d-slice-btn is-hidden",attr:{"aria-label":H("helper.toggleSliceLabel"),"aria-pressed":"false"}});Qr(Ve,"toggle-slice"),Ve.appendChild(Br('')),Ve.createSpan({cls:"ai3d-slice-btn-text",text:H("helper.sliceButtonText")}),Ve.addEventListener("click",()=>{let X=i();if(!X||!Hd(X))return;X.isSliceActive()||Ee();let xe=X.toggleSlice();se(),vi(Ve,xe?H("helper.sliceOn"):H("helper.sliceOff"))});let Ze=Gy((Oi=a==null?void 0:a().renderScale)!=null?Oi:1),Kt=D1(Ze),Bt=C(h.createEl("button",{cls:"ai3d-inline-btn ai3d-res-btn",attr:{"aria-label":H("helper.changeResolutionLabel")}}));Qr(Bt,"change-resolution");function wi(X=null){var kt,st;let xe=O1(X,(st=(kt=a==null?void 0:a().renderScale)!=null?kt:Mg[Kt])!=null?st:1);Kt=D1(xe);let At=q$(xe);Bt.textContent=At,Bt.setAttribute("title",Wi("helper.resolutionValue",{value:At}))}wi(),Bt.addEventListener("click",()=>{let X=i();if(!X||!GE(X))return;Kt=(D1(O1(X,Mg[Kt]))+1)%Mg.length;let At=X.setRenderScale(Mg[Kt]),kt=O1(X,At);wi(X),vi(Bt,Wi("helper.resolutionValue",{value:q$(kt)}))});let ae=C(h.createEl("button",{cls:"ai3d-inline-btn is-hidden",attr:{"aria-label":H("helper.toggleAnimationLabel"),"aria-pressed":"false"}}));Qr(ae,"toggle-animation"),ae.appendChild(Br('')),ae.addEventListener("click",()=>{let X=i();if(!(X!=null&&X.toggleAnimation))return;let xe=X.toggleAnimation();ae.replaceChildren(Br(xe?'':'')),L(ae,xe),vi(ae,xe?H("helper.playing"):H("helper.paused"))});let Ti=m.createEl("button",{cls:"ai3d-inline-btn is-hidden",attr:{"aria-label":H("helper.toggleMeasurementLabel"),"aria-pressed":"false",title:H("helper.toggleMeasurementLabel")}});Qr(Ti,"toggle-measurement"),Ti.appendChild(Br('')),Ti.addEventListener("click",()=>{let X=i();if(!X||!cn(X))return;X.isMeasurementActive()||Ee();let xe=X.toggleMeasurement();se(),vi(Ti,xe?H("helper.measurementOn"):H("helper.measurementOff")),xe||L(ft,!1)});function hi(X){let xe=i();!xe||!cn(xe)||(xe.clearMeasurements(),L(Ti,xe.isMeasurementActive()),Qe(),vi(X,H("helper.measurementsCleared")))}function rr(X){let xe=i();if(!xe||!cn(xe))return;let At=xe.exportMeasurements();if(!At){vi(X,H("helper.noMeasurements"));return}navigator.clipboard.writeText(At).then(()=>{vi(X,H("helper.measurementsCopied"))}).catch(()=>{vi(X,H("helper.failed"))})}let Ke=m.createEl("button",{cls:"ai3d-measurement-strip is-hidden",attr:{"aria-expanded":"false","aria-label":H("helper.calibrateLabel")}});Qr(Ke,"toggle-measurement-details"),Ke.setAttribute("aria-live","polite");let ar=Ke.createSpan({cls:"ai3d-measurement-strip-value"}),Z=Ke.createSpan({cls:"ai3d-measurement-strip-meta"});function U(){let X=i();return X&&cn(X)?X:null}function ge(X){X!==S&&(T==null||T(),T=null,S=X,X!=null&&X.observeMeasurements&&(T=X.observeMeasurements(()=>{ue(),Qe()})))}function De(X){var At;if(X.phase==="select-target")return H("helper.measurementSelectTarget");if(X.phase==="picking-end"&&X.snapKind)return ke(X.snapKind);if(X.phase==="picking-end")return H("helper.measurementPickEnd");let xe=(At=X.records[X.records.length-1])!=null?At:null;return xe?zf(xe.reading.distance,xe.reading.unit):X.snapKind?ke(X.snapKind):X.phase==="ready"?H("helper.measurementPickStart"):X.phase==="reviewing"?H("helper.measurementReviewing"):H("helper.measurementStripEmpty")}function ke(X){switch(X){case"vertex":return H("helper.measurementSnapVertex");case"edge":return H("helper.measurementSnapEdge");case"free":return H("helper.measurementSnapFree")}}function it(X){return X.records.length>0?Wi("helper.measurementStripSaved",{count:String(X.records.length)}):X.phase==="select-target"?H("helper.measurementTargetMissing"):X.targetScope==="model"?H("helper.measurementTargetModel"):X.targetName?Wi("helper.measurementTargetLabel",{target:X.targetName}):X.unit}function Qe(){let X=U();if(ge(X),!X){Ke.classList.add("is-hidden"),Ut.classList.add("is-hidden"),Ke.classList.remove("is-expanded"),Ke.setAttribute("aria-expanded","false"),Ce.disabled=!0,ft.disabled=!0;return}let xe=X.getMeasurementState(),At=xe.active,kt=xe.records,st=kt.length>0;Ke.classList.toggle("is-hidden",xe.phase==="inactive"),!At&&!st&&(Ut.classList.add("is-hidden"),Ke.classList.remove("is-expanded"),Ke.setAttribute("aria-expanded","false")),Ke.classList.toggle("is-active",At),Ke.classList.toggle("is-pending",xe.phase==="picking-end"),Ke.classList.toggle("is-targeting",xe.phase==="select-target"),Ke.classList.toggle("is-reviewing",xe.phase==="reviewing"),Ke.classList.toggle("has-records",st),Ke.dataset.ai3dMeasurementPhase=xe.phase,ar.textContent=De(xe),Z.textContent=it(xe),Ke.setAttribute("aria-label",[H("helper.measurementStripTitle"),ar.textContent,Z.textContent,H("helper.calibrateLabel")].filter(Boolean).join(" ")),rt.textContent=st?Wi("helper.measurementStripSaved",{count:String(kt.length)}):H("helper.measurementNoRecords");let Qt=st;Ce.disabled=!Qt,ft.disabled=!Qt,L(Ti,At)}let Me=g.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.copySnapshotLabel")}});Qr(Me,"copy-snapshot"),Me.appendChild(Br('')),Me.addEventListener("click",()=>{let X=i();if(X)try{let xe=X.captureSnapshot();if(!xe)return;let At=Z$(xe);navigator.clipboard.write([new ClipboardItem({"image/png":At})]).then(()=>{vi(Me,H("helper.copied"))}).catch(()=>{vi(Me,H("helper.failed"))})}catch(xe){console.error("[AI3D] Copy snapshot failed:",xe),vi(Me,H("helper.failed"))}});let Pe=C(g.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.saveSnapshotLabel")}}));Qr(Pe,"save-snapshot"),Pe.appendChild(Br('')),Pe.addEventListener("click",()=>{var xe,At;let X=i();if(X)try{let kt=X.captureSnapshot();if(!kt)return;let st=r(),Qt=gn(st)||"model",$r=a==null?void 0:a(),Zi=(xe=$r==null?void 0:$r.snapshotFolder)!=null?xe:"Media/3D Previews",cl=(At=$r==null?void 0:$r.snapshotNaming)!=null?At:"model-name",nc=Date.now(),cS=cl==="timestamp"?`snapshot_${nc}.png`:`${Qt}_snapshot_${nc}.png`,Vte=Z$(kt),Yg=new FileReader;Yg.onload=()=>{let Gte=Yg.result;t.vault.adapter.exists(Zi).then(D0=>D0?Promise.resolve():t.vault.createFolder(Zi).catch(kte=>{TTe.warn("Failed to create vault folder",{path:Zi,error:String(kte)})})).then(()=>t.vault.createBinary(`${Zi}/${cS}`,Gte)).then(()=>{vi(Pe,H("helper.saved"))}).catch(D0=>{console.error("[AI3D] Save snapshot failed:",D0),vi(Pe,H("helper.failed"))})},Yg.onerror=()=>{console.error("[AI3D] FileReader error"),vi(Pe,H("helper.failed"))},Yg.onabort=()=>{console.error("[AI3D] FileReader aborted"),vi(Pe,H("helper.failed"))},Yg.readAsArrayBuffer(Vte)}catch(kt){console.error("[AI3D] Save snapshot failed:",kt),vi(Pe,H("helper.failed"))}});let ut=C(g.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.downloadSnapshotLabel")}}));Qr(ut,"download-snapshot"),ut.appendChild(Br('')),ut.addEventListener("click",()=>{let X=i();if(X)try{let xe=X.captureSnapshot();if(!xe)return;let At=r(),st=`${gn(At)||"model"}_snapshot_${Date.now()}.png`,Qt=createEl("a");Qt.href=xe,Qt.download=st,activeDocument.body.appendChild(Qt),Qt.click(),Qt.remove(),vi(ut,H("helper.downloaded"))}catch(xe){console.error("[AI3D] Download snapshot failed:",xe),vi(ut,H("helper.failed"))}});let bt=C(g.createEl("button",{cls:"ai3d-inline-btn",attr:{"aria-label":H("helper.removePreviewLabel")}}));Qr(bt,"remove-preview"),bt.appendChild(Br('')),bt.addEventListener("click",s);let qe=m.createEl("button",{cls:"ai3d-inline-btn is-hidden ai3d-annot-btn",attr:{"aria-label":H(d.labelKey),"aria-pressed":"false"}});Qr(qe,"toggle-annotation"),qe.appendChild(Br(''));let Je=qe.createSpan({cls:"ai3d-pin-badge is-hidden"});qe.addEventListener("click",()=>{if(!o)return;M||Ue();let X=o();M=X,se(),vi(qe,X?H(d.activeTooltipKey):H(d.inactiveTooltipKey))});let Wt=u.createEl("button",{cls:"ai3d-inline-btn ai3d-mobile-more-toggle",attr:{"aria-label":H("helper.showMoreActionsLabel"),"aria-pressed":"false"}});Wt.appendChild(Br('')),Wt.addEventListener("click",()=>{O=!O,Wt.setAttribute("aria-label",O?H("helper.hideMoreActionsLabel"):H("helper.showMoreActionsLabel")),V(),vi(Wt,O?H("helper.moreActionsShown"):H("helper.moreActionsHidden"))}),n.insertBefore(u,e.nextSibling);let Ut=u.createDiv({cls:"ai3d-measurement-details is-hidden"});Ut.setAttribute("role","group"),Ut.setAttribute("aria-label",H("helper.calibrateTitle")),Ut.addEventListener("pointerdown",_),Ut.addEventListener("mousedown",_),Ut.addEventListener("click",_),Ut.createDiv({cls:"ai3d-measurement-details-title",text:H("helper.calibrateTitle")});let yi=Ut.createDiv({cls:"ai3d-measurement-section ai3d-measurement-records-section"});yi.createDiv({cls:"ai3d-measurement-section-title",text:H("helper.measurementRecordsTitle")});let oe=yi.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-detail-actions"}),rt=oe.createSpan({cls:"ai3d-measurement-record-summary"}),Ce=oe.createEl("button",{cls:"ai3d-inline-btn ai3d-measurement-detail-action",attr:{"aria-label":H("helper.copyMeasurementsLabel")}});Qr(Ce,"copy-measurements"),Ce.appendChild(Br('')),Ce.addEventListener("click",()=>{rr(Ce)});let ft=oe.createEl("button",{cls:"ai3d-inline-btn ai3d-measurement-detail-action",attr:{"aria-label":H("helper.clearMeasurementsLabel")}});Qr(ft,"clear-measurements"),ft.appendChild(Br('')),ft.addEventListener("click",()=>{hi(ft)});let nt=Ut.createDiv({cls:"ai3d-measurement-section ai3d-measurement-calibration-section"});nt.createDiv({cls:"ai3d-measurement-section-title",text:H("helper.measurementCalibrationTitle")});let Ge=nt.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-unit-row"});Ge.createSpan({cls:"ai3d-measurement-detail-label",text:H("helper.measurementUnitLabel")});let Mt=Ge.createEl("select",{cls:"ai3d-measurement-detail-select"});for(let X of["um","mm","cm","m"]){let xe=Mt.createEl("option");xe.value=X,xe.textContent=X}Mt.value="mm";let qt=nt.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-reference-row"});qt.createSpan({cls:"ai3d-measurement-detail-label",text:H("helper.calibrateReference")});let Er=qt.createSpan({cls:"ai3d-measurement-detail-readonly ai3d-measurement-reference-value"}),_i=qt.createEl("input",{cls:"ai3d-measurement-detail-input ai3d-measurement-reference-input",attr:{type:"number",step:"any",min:"0",placeholder:H("helper.calibrateReferencePlaceholder")}}),Gr=qt.createEl("button",{cls:"ai3d-inline-btn ai3d-measurement-reference-apply",text:H("helper.calibrateReferenceApply"),attr:{type:"button"}});Qr(Gr,"calibrate-reference");let cr=Ut.createDiv({cls:"ai3d-measurement-section ai3d-measurement-size-section"});cr.createDiv({cls:"ai3d-measurement-section-title",text:H("helper.measurementModelSizeTitle")});let Bs=cr.createDiv({cls:"ai3d-measurement-detail-row"});Bs.createSpan({cls:"ai3d-measurement-detail-label",text:H("helper.calibrateCurrent")});let aS=Bs.createSpan({cls:"ai3d-measurement-detail-readonly"}),kg=Bs.createSpan({cls:"ai3d-measurement-detail-readonly"}),zg=Bs.createSpan({cls:"ai3d-measurement-detail-readonly"}),za=cr.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-size-row"});za.createSpan({cls:"ai3d-measurement-detail-label",text:H("helper.calibrateReal")});let ll=za.createEl("input",{cls:"ai3d-measurement-detail-input",attr:{type:"number",step:"any",placeholder:"X"}}),ic=za.createEl("input",{cls:"ai3d-measurement-detail-input",attr:{type:"number",step:"any",placeholder:"Y"}}),rc=za.createEl("input",{cls:"ai3d-measurement-detail-input",attr:{type:"number",step:"any",placeholder:"Z"}}),Hg=cr.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-size-options"}).createEl("label",{cls:"ai3d-measurement-detail-lock"}),Zd=Hg.createEl("input",{attr:{type:"checkbox",checked:"true"}});Hg.appendChild(activeDocument.createTextNode(" "+H("helper.calibrateLock")));let Xg=cr.createDiv({cls:"ai3d-measurement-detail-row ai3d-measurement-detail-scale-actions"}),Oh=Xg.createEl("button",{cls:"ai3d-inline-btn",text:H("helper.calibrateApply")}),oS=Xg.createEl("button",{cls:"ai3d-inline-btn",text:H("helper.calibrateReset")}),Us=null;function lS(){var At;let X=i();if(!X||!cn(X))return null;let xe=X.getMeasurementState().records;return(At=xe[xe.length-1])!=null?At:null}function I0(){let X=i();if(!X||!cn(X))return;let xe=X.getMeasurementState(),At=xe.bounds,kt=xe.scale;if(Mt.value=xe.unit,Us=At,At){let Qt=xe.unit;aS.textContent=`X: ${No(At.x*kt.x)} ${Qt}`,kg.textContent=`Y: ${No(At.y*kt.y)} ${Qt}`,zg.textContent=`Z: ${No(At.z*kt.z)} ${Qt}`}else aS.textContent="X: -",kg.textContent="Y: -",zg.textContent="Z: -";let st=lS();Er.textContent=st?zf(st.reading.distance,st.reading.unit,!1):H("helper.calibrateReferenceEmpty"),_i.disabled=!st,Gr.disabled=!st,_i.placeholder=st?No(st.reading.distance):H("helper.calibrateReferencePlaceholder")}function C0(){var Qt,$r;let X=i();if(!X||!cn(X)||!Us)return;let xe=parseFloat(ll.value),At=parseFloat(ic.value),kt=parseFloat(rc.value),st=EV(Us,{x:Number.isFinite(xe)?xe:void 0,y:Number.isFinite(At)?At:void 0,z:Number.isFinite(kt)?kt:void 0},X.getMeasurementScale(),Zd.checked);if(!st){vi(Oh,H("helper.calibrateNeedsValue"));return}(Qt=X.setMeasurementUnit)==null||Qt.call(X,Mt.value),($r=X.setMeasurementScale)==null||$r.call(X,st),ce(),Qe(),vi(Oh,H("helper.calibrated"))}function P0(){var st,Qt;let X=i();if(!X||!cn(X))return;let xe=parseFloat(_i.value);(st=X.setMeasurementUnit)==null||st.call(X,Mt.value);let At=lS();if(!At||!Number.isFinite(xe)||xe<=0){vi(Gr,H("helper.calibrateNeedsValue"));return}let kt=vV(X.getMeasurementScale(),At.reading.distance,xe);if(!kt){vi(Gr,H("helper.calibrateNeedsValue"));return}(Qt=X.setMeasurementScale)==null||Qt.call(X,kt),_i.value="",ce(),Qe(),vi(Gr,H("helper.calibrated"))}function L0(){var xe,At;let X=i();!X||!cn(X)||((xe=X.setMeasurementUnit)==null||xe.call(X,Mt.value),(At=X.setMeasurementScale)==null||At.call(X,{x:1,y:1,z:1}),_i.value="",ce(),Qe(),vi(oS,H("helper.calibrateResetDone")))}function W(X){if(!Zd.checked||!Us)return;let At=parseFloat((X==="x"?ll:X==="y"?ic:rc).value);if(!isFinite(At)||At===0)return;let kt=Us[X];if(kt<=1e-4)return;let st=At/kt;X!=="x"&&(ll.value=No(Us.x*st)),X!=="y"&&(ic.value=No(Us.y*st)),X!=="z"&&(rc.value=No(Us.z*st))}ll.addEventListener("input",()=>W("x")),ic.addEventListener("input",()=>W("y")),rc.addEventListener("input",()=>W("z")),Mt.addEventListener("change",()=>{let X=i();!X||!cn(X)||(X.setMeasurementUnit(Mt.value),ce(),Qe())}),Gr.addEventListener("click",P0),Oh.addEventListener("click",C0),oS.addEventListener("click",L0);function ce(){if(I0(),Us){let X=i(),xe=X&&cn(X)?X.getMeasurementScale():{x:1,y:1,z:1};ll.value=No(Us.x*xe.x),ic.value=No(Us.y*xe.y),rc.value=No(Us.z*xe.z)}else ll.value="",ic.value="",rc.value=""}function Re(X,xe){X&&ce(),Ut.classList.toggle("is-hidden",!X),Ke.classList.toggle("is-expanded",X),Ke.setAttribute("aria-expanded",String(X)),Qe(),vi(xe,X?H("helper.calibrateOpen"):H("helper.calibrateClose"))}Ke.addEventListener("click",()=>{Ke.classList.contains("is-hidden")||Re(Ut.classList.contains("is-hidden"),Ke)});let Se=u.createDiv({cls:"ai3d-slice-details is-hidden"});Se.setAttribute("role","group"),Se.setAttribute("aria-label",H("helper.sliceTitle")),Se.addEventListener("pointerdown",_),Se.addEventListener("mousedown",_),Se.addEventListener("click",_);let Te=Se.createDiv({cls:"ai3d-slice-header"});Te.createSpan({cls:"ai3d-slice-title",text:H("helper.sliceTitle")});let St=Te.createSpan({cls:"ai3d-slice-summary"}),It=Te.createEl("button",{cls:"ai3d-slice-reset-btn",attr:{type:"button","aria-label":H("helper.sliceReset")}});It.appendChild(Br(''));let pt=Se.createDiv({cls:"ai3d-slice-row ai3d-slice-status-row"});pt.createSpan({cls:"ai3d-slice-label",text:H("helper.sliceOffsetLabel")});let Lt=pt.createDiv({cls:"ai3d-slice-number-control"}),Dt=Lt.createEl("input",{cls:"ai3d-slice-number-input ai3d-slice-offset-value",attr:{type:"number",min:"0",max:"100",step:"0.1",inputmode:"decimal"}});Lt.createSpan({cls:"ai3d-slice-number-unit",text:"%"});let oi=Se.createDiv({cls:"ai3d-slice-row ai3d-slice-rotation-row"});oi.createSpan({cls:"ai3d-slice-label",text:H("helper.sliceRotationLabel")});let si={};for(let X of["x","y","z"]){let xe=oi.createDiv({cls:`ai3d-slice-axis-control ai3d-slice-axis-${X}`});xe.createSpan({cls:"ai3d-slice-axis-label",text:X.toUpperCase()}),si[X]=xe.createEl("input",{cls:"ai3d-slice-number-input ai3d-slice-rotation-input",attr:{type:"number",min:"-180",max:"180",step:"0.1",inputmode:"decimal","aria-label":`${H("helper.sliceRotationLabel")} ${X.toUpperCase()}`}}),xe.createSpan({cls:"ai3d-slice-number-unit",text:"\xB0"})}function Ft(X){let xe=Math.round((Number.isFinite(X)?X:0)*10)/10;return Number.isInteger(xe)?String(xe):xe.toFixed(1)}function ji(){let X=i();return X&&Hd(X)?X:null}function Nr(){let X=ji();X&&(X.resetSlicePlane(),$i())}function Pr(X){X!==A&&(R==null||R(),R=null,A=X,X!=null&&X.observeSlice&&(R=X.observeSlice(()=>{ue(),$i()})))}function $i(){var kt;let X=ji();if(Pr(X),!X){Se.classList.add("is-hidden");return}let xe=X.getSliceState();L(Ve,xe.active),Se.classList.toggle("is-hidden",!xe.active),activeDocument.activeElement!==Dt&&(Dt.value=Ft(Math.max(0,Math.min(xe.offset,1))*100));let At=(kt=xe.rotationDegrees)!=null?kt:{x:0,y:0,z:0};for(let st of["x","y","z"])activeDocument.activeElement!==si[st]&&(si[st].value=Ft(At[st]));St.textContent=xe.dragging?H(xe.interactionMode==="rotate"?"helper.sliceRotating":"helper.sliceMoving"):H("helper.sliceGizmoReady")}It.addEventListener("click",Nr);let dn=()=>{let X=ji();if(!X)return;let xe=Number.parseFloat(Dt.value);if(!Number.isFinite(xe)){$i();return}X.setSliceOffset(Math.max(0,Math.min(xe,100))/100)},yt=()=>{var kt;let X=ji();if(!X)return;let xe=(kt=X.getSliceState().rotationDegrees)!=null?kt:{x:0,y:0,z:0},At=st=>{let Qt=Number.parseFloat(si[st].value);return Number.isFinite(Qt)?Qt:xe[st]};X.setSliceRotation({x:At("x"),y:At("y"),z:At("z")})};Dt.addEventListener("change",dn),Dt.addEventListener("keydown",X=>{X.key==="Enter"&&dn()});for(let X of["x","y","z"])si[X].addEventListener("change",yt),si[X].addEventListener("keydown",xe=>{xe.key==="Enter"&&yt()});return V(),se(),{showAnimButton(){ae.classList.remove("is-hidden"),w()},showAnnotateButton(){qe.classList.remove("is-hidden"),w()},updateAnnotationBadge(X){X>0?(Je.textContent=String(X),Je.classList.remove("is-hidden")):Je.classList.add("is-hidden")},setMobileInteractionMode(X){f&&q(X)},syncCapabilities:se}}function vi(n,e){var i;(i=N1.get(n))==null||i.remove();let t=n.createSpan({cls:"ai3d-tooltip"});t.textContent=e,N1.set(n,t),window.setTimeout(()=>{t.remove(),N1.delete(n)},1500)}var TTe,Mg,ATe,N1,w1=y(()=>{"use strict";xn();zn();Ah();Ma();As();sv();L1();j$();TTe=er("helper-buttons");Mg=[.5,.75,1,1.25,1.5,2],ATe=2;N1=new WeakMap});function $$(n){let e=ma(n.sourceExt),t=[];return e!==n.sourceExt&&t.push(`Normalized extension '${n.sourceExt}' -> '${e}'.`),xTe.debug("prepare direct load",{path:n.path,sourceExt:n.sourceExt,normalizedExt:e,warningCount:t.length}),{effectivePath:n.path,effectiveExt:e,warnings:t}}var xTe,J$=y(()=>{"use strict";Wa();zn();xTe=er("direct-load-service")});var eJ={};Be(eJ,{MissingConverterError:()=>Xd,MobileConversionUnavailableError:()=>xh,describeModelLoadFailure:()=>WE,formatModelLoadFailure:()=>ky,isMissingConverterError:()=>zE});function zy(n){return`.${n.trim().toLowerCase()}`}function zE(n){return n instanceof Xd}function ky(n){var e;if(n instanceof Xd){let t=(e=RTe[n.converterId])!=null?e:n.converterId;return Wi("modelLoad.warningMessage",{ext:zy(n.sourceExt),converterName:t})}return n instanceof xh?Wi("modelLoad.mobileWarningMessage",{ext:zy(n.sourceExt)}):Wi("modelLoad.errorMessage",{reason:n instanceof Error?n.message:String(n)})}function WE(n){return n instanceof Xd?{level:"warning",title:H("modelLoad.warningTitle"),message:ky(n),hint:H("modelLoad.warningHint")}:n instanceof xh?{level:"warning",title:H("modelLoad.warningTitle"),message:ky(n),hint:H("modelLoad.mobileWarningHint")}:{level:"error",title:H("modelLoad.errorTitle"),message:ky(n),hint:H("modelLoad.errorHint")}}var RTe,Xd,xh,yg=y(()=>{"use strict";xn();RTe={freecad:"FreeCAD",obj2gltf:"obj2gltf",fbx2gltf:"FBX2glTF",assimp:"mesh",sldprt:"SolidWorks"};Xd=class extends Error{constructor(t,i){super(`Converter '${t}' is not registered for ${zy(i)}. Enable the matching converter in plugin settings before loading this format.`);this.converterId=t;this.sourceExt=i;this.name="MissingConverterError"}},xh=class extends Error{constructor(t){super(`Format ${zy(t)} requires local conversion tools that are unavailable on iOS, iPadOS, and Android.`);this.sourceExt=t;this.name="MobileConversionUnavailableError"}}});var nJ={};Be(nJ,{convertForPreview:()=>LTe});function iJ(n,e){let t=n.lastIndexOf("."),i=t>0?n.slice(0,t):n,r=Math.max(i.lastIndexOf("/"),i.lastIndexOf("\\")),s=i.slice(0,r+1),a=i.slice(r+1);return`${s}${a}.ai3d-converted.${e}`}function bTe(n){let e=2166136261;for(let t=0;t>>0).toString(16).padStart(8,"0")}function rJ(n){let e=$n(n);return Qn(n,e).replace(/[^A-Za-z0-9._-]+/g,"_").replace(/^_+|_+$/g,"").slice(0,80)||"model"}function tJ(n){return Qn(n,$n(n)).toLowerCase()}function MTe(n,e,t){if(!t)return iJ(n,e);let i=rJ(n),r=bTe(`${n}::${e}`);return tr(t,`${i}-${r}.ai3d-converted.${e}`)}function yTe(n,e,t){return n.converterId!==e?!1:t?n.converterId===t.converterId&&n.converterCacheKey===t.cacheKey:!0}async function ITe(n){if(!n)return!1;try{return await Ss(n,Ts),!0}catch(e){return!1}}async function Hy(n,e,t){if(!e)return!1;try{let[i,r]=await Promise.all([t!=null?t:Mu(n),Mu(e)]);return r.size>0&&r.mtimeMs>=i.mtimeMs}catch(i){return!1}}async function CTe(n){return typeof n=="function"?await n():n}async function PTe(n,e,t,i){var l,c;let r=(c=(l=n.convertedAssetCache)==null?void 0:l.entries())!=null?c:[];if(r.length===0)return;let s=tJ(n.sourcePath),a=rJ(n.sourcePath),o=r.filter(f=>f.sourcePath!==n.sourcePath&&f.sourceExt===n.sourceExt&&f.targetExt===e&&f.outputExt===e&&f.converterId===t&&tJ(f.sourcePath)===s&&Qn(f.outputPath).startsWith(`${a}-`)&&Qn(f.outputPath).endsWith(`.ai3d-converted.${e}`)).sort((f,d)=>d.createdAt-f.createdAt);for(let f of o)if(await Hy(n.sourcePath,f.outputPath,i))return f}async function LTe(n){var u,h,m,g,p,_,v,E,S,T;if(n.capability.strategy!=="convert")throw new Error(`Expected convert strategy, got '${n.capability.strategy}'.`);let e=n.capability.converterId,t=(u=n.capability.outputFormat)!=null?u:"glb";if(!e)throw new Error(`Format .${n.sourceExt} does not define a converter id.`);mf.info("prepare conversion route",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,converterId:e});let i=null,r=()=>(i!=null||(i=Mu(n.sourcePath)),i),s=(h=n.convertedAssetCache)==null?void 0:h.get(n.sourcePath,n.sourceExt,t);if(s)if(!await ITe(s.outputPath))mf.warn("conversion cache stale",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:s.outputPath}),(m=n.convertedAssetCache)==null||m.delete(n.sourcePath,n.sourceExt,t);else if(!yTe(s,e))mf.warn("conversion cache identity mismatch",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,cachedConverterId:s.converterId,cachedConverterCacheKey:s.converterCacheKey,currentConverterId:e}),(g=n.convertedAssetCache)==null||g.delete(n.sourcePath,n.sourceExt,t);else if(!await Hy(n.sourcePath,s.outputPath,r()))mf.warn("conversion cache output older than source",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:s.outputPath}),(p=n.convertedAssetCache)==null||p.delete(n.sourcePath,n.sourceExt,t);else return mf.info("conversion cache hit",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:s.outputPath}),{effectivePath:s.outputPath,effectiveExt:s.outputExt,warnings:[...s.warnings,"Using cached conversion output."]};let a=MTe(n.sourcePath,t,n.outputRoot);if(await Hy(n.sourcePath,a,r()))return mf.info("conversion output already exists",{sourcePath:n.sourcePath,outputPath:a}),(_=n.convertedAssetCache)==null||_.set({cacheVersion:2,converterId:e,converterCacheKey:e,sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:a,outputExt:t,warnings:["Using existing conversion output."],createdAt:Date.now()}),{effectivePath:a,effectiveExt:t,warnings:["Using existing conversion output."]};let o=iJ(n.sourcePath,t);if(o!==a&&await Hy(n.sourcePath,o,r()))return mf.info("legacy conversion output already exists",{sourcePath:n.sourcePath,outputPath:o}),(v=n.convertedAssetCache)==null||v.set({cacheVersion:2,converterId:e,converterCacheKey:e,sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:o,outputExt:t,warnings:["Using existing conversion output."],createdAt:Date.now()}),{effectivePath:o,effectiveExt:t,warnings:["Using existing conversion output."]};let l=await PTe(n,t,e,r());if(l)return mf.info("relocated conversion cache hit",{sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,previousSourcePath:l.sourcePath,outputPath:l.outputPath}),(E=n.convertedAssetCache)==null||E.set({cacheVersion:2,converterId:l.converterId,converterCacheKey:l.converterCacheKey,sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:l.outputPath,outputExt:t,warnings:[...l.warnings,"Using relocated conversion output."],createdAt:Date.now()}),{effectivePath:l.outputPath,effectiveExt:t,warnings:[...l.warnings,"Using relocated conversion output."]};let c=await CTe(n.conversionManager);if(!c)throw new Error(`Format .${n.sourceExt} requires conversion support, but no conversion manager is available.`);if(!c.canConvert(n.sourceExt))throw new Xd(e,n.sourceExt);let f=await c.getConverterCacheIdentity(n.sourceExt);n.outputRoot&&await Zn(n.outputRoot,{recursive:!0});let d=await c.convert({sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:a});return(T=n.convertedAssetCache)==null||T.set({cacheVersion:2,converterId:e,converterCacheKey:(S=f==null?void 0:f.cacheKey)!=null?S:e,sourcePath:n.sourcePath,sourceExt:n.sourceExt,targetExt:t,outputPath:d.outputPath,outputExt:d.outputExt,warnings:d.warnings,createdAt:Date.now()}),mf.info("conversion route done",{sourcePath:n.sourcePath,outputPath:d.outputPath,warningCount:d.warnings.length}),{effectivePath:d.outputPath,effectiveExt:d.outputExt,warnings:d.warnings}}var mf,sJ=y(()=>{"use strict";N0();zn();hr();yg();mf=er("conversion-service")});var aJ={};Be(aJ,{prepareModelInput:()=>Ig});function DTe(n,e){var t;return!!((t=n.preferConversionExts)!=null&&t.includes(e))}async function Ig(n){var a,o;let e=ma((a=n.path.split(".").pop())!=null?a:""),t=Kg(e);if(Yd.info("prepare model input",{path:n.path,sourceExt:e}),!t||!t.enabled)throw Yd.warn("unsupported format",{sourceExt:e,path:n.path}),jg(e)?new Error("SPLAT preview is disabled in packaged builds. Local-only .splat support is planned; .spz and .sog remain unavailable until their decoders can be bundled locally."):new Error(`Unsupported format: .${e}`);let i=DTe(n,e);if(t.strategy==="convert"||i&&!!t.converterId){if(Rr())throw Yd.warn("conversion unavailable on mobile",{sourceExt:e,path:n.path}),new xh(e);if(!n.absolutePath)throw Yd.error("filesystem path missing for conversion",{sourceExt:e,path:n.path}),new Error(`Format .${e} requires a local filesystem path for conversion, but none was resolved for '${n.path}'.`);let l=t.strategy==="convert"?t:{...t,strategy:"convert",outputFormat:(o=t.outputFormat)!=null?o:"glb"};if(!l.converterId)throw Yd.error("preferred conversion route missing converter id",{sourceExt:e,path:n.path}),new Error(`Format .${e} is configured to prefer conversion, but no converter id is defined.`);i&&t.strategy==="direct"&&Yd.info("preferred conversion route",{sourceExt:e,path:n.path,converterId:l.converterId});let{convertForPreview:c}=await Promise.resolve().then(()=>(sJ(),nJ)),f=await c({sourcePath:n.absolutePath,sourceExt:e,capability:l,conversionManager:n.conversionManager,convertedAssetCache:n.convertedAssetCache,outputRoot:n.conversionOutputRoot});return Yd.info("conversion completed",{sourceExt:e,outputExt:f.effectiveExt,outputPath:f.effectivePath,warningCount:f.warnings.length}),{sourcePath:n.path,sourceExt:e,strategy:"convert",effectivePath:f.effectivePath,effectiveExt:f.effectiveExt,warnings:f.warnings}}let s=$$({path:n.path,sourceExt:e});return Yd.debug("direct route",{sourceExt:e,path:n.path,warningCount:s.warnings.length}),{sourcePath:n.path,sourceExt:e,strategy:t.strategy,effectivePath:s.effectivePath,effectiveExt:s.effectiveExt,warnings:s.warnings}}var Yd,Xy=y(()=>{"use strict";Wa();J$();yg();zn();Ma();Yd=er("model-pipeline")});function HE(n){return{path:n.effectivePath,ext:n.effectiveExt,strategy:n.strategy,sourcePath:n.sourcePath,sourceExt:n.sourceExt,warnings:n.warnings}}var F1=y(()=>{"use strict"});function Rh(n,e){var r;let i=e.auxiliaryFileFolder.trim()||HU(n,OTe);return(r=Ec(n,i))!=null?r:void 0}var OTe,Yy=y(()=>{"use strict";As();OTe="ai-model-workbench/converted-assets"});function bh(n){let e=n.createDiv({cls:"ai3d-loading-overlay"}),t=e.createDiv({cls:"ai3d-loading-skeleton"});t.createDiv({cls:"ai3d-loading-skeleton-canvas"});let i=t.createDiv({cls:"ai3d-loading-skeleton-meta"});i.createDiv({cls:"ai3d-loading-skeleton-line"}),i.createDiv({cls:"ai3d-loading-skeleton-line is-short"}),e.createDiv({cls:"ai3d-loading-spinner"});let r=e.createDiv({cls:"ai3d-loading-text"}),s="loading.default",a="",o=()=>{r.textContent=s?H(s):a};o();let c=e.createDiv({cls:"ai3d-loading-bar-track"}).createDiv({cls:"ai3d-loading-bar-fill is-indeterminate"}),f=!1,d=nB(()=>{!f&&s&&o()});return{el:e,setPhase(u){s=null,a=u,f||o()},setPhaseKey(u){s=u,f||o()},setProgress(u){f||(u<0?(c.className="ai3d-loading-bar-fill is-indeterminate",c.style.removeProperty("--bar-width")):(c.className="ai3d-loading-bar-fill",c.style.setProperty("--bar-width",`${Math.min(100,Math.max(0,u))}%`)))},hide(){f||(f=!0,d(),e.classList.add("is-hiding"),window.setTimeout(()=>e.remove(),300))}}}var Ky=y(()=>{"use strict";xn()});var B1={};Be(B1,{renderModelLoadFailure:()=>XE,renderModelPerformanceFeedback:()=>YE});function XE(n,e){let t=n.createDiv({cls:"ai3d-inline-empty ai3d-load-feedback-shell"});Rr()&&t.classList.add("is-mobile");let i=t.createDiv({cls:`ai3d-load-feedback is-${e.level}`});return i.createDiv({cls:"ai3d-load-feedback-title",text:e.title}),i.createDiv({cls:"ai3d-load-feedback-message",text:e.message}),i.createDiv({cls:"ai3d-load-feedback-hint",text:e.hint}),t}function YE(n,e){var o,l,c,f,d,u,h;if((!e.performanceTier||e.performanceTier==="light")&&!((o=e.resourceWarnings)!=null&&o.length))return null;let t=(l=e.performanceTier)!=null?l:"light",i=((c=e.splatCount)!=null?c:e.triangleCount).toLocaleString(),r=e.splatCount!==void 0?"splats":"triangles",s=n.createDiv({cls:`ai3d-performance-feedback is-${t}`});s.createDiv({cls:"ai3d-performance-feedback-tier",text:(f=e.resourceWarnings)!=null&&f.length?"assets":(d=e.performanceTier)!=null?d:"light"}),s.createDiv({cls:"ai3d-performance-feedback-meta",text:(u=e.resourceWarnings)!=null&&u.length?e.resourceWarnings[0]:`${i} ${r} \xB7 ${e.materialCount.toLocaleString()} materials`});let a=[...(h=e.resourceWarnings)!=null?h:[],...e.performanceHint?[e.performanceHint]:[]];return a.length>0&&(s.title=a.join(` `)),window.setTimeout(()=>s.classList.add("is-subtle"),4200),s}var KE=y(()=>{"use strict";Ma()});function pf(n){var t;let e=(t=(n!=null?n:"").split(".").pop())==null?void 0:t.trim().toLowerCase();return NTe.has(e)?e:"glb"}function Mh(n,e,t){return typeof n=="string"&&wTe.has(n)?n:e===t?"direct":"convert"}var NTe,wTe,jy=y(()=>{"use strict";NTe=new Set(["glb","gltf","stl","obj","splat","ply","fbx","step","stp","iges","igs","brep","sldprt","3mf","dae"]),wTe=new Set(["direct","convert"])});function Cg(n,e,t){uJ(n,{label:Wi(cJ[e],{model:Qs(t)||H("workbench.modelTitle")}),shortcutKeys:FTe})}function fJ(n){uJ(n,{label:H(cJ.grid),shortcutKeys:BTe})}function Pg(n,e){n.addEventListener("keydown",t=>{var s,a,o,l,c;let i=e();if(!i)return;let r=t.key.toLowerCase();r==="r"?((s=i.resetView)==null||s.call(i),t.preventDefault()):r==="w"?((a=i.toggleWireframe)==null||a.call(i),t.preventDefault()):r==="g"?((o=i.toggleOrientationGizmo)==null||o.call(i),t.preventDefault()):r==="b"?((l=i.toggleBoundingBox)==null||l.call(i),t.preventDefault()):r===" "?((c=i.toggleAnimation)==null||c.call(i),t.preventDefault()):r==="m"?(cn(i)&&i.toggleMeasurement(),t.preventDefault()):r==="escape"&&cn(i)&&dx(i)&&t.preventDefault()})}function dJ(n,e){n.addEventListener("keydown",t=>{var s,a;let i=e();if(!i)return;let r=t.key.toLowerCase();r==="r"?((s=i.resetView)==null||s.call(i),t.preventDefault()):r==="w"&&((a=i.toggleWireframe)==null||a.call(i),t.preventDefault())})}function uJ(n,e){zTe(n),n.setAttribute("role","application"),VTe(n,e.label),n.setAttribute("aria-keyshortcuts",e.shortcutKeys.join(" ")),kTe(n),n.dataset.testid="ai3d-preview-canvas"}function VTe(n,e){let t=n.dataset.ai3dLabelId,i=t?n.ownerDocument.getElementById(t):null,r=i instanceof HTMLElement?i:GTe(n);if(!r){n.removeAttribute("aria-label"),n.removeAttribute("aria-labelledby"),delete n.dataset.ai3dLabelId;return}r.setText(e),n.dataset.ai3dLabelId=r.id,n.setAttribute("aria-labelledby",r.id),n.removeAttribute("aria-label")}function GTe(n){let e=n.parentElement;if(!e)return null;let t=e.createSpan({cls:"ai3d-visually-hidden"});return t.id=`ai3d-preview-canvas-label-${++UTe}`,t}function kTe(n){n.removeAttribute("title"),n.removeAttribute("data-tooltip"),n.removeAttribute("aria-description")}function zTe(n){if(lJ(n),oJ.has(n)||typeof MutationObserver=="undefined")return;oJ.add(n),new MutationObserver(()=>lJ(n)).observe(n,{attributes:!0,attributeFilter:["tabindex"]})}function lJ(n){n.tabIndex!==0&&(n.tabIndex=0),n.getAttribute("tabindex")!=="0"&&n.setAttribute("tabindex","0")}var FTe,BTe,oJ,UTe,cJ,Zy=y(()=>{"use strict";xn();sv();Ah();As();FTe=["R","W","G","B","M","Space"],BTe=["R","W"],oJ=new WeakSet,UTe=0,cJ={inline:"previewCanvas.inlineLabel",grid:"previewCanvas.gridLabel","live-preview":"previewCanvas.liveLabel","direct-view":"previewCanvas.directLabel"}});function hJ(n){let{contentEl:e,filePath:t,mobile:i,getPreview:r}=n,s=e.createDiv({cls:"ai3d-workspace"}),a=s.createDiv({cls:"ai3d-workspace-track-top"}),o=a.createDiv({cls:"ai3d-workspace-main"}),l=a.createDiv({cls:"ai3d-resize-handle ai3d-resize-handle-h"}),c=a.createDiv({cls:"ai3d-workspace-sidebar"}),f=createDiv(),d=f.createDiv({cls:"ai3d-preview-host"}),u=f.createEl("canvas");u.className="ai3d-canvas-full",Cg(u,"direct-view",t),Pg(u,r),d.appendChild(u);let h=f.createDiv();h.className="ai3d-annot-mode-overlay is-hidden",d.appendChild(h),o.appendChild(d);let m=c.createDiv({cls:"ai3d-sidebar-content"}),g=m.createDiv({cls:"ai3d-direct-workbench-panel is-hidden"}),p=m.createDiv({cls:"ai3d-sidebar-body"}),_=s.createDiv({cls:"ai3d-resize-handle ai3d-resize-handle-v"});return i&&o.createDiv({cls:"ai3d-mobile-mode-hint ai3d-mobile-mode-hint--inline",text:H("directView.mobileHint")}),{workspace:s,topTrack:a,mainArea:o,hHandle:l,host:d,canvas:u,modeOverlay:h,sidebarContent:p,vHandle:_,workbenchPanel:g}}var mJ=y(()=>{"use strict";xn();Zy()});function qy(n){return Math.round(n!=null?n:0).toLocaleString()}function WTe(n){return[n.boundingSize.x,n.boundingSize.y,n.boundingSize.z].map(e=>e.toFixed(2)).join(" x ")}function HTe(n){return n==="three"?"Three.js":"Babylon.js"}function pJ(n){var f,d;let{panel:e,summary:t,route:i,registeredPartCount:r}=n;e.empty(),e.removeClass("is-hidden"),e.dataset.ai3dBackend=i.backend,e.dataset.ai3dRouteReason=i.reason;let s=e.createDiv({cls:"ai3d-direct-workbench-overview"}),a=s.createDiv({cls:"ai3d-direct-workbench-status"}),o=a.createDiv({cls:"ai3d-direct-workbench-line"});o.createSpan({cls:"ai3d-direct-workbench-label",text:H("directWorkbench.backendLabel")}),o.createSpan({cls:"ai3d-direct-workbench-value",text:HTe(i.backend)});let l=a.createDiv({cls:"ai3d-direct-workbench-line ai3d-direct-workbench-route"});l.createSpan({cls:"ai3d-direct-workbench-label",text:H("directWorkbench.routeLabel")}),l.createSpan({cls:"ai3d-direct-workbench-value",text:i.reason});let c=s.createDiv({cls:"ai3d-direct-workbench-metrics"});Lg(c,H("workbench.meshesLabel"),qy(t.meshCount)),Lg(c,H("directWorkbench.partCandidatesLabel"),qy(r)),Lg(c,t.splatCount!==void 0?H("workbench.splatsLabel"):H("workbench.trianglesLabel"),qy((f=t.splatCount)!=null?f:t.triangleCount)),Lg(c,H("workbench.materialsLabel"),qy(t.materialCount)),Lg(c,H("workbench.boundingSizeLabel"),WTe(t)),Lg(c,H("directWorkbench.performanceLabel"),(d=t.performanceTier)!=null?d:"light")}function Lg(n,e,t){let i=n.createDiv({cls:"ai3d-direct-workbench-metric"});i.createSpan({cls:"ai3d-direct-workbench-label",text:e}),i.createSpan({cls:"ai3d-direct-workbench-value",text:t})}var gJ=y(()=>{"use strict";xn()});function XTe(n,e){return n.experimentalThreeWorkbench&&n.useThreeRenderer&&e.strategy==="direct"&&Qy.has(e.ext)&&Qy.has(e.sourceExt)}function YTe(n){return _J.has(n.ext)?n.strategy==="direct"?_J.has(n.sourceExt):n.strategy==="convert"&&Qy.has(n.ext):!1}function KTe(n,e){return n.useThreeForConvertedDirectView&&e.strategy==="convert"&&Qy.has(e.ext)}function vJ(n,e){let t=XTe(n,e),i=YTe(e),r=KTe(n,e);return{ext:e.ext,annotationMode:"edit",allowEditModeOnThree:!0,allowWorkbenchFeaturesOnThree:t,requireWorkbenchFeatures:t||!i,rendererRollout:r?"three-direct-glb":n.previewRendererRollout,useThreeRenderer:r?!0:n.useThreeRenderer}}var _J,Qy,EJ=y(()=>{"use strict";_J=new Set(["glb","gltf","stl","ply","obj"]),Qy=new Set(["glb","gltf"])});function Dg(n){return{renderQuality:n.renderQuality,renderScale:n.renderScale}}function tAe(n,e){return!Number.isFinite(e!=null?e:Number.NaN)||(e!=null?e:0)<=0?Dg(n):(e!=null?e:0)>=ZTe?{renderQuality:n.renderQuality==="high"?"medium":n.renderQuality,renderScale:Math.min(n.renderScale,U1)}:(e!=null?e:0)>=jTe?{renderQuality:n.renderQuality==="low"?"low":"medium",renderScale:Math.min(n.renderScale,AJ)}:Dg(n)}function G1(n){var e;return(e=n.splatCount)!=null?e:n.triangleCount}function iAe(n){return n.splatCount!==void 0?n.splatCount>=TJ:G1(n)>=QTe}function rAe(n){return n.splatCount!==void 0?n.splatCount>=JTe:G1(n)>=$Te}function nAe(n){return n.splatCount!==void 0?n.splatCount>=TJ:G1(n)>=qTe}function xJ(n,e){return e.performanceTier==="extreme"?rAe(e)?{renderQuality:n.renderQuality==="low"?"low":"medium",renderScale:Math.min(n.renderScale,U1)}:Dg(n):e.performanceTier==="heavy"?iAe(e)?{renderQuality:n.renderQuality==="low"?"low":"medium",renderScale:Math.min(n.renderScale,U1)}:Dg(n):e.performanceTier==="medium"&&nAe(e)?{renderQuality:n.renderQuality,renderScale:Math.min(n.renderScale,AJ)}:Dg(n)}function Og(n){return n.startsWith("/")||n.startsWith("\\")||/^[A-Za-z]:[\\/]/.test(n)}function $y(n){var e;return(e=n.split(/[?#]/,1)[0])!=null?e:n}function RJ(n){try{return decodeURIComponent(n)}catch(e){return n}}function V1(n){let e=RJ(n).replace(/\\/g,"/"),t=[];for(let i of e.split("/"))if(!(!i||i===".")){if(i===".."){t.pop();continue}t.push(i)}return t.join("/")}function bJ(n,e){return V1(n?`${n}/${$y(e)}`:$y(e))}function MJ(n){let e=n.replace(/\\/g,"/").replace(/\/+$/,""),t=e.lastIndexOf("/");return t>0?e.slice(0,t):""}function sAe(n){return!n||n.startsWith("data:")?!0:eAe.test(n)&&!Og(n)}function aAe(n,e){return Og(n)?V1($y(e)):bJ(MJ(n),e)}async function oAe(n,e){let t=await lAe(n,e);return t===null?null:e.toLowerCase().split(/[?#]/,1)[0].endsWith(".gltf")?dAe(n,e,t):t}async function lAe(n,e){if(Og(e))try{let{stat:i}=await Promise.resolve().then(()=>(hr(),OA));return(await i(e)).size}catch(i){return null}let t=n.vault.getAbstractFileByPath(e);return yJ(t)?t.stat.size:null}async function cAe(n,e){if(Og(e))try{let{readFile:r}=await Promise.resolve().then(()=>(hr(),OA));return new TextDecoder().decode(await r(e))}catch(r){return null}let t=n.vault.getAbstractFileByPath(e),i=n.vault;if(!(t instanceof SJ.TFile)||typeof i.read!="function")return null;try{return await i.read(t)}catch(r){return null}}async function fAe(n,e,t){if(Og(e))try{let{pathJoin:a,pathNormalize:o,stat:l}=await Promise.resolve().then(()=>(hr(),OA)),c=$y(RJ(t)),f=o(e.replace(/[\\/][^\\/]*$/,"")),d=Og(c)?o(c):o(a(f,c));return(await l(d)).size}catch(a){return null}let i=MJ(e),r=bJ(i,t),s=n.vault.getAbstractFileByPath(r);return yJ(s)?s.stat.size:null}async function dAe(n,e,t){var l,c;let i=await cAe(n,e);if(!i)return t;let r;try{r=JSON.parse(i)}catch(f){return t}let s=t,a=new Set,o=async(f,d)=>{var p;let u=f==null?void 0:f.uri;if(!u||sAe(u))return;let h=aAe(e,u);if(!h||a.has(h))return;a.add(h);let m=await fAe(n,e,u);if(m!==null&&Number.isFinite(m)&&m>0){s+=m;return}let g=(p=f==null?void 0:f.byteLength)!=null?p:d;Number.isFinite(g)&&(g!=null?g:0)>0&&(s+=g!=null?g:0)};for(let f of(l=r.buffers)!=null?l:[])await o(f,f.byteLength);for(let f of(c=r.images)!=null?c:[])await o(f);return s}function yJ(n){let e=n;return!!e&&typeof e=="object"&&!!e.stat&&typeof e.stat.size=="number"}async function Ng(n,e,t){return tAe(t,await oAe(n,e))}var SJ,jTe,ZTe,qTe,QTe,$Te,TJ,JTe,AJ,U1,eAe,Jy=y(()=>{"use strict";SJ=require("obsidian"),jTe=64*1024*1024,ZTe=192*1024*1024,qTe=18e4,QTe=45e4,$Te=12e5,TJ=65e4,JTe=15e5,AJ=1.25,U1=1,eAe=/^[a-z][a-z0-9+.-]*:/i});function hAe(n,e,t){let i=new Promise((r,s)=>{let a=window.setTimeout(()=>{s(new k1(`Conversion did not complete within ${e}ms`))},e);n.then(()=>window.clearTimeout(a)).catch(()=>window.clearTimeout(a))});return Promise.race([n,i])}var jE,uAe,k1,e0,IJ=y(()=>{"use strict";Wa();zn();jE=er("conversion-manager"),uAe=3e5,k1=class extends Error{constructor(e="Conversion timed out"){super(e),this.name="ConversionTimeoutError"}};e0=class{constructor(){this.converters=new Map;this.pending=new Map}getConverter(e){return this.converters.get(ma(e))}registerConverter(e){jE.info("register converter",{converterId:e.id,sourceExts:[...e.sourceExts]});for(let t of e.sourceExts)this.converters.set(ma(t),e)}canConvert(e){let t=ma(e),i=this.converters.has(t);return jE.debug("can convert",{ext:t,ok:i}),i}async getConverterCacheIdentity(e){let t=this.getConverter(e);if(t)return{converterId:t.id,cacheKey:await t.getCacheKey()}}async convert(e){var o;let t=ma(e.sourceExt),i=this.getConverter(t);if(!i)throw jE.error("converter missing",{ext:t,targetExt:e.targetExt}),new Error(`No converter registered for .${t}`);let r=`${e.sourcePath}::${t}::${e.targetExt}`,s=this.pending.get(r);if(s)return jE.info("joining in-flight conversion",{key:r}),s;jE.info("dispatch conversion",{converterId:i.id,ext:t,targetExt:e.targetExt});let a=hAe(i.convert({...e,sourceExt:t}),(o=e.timeoutMs)!=null?o:uAe,{converterId:i.id,ext:t,targetExt:e.targetExt});this.pending.set(r,a);try{return await a}finally{this.pending.delete(r)}}}});var Q1={};Be(Q1,{describeConverterCommandSource:()=>K1,inspectAllConverterCommands:()=>DAe,inspectConverterCommand:()=>q1,listConverterCommandSpecs:()=>LAe,resolveConverterCommand:()=>OAe,resolveConverterInvocation:()=>Wn});function H1(...n){let e=(Xe==null?void 0:Xe.platform)==="darwin"?["/opt/homebrew/bin","/usr/local/bin","/opt/local/bin","/usr/bin"]:["/usr/local/bin","/opt/homebrew/bin","/opt/local/bin","/usr/bin"];return Array.from(new Set(e.flatMap(t=>n.map(i=>`${t}/${i}`))))}function gAe(){var r,s,a;if((Xe==null?void 0:Xe.platform)==="darwin")return["/Applications/FreeCAD.app/Contents/MacOS/FreeCADCmd","/Applications/FreeCAD.app/Contents/Resources/bin/FreeCADCmd","/Applications/FreeCAD.app/Contents/Resources/bin/freecadcmd",...H1("FreeCADCmd","freecadcmd")];if((Xe==null?void 0:Xe.platform)!=="win32")return["/usr/local/bin/freecadcmd","/opt/homebrew/bin/freecadcmd","/opt/local/bin/freecadcmd","/snap/freecad/current/usr/bin/freecadcmd","/usr/bin/freecadcmd"];let n=[],e=(r=Xe==null?void 0:Xe.env)==null?void 0:r.LOCALAPPDATA,t=(s=Xe==null?void 0:Xe.env)==null?void 0:s.ProgramFiles,i=(a=Xe==null?void 0:Xe.env)==null?void 0:a["ProgramFiles(x86)"];if(e&&n.push(tr(e,"Programs","FreeCAD","bin","FreeCADCmd.exe")),t&&n.push(tr(t,"FreeCAD","bin","FreeCADCmd.exe")),e)for(let o of["1.2","1.1","1.0","0.22","0.21","0.20"])n.push(`${e}/Programs/FreeCAD ${o}/bin/FreeCADCmd.exe`);if(t)for(let o of["1.2","1.1","1.0","0.22","0.21","0.20"])n.push(`${t}/FreeCAD ${o}/bin/FreeCADCmd.exe`);return i&&n.push(`${i}/FreeCAD/bin/FreeCADCmd.exe`),n}function _Ae(n){var a,o,l,c;if((Xe==null?void 0:Xe.platform)!=="win32")return[];let e=(a=Xe==null?void 0:Xe.env)==null?void 0:a.APPDATA,t=(o=Xe==null?void 0:Xe.env)==null?void 0:o.LOCALAPPDATA,i=(l=Xe==null?void 0:Xe.env)==null?void 0:l.npm_config_prefix,r=(c=Xe==null?void 0:Xe.env)==null?void 0:c.USERPROFILE,s=[i,e?tr(e,"npm"):void 0,t?tr(t,"npm"):void 0,r?tr(r,"AppData","Roaming","npm"):void 0].filter(f=>!!f);return Array.from(new Set(s.map(f=>tr(f,n))))}function vAe(...n){var s,a,o;if((Xe==null?void 0:Xe.platform)!=="win32")return[];let e=(s=Xe==null?void 0:Xe.env)==null?void 0:s.ProgramFiles,t=(a=Xe==null?void 0:Xe.env)==null?void 0:a["ProgramFiles(x86)"],i=(o=Xe==null?void 0:Xe.env)==null?void 0:o.LOCALAPPDATA,r=[e,t,i?tr(i,"Programs"):void 0].filter(l=>!!l);return Array.from(new Set(r.flatMap(l=>n.map(c=>tr(l,c)))))}async function Z1(n){try{return await Ss(n,(Xe==null?void 0:Xe.platform)==="win32"?Ts:nP),!0}catch(e){return!1}}function z1(n){let e=n==null?void 0:n.trim();if(e)return e}function PJ(n){return EAe.test(n)?{ok:!1,reason:"Command contains unsafe shell metacharacters."}:{ok:!0}}function SAe(n,e){for(let t of[n,...e]){let i=PJ(t);if(!i.ok)return i}return{ok:!0}}async function TAe(n){try{return(await Mu(n)).isFile()}catch(e){return!1}}function AAe(n){let e=[],t="",i=null;for(let r=0;rr.trim().toLowerCase()).filter(Boolean);return e!=null&&e.length?e:mAe}async function MAe(n){var r;let e=(r=Xe==null?void 0:Xe.env)==null?void 0:r.PATH;if(!e)return;let t=e.split(sP).map(s=>s.trim()).filter(Boolean),i=(Xe==null?void 0:Xe.platform)==="win32"?bAe(n):[""];for(let s of t)for(let a of i){let o=tr(s,a?`${n}${a}`:n);if(await Z1(o))return o}}function X1(n,e,t=15e3){let i=PJ(n);return i.ok?new Promise((r,s)=>{ba(n,e,{timeout:t,windowsHide:!0,maxBuffer:4*1024*1024},(a,o,l)=>{if(a){s(new Error((l||o||a.message).toString().trim()||a.message));return}r({stdout:o!=null?o:"",stderr:l!=null?l:""})})}):Promise.reject(new Error(`Refusing to execute converter command: ${i.reason}`))}function Y1(n){let t=(n instanceof Error?n.message:String(n)).replace(/\s+/g," ").trim();return t.length>180?`${t.slice(0,177)}...`:t}async function W1(n,e,t,i){let r="";for(let s of t)try{return await X1(n,[...e,...s]),{ok:!0,detail:""}}catch(a){let o=Y1(a);if(i.test(o))return{ok:!0,detail:""};r=o}return{ok:!1,detail:r||"Command probe failed."}}async function yAe(n){var i;if(!n.available)return[];let e=(i=n.resolvedPath)!=null?i:n.executable,t=[...n.args];if(n.id==="freecad"){let r=[];for(let s of pAe)try{await X1(e,[...t,"-c",s.probe]),r.push({kind:"cad-python",label:s.label,ok:!0,detail:""})}catch(a){r.push({kind:"cad-python",label:s.label,ok:!1,detail:Y1(a)})}return r}if(n.id==="assimp")try{return await X1(e,[...t,"-c","import trimesh, numpy, networkx, collada; print('ok')"]),[{kind:"mesh-python",ok:!0,detail:""}]}catch(r){return[{kind:"mesh-python",ok:!1,detail:Y1(r)}]}if(n.id==="freecadcmd"){let r=await W1(e,t,[["--version"],["--help"]],/freecad|usage|help|version/i);return[{kind:"freecadcmd-cli",ok:r.ok,detail:r.detail}]}if(n.id==="obj2gltf"){let r=await W1(e,t,[["--version"],["--help"]],/obj2gltf|usage|help|version/i);return[{kind:"obj2gltf-cli",ok:r.ok,detail:r.detail}]}if(n.id==="fbx2gltf"){let r=await W1(e,t,[["--version"],["--help"]],/fbx2gltf|usage|help|version/i);return[{kind:"fbx2gltf-cli",ok:r.ok,detail:r.detail}]}return[]}function IAe(n){let e=j1.find(t=>t.id===n);if(!e)throw new Error(`Unknown converter command id: ${n}`);return e}function CAe(n){var s,a,o,l;let e=(a=(s=Xe==null?void 0:Xe.env)==null?void 0:s.ProgramFiles)==null?void 0:a.toLowerCase(),t=(l=(o=Xe==null?void 0:Xe.env)==null?void 0:o["ProgramFiles(x86)"])==null?void 0:l.toLowerCase(),i=[],r=[];for(let c of n.knownCandidates){let f=c.toLowerCase(),d=(Xe==null?void 0:Xe.platform)==="win32"&&((e?f.startsWith(e):!1)||(t?f.startsWith(t):!1)),u=(Xe==null?void 0:Xe.platform)!=="win32"&&(c.startsWith("/usr/bin/")||c.startsWith("/snap/freecad/current/usr/bin/"));d||u?r.push(c):i.push(c)}return{userCandidates:i,systemCandidates:r}}async function CJ(n,e,t){for(let i of e)if(await Z1(i))return{id:n.id,label:n.label,envVar:n.envVar,settingsKey:n.settingsKey,command:i,executable:i,args:[],resolvedPath:i,available:!0,source:"candidate",detail:t,checkedCandidates:[i]}}function PAe(n,e){let t=[];return n.length&&t.push(`Checked common user locations: ${n.join("; ")}`),e.length&&t.push(`Checked system fallback locations: ${e.join("; ")}`),t.join(". ")}async function t0(n,e,t,i){let r=xAe(e),s=SAe(r.executable,r.args);if(!s.ok)return{id:n.id,label:n.label,envVar:n.envVar,settingsKey:n.settingsKey,configuredCommand:i,command:e,executable:r.executable,args:r.args,resolvedPath:void 0,available:!1,source:t,detail:s.reason,checkedCandidates:[r.executable]};if(RAe(r.executable)){let[o,l]=await Promise.all([Z1(r.executable),TAe(r.executable)]),c=o&&l;return{id:n.id,label:n.label,envVar:n.envVar,settingsKey:n.settingsKey,configuredCommand:i,command:e,executable:r.executable,args:r.args,resolvedPath:c?r.executable:void 0,available:c,source:t,detail:c?`Using ${K1(t)} path.`:"Configured path was not found or is not executable.",checkedCandidates:[r.executable]}}let a=await MAe(r.executable);return{id:n.id,label:n.label,envVar:n.envVar,settingsKey:n.settingsKey,configuredCommand:i,command:e,executable:r.executable,args:r.args,resolvedPath:a,available:!!a,source:t,detail:a?`Resolved from ${K1(t)} via PATH lookup.`:"Command name was not found on PATH.",checkedCandidates:[r.executable]}}function LAe(){return j1}function K1(n){switch(n){case"settings":return"plugin settings";case"env":return"environment variable";case"candidate":return"known install location";case"path":return"PATH fallback"}}async function q1(n,e){var u,h,m;let t=IAe(n),{userCandidates:i,systemCandidates:r}=CAe(t),s=z1(e);if(s)return t0(t,s,"settings",s);let a=z1((u=Xe==null?void 0:Xe.env)==null?void 0:u[t.envVar]);if(a)return t0(t,a,"env");for(let g of(h=t.envVarAliases)!=null?h:[]){let p=z1((m=Xe==null?void 0:Xe.env)==null?void 0:m[g]);if(p)return t0(t,p,"env")}let o=await CJ(t,i,"Detected at a common user-managed install location.");if(o)return o;let l=[];for(let g of t.fallbackCommands){let p=await t0(t,g,"path");if(l.push(p),p.available)return p}let c=await CJ(t,r,"Detected at a system fallback install location.");if(c)return c;let f=l.flatMap(g=>g.checkedCandidates),d=PAe(i,r);return{...l[0],detail:d?`Command name was not found on PATH. ${d}`:"Command name was not found on PATH.",checkedCandidates:[...i,...f,...r]}}async function DAe(n){let e=await Promise.all(j1.map(t=>q1(t.id,n[t.settingsKey])));return Promise.all(e.map(async t=>({...t,dependencyChecks:await yAe(t)})))}async function OAe(n,e){return(await Wn(n,e)).command}async function Wn(n,e){var i;let t=await q1(n,e);if(!t.available&&t.detail==="Command contains unsafe shell metacharacters.")throw new Error(`Refusing to resolve converter command '${n}': ${t.detail}`);return{command:(i=t.resolvedPath)!=null?i:t.executable,args:[...t.args]}}var Xe,mAe,pAe,j1,EAe,Kd=y(()=>{"use strict";hr();hr();hr();Xe=Dm(),mAe=[".exe",".cmd",".bat",".com"],pAe=[{label:"CadQuery import",probe:"import cadquery; print('ok')"},{label:"trimesh import",probe:"import trimesh; print('ok')"},{label:"OCP STEP readers",probe:["from OCP.STEPCAFControl import STEPCAFControl_Reader","from OCP.STEPControl import STEPControl_Reader","from OCP.BRepMesh import BRepMesh_IncrementalMesh","print('ok')"].join("; ")},{label:"OCCT GLB writer",probe:"from OCP.RWGltf import RWGltf_CafWriter, RWGltf_WriterTrsfFormat; print('ok')"}];j1=[{id:"freecad",label:"Python (CadQuery/OCCT)",settingsKey:"freecadCommand",envVar:"AI3D_FREECAD_CMD",fallbackCommands:(Xe==null?void 0:Xe.platform)==="win32"?["py","python"]:["python3","python"],knownCandidates:(Xe==null?void 0:Xe.platform)==="win32"?[]:["/usr/local/bin/python3","/opt/homebrew/bin/python3","/opt/local/bin/python3","/usr/bin/python3"]},{id:"obj2gltf",label:"obj2gltf",settingsKey:"obj2gltfCommand",envVar:"AI3D_OBJ2GLTF_CMD",fallbackCommands:(Xe==null?void 0:Xe.platform)==="win32"?["obj2gltf.cmd"]:["obj2gltf"],knownCandidates:(Xe==null?void 0:Xe.platform)==="win32"?_Ae("obj2gltf.cmd"):H1("obj2gltf")},{id:"fbx2gltf",label:"FBX2glTF",settingsKey:"fbx2gltfCommand",envVar:"AI3D_FBX2GLTF_CMD",fallbackCommands:(Xe==null?void 0:Xe.platform)==="win32"?["FBX2glTF.exe"]:["FBX2glTF","fbx2gltf"],knownCandidates:(Xe==null?void 0:Xe.platform)==="win32"?vAe(tr("FBX2glTF","FBX2glTF-windows-x64.exe"),tr("FBX2glTF","FBX2glTF.exe")):H1("FBX2glTF","fbx2gltf")},{id:"assimp",label:"Python (trimesh)",settingsKey:"assimpCommand",envVar:"AI3D_ASSIMP_CMD",fallbackCommands:(Xe==null?void 0:Xe.platform)==="win32"?["py","python"]:["python3","python"],knownCandidates:(Xe==null?void 0:Xe.platform)==="win32"?[]:["/usr/local/bin/python3","/opt/homebrew/bin/python3","/opt/local/bin/python3","/usr/bin/python3"]},{id:"freecadcmd",label:"FreeCAD (SLDPRT)",settingsKey:"freecadcmdCommand",envVar:"AI3D_FREECADCMD",envVarAliases:["AI3D_FREECMDCMD"],fallbackCommands:(Xe==null?void 0:Xe.platform)==="win32"?["FreeCADCmd.exe"]:["freecadcmd","FreeCADCmd"],knownCandidates:gAe()}];EAe=/[;|&<>$`\r\n\t]/});var DJ,LJ=y(()=>{DJ=`import cadquery as cq import trimesh diff --git a/manifest.json b/manifest.json index 5b39882..5e2e7e9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "ai-model-workbench", "name": "AI Model Workbench", - "version": "0.7.5", + "version": "0.7.6", "minAppVersion": "1.5.0", "description": "Turn 3D models into linked knowledge assets.", "author": "flash", diff --git a/package-lock.json b/package-lock.json index e2b1d8b..cab68cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-ai-model-workbench", - "version": "0.7.5", + "version": "0.7.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-ai-model-workbench", - "version": "0.7.5", + "version": "0.7.6", "dependencies": { "@babylonjs/core": "^9.6.0", "@babylonjs/loaders": "^9.6.0", diff --git a/package.json b/package.json index bb4eb77..624af92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-ai-model-workbench", - "version": "0.7.5", + "version": "0.7.6", "private": true, "description": "Obsidian plugin for turning 3D models into linked knowledge assets.", "scripts": { diff --git a/src/render/babylon/scene.ts b/src/render/babylon/scene.ts index 855a687..89271a9 100644 --- a/src/render/babylon/scene.ts +++ b/src/render/babylon/scene.ts @@ -1869,7 +1869,7 @@ export class BabylonModelPreview implements WorkbenchPreview { const startedAt = performance.now(); if (this.focusWorldPointFrame) { - activeWindow.cancelAnimationFrame(this.focusWorldPointFrame); + window.cancelAnimationFrame(this.focusWorldPointFrame); this.focusWorldPointFrame = 0; } @@ -2024,7 +2024,7 @@ export class BabylonModelPreview implements WorkbenchPreview { destroy() { this.engine.stopRenderLoop(); if (this.focusWorldPointFrame) { - activeWindow.cancelAnimationFrame(this.focusWorldPointFrame); + window.cancelAnimationFrame(this.focusWorldPointFrame); this.focusWorldPointFrame = 0; } this._onPickCallbacks = []; @@ -2062,7 +2062,7 @@ export class BabylonModelPreview implements WorkbenchPreview { this.viewportObserver = null; this.resizeObs.disconnect(); if (this.sliceMoveFrame) { - activeWindow.cancelAnimationFrame(this.sliceMoveFrame); + window.cancelAnimationFrame(this.sliceMoveFrame); this.sliceMoveFrame = 0; } this.pendingSliceMove = null; @@ -2382,7 +2382,7 @@ export class BabylonModelPreview implements WorkbenchPreview { clientY: event.clientY, }; if (!this.sliceMoveFrame) { - this.sliceMoveFrame = activeWindow.requestAnimationFrame(() => { + this.sliceMoveFrame = window.requestAnimationFrame(() => { this.sliceMoveFrame = 0; this.flushSliceDragUpdate(); }); @@ -2392,7 +2392,7 @@ export class BabylonModelPreview implements WorkbenchPreview { private flushSliceDragUpdate(): void { if (this.sliceMoveFrame) { - activeWindow.cancelAnimationFrame(this.sliceMoveFrame); + window.cancelAnimationFrame(this.sliceMoveFrame); this.sliceMoveFrame = 0; } const sample = this.pendingSliceMove; @@ -2479,7 +2479,7 @@ export class BabylonModelPreview implements WorkbenchPreview { private stabilizeCameraForSliceDrag(): void { if (this.focusWorldPointFrame) { - activeWindow.cancelAnimationFrame(this.focusWorldPointFrame); + window.cancelAnimationFrame(this.focusWorldPointFrame); this.focusWorldPointFrame = 0; } this.camera.inertialAlphaOffset = 0; diff --git a/versions.json b/versions.json index 923e91d..cf979e2 100644 --- a/versions.json +++ b/versions.json @@ -1 +1 @@ -{"0.0.1":"1.5.0","0.0.2":"1.5.0","0.0.3":"1.5.0","0.0.4":"1.5.0","0.0.5-beta.0":"1.5.0","0.1.1":"1.5.0","0.1.2":"1.5.0","0.1.4":"1.5.0","0.1.5":"1.5.0","0.1.6":"1.5.0","0.1.7":"1.5.0","0.1.8":"1.5.0","0.1.9":"1.5.0","0.2.0":"1.5.0","0.2.1":"1.5.0","0.2.2":"1.5.0","0.2.3":"1.5.0","0.2.4":"1.5.0","0.2.5":"1.5.0","0.3.0":"1.5.0","0.3.1":"1.5.0","0.4.0":"1.5.0","0.4.3":"1.5.0","0.5.1":"1.5.0","0.5.3":"1.5.0","0.5.5":"1.5.0","0.5.7":"1.5.0","0.5.8":"1.5.0","0.6.0":"1.5.0","0.6.1":"1.5.0","0.7.0":"1.5.0","0.7.1":"1.5.0","0.7.5":"1.5.0"} +{"0.0.1":"1.5.0","0.0.2":"1.5.0","0.0.3":"1.5.0","0.0.4":"1.5.0","0.0.5-beta.0":"1.5.0","0.1.1":"1.5.0","0.1.2":"1.5.0","0.1.4":"1.5.0","0.1.5":"1.5.0","0.1.6":"1.5.0","0.1.7":"1.5.0","0.1.8":"1.5.0","0.1.9":"1.5.0","0.2.0":"1.5.0","0.2.1":"1.5.0","0.2.2":"1.5.0","0.2.3":"1.5.0","0.2.4":"1.5.0","0.2.5":"1.5.0","0.3.0":"1.5.0","0.3.1":"1.5.0","0.4.0":"1.5.0","0.4.3":"1.5.0","0.5.1":"1.5.0","0.5.3":"1.5.0","0.5.5":"1.5.0","0.5.7":"1.5.0","0.5.8":"1.5.0","0.6.0":"1.5.0","0.6.1":"1.5.0","0.7.0":"1.5.0","0.7.1":"1.5.0","0.7.5":"1.5.0","0.7.6":"1.5.0"}