fluidcad 0.0.37 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4199,7 +4199,7 @@ void main() {
4199
4199
  #include <premultiplied_alpha_fragment>
4200
4200
 
4201
4201
  }
4202
- `};var ld=class extends Yr{constructor(e){super({type:`LineMaterial`,uniforms:Kr.clone(Oo.line.uniforms),vertexShader:Oo.line.vertexShader,fragmentShader:Oo.line.fragmentShader,clipping:!0}),this.isLineMaterial=!0,this.setValues(e)}get color(){return this.uniforms.diffuse.value}set color(e){this.uniforms.diffuse.value=e}get worldUnits(){return`WORLD_UNITS`in this.defines}set worldUnits(e){e===!0?this.defines.WORLD_UNITS=``:delete this.defines.WORLD_UNITS}get linewidth(){return this.uniforms.linewidth.value}set linewidth(e){this.uniforms.linewidth&&(this.uniforms.linewidth.value=e)}get dashed(){return`USE_DASH`in this.defines}set dashed(e){e===!0!==this.dashed&&(this.needsUpdate=!0),e===!0?this.defines.USE_DASH=``:delete this.defines.USE_DASH}get dashScale(){return this.uniforms.dashScale.value}set dashScale(e){this.uniforms.dashScale.value=e}get dashSize(){return this.uniforms.dashSize.value}set dashSize(e){this.uniforms.dashSize.value=e}get dashOffset(){return this.uniforms.dashOffset.value}set dashOffset(e){this.uniforms.dashOffset.value=e}get gapSize(){return this.uniforms.gapSize.value}set gapSize(e){this.uniforms.gapSize.value=e}get opacity(){return this.uniforms.opacity.value}set opacity(e){this.uniforms&&(this.uniforms.opacity.value=e)}get resolution(){return this.uniforms.resolution.value}set resolution(e){this.uniforms.resolution.value.copy(e)}get alphaToCoverage(){return`USE_ALPHA_TO_COVERAGE`in this.defines}set alphaToCoverage(e){this.defines&&(e===!0!==this.alphaToCoverage&&(this.needsUpdate=!0),e===!0?this.defines.USE_ALPHA_TO_COVERAGE=``:delete this.defines.USE_ALPHA_TO_COVERAGE)}},ud=new Bt,dd=new R,fd=new R,pd=new Bt,md=new Bt,hd=new Bt,gd=new R,_d=new yn,vd=new So,yd=new R,bd=new Gt,xd=new un,Sd=new Bt,Cd,wd;function Td(e,t,n){return Sd.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),Sd.multiplyScalar(1/Sd.w),Sd.x=wd/n.width,Sd.y=wd/n.height,Sd.applyMatrix4(e.projectionMatrixInverse),Sd.multiplyScalar(1/Sd.w),Math.abs(Math.max(Sd.x,Sd.y))}function Ed(e,t){let n=e.matrixWorld,r=e.geometry,i=r.attributes.instanceStart,a=r.attributes.instanceEnd,o=Math.min(r.instanceCount,i.count);for(let r=0,s=o;r<s;r++){vd.start.fromBufferAttribute(i,r),vd.end.fromBufferAttribute(a,r),vd.applyMatrix4(n);let o=new R,s=new R;Cd.distanceSqToSegment(vd.start,vd.end,s,o),s.distanceTo(o)<wd*.5&&t.push({point:s,pointOnLine:o,distance:Cd.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function Dd(e,t,n){let r=t.projectionMatrix,i=e.material.resolution,a=e.matrixWorld,o=e.geometry,s=o.attributes.instanceStart,c=o.attributes.instanceEnd,l=Math.min(o.instanceCount,s.count),u=-t.near;Cd.at(1,hd),hd.w=1,hd.applyMatrix4(t.matrixWorldInverse),hd.applyMatrix4(r),hd.multiplyScalar(1/hd.w),hd.x*=i.x/2,hd.y*=i.y/2,hd.z=0,gd.copy(hd),_d.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(pd.fromBufferAttribute(s,t),md.fromBufferAttribute(c,t),pd.w=1,md.w=1,pd.applyMatrix4(_d),md.applyMatrix4(_d),pd.z>u&&md.z>u)continue;if(pd.z>u){let e=pd.z-md.z,t=(pd.z-u)/e;pd.lerp(md,t)}else if(md.z>u){let e=md.z-pd.z,t=(md.z-u)/e;md.lerp(pd,t)}pd.applyMatrix4(r),md.applyMatrix4(r),pd.multiplyScalar(1/pd.w),md.multiplyScalar(1/md.w),pd.x*=i.x/2,pd.y*=i.y/2,md.x*=i.x/2,md.y*=i.y/2,vd.start.copy(pd),vd.start.z=0,vd.end.copy(md),vd.end.z=0;let o=vd.closestPointToPointParameter(gd,!0);vd.at(o,yd);let l=ht.lerp(pd.z,md.z,o),d=l>=-1&&l<=1,f=gd.distanceTo(yd)<wd*.5;if(d&&f){vd.start.fromBufferAttribute(s,t),vd.end.fromBufferAttribute(c,t),vd.start.applyMatrix4(a),vd.end.applyMatrix4(a);let r=new R,i=new R;Cd.distanceSqToSegment(vd.start,vd.end,i,r),n.push({point:i,pointOnLine:r,distance:Cd.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var Od=class extends U{constructor(e=new cd,t=new ld({color:Math.random()*16777215})){super(e,t),this.isLineSegments2=!0,this.type=`LineSegments2`}computeLineDistances(){let e=this.geometry,t=e.attributes.instanceStart,n=e.attributes.instanceEnd,r=new Float32Array(2*t.count);for(let e=0,i=0,a=t.count;e<a;e++,i+=2)dd.fromBufferAttribute(t,e),fd.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+dd.distanceTo(fd);let i=new co(r,2,1);return e.setAttribute(`instanceDistanceStart`,new fi(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new fi(i,1,1)),this}raycast(e,t){let n=this.material.worldUnits,r=e.camera;r===null&&!n&&console.error(`LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.`);let i=e.params.Line2!==void 0&&e.params.Line2.threshold||0;Cd=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;wd=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),xd.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?wd*.5:Td(r,Math.max(r.near,xd.distanceToPoint(Cd.origin)),s.resolution),xd.radius+=c,Cd.intersectsSphere(xd)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),bd.copy(o.boundingBox).applyMatrix4(a);let l;l=n?wd*.5:Td(r,Math.max(r.near,bd.distanceToPoint(Cd.origin)),s.resolution),bd.expandByScalar(l),Cd.intersectsBox(bd)!==!1&&(n?Ed(this,t):Dd(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport(ud),this.material.uniforms.resolution.value.set(ud.z,ud.w))}},kd=class extends cd{constructor(){super(),this.isLineGeometry=!0,this.type=`LineGeometry`}setPositions(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setPositions(n),this}setColors(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setColors(n),this}setFromPoints(e){let t=e.length-1,n=new Float32Array(6*t);for(let r=0;r<t;r++)n[6*r]=e[r].x,n[6*r+1]=e[r].y,n[6*r+2]=e[r].z||0,n[6*r+3]=e[r+1].x,n[6*r+4]=e[r+1].y,n[6*r+5]=e[r+1].z||0;return super.setPositions(n),this}fromLine(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}},Ad=class extends Od{constructor(e=new kd,t=new ld({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},jd=e=>{let t=new B,n=[],r=[],{isSphere:i}=e;return Fu.forEach((a,o)=>{let{enabled:s,line:c,scale:l,color:u}=e[a];if(!s||!c)return;let d=o<3?1:-1,f=(i?Gu-l/2:.975)*d;n.push(a.includes(`x`)?f:0,a.includes(`y`)?f:0,a.includes(`z`)?f:0,0,0,0);let p=t.set(u).toArray();r.push(...p,...p)}),n.length?new Ad(new kd().setPositions(n).setColors(r),new ld({linewidth:e.lineWidth,vertexColors:!0,resolution:new L(window.innerWidth,window.innerHeight)})).computeLineDistances():null},Md=e=>{let{corners:t,edges:n}=e,r=[],i=Xu(e),a=ed(e,i);return r.push(...a),t.enabled&&r.push(...td(e,i)),n.enabled&&r.push(...nd(e,i,t.enabled?7:6)),[r,ad(a,e),jd(e)]},Nd=(e,t=!0)=>{let{material:n,userData:r}=e,{opacity:i,color:a,scale:o}=t?r.hover:r;e.scale.setScalar(o),n.opacity=i,n.map?Zu(n.map,t):n.color.set(a)},Pd=new yn,Fd=new mo,Id=new L,Ld=new R,Rd=new Bt,zd=class extends Kn{constructor(e,t,n={}){super(),bu(this,`enabled`,!0),bu(this,`camera`),bu(this,`renderer`),bu(this,`options`),bu(this,`target`,new R),bu(this,`animated`,!0),bu(this,`speed`,1),bu(this,`animating`,!1),bu(this,`_options`),bu(this,`_intersections`),bu(this,`_background`,null),bu(this,`_viewport`,[0,0,0,0]),bu(this,`_originalViewport`,[0,0,0,0]),bu(this,`_originalScissor`,[0,0,0,0]),bu(this,`_scene`),bu(this,`_camera`),bu(this,`_container`),bu(this,`_domElement`),bu(this,`_domRect`),bu(this,`_dragging`,!1),bu(this,`_distance`,0),bu(this,`_clock`,new Ya),bu(this,`_targetQuaternion`,new gt),bu(this,`_quaternionStart`,new gt),bu(this,`_quaternionEnd`,new gt),bu(this,`_pointerStart`,new L),bu(this,`_focus`,null),bu(this,`_placement`),bu(this,`_controls`),bu(this,`_controlsListeners`),this.camera=e,this.renderer=t,this._scene=new li().add(this),this.set(n)}get placement(){return this._placement}set placement(e){this._placement=xu(this._domElement,e),this.domUpdate()}set(e={}){this.dispose(),this.options=e,this._options=Ju(e),this._camera=this._options.isSphere?new Ua(-1.8,1.8,1.8,-1.8,5,10):new ei(26,1,5,10),this._camera.position.set(0,0,7);let[t,n,r]=Md(this._options);n&&this.add(n),r&&this.add(r),this.add(...t),this._background=n,this._intersections=t;let{container:i,animated:a,speed:o}=this._options;return this.animated=a,this.speed=o,this._container=i?Cu(i):document.body,this._domElement=Su(this._options),this._domElement.onpointerdown=e=>this._onPointerDown(e),this._domElement.onpointermove=e=>this._onPointerMove(e),this._domElement.onpointerleave=()=>this._onPointerLeave(),this._container.appendChild(this._domElement),this._controls&&this.attachControls(this._controls),this.update(),this._updateOrientation(!0),this}render(){this.animating&&this._animate();let{renderer:e,_viewport:t}=this,n=e.getScissorTest(),r=e.autoClear;return e.autoClear=!1,e.setViewport(...t),n&&e.setScissor(...t),e.clear(!1,!0,!1),e.render(this._scene,this._camera),e.setViewport(...this._originalViewport),n&&e.setScissor(...this._originalScissor),e.autoClear=r,this}domUpdate(){this._domRect=this._domElement.getBoundingClientRect();let e=this.renderer,t=this._domRect,n=e.domElement.getBoundingClientRect();return this._viewport.splice(0,4,t.left-n.left,e.domElement.clientHeight-(t.top-n.top+t.height),t.width,t.height),e.getViewport(Rd).toArray(this._originalViewport),e.getScissorTest()&&e.getScissor(Rd).toArray(this._originalScissor),this}cameraUpdate(){return this._updateOrientation(),this}update(e=!0){return e&&this._controls&&this._controls.update(),this.domUpdate().cameraUpdate()}attachControls(e){return this.detachControls(),this.target=e.target,this._controlsListeners={start:()=>e.enabled=!1,end:()=>e.enabled=!0,change:()=>this.update(!1)},this.addEventListener(`start`,this._controlsListeners.start),this.addEventListener(`end`,this._controlsListeners.end),e.addEventListener(`change`,this._controlsListeners.change),this._controls=e,this}detachControls(){if(!(!this._controlsListeners||!this._controls))return this.target=new R().copy(this._controls.target),this.removeEventListener(`start`,this._controlsListeners.start),this.removeEventListener(`end`,this._controlsListeners.end),this._controls.removeEventListener(`change`,this._controlsListeners.change),this._controlsListeners=void 0,this._controls=void 0,this}dispose(){var e;this.detachControls(),this.children.forEach(e=>{var t,n,r;this.remove(e);let i=e;(t=i.material)==null||t.dispose(),(n=i.material?.map)==null||n.dispose(),(r=i.geometry)==null||r.dispose()}),(e=this._domElement)==null||e.remove()}_updateOrientation(e=!0){e&&(this.quaternion.copy(this.camera.quaternion).invert(),this.updateMatrixWorld()),Du(this._options,this._intersections,this.camera)}_animate(){let{position:e,quaternion:t}=this.camera;if(e.set(0,0,1),!this.animated){e.applyQuaternion(this._quaternionEnd).multiplyScalar(this._distance).add(this.target),t.copy(this._targetQuaternion),this._updateOrientation(),this.animating=!1,this.dispatchEvent({type:`change`}),this.dispatchEvent({type:`end`});return}this._controls&&(this._controls.enabled=!1);let n=this._clock.getDelta()*Nu*this.speed;this._quaternionStart.rotateTowards(this._quaternionEnd,n),e.applyQuaternion(this._quaternionStart).multiplyScalar(this._distance).add(this.target),t.rotateTowards(this._targetQuaternion,n),this._updateOrientation(),requestAnimationFrame(()=>this.dispatchEvent({type:`change`})),this._quaternionStart.angleTo(this._quaternionEnd)<Mu&&(this._controls&&(this._controls.enabled=!0),this.animating=!1,this.dispatchEvent({type:`end`}))}_setOrientation(e){let t=this.camera,n=this.target;Ld.copy(e).multiplyScalar(this._distance),Pd.setPosition(Ld).lookAt(Ld,this.position,this.up),this._targetQuaternion.setFromRotationMatrix(Pd),Ld.add(n),Pd.lookAt(Ld,n,this.up),this._quaternionEnd.setFromRotationMatrix(Pd),Pd.setPosition(t.position).lookAt(t.position,n,this.up),this._quaternionStart.setFromRotationMatrix(Pd),this.animating=!0,this._clock.start(),this.dispatchEvent({type:`start`})}_onPointerDown(e){if(!this.enabled)return;let t=e=>{if(!this._dragging){if(Ou(e,this._pointerStart))return;this._dragging=!0}let t=Id.set(e.clientX,e.clientY).sub(this._pointerStart).multiplyScalar(1/this._domRect.width*Math.PI),n=this.coordinateConversion(Ld.subVectors(this.camera.position,this.target)),r=Fd.setFromVector3(n);r.theta=a-t.x,r.phi=wu(o-t.y,Mu,Math.PI-Mu),this.coordinateConversion(this.camera.position.setFromSpherical(r),!0).add(this.target),this.camera.lookAt(this.target),this.quaternion.copy(this.camera.quaternion).invert(),this._updateOrientation(!1),this.dispatchEvent({type:`change`})},n=()=>{if(document.removeEventListener(`pointermove`,t,!1),document.removeEventListener(`pointerup`,n,!1),!this._dragging)return this._handleClick(e);this._focus&&=(Nd(this._focus,!1),null),this._dragging=!1,this.dispatchEvent({type:`end`})};if(this.animating)return;e.preventDefault(),this._pointerStart.set(e.clientX,e.clientY);let r=this.coordinateConversion(Ld.subVectors(this.camera.position,this.target)),i=Fd.setFromVector3(r),a=i.theta,o=i.phi;this._distance=i.radius,document.addEventListener(`pointermove`,t,!1),document.addEventListener(`pointerup`,n,!1),this.dispatchEvent({type:`start`})}coordinateConversion(e,t=!1){let{x:n,y:r,z:i}=e,a=Kn.DEFAULT_UP;return a.x===1?t?e.set(r,i,n):e.set(i,n,r):a.z===1?t?e.set(i,n,r):e.set(r,i,n):e}_onPointerMove(e){!this.enabled||this._dragging||(this._background&&Ku(this._background,!0),this._handleHover(e))}_onPointerLeave(){!this.enabled||this._dragging||(this._background&&Ku(this._background,!1),this._focus&&Nd(this._focus,!1),this._domElement.style.cursor=``)}_handleClick(e){let t=ju(e,this._domRect,this._camera,this._intersections);this._focus&&=(Nd(this._focus,!1),null),t&&(this._setOrientation(t.object.position),this.dispatchEvent({type:`change`}))}_handleHover(e){let t=ju(e,this._domRect,this._camera,this._intersections)?.object||null;this._focus!==t&&(this._domElement.style.cursor=t?`pointer`:``,this._focus&&Nd(this._focus,!1),(this._focus=t)?Nd(t,!0):Du(this._options,this._intersections,this.camera))}},Bd=class extends Ue{target=new R;constructor(e){super(),this.cc=e,e.addEventListener(`update`,()=>{e.getTarget(this.target),this.dispatchEvent({type:`change`})})}get enabled(){return this.cc.enabled}set enabled(e){this.cc.enabled=e}update(){let e=this.cc.camera.position,t=this.target;this.cc.setLookAt(e.x,e.y,e.z,t.x,t.y,t.z,!1)}},Vd=new Set;function Hd(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Ud(){Wd.faceColor.set(Hd(`--scene-face-color`,`#969696`)),Wd.edgeColor.set(Hd(`--scene-edge-color`,`#000000`)),Wd.gridColor.set(Hd(`--scene-grid-color`,`#6f6f6f`)),Wd.metaEdgeColor.set(Hd(`--scene-meta-edge-color`,`#b0b0b0`)),Wd.highlightColor.set(Hd(`--scene-highlight-color`,`#ffb433`)),Wd.selectEdgeColor.set(Hd(`--scene-select-edge-color`,`#11a4ed`)),Wd.selectFaceColor.set(Hd(`--scene-select-face-color`,`#5c9fcc`)),Wd.constraintColor.set(Hd(`--scene-constraint-color`,`#cccccc`)),Wd.backgroundColor.set(Hd(`--color-base-100`,`#1e1e1e`))}var Wd={faceColor:new B(`#969696`),edgeColor:new B(`#000000`),gridColor:new B(`#6f6f6f`),metaEdgeColor:new B(`#b0b0b0`),highlightColor:new B(`#ffb433`),selectEdgeColor:new B(`#11a4ed`),selectFaceColor:new B(`#5c9fcc`),constraintColor:new B(`#cccccc`),backgroundColor:new B(`#1e1e1e`)};Ud(),new MutationObserver(()=>{Ud();for(let e of Vd)e()}).observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]});function Gd(e){return Vd.add(e),()=>Vd.delete(e)}var Kd=class e{static resolution=new L(window.innerWidth,window.innerHeight);static materials=new Set;static register(t){t.resolution.copy(e.resolution),e.materials.add(t),t.addEventListener(`dispose`,()=>{e.materials.delete(t)})}static setResolution(t,n){e.resolution.set(t,n);for(let t of e.materials)t.resolution.copy(e.resolution)}};_u.install({THREE:{Vector2:L,Vector3:R,Vector4:Bt,Quaternion:gt,Matrix4:yn,Spherical:mo,Box3:Gt,Sphere:un,Raycaster:uo,MathUtils:{DEG2RAD:ht.DEG2RAD,clamp:ht.clamp}}});var qd=new R(0,0,1),Jd=120,Yd=1.1,Xd=class{scene;renderer;gizmo;orthoCamera;perspCamera;activeCamera=`orthographic`;_cc;_adapter;dirLight;renderRequested=!1;resizeObserver;clock=new Ya;animFrameId=0;gizmoWasActive=!1;constructor(e){this.container=e,Kn.DEFAULT_UP=qd.clone();let t=e.clientWidth||window.innerWidth,n=e.clientHeight||window.innerHeight;this.renderer=new Dl({antialias:!0,alpha:!0}),this.renderer.setSize(t,n),this.renderer.setPixelRatio(window.devicePixelRatio),Kd.setResolution(t,n),this.renderer.toneMapping=4,this.renderer.outputColorSpace=Ie,this.renderer.localClippingEnabled=!0,e.appendChild(this.renderer.domElement),this.scene=new li,this.scene.background=Wd.backgroundColor.clone();let r=t/n;this.orthoCamera=new Ua(-r*Jd/2,r*Jd/2,Jd/2,-Jd/2,-1e4,1e4),this.orthoCamera.position.set(50,-50,40),this.orthoCamera.up.copy(qd),this.orthoCamera.lookAt(0,0,0),this.perspCamera=new ei(50,r,.5,1e4),this.perspCamera.position.set(50,-50,40),this.perspCamera.up.copy(qd),this.perspCamera.lookAt(0,0,0),this.dirLight=new Ga(16777215,1),this.scene.add(this.dirLight),this.scene.add(new Ka(14544639,2.5)),this._cc=new _u(this.orthoCamera,this.renderer.domElement),this._cc.dollyToCursor=!0,this._cc.smoothTime=.1,this._cc.draggingSmoothTime=.05,this.configureTouchForMode(`orthographic`),this._cc.updateCameraUp(),this._adapter=new Bd(this._cc),this.gizmo=new zd(this.camera,this.renderer,{size:80,type:`sphere`}),this._cc.setLookAt(50,-50,40,0,0,0,!1),this._cc.getTarget(this._adapter.target),this.gizmo.target=this._adapter.target,this.gizmo.attachControls(this._adapter),this.gizmo.addEventListener(`change`,()=>this.requestRender()),this.resizeObserver=new ResizeObserver(()=>this.handleResize()),this.resizeObserver.observe(e),Gd(()=>{this.scene.background=Wd.backgroundColor.clone(),this.requestRender()}),this.tick()}get camera(){return this.activeCamera===`orthographic`?this.orthoCamera:this.perspCamera}createPickingRaycaster(e,t){let n=this.camera;n.updateMatrixWorld(),n.updateProjectionMatrix();let r=new uo;if(r.setFromCamera(new L(e,t),n),n.isOrthographicCamera){let e=n,t=Math.max(Math.abs(e.far-e.near),1);r.ray.origin.addScaledVector(r.ray.direction,-t)}return r}get cameraControls(){return this._cc}get controls(){return this._adapter}requestRender(){this.renderRequested=!0}fitToBox(e,t){let n=e.getCenter(new R),r=e.getSize(new R).length()/2;if(r===0)return;let i=new un(n,r*Yd);this._cc.fitToSphere(i,t)}switchCamera(e){if(e===this.activeCamera)return;let t=new R,n=new R;this._cc.getPosition(t),this._cc.getTarget(n);let r=this.camera.up.clone();if(this.activeCamera===`orthographic`&&e===`perspective`){let e=(this.orthoCamera.top-this.orthoCamera.bottom)/this.orthoCamera.zoom,r=ht.DEG2RAD*this.perspCamera.fov*.5,i=e*.5/Math.tan(r),a=t.clone().sub(n).normalize();t.copy(n).add(a.multiplyScalar(i))}this.activeCamera=e;let i=this.camera;i.position.copy(t),i.up.copy(r),i.lookAt(n),this._cc.dispose(),this._cc=new _u(i,this.renderer.domElement),this._cc.dollyToCursor=!0,this._cc.smoothTime=.1,this._cc.draggingSmoothTime=.05,this._cc.setLookAt(t.x,t.y,t.z,n.x,n.y,n.z,!1),this._cc.updateCameraUp(),this.configureTouchForMode(e),this._adapter=new Bd(this._cc),this._cc.getTarget(this._adapter.target),this.gizmo.camera=i,this.gizmo.target=this._adapter.target,this.gizmo.attachControls(this._adapter),this.gizmo.update(),this.requestRender()}render(){this.updateLightPositions(),this.renderer.render(this.scene,this.camera),this.gizmo.render()}dispose(){cancelAnimationFrame(this.animFrameId),this.resizeObserver.disconnect(),this._cc.dispose(),this.scene.clear(),this.renderer.dispose()}tick=()=>{let e=this.clock.getDelta(),t=!1;if(this._cc.enabled){if(this.gizmoWasActive){this._cc.updateCameraUp();let e=this.camera.position,t=this._adapter.target;this._cc.setLookAt(e.x,e.y,e.z,t.x,t.y,t.z,!1),this.gizmoWasActive=!1}t=this._cc.update(e)}else this.gizmoWasActive=!0;(t||this.renderRequested||!this._cc.enabled)&&(this.render(),this.renderRequested=!1),this.animFrameId=requestAnimationFrame(this.tick)};configureTouchForMode(e){e===`orthographic`?(this._cc.touches.one=_u.ACTION.TOUCH_ROTATE,this._cc.touches.two=_u.ACTION.TOUCH_ZOOM_TRUCK):(this._cc.touches.one=_u.ACTION.TOUCH_ROTATE,this._cc.touches.two=_u.ACTION.TOUCH_DOLLY_TRUCK)}handleResize(){let e=this.container.clientWidth,t=this.container.clientHeight||window.innerHeight;if(e===0||t===0)return;let n=e/t;this.renderer.setSize(e,t),this.renderer.setPixelRatio(window.devicePixelRatio),Kd.setResolution(e,t),this.orthoCamera.left=-n*Jd/2,this.orthoCamera.right=n*Jd/2,this.orthoCamera.top=Jd/2,this.orthoCamera.bottom=-Jd/2,this.orthoCamera.updateProjectionMatrix(),this.perspCamera.aspect=n,this.perspCamera.updateProjectionMatrix(),this.gizmo.update(),this.requestRender()}updateLightPositions(){let e=new R;this.camera.getWorldDirection(e),this.dirLight.position.copy(e.multiplyScalar(-10)),this.dirLight.target.position.set(0,0,0),this.dirLight.target.updateMatrixWorld()}},Zd=class extends U{constructor(e=10,t=100,n=new B(`white`),r=8e3,i=new R(0,1,0)){let a=new ma(2,2,1,1),o=new Yr({side:0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:2,uniforms:{uSize1:{value:e},uSize2:{value:t},uColor:{value:n},uDistance:{value:r},uNormal:{value:i.normalize()}},transparent:!0,vertexShader:`
4202
+ `};var ld=class extends Yr{constructor(e){super({type:`LineMaterial`,uniforms:Kr.clone(Oo.line.uniforms),vertexShader:Oo.line.vertexShader,fragmentShader:Oo.line.fragmentShader,clipping:!0}),this.isLineMaterial=!0,this.setValues(e)}get color(){return this.uniforms.diffuse.value}set color(e){this.uniforms.diffuse.value=e}get worldUnits(){return`WORLD_UNITS`in this.defines}set worldUnits(e){e===!0?this.defines.WORLD_UNITS=``:delete this.defines.WORLD_UNITS}get linewidth(){return this.uniforms.linewidth.value}set linewidth(e){this.uniforms.linewidth&&(this.uniforms.linewidth.value=e)}get dashed(){return`USE_DASH`in this.defines}set dashed(e){e===!0!==this.dashed&&(this.needsUpdate=!0),e===!0?this.defines.USE_DASH=``:delete this.defines.USE_DASH}get dashScale(){return this.uniforms.dashScale.value}set dashScale(e){this.uniforms.dashScale.value=e}get dashSize(){return this.uniforms.dashSize.value}set dashSize(e){this.uniforms.dashSize.value=e}get dashOffset(){return this.uniforms.dashOffset.value}set dashOffset(e){this.uniforms.dashOffset.value=e}get gapSize(){return this.uniforms.gapSize.value}set gapSize(e){this.uniforms.gapSize.value=e}get opacity(){return this.uniforms.opacity.value}set opacity(e){this.uniforms&&(this.uniforms.opacity.value=e)}get resolution(){return this.uniforms.resolution.value}set resolution(e){this.uniforms.resolution.value.copy(e)}get alphaToCoverage(){return`USE_ALPHA_TO_COVERAGE`in this.defines}set alphaToCoverage(e){this.defines&&(e===!0!==this.alphaToCoverage&&(this.needsUpdate=!0),e===!0?this.defines.USE_ALPHA_TO_COVERAGE=``:delete this.defines.USE_ALPHA_TO_COVERAGE)}},ud=new Bt,dd=new R,fd=new R,pd=new Bt,md=new Bt,hd=new Bt,gd=new R,_d=new yn,vd=new So,yd=new R,bd=new Gt,xd=new un,Sd=new Bt,Cd,wd;function Td(e,t,n){return Sd.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),Sd.multiplyScalar(1/Sd.w),Sd.x=wd/n.width,Sd.y=wd/n.height,Sd.applyMatrix4(e.projectionMatrixInverse),Sd.multiplyScalar(1/Sd.w),Math.abs(Math.max(Sd.x,Sd.y))}function Ed(e,t){let n=e.matrixWorld,r=e.geometry,i=r.attributes.instanceStart,a=r.attributes.instanceEnd,o=Math.min(r.instanceCount,i.count);for(let r=0,s=o;r<s;r++){vd.start.fromBufferAttribute(i,r),vd.end.fromBufferAttribute(a,r),vd.applyMatrix4(n);let o=new R,s=new R;Cd.distanceSqToSegment(vd.start,vd.end,s,o),s.distanceTo(o)<wd*.5&&t.push({point:s,pointOnLine:o,distance:Cd.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function Dd(e,t,n){let r=t.projectionMatrix,i=e.material.resolution,a=e.matrixWorld,o=e.geometry,s=o.attributes.instanceStart,c=o.attributes.instanceEnd,l=Math.min(o.instanceCount,s.count),u=-t.near;Cd.at(1,hd),hd.w=1,hd.applyMatrix4(t.matrixWorldInverse),hd.applyMatrix4(r),hd.multiplyScalar(1/hd.w),hd.x*=i.x/2,hd.y*=i.y/2,hd.z=0,gd.copy(hd),_d.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(pd.fromBufferAttribute(s,t),md.fromBufferAttribute(c,t),pd.w=1,md.w=1,pd.applyMatrix4(_d),md.applyMatrix4(_d),pd.z>u&&md.z>u)continue;if(pd.z>u){let e=pd.z-md.z,t=(pd.z-u)/e;pd.lerp(md,t)}else if(md.z>u){let e=md.z-pd.z,t=(md.z-u)/e;md.lerp(pd,t)}pd.applyMatrix4(r),md.applyMatrix4(r),pd.multiplyScalar(1/pd.w),md.multiplyScalar(1/md.w),pd.x*=i.x/2,pd.y*=i.y/2,md.x*=i.x/2,md.y*=i.y/2,vd.start.copy(pd),vd.start.z=0,vd.end.copy(md),vd.end.z=0;let o=vd.closestPointToPointParameter(gd,!0);vd.at(o,yd);let l=ht.lerp(pd.z,md.z,o),d=l>=-1&&l<=1,f=gd.distanceTo(yd)<wd*.5;if(d&&f){vd.start.fromBufferAttribute(s,t),vd.end.fromBufferAttribute(c,t),vd.start.applyMatrix4(a),vd.end.applyMatrix4(a);let r=new R,i=new R;Cd.distanceSqToSegment(vd.start,vd.end,i,r),n.push({point:i,pointOnLine:r,distance:Cd.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var Od=class extends U{constructor(e=new cd,t=new ld({color:Math.random()*16777215})){super(e,t),this.isLineSegments2=!0,this.type=`LineSegments2`}computeLineDistances(){let e=this.geometry,t=e.attributes.instanceStart,n=e.attributes.instanceEnd,r=new Float32Array(2*t.count);for(let e=0,i=0,a=t.count;e<a;e++,i+=2)dd.fromBufferAttribute(t,e),fd.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+dd.distanceTo(fd);let i=new co(r,2,1);return e.setAttribute(`instanceDistanceStart`,new fi(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new fi(i,1,1)),this}raycast(e,t){let n=this.material.worldUnits,r=e.camera;r===null&&!n&&console.error(`LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.`);let i=e.params.Line2!==void 0&&e.params.Line2.threshold||0;Cd=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;wd=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),xd.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?wd*.5:Td(r,Math.max(r.near,xd.distanceToPoint(Cd.origin)),s.resolution),xd.radius+=c,Cd.intersectsSphere(xd)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),bd.copy(o.boundingBox).applyMatrix4(a);let l;l=n?wd*.5:Td(r,Math.max(r.near,bd.distanceToPoint(Cd.origin)),s.resolution),bd.expandByScalar(l),Cd.intersectsBox(bd)!==!1&&(n?Ed(this,t):Dd(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport(ud),this.material.uniforms.resolution.value.set(ud.z,ud.w))}},kd=class extends cd{constructor(){super(),this.isLineGeometry=!0,this.type=`LineGeometry`}setPositions(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setPositions(n),this}setColors(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setColors(n),this}setFromPoints(e){let t=e.length-1,n=new Float32Array(6*t);for(let r=0;r<t;r++)n[6*r]=e[r].x,n[6*r+1]=e[r].y,n[6*r+2]=e[r].z||0,n[6*r+3]=e[r+1].x,n[6*r+4]=e[r+1].y,n[6*r+5]=e[r+1].z||0;return super.setPositions(n),this}fromLine(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}},Ad=class extends Od{constructor(e=new kd,t=new ld({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},jd=e=>{let t=new B,n=[],r=[],{isSphere:i}=e;return Fu.forEach((a,o)=>{let{enabled:s,line:c,scale:l,color:u}=e[a];if(!s||!c)return;let d=o<3?1:-1,f=(i?Gu-l/2:.975)*d;n.push(a.includes(`x`)?f:0,a.includes(`y`)?f:0,a.includes(`z`)?f:0,0,0,0);let p=t.set(u).toArray();r.push(...p,...p)}),n.length?new Ad(new kd().setPositions(n).setColors(r),new ld({linewidth:e.lineWidth,vertexColors:!0,resolution:new L(window.innerWidth,window.innerHeight)})).computeLineDistances():null},Md=e=>{let{corners:t,edges:n}=e,r=[],i=Xu(e),a=ed(e,i);return r.push(...a),t.enabled&&r.push(...td(e,i)),n.enabled&&r.push(...nd(e,i,t.enabled?7:6)),[r,ad(a,e),jd(e)]},Nd=(e,t=!0)=>{let{material:n,userData:r}=e,{opacity:i,color:a,scale:o}=t?r.hover:r;e.scale.setScalar(o),n.opacity=i,n.map?Zu(n.map,t):n.color.set(a)},Pd=new yn,Fd=new mo,Id=new L,Ld=new R,Rd=new Bt,zd=class extends Kn{constructor(e,t,n={}){super(),bu(this,`enabled`,!0),bu(this,`camera`),bu(this,`renderer`),bu(this,`options`),bu(this,`target`,new R),bu(this,`animated`,!0),bu(this,`speed`,1),bu(this,`animating`,!1),bu(this,`_options`),bu(this,`_intersections`),bu(this,`_background`,null),bu(this,`_viewport`,[0,0,0,0]),bu(this,`_originalViewport`,[0,0,0,0]),bu(this,`_originalScissor`,[0,0,0,0]),bu(this,`_scene`),bu(this,`_camera`),bu(this,`_container`),bu(this,`_domElement`),bu(this,`_domRect`),bu(this,`_dragging`,!1),bu(this,`_distance`,0),bu(this,`_clock`,new Ya),bu(this,`_targetQuaternion`,new gt),bu(this,`_quaternionStart`,new gt),bu(this,`_quaternionEnd`,new gt),bu(this,`_pointerStart`,new L),bu(this,`_focus`,null),bu(this,`_placement`),bu(this,`_controls`),bu(this,`_controlsListeners`),this.camera=e,this.renderer=t,this._scene=new li().add(this),this.set(n)}get placement(){return this._placement}set placement(e){this._placement=xu(this._domElement,e),this.domUpdate()}set(e={}){this.dispose(),this.options=e,this._options=Ju(e),this._camera=this._options.isSphere?new Ua(-1.8,1.8,1.8,-1.8,5,10):new ei(26,1,5,10),this._camera.position.set(0,0,7);let[t,n,r]=Md(this._options);n&&this.add(n),r&&this.add(r),this.add(...t),this._background=n,this._intersections=t;let{container:i,animated:a,speed:o}=this._options;return this.animated=a,this.speed=o,this._container=i?Cu(i):document.body,this._domElement=Su(this._options),this._domElement.onpointerdown=e=>this._onPointerDown(e),this._domElement.onpointermove=e=>this._onPointerMove(e),this._domElement.onpointerleave=()=>this._onPointerLeave(),this._container.appendChild(this._domElement),this._controls&&this.attachControls(this._controls),this.update(),this._updateOrientation(!0),this}render(){this.animating&&this._animate();let{renderer:e,_viewport:t}=this,n=e.getScissorTest(),r=e.autoClear;return e.autoClear=!1,e.setViewport(...t),n&&e.setScissor(...t),e.clear(!1,!0,!1),e.render(this._scene,this._camera),e.setViewport(...this._originalViewport),n&&e.setScissor(...this._originalScissor),e.autoClear=r,this}domUpdate(){this._domRect=this._domElement.getBoundingClientRect();let e=this.renderer,t=this._domRect,n=e.domElement.getBoundingClientRect();return this._viewport.splice(0,4,t.left-n.left,e.domElement.clientHeight-(t.top-n.top+t.height),t.width,t.height),e.getViewport(Rd).toArray(this._originalViewport),e.getScissorTest()&&e.getScissor(Rd).toArray(this._originalScissor),this}cameraUpdate(){return this._updateOrientation(),this}update(e=!0){return e&&this._controls&&this._controls.update(),this.domUpdate().cameraUpdate()}attachControls(e){return this.detachControls(),this.target=e.target,this._controlsListeners={start:()=>e.enabled=!1,end:()=>e.enabled=!0,change:()=>this.update(!1)},this.addEventListener(`start`,this._controlsListeners.start),this.addEventListener(`end`,this._controlsListeners.end),e.addEventListener(`change`,this._controlsListeners.change),this._controls=e,this}detachControls(){if(!(!this._controlsListeners||!this._controls))return this.target=new R().copy(this._controls.target),this.removeEventListener(`start`,this._controlsListeners.start),this.removeEventListener(`end`,this._controlsListeners.end),this._controls.removeEventListener(`change`,this._controlsListeners.change),this._controlsListeners=void 0,this._controls=void 0,this}dispose(){var e;this.detachControls(),this.children.forEach(e=>{var t,n,r;this.remove(e);let i=e;(t=i.material)==null||t.dispose(),(n=i.material?.map)==null||n.dispose(),(r=i.geometry)==null||r.dispose()}),(e=this._domElement)==null||e.remove()}_updateOrientation(e=!0){e&&(this.quaternion.copy(this.camera.quaternion).invert(),this.updateMatrixWorld()),Du(this._options,this._intersections,this.camera)}_animate(){let{position:e,quaternion:t}=this.camera;if(e.set(0,0,1),!this.animated){e.applyQuaternion(this._quaternionEnd).multiplyScalar(this._distance).add(this.target),t.copy(this._targetQuaternion),this._updateOrientation(),this.animating=!1,this.dispatchEvent({type:`change`}),this.dispatchEvent({type:`end`});return}this._controls&&(this._controls.enabled=!1);let n=this._clock.getDelta()*Nu*this.speed;this._quaternionStart.rotateTowards(this._quaternionEnd,n),e.applyQuaternion(this._quaternionStart).multiplyScalar(this._distance).add(this.target),t.rotateTowards(this._targetQuaternion,n),this._updateOrientation(),requestAnimationFrame(()=>this.dispatchEvent({type:`change`})),this._quaternionStart.angleTo(this._quaternionEnd)<Mu&&(this._controls&&(this._controls.enabled=!0),this.animating=!1,this.dispatchEvent({type:`end`}))}_setOrientation(e){let t=this.camera,n=this.target;Ld.copy(e).multiplyScalar(this._distance),Pd.setPosition(Ld).lookAt(Ld,this.position,this.up),this._targetQuaternion.setFromRotationMatrix(Pd),Ld.add(n),Pd.lookAt(Ld,n,this.up),this._quaternionEnd.setFromRotationMatrix(Pd),Pd.setPosition(t.position).lookAt(t.position,n,this.up),this._quaternionStart.setFromRotationMatrix(Pd),this.animating=!0,this._clock.start(),this.dispatchEvent({type:`start`})}_onPointerDown(e){if(!this.enabled)return;let t=e=>{if(!this._dragging){if(Ou(e,this._pointerStart))return;this._dragging=!0}let t=Id.set(e.clientX,e.clientY).sub(this._pointerStart).multiplyScalar(1/this._domRect.width*Math.PI),n=this.coordinateConversion(Ld.subVectors(this.camera.position,this.target)),r=Fd.setFromVector3(n);r.theta=a-t.x,r.phi=wu(o-t.y,Mu,Math.PI-Mu),this.coordinateConversion(this.camera.position.setFromSpherical(r),!0).add(this.target),this.camera.lookAt(this.target),this.quaternion.copy(this.camera.quaternion).invert(),this._updateOrientation(!1),this.dispatchEvent({type:`change`})},n=()=>{if(document.removeEventListener(`pointermove`,t,!1),document.removeEventListener(`pointerup`,n,!1),!this._dragging)return this._handleClick(e);this._focus&&=(Nd(this._focus,!1),null),this._dragging=!1,this.dispatchEvent({type:`end`})};if(this.animating)return;e.preventDefault(),this._pointerStart.set(e.clientX,e.clientY);let r=this.coordinateConversion(Ld.subVectors(this.camera.position,this.target)),i=Fd.setFromVector3(r),a=i.theta,o=i.phi;this._distance=i.radius,document.addEventListener(`pointermove`,t,!1),document.addEventListener(`pointerup`,n,!1),this.dispatchEvent({type:`start`})}coordinateConversion(e,t=!1){let{x:n,y:r,z:i}=e,a=Kn.DEFAULT_UP;return a.x===1?t?e.set(r,i,n):e.set(i,n,r):a.z===1?t?e.set(i,n,r):e.set(r,i,n):e}_onPointerMove(e){!this.enabled||this._dragging||(this._background&&Ku(this._background,!0),this._handleHover(e))}_onPointerLeave(){!this.enabled||this._dragging||(this._background&&Ku(this._background,!1),this._focus&&Nd(this._focus,!1),this._domElement.style.cursor=``)}_handleClick(e){let t=ju(e,this._domRect,this._camera,this._intersections);this._focus&&=(Nd(this._focus,!1),null),t&&(this._setOrientation(t.object.position),this.dispatchEvent({type:`change`}))}_handleHover(e){let t=ju(e,this._domRect,this._camera,this._intersections)?.object||null;this._focus!==t&&(this._domElement.style.cursor=t?`pointer`:``,this._focus&&Nd(this._focus,!1),(this._focus=t)?Nd(t,!0):Du(this._options,this._intersections,this.camera))}},Bd=class extends Ue{target=new R;constructor(e){super(),this.cc=e,e.addEventListener(`update`,()=>{e.getTarget(this.target),this.dispatchEvent({type:`change`})})}get enabled(){return this.cc.enabled}set enabled(e){this.cc.enabled=e}update(){let e=this.cc.camera.position,t=this.target;this.cc.setLookAt(e.x,e.y,e.z,t.x,t.y,t.z,!1)}},Vd=new Set;function Hd(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Ud(){Wd.faceColor.set(Hd(`--scene-face-color`,`#969696`)),Wd.edgeColor.set(Hd(`--scene-edge-color`,`#000000`)),Wd.gridColor.set(Hd(`--scene-grid-color`,`#6f6f6f`)),Wd.metaEdgeColor.set(Hd(`--scene-meta-edge-color`,`#b0b0b0`)),Wd.highlightColor.set(Hd(`--scene-highlight-color`,`#ffb433`)),Wd.selectEdgeColor.set(Hd(`--scene-select-edge-color`,`#11a4ed`)),Wd.selectFaceColor.set(Hd(`--scene-select-face-color`,`#5c9fcc`)),Wd.constraintColor.set(Hd(`--scene-constraint-color`,`#cccccc`)),Wd.backgroundColor.set(Hd(`--color-base-100`,`#1e1e1e`))}var Wd={faceColor:new B(`#969696`),edgeColor:new B(`#000000`),gridColor:new B(`#6f6f6f`),metaEdgeColor:new B(`#b0b0b0`),highlightColor:new B(`#ffb433`),selectEdgeColor:new B(`#11a4ed`),selectFaceColor:new B(`#5c9fcc`),constraintColor:new B(`#cccccc`),backgroundColor:new B(`#1e1e1e`)};Ud(),new MutationObserver(()=>{Ud();for(let e of Vd)e()}).observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]});function Gd(e){return Vd.add(e),()=>Vd.delete(e)}var Kd=class e{static resolution=new L(window.innerWidth,window.innerHeight);static materials=new Set;static register(t){t.resolution.copy(e.resolution),e.materials.add(t),t.addEventListener(`dispose`,()=>{e.materials.delete(t)})}static setResolution(t,n){e.resolution.set(t,n);for(let t of e.materials)t.resolution.copy(e.resolution)}},qd=new L;function Jd(e){e.getSize(qd);let t=qd.y;return t>0?t:e.domElement.clientHeight||1}function Yd(e,t){if(e instanceof Ua)return(e.top-e.bottom)/e.zoom;if(e instanceof ei){let n=e.position.distanceTo(t),r=e.fov*Math.PI/180;return 2*n*Math.tan(r/2)}return 1}function Xd(e,t,n,r){let i=Jd(e),a=Yd(t,n);return r/i*a}function Zd(e,t,n,r,i){let a=Xd(e,t,n,r)/i;return!Number.isFinite(a)||a<=0?1e-4:Math.min(Math.max(a,1e-4),1e6)}var Qd=null,$d=null;function ef(e,t){Qd=e,$d=t}function tf(e,t,n,r,i){Qd&&$d&&(t.scale.setScalar(Zd(Qd,$d(),n,r,i)),t.updateMatrixWorld(!0)),e.onBeforeRender=(e,a,o)=>{t.scale.setScalar(Zd(e,o,n,r,i)),t.updateMatrixWorld(!0)}}_u.install({THREE:{Vector2:L,Vector3:R,Vector4:Bt,Quaternion:gt,Matrix4:yn,Spherical:mo,Box3:Gt,Sphere:un,Raycaster:uo,MathUtils:{DEG2RAD:ht.DEG2RAD,clamp:ht.clamp}}});var nf=new R(0,0,1),rf=120,af=1.1,of=class{scene;renderer;gizmo;orthoCamera;perspCamera;activeCamera=`orthographic`;_cc;_adapter;dirLight;renderRequested=!1;resizeObserver;clock=new Ya;animFrameId=0;gizmoWasActive=!1;constructor(e){this.container=e,Kn.DEFAULT_UP=nf.clone();let t=e.clientWidth||window.innerWidth,n=e.clientHeight||window.innerHeight;this.renderer=new Dl({antialias:!0,alpha:!0}),this.renderer.setSize(t,n),this.renderer.setPixelRatio(window.devicePixelRatio),Kd.setResolution(t,n),this.renderer.toneMapping=4,this.renderer.outputColorSpace=Ie,this.renderer.localClippingEnabled=!0,e.appendChild(this.renderer.domElement),this.scene=new li,this.scene.background=Wd.backgroundColor.clone();let r=t/n;this.orthoCamera=new Ua(-r*rf/2,r*rf/2,rf/2,-rf/2,-1e4,1e4),this.orthoCamera.position.set(50,-50,40),this.orthoCamera.up.copy(nf),this.orthoCamera.lookAt(0,0,0),this.perspCamera=new ei(50,r,.5,1e4),this.perspCamera.position.set(50,-50,40),this.perspCamera.up.copy(nf),this.perspCamera.lookAt(0,0,0),ef(this.renderer,()=>this.camera),this.dirLight=new Ga(16777215,1),this.scene.add(this.dirLight),this.scene.add(new Ka(14544639,2.5)),this._cc=new _u(this.orthoCamera,this.renderer.domElement),this._cc.dollyToCursor=!0,this._cc.smoothTime=.1,this._cc.draggingSmoothTime=.05,this.configureTouchForMode(`orthographic`),this._cc.updateCameraUp(),this._adapter=new Bd(this._cc),this.gizmo=new zd(this.camera,this.renderer,{size:80,type:`sphere`}),this._cc.setLookAt(50,-50,40,0,0,0,!1),this._cc.getTarget(this._adapter.target),this.gizmo.target=this._adapter.target,this.gizmo.attachControls(this._adapter),this.gizmo.addEventListener(`change`,()=>this.requestRender()),this.resizeObserver=new ResizeObserver(()=>this.handleResize()),this.resizeObserver.observe(e),Gd(()=>{this.scene.background=Wd.backgroundColor.clone(),this.requestRender()}),this.tick()}get camera(){return this.activeCamera===`orthographic`?this.orthoCamera:this.perspCamera}createPickingRaycaster(e,t){let n=this.camera;n.updateMatrixWorld(),n.updateProjectionMatrix();let r=new uo;if(r.setFromCamera(new L(e,t),n),n.isOrthographicCamera){let e=n,t=Math.max(Math.abs(e.far-e.near),1);r.ray.origin.addScaledVector(r.ray.direction,-t)}return r}get cameraControls(){return this._cc}get controls(){return this._adapter}requestRender(){this.renderRequested=!0}fitToBox(e,t){let n=e.getCenter(new R),r=e.getSize(new R).length()/2;if(r===0)return;let i=new un(n,r*af);this._cc.fitToSphere(i,t)}switchCamera(e){if(e===this.activeCamera)return;let t=new R,n=new R;this._cc.getPosition(t),this._cc.getTarget(n);let r=this.camera.up.clone();if(this.activeCamera===`orthographic`&&e===`perspective`){let e=(this.orthoCamera.top-this.orthoCamera.bottom)/this.orthoCamera.zoom,r=ht.DEG2RAD*this.perspCamera.fov*.5,i=e*.5/Math.tan(r),a=t.clone().sub(n).normalize();t.copy(n).add(a.multiplyScalar(i))}this.activeCamera=e;let i=this.camera;i.position.copy(t),i.up.copy(r),i.lookAt(n),this._cc.dispose(),this._cc=new _u(i,this.renderer.domElement),this._cc.dollyToCursor=!0,this._cc.smoothTime=.1,this._cc.draggingSmoothTime=.05,this._cc.setLookAt(t.x,t.y,t.z,n.x,n.y,n.z,!1),this._cc.updateCameraUp(),this.configureTouchForMode(e),this._adapter=new Bd(this._cc),this._cc.getTarget(this._adapter.target),this.gizmo.camera=i,this.gizmo.target=this._adapter.target,this.gizmo.attachControls(this._adapter),this.gizmo.update(),this.requestRender()}render(){this.updateLightPositions(),this.renderer.render(this.scene,this.camera),this.gizmo.render()}dispose(){cancelAnimationFrame(this.animFrameId),this.resizeObserver.disconnect(),this._cc.dispose(),this.scene.clear(),this.renderer.dispose()}tick=()=>{let e=this.clock.getDelta(),t=!1;if(this._cc.enabled){if(this.gizmoWasActive){this._cc.updateCameraUp();let e=this.camera.position,t=this._adapter.target;this._cc.setLookAt(e.x,e.y,e.z,t.x,t.y,t.z,!1),this.gizmoWasActive=!1}t=this._cc.update(e)}else this.gizmoWasActive=!0;(t||this.renderRequested||!this._cc.enabled)&&(this.render(),this.renderRequested=!1),this.animFrameId=requestAnimationFrame(this.tick)};configureTouchForMode(e){e===`orthographic`?(this._cc.touches.one=_u.ACTION.TOUCH_ROTATE,this._cc.touches.two=_u.ACTION.TOUCH_ZOOM_TRUCK):(this._cc.touches.one=_u.ACTION.TOUCH_ROTATE,this._cc.touches.two=_u.ACTION.TOUCH_DOLLY_TRUCK)}handleResize(){let e=this.container.clientWidth,t=this.container.clientHeight||window.innerHeight;if(e===0||t===0)return;let n=e/t;this.renderer.setSize(e,t),this.renderer.setPixelRatio(window.devicePixelRatio),Kd.setResolution(e,t),this.orthoCamera.left=-n*rf/2,this.orthoCamera.right=n*rf/2,this.orthoCamera.top=rf/2,this.orthoCamera.bottom=-rf/2,this.orthoCamera.updateProjectionMatrix(),this.perspCamera.aspect=n,this.perspCamera.updateProjectionMatrix(),this.gizmo.update(),this.requestRender()}updateLightPositions(){let e=new R;this.camera.getWorldDirection(e),this.dirLight.position.copy(e.multiplyScalar(-10)),this.dirLight.target.position.set(0,0,0),this.dirLight.target.updateMatrixWorld()}},sf=class extends U{constructor(e=10,t=100,n=new B(`white`),r=8e3,i=new R(0,1,0)){let a=new ma(2,2,1,1),o=new Yr({side:0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:2,uniforms:{uSize1:{value:e},uSize2:{value:t},uColor:{value:n},uDistance:{value:r},uNormal:{value:i.normalize()}},transparent:!0,vertexShader:`
4203
4203
 
4204
4204
  varying vec3 worldPosition;
4205
4205
 
@@ -4272,7 +4272,7 @@ void main() {
4272
4272
 
4273
4273
  }
4274
4274
 
4275
- `,extensions:{clipCullDistance:!1,multiDraw:!1}});super(a,o),this.frustumCulled=!1}},Qd={cameraMode:`orthographic`,showGrid:!0,sectionView:!0},$d=new class{current={...Qd};listeners=new Set;update(e){Object.assign(this.current,e);for(let e of this.listeners)e(this.current)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function ef(e){$d.update({showGrid:e.showGrid,cameraMode:e.cameraMode})}var tf=new R(0,0,1),nf=new R(50,-50,40),rf=50;function af(e){return new R(e.x,e.y,e.z)}var of=class{mode=`default`;cameraBackup=null;cameraBackupMode=null;enabled=!0;lastGridNormal=tf.clone();lastGridPosition;_sectionPlane=null;constructor(e){this.ctx=e,this.setupDefaultAxes(),this.setupGrid(tf),$d.subscribe(()=>this.applyGridVisibility()),Gd(()=>this.rebuildGrid())}get currentMode(){return this.mode}get isSketchMode(){return this.mode===`sketch`}get sectionPlane(){return this._sectionPlane}set sketchEnabled(e){this.enabled=e}enterDefaultMode(){this.mode===`sketch`&&(this._sectionPlane=null,this.restoreCamera(),this.cameraBackupMode===`perspective`&&(this.ctx.switchCamera(`perspective`),$d.update({cameraMode:`perspective`})),this.cameraBackupMode=null),this.mode=`default`,this.ctx.camera.up.copy(Kn.DEFAULT_UP),this.ctx.cameraControls.updateCameraUp(),this.showDefaultAxes(),this.setupGrid(tf)}enterSketchMode(e){if(!this.enabled)return;this.mode=`sketch`,$d.current.cameraMode===`perspective`&&(this.cameraBackupMode=`perspective`,this.ctx.switchCamera(`orthographic`)),this.positionCameraForSketch(e),this.showSketchAxes(e);let t=af(e.normal),n=af(e.origin);this.setupGrid(t,n.add(t.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}enforceSketchNormal(e){let t=this.ctx.cameraControls,n=af(e.normal),r=af(e.yDirection),i=new R;t.getTarget(i);let a=i.clone().add(n.clone().multiplyScalar(rf));this.ctx.camera.up.copy(r),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,i.x,i.y,i.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.showSketchAxes(e);let o=af(e.origin);this.setupGrid(n,o.add(n.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}positionCameraForSketch(e){let t=this.ctx.cameraControls;if(!this.cameraBackup){let e=new R,n=new R;t.getPosition(e),t.getTarget(n),this.cameraBackup={position:e,target:n}}let n=af(e.center),r=af(e.normal),i=af(e.yDirection),a=n.clone().add(r.clone().multiplyScalar(rf));this.ctx.camera.up.copy(i),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,n.x,n.y,n.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target}restoreCamera(){let e=this.ctx.cameraControls,t=this.cameraBackup,n=t?.position??nf.clone(),r=t?.target??new R(0,0,0);this.ctx.camera.up.copy(Kn.DEFAULT_UP),e.updateCameraUp(),e.normalizeRotations(),e.setLookAt(n.x,n.y,n.z,r.x,r.y,r.z,!1),e.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.cameraBackup=null}setupDefaultAxes(){let e=new Co(1e3);e.name=`defaultAxesHelper`,this.ctx.scene.add(e)}showDefaultAxes(){this.removeByName(`sketchAxesHelper`);let e=this.ctx.scene.getObjectByName(`defaultAxesHelper`);e&&(e.visible=!0)}showSketchAxes(e){let t=this.ctx.scene.getObjectByName(`defaultAxesHelper`);t&&(t.visible=!1),this.removeByName(`sketchAxesHelper`);let n=new Co(1e3);n.name=`sketchAxesHelper`;let r=af(e.origin),i=af(e.xDirection),a=af(e.yDirection),o=af(e.normal),s=new yn().makeBasis(i,a,o);s.setPosition(r),n.matrix.copy(s),n.matrixAutoUpdate=!1,this.ctx.scene.add(n)}rebuildGrid(){this.setupGrid(this.lastGridNormal,this.lastGridPosition),this.ctx.requestRender()}setupGrid(e,t){this.lastGridNormal=e.clone(),this.lastGridPosition=t?.clone(),this.removeByName(`grid`);let n=new Zd(10,100,Wd.gridColor,1e5,e);n.name=`grid`,t&&n.position.copy(t),n.visible=this.mode===`sketch`||$d.current.showGrid,this.ctx.scene.add(n)}applyGridVisibility(){let e=this.ctx.scene.getObjectByName(`grid`);e&&(e.visible=this.mode===`sketch`||$d.current.showGrid,this.ctx.requestRender())}createSectionPlane(e){let t=af(e.normal).negate(),n=af(e.origin);this._sectionPlane||=new Mi,this._sectionPlane.setFromNormalAndCoplanarPoint(t,n)}removeByName(e){let t=this.ctx.scene.getObjectByName(e);t&&this.ctx.scene.remove(t)}},sf=new Gt,cf=new R,lf=class extends qa{constructor(){super(),this.isLineSegmentsGeometry=!0,this.type=`LineSegmentsGeometry`,this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this.setAttribute(`position`,new br([-1,2,0,1,2,0,-1,1,0,1,1,0,-1,0,0,1,0,0,-1,-1,0,1,-1,0],3)),this.setAttribute(`uv`,new br([-1,2,1,2,-1,1,1,1,-1,-1,1,-1,-1,-2,1,-2],2))}applyMatrix4(e){let t=this.attributes.instanceStart,n=this.attributes.instanceEnd;return t!==void 0&&(t.applyMatrix4(e),n.applyMatrix4(e),t.needsUpdate=!0),this.boundingBox!==null&&this.computeBoundingBox(),this.boundingSphere!==null&&this.computeBoundingSphere(),this}setPositions(e){let t;e instanceof Float32Array?t=e:Array.isArray(e)&&(t=new Float32Array(e));let n=new co(t,6,1);return this.setAttribute(`instanceStart`,new fi(n,3,0)),this.setAttribute(`instanceEnd`,new fi(n,3,3)),this.instanceCount=this.attributes.instanceStart.count,this.computeBoundingBox(),this.computeBoundingSphere(),this}setColors(e){let t;e instanceof Float32Array?t=e:Array.isArray(e)&&(t=new Float32Array(e));let n=new co(t,6,1);return this.setAttribute(`instanceColorStart`,new fi(n,3,0)),this.setAttribute(`instanceColorEnd`,new fi(n,3,3)),this}fromWireframeGeometry(e){return this.setPositions(e.attributes.position.array),this}fromEdgesGeometry(e){return this.setPositions(e.attributes.position.array),this}fromMesh(e){return this.fromWireframeGeometry(new ga(e.geometry)),this}fromLineSegments(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new Gt);let e=this.attributes.instanceStart,t=this.attributes.instanceEnd;e!==void 0&&t!==void 0&&(this.boundingBox.setFromBufferAttribute(e),sf.setFromBufferAttribute(t),this.boundingBox.union(sf))}computeBoundingSphere(){this.boundingSphere===null&&(this.boundingSphere=new un),this.boundingBox===null&&this.computeBoundingBox();let e=this.attributes.instanceStart,t=this.attributes.instanceEnd;if(e!==void 0&&t!==void 0){let n=this.boundingSphere.center;this.boundingBox.getCenter(n);let r=0;for(let i=0,a=e.count;i<a;i++)cf.fromBufferAttribute(e,i),r=Math.max(r,n.distanceToSquared(cf)),cf.fromBufferAttribute(t,i),r=Math.max(r,n.distanceToSquared(cf));this.boundingSphere.radius=Math.sqrt(r),isNaN(this.boundingSphere.radius)&&console.error(`THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.`,this)}}toJSON(){}};G.line={worldUnits:{value:1},linewidth:{value:1},resolution:{value:new L(1,1)},dashOffset:{value:0},dashScale:{value:1},dashSize:{value:1},gapSize:{value:1}},Oo.line={uniforms:Kr.merge([G.common,G.fog,G.line]),vertexShader:`
4275
+ `,extensions:{clipCullDistance:!1,multiDraw:!1}});super(a,o),this.frustumCulled=!1}},cf={cameraMode:`orthographic`,showGrid:!0,sectionView:!0},lf=new class{current={...cf};listeners=new Set;update(e){Object.assign(this.current,e);for(let e of this.listeners)e(this.current)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function uf(e){lf.update({showGrid:e.showGrid,cameraMode:e.cameraMode})}var df=new R(0,0,1),ff=new R(50,-50,40),pf=50;function mf(e){return new R(e.x,e.y,e.z)}var hf=class{mode=`default`;cameraBackup=null;cameraBackupMode=null;enabled=!0;lastGridNormal=df.clone();lastGridPosition;_sectionPlane=null;constructor(e){this.ctx=e,this.setupDefaultAxes(),this.setupGrid(df),lf.subscribe(()=>this.applyGridVisibility()),Gd(()=>this.rebuildGrid())}get currentMode(){return this.mode}get isSketchMode(){return this.mode===`sketch`}get sectionPlane(){return this._sectionPlane}set sketchEnabled(e){this.enabled=e}enterDefaultMode(){this.mode===`sketch`&&(this._sectionPlane=null,this.restoreCamera(),this.cameraBackupMode===`perspective`&&(this.ctx.switchCamera(`perspective`),lf.update({cameraMode:`perspective`})),this.cameraBackupMode=null),this.mode=`default`,this.ctx.camera.up.copy(Kn.DEFAULT_UP),this.ctx.cameraControls.updateCameraUp(),this.showDefaultAxes(),this.setupGrid(df)}enterSketchMode(e){if(!this.enabled)return;this.mode=`sketch`,lf.current.cameraMode===`perspective`&&(this.cameraBackupMode=`perspective`,this.ctx.switchCamera(`orthographic`)),this.positionCameraForSketch(e),this.showSketchAxes(e);let t=mf(e.normal),n=mf(e.origin);this.setupGrid(t,n.add(t.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}enforceSketchNormal(e){let t=this.ctx.cameraControls,n=mf(e.normal),r=mf(e.yDirection),i=new R;t.getTarget(i);let a=i.clone().add(n.clone().multiplyScalar(pf));this.ctx.camera.up.copy(r),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,i.x,i.y,i.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.showSketchAxes(e);let o=mf(e.origin);this.setupGrid(n,o.add(n.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}positionCameraForSketch(e){let t=this.ctx.cameraControls;if(!this.cameraBackup){let e=new R,n=new R;t.getPosition(e),t.getTarget(n),this.cameraBackup={position:e,target:n}}let n=mf(e.center),r=mf(e.normal),i=mf(e.yDirection),a=n.clone().add(r.clone().multiplyScalar(pf));this.ctx.camera.up.copy(i),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,n.x,n.y,n.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target}restoreCamera(){let e=this.ctx.cameraControls,t=this.cameraBackup,n=t?.position??ff.clone(),r=t?.target??new R(0,0,0);this.ctx.camera.up.copy(Kn.DEFAULT_UP),e.updateCameraUp(),e.normalizeRotations(),e.setLookAt(n.x,n.y,n.z,r.x,r.y,r.z,!1),e.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.cameraBackup=null}setupDefaultAxes(){let e=new Co(1e3);e.name=`defaultAxesHelper`,this.ctx.scene.add(e)}showDefaultAxes(){this.removeByName(`sketchAxesHelper`);let e=this.ctx.scene.getObjectByName(`defaultAxesHelper`);e&&(e.visible=!0)}showSketchAxes(e){let t=this.ctx.scene.getObjectByName(`defaultAxesHelper`);t&&(t.visible=!1),this.removeByName(`sketchAxesHelper`);let n=new Co(1e3);n.name=`sketchAxesHelper`;let r=mf(e.origin),i=mf(e.xDirection),a=mf(e.yDirection),o=mf(e.normal),s=new yn().makeBasis(i,a,o);s.setPosition(r),n.matrix.copy(s),n.matrixAutoUpdate=!1,this.ctx.scene.add(n)}rebuildGrid(){this.setupGrid(this.lastGridNormal,this.lastGridPosition),this.ctx.requestRender()}setupGrid(e,t){this.lastGridNormal=e.clone(),this.lastGridPosition=t?.clone(),this.removeByName(`grid`);let n=new sf(10,100,Wd.gridColor,1e5,e);n.name=`grid`,t&&n.position.copy(t),n.visible=this.mode===`sketch`||lf.current.showGrid,this.ctx.scene.add(n)}applyGridVisibility(){let e=this.ctx.scene.getObjectByName(`grid`);e&&(e.visible=this.mode===`sketch`||lf.current.showGrid,this.ctx.requestRender())}createSectionPlane(e){let t=mf(e.normal).negate(),n=mf(e.origin);this._sectionPlane||=new Mi,this._sectionPlane.setFromNormalAndCoplanarPoint(t,n)}removeByName(e){let t=this.ctx.scene.getObjectByName(e);t&&this.ctx.scene.remove(t)}},gf=new Gt,_f=new R,vf=class extends qa{constructor(){super(),this.isLineSegmentsGeometry=!0,this.type=`LineSegmentsGeometry`,this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this.setAttribute(`position`,new br([-1,2,0,1,2,0,-1,1,0,1,1,0,-1,0,0,1,0,0,-1,-1,0,1,-1,0],3)),this.setAttribute(`uv`,new br([-1,2,1,2,-1,1,1,1,-1,-1,1,-1,-1,-2,1,-2],2))}applyMatrix4(e){let t=this.attributes.instanceStart,n=this.attributes.instanceEnd;return t!==void 0&&(t.applyMatrix4(e),n.applyMatrix4(e),t.needsUpdate=!0),this.boundingBox!==null&&this.computeBoundingBox(),this.boundingSphere!==null&&this.computeBoundingSphere(),this}setPositions(e){let t;e instanceof Float32Array?t=e:Array.isArray(e)&&(t=new Float32Array(e));let n=new co(t,6,1);return this.setAttribute(`instanceStart`,new fi(n,3,0)),this.setAttribute(`instanceEnd`,new fi(n,3,3)),this.instanceCount=this.attributes.instanceStart.count,this.computeBoundingBox(),this.computeBoundingSphere(),this}setColors(e){let t;e instanceof Float32Array?t=e:Array.isArray(e)&&(t=new Float32Array(e));let n=new co(t,6,1);return this.setAttribute(`instanceColorStart`,new fi(n,3,0)),this.setAttribute(`instanceColorEnd`,new fi(n,3,3)),this}fromWireframeGeometry(e){return this.setPositions(e.attributes.position.array),this}fromEdgesGeometry(e){return this.setPositions(e.attributes.position.array),this}fromMesh(e){return this.fromWireframeGeometry(new ga(e.geometry)),this}fromLineSegments(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new Gt);let e=this.attributes.instanceStart,t=this.attributes.instanceEnd;e!==void 0&&t!==void 0&&(this.boundingBox.setFromBufferAttribute(e),gf.setFromBufferAttribute(t),this.boundingBox.union(gf))}computeBoundingSphere(){this.boundingSphere===null&&(this.boundingSphere=new un),this.boundingBox===null&&this.computeBoundingBox();let e=this.attributes.instanceStart,t=this.attributes.instanceEnd;if(e!==void 0&&t!==void 0){let n=this.boundingSphere.center;this.boundingBox.getCenter(n);let r=0;for(let i=0,a=e.count;i<a;i++)_f.fromBufferAttribute(e,i),r=Math.max(r,n.distanceToSquared(_f)),_f.fromBufferAttribute(t,i),r=Math.max(r,n.distanceToSquared(_f));this.boundingSphere.radius=Math.sqrt(r),isNaN(this.boundingSphere.radius)&&console.error(`THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.`,this)}}toJSON(){}};G.line={worldUnits:{value:1},linewidth:{value:1},resolution:{value:new L(1,1)},dashOffset:{value:0},dashScale:{value:1},dashSize:{value:1},gapSize:{value:1}},Oo.line={uniforms:Kr.merge([G.common,G.fog,G.line]),vertexShader:`
4276
4276
  #include <common>
4277
4277
  #include <color_pars_vertex>
4278
4278
  #include <fog_pars_vertex>
@@ -4641,7 +4641,7 @@ void main() {
4641
4641
  #include <premultiplied_alpha_fragment>
4642
4642
 
4643
4643
  }
4644
- `};var uf=class extends Yr{constructor(e){super({type:`LineMaterial`,uniforms:Kr.clone(Oo.line.uniforms),vertexShader:Oo.line.vertexShader,fragmentShader:Oo.line.fragmentShader,clipping:!0}),this.isLineMaterial=!0,this.setValues(e)}get color(){return this.uniforms.diffuse.value}set color(e){this.uniforms.diffuse.value=e}get worldUnits(){return`WORLD_UNITS`in this.defines}set worldUnits(e){e===!0?this.defines.WORLD_UNITS=``:delete this.defines.WORLD_UNITS}get linewidth(){return this.uniforms.linewidth.value}set linewidth(e){this.uniforms.linewidth&&(this.uniforms.linewidth.value=e)}get dashed(){return`USE_DASH`in this.defines}set dashed(e){e===!0!==this.dashed&&(this.needsUpdate=!0),e===!0?this.defines.USE_DASH=``:delete this.defines.USE_DASH}get dashScale(){return this.uniforms.dashScale.value}set dashScale(e){this.uniforms.dashScale.value=e}get dashSize(){return this.uniforms.dashSize.value}set dashSize(e){this.uniforms.dashSize.value=e}get dashOffset(){return this.uniforms.dashOffset.value}set dashOffset(e){this.uniforms.dashOffset.value=e}get gapSize(){return this.uniforms.gapSize.value}set gapSize(e){this.uniforms.gapSize.value=e}get opacity(){return this.uniforms.opacity.value}set opacity(e){this.uniforms&&(this.uniforms.opacity.value=e)}get resolution(){return this.uniforms.resolution.value}set resolution(e){this.uniforms.resolution.value.copy(e)}get alphaToCoverage(){return`USE_ALPHA_TO_COVERAGE`in this.defines}set alphaToCoverage(e){this.defines&&(e===!0!==this.alphaToCoverage&&(this.needsUpdate=!0),e===!0?this.defines.USE_ALPHA_TO_COVERAGE=``:delete this.defines.USE_ALPHA_TO_COVERAGE)}},df=new Bt,ff=new R,pf=new R,mf=new Bt,hf=new Bt,gf=new Bt,_f=new R,vf=new yn,yf=new So,bf=new R,xf=new Gt,Sf=new un,Cf=new Bt,wf,Tf;function Ef(e,t,n){return Cf.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),Cf.multiplyScalar(1/Cf.w),Cf.x=Tf/n.width,Cf.y=Tf/n.height,Cf.applyMatrix4(e.projectionMatrixInverse),Cf.multiplyScalar(1/Cf.w),Math.abs(Math.max(Cf.x,Cf.y))}function Df(e,t){let n=e.matrixWorld,r=e.geometry,i=r.attributes.instanceStart,a=r.attributes.instanceEnd,o=Math.min(r.instanceCount,i.count);for(let r=0,s=o;r<s;r++){yf.start.fromBufferAttribute(i,r),yf.end.fromBufferAttribute(a,r),yf.applyMatrix4(n);let o=new R,s=new R;wf.distanceSqToSegment(yf.start,yf.end,s,o),s.distanceTo(o)<Tf*.5&&t.push({point:s,pointOnLine:o,distance:wf.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function Of(e,t,n){let r=t.projectionMatrix,i=e.material.resolution,a=e.matrixWorld,o=e.geometry,s=o.attributes.instanceStart,c=o.attributes.instanceEnd,l=Math.min(o.instanceCount,s.count),u=-t.near;wf.at(1,gf),gf.w=1,gf.applyMatrix4(t.matrixWorldInverse),gf.applyMatrix4(r),gf.multiplyScalar(1/gf.w),gf.x*=i.x/2,gf.y*=i.y/2,gf.z=0,_f.copy(gf),vf.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(mf.fromBufferAttribute(s,t),hf.fromBufferAttribute(c,t),mf.w=1,hf.w=1,mf.applyMatrix4(vf),hf.applyMatrix4(vf),mf.z>u&&hf.z>u)continue;if(mf.z>u){let e=mf.z-hf.z,t=(mf.z-u)/e;mf.lerp(hf,t)}else if(hf.z>u){let e=hf.z-mf.z,t=(hf.z-u)/e;hf.lerp(mf,t)}mf.applyMatrix4(r),hf.applyMatrix4(r),mf.multiplyScalar(1/mf.w),hf.multiplyScalar(1/hf.w),mf.x*=i.x/2,mf.y*=i.y/2,hf.x*=i.x/2,hf.y*=i.y/2,yf.start.copy(mf),yf.start.z=0,yf.end.copy(hf),yf.end.z=0;let o=yf.closestPointToPointParameter(_f,!0);yf.at(o,bf);let l=ht.lerp(mf.z,hf.z,o),d=l>=-1&&l<=1,f=_f.distanceTo(bf)<Tf*.5;if(d&&f){yf.start.fromBufferAttribute(s,t),yf.end.fromBufferAttribute(c,t),yf.start.applyMatrix4(a),yf.end.applyMatrix4(a);let r=new R,i=new R;wf.distanceSqToSegment(yf.start,yf.end,i,r),n.push({point:i,pointOnLine:r,distance:wf.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var kf=class extends U{constructor(e=new lf,t=new uf({color:Math.random()*16777215})){super(e,t),this.isLineSegments2=!0,this.type=`LineSegments2`}computeLineDistances(){let e=this.geometry,t=e.attributes.instanceStart,n=e.attributes.instanceEnd,r=new Float32Array(2*t.count);for(let e=0,i=0,a=t.count;e<a;e++,i+=2)ff.fromBufferAttribute(t,e),pf.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+ff.distanceTo(pf);let i=new co(r,2,1);return e.setAttribute(`instanceDistanceStart`,new fi(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new fi(i,1,1)),this}raycast(e,t){let n=this.material.worldUnits,r=e.camera;r===null&&!n&&console.error(`LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.`);let i=e.params.Line2===void 0?0:e.params.Line2.threshold||0;wf=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;Tf=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),Sf.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?Tf*.5:Ef(r,Math.max(r.near,Sf.distanceToPoint(wf.origin)),s.resolution),Sf.radius+=c,wf.intersectsSphere(Sf)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),xf.copy(o.boundingBox).applyMatrix4(a);let l;l=n?Tf*.5:Ef(r,Math.max(r.near,xf.distanceToPoint(wf.origin)),s.resolution),xf.expandByScalar(l),wf.intersectsBox(xf)!==!1&&(n?Df(this,t):Of(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport(df),this.material.uniforms.resolution.value.set(df.z,df.w))}},Af={color:``,lineWidth:1,opacity:1,depthWrite:!0,transparent:!1},jf=class e extends oi{constructor(t,n={}){super();let r={...Af,...n};for(let n of t.meshes){let t=e.expandIndexedPositions(n.vertices,n.indices),i=new lf;i.setPositions(t);let a=new uf({color:r.color||Wd.edgeColor.getHex(),linewidth:r.lineWidth,transparent:r.transparent||r.opacity<1,opacity:r.opacity,side:2,depthWrite:r.depthWrite,depthTest:r.depthWrite});Kd.register(a);let o=new kf(i,a);o.userData.isEdgeLine=!0,n.edgeIndex!==void 0&&(o.userData.edgeIndex=n.edgeIndex),this.add(o)}}static expandIndexedPositions(e,t){let n=new Float32Array(t.length*3);for(let r=0;r<t.length;r++){let i=t[r]*3;n[r*3]=e[i],n[r*3+1]=e[i+1],n[r*3+2]=e[i+2]}return n}},Mf={color:``,opacity:1},Nf=class extends oi{constructor(e,t={}){super();let n={...Mf,...t};for(let r of e.meshes){let e=new H;e.setAttribute(`position`,new V(new Float32Array(r.vertices),3)),e.setAttribute(`normal`,new V(new Float32Array(r.normals),3));let i=r.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new V(new i(r.indices),1)),e.computeBoundingBox();let a=t?.color??r.color??`#`+Wd.faceColor.getHexString(),o=t?.color!==void 0||t?.opacity!==void 0,s=new U(e,new va({color:a,transparent:o||n.opacity<1,opacity:n.opacity,depthWrite:!o,polygonOffset:!0,polygonOffsetFactor:o?-1:1,polygonOffsetUnits:1,side:2}));r.faceMapping&&(s.userData.faceMapping=r.faceMapping),this.add(s)}}},Pf=class extends oi{constructor(e,t){super();for(let n of e.meshes)if(n.label===`solid-faces`){let e=new Nf({shapeType:`face`,meshes:[n]},t?.face);e.renderOrder=1,this.add(e)}else if(n.label===`solid-edges`){let e=new jf({shapeType:`edge`,meshes:[n]},t?.edge);e.renderOrder=2,this.add(e)}}},Ff=4,If=1.5,Lf=.6,Rf=Ff+If+Lf+If,zf=`
4644
+ `};var yf=class extends Yr{constructor(e){super({type:`LineMaterial`,uniforms:Kr.clone(Oo.line.uniforms),vertexShader:Oo.line.vertexShader,fragmentShader:Oo.line.fragmentShader,clipping:!0}),this.isLineMaterial=!0,this.setValues(e)}get color(){return this.uniforms.diffuse.value}set color(e){this.uniforms.diffuse.value=e}get worldUnits(){return`WORLD_UNITS`in this.defines}set worldUnits(e){e===!0?this.defines.WORLD_UNITS=``:delete this.defines.WORLD_UNITS}get linewidth(){return this.uniforms.linewidth.value}set linewidth(e){this.uniforms.linewidth&&(this.uniforms.linewidth.value=e)}get dashed(){return`USE_DASH`in this.defines}set dashed(e){e===!0!==this.dashed&&(this.needsUpdate=!0),e===!0?this.defines.USE_DASH=``:delete this.defines.USE_DASH}get dashScale(){return this.uniforms.dashScale.value}set dashScale(e){this.uniforms.dashScale.value=e}get dashSize(){return this.uniforms.dashSize.value}set dashSize(e){this.uniforms.dashSize.value=e}get dashOffset(){return this.uniforms.dashOffset.value}set dashOffset(e){this.uniforms.dashOffset.value=e}get gapSize(){return this.uniforms.gapSize.value}set gapSize(e){this.uniforms.gapSize.value=e}get opacity(){return this.uniforms.opacity.value}set opacity(e){this.uniforms&&(this.uniforms.opacity.value=e)}get resolution(){return this.uniforms.resolution.value}set resolution(e){this.uniforms.resolution.value.copy(e)}get alphaToCoverage(){return`USE_ALPHA_TO_COVERAGE`in this.defines}set alphaToCoverage(e){this.defines&&(e===!0!==this.alphaToCoverage&&(this.needsUpdate=!0),e===!0?this.defines.USE_ALPHA_TO_COVERAGE=``:delete this.defines.USE_ALPHA_TO_COVERAGE)}},bf=new Bt,xf=new R,Sf=new R,Cf=new Bt,wf=new Bt,Tf=new Bt,Ef=new R,Df=new yn,Of=new So,kf=new R,Af=new Gt,jf=new un,Mf=new Bt,Nf,Pf;function Ff(e,t,n){return Mf.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),Mf.multiplyScalar(1/Mf.w),Mf.x=Pf/n.width,Mf.y=Pf/n.height,Mf.applyMatrix4(e.projectionMatrixInverse),Mf.multiplyScalar(1/Mf.w),Math.abs(Math.max(Mf.x,Mf.y))}function If(e,t){let n=e.matrixWorld,r=e.geometry,i=r.attributes.instanceStart,a=r.attributes.instanceEnd,o=Math.min(r.instanceCount,i.count);for(let r=0,s=o;r<s;r++){Of.start.fromBufferAttribute(i,r),Of.end.fromBufferAttribute(a,r),Of.applyMatrix4(n);let o=new R,s=new R;Nf.distanceSqToSegment(Of.start,Of.end,s,o),s.distanceTo(o)<Pf*.5&&t.push({point:s,pointOnLine:o,distance:Nf.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function Lf(e,t,n){let r=t.projectionMatrix,i=e.material.resolution,a=e.matrixWorld,o=e.geometry,s=o.attributes.instanceStart,c=o.attributes.instanceEnd,l=Math.min(o.instanceCount,s.count),u=-t.near;Nf.at(1,Tf),Tf.w=1,Tf.applyMatrix4(t.matrixWorldInverse),Tf.applyMatrix4(r),Tf.multiplyScalar(1/Tf.w),Tf.x*=i.x/2,Tf.y*=i.y/2,Tf.z=0,Ef.copy(Tf),Df.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(Cf.fromBufferAttribute(s,t),wf.fromBufferAttribute(c,t),Cf.w=1,wf.w=1,Cf.applyMatrix4(Df),wf.applyMatrix4(Df),Cf.z>u&&wf.z>u)continue;if(Cf.z>u){let e=Cf.z-wf.z,t=(Cf.z-u)/e;Cf.lerp(wf,t)}else if(wf.z>u){let e=wf.z-Cf.z,t=(wf.z-u)/e;wf.lerp(Cf,t)}Cf.applyMatrix4(r),wf.applyMatrix4(r),Cf.multiplyScalar(1/Cf.w),wf.multiplyScalar(1/wf.w),Cf.x*=i.x/2,Cf.y*=i.y/2,wf.x*=i.x/2,wf.y*=i.y/2,Of.start.copy(Cf),Of.start.z=0,Of.end.copy(wf),Of.end.z=0;let o=Of.closestPointToPointParameter(Ef,!0);Of.at(o,kf);let l=ht.lerp(Cf.z,wf.z,o),d=l>=-1&&l<=1,f=Ef.distanceTo(kf)<Pf*.5;if(d&&f){Of.start.fromBufferAttribute(s,t),Of.end.fromBufferAttribute(c,t),Of.start.applyMatrix4(a),Of.end.applyMatrix4(a);let r=new R,i=new R;Nf.distanceSqToSegment(Of.start,Of.end,i,r),n.push({point:i,pointOnLine:r,distance:Nf.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var Rf=class extends U{constructor(e=new vf,t=new yf({color:Math.random()*16777215})){super(e,t),this.isLineSegments2=!0,this.type=`LineSegments2`}computeLineDistances(){let e=this.geometry,t=e.attributes.instanceStart,n=e.attributes.instanceEnd,r=new Float32Array(2*t.count);for(let e=0,i=0,a=t.count;e<a;e++,i+=2)xf.fromBufferAttribute(t,e),Sf.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+xf.distanceTo(Sf);let i=new co(r,2,1);return e.setAttribute(`instanceDistanceStart`,new fi(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new fi(i,1,1)),this}raycast(e,t){let n=this.material.worldUnits,r=e.camera;r===null&&!n&&console.error(`LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.`);let i=e.params.Line2===void 0?0:e.params.Line2.threshold||0;Nf=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;Pf=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),jf.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?Pf*.5:Ff(r,Math.max(r.near,jf.distanceToPoint(Nf.origin)),s.resolution),jf.radius+=c,Nf.intersectsSphere(jf)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),Af.copy(o.boundingBox).applyMatrix4(a);let l;l=n?Pf*.5:Ff(r,Math.max(r.near,Af.distanceToPoint(Nf.origin)),s.resolution),Af.expandByScalar(l),Nf.intersectsBox(Af)!==!1&&(n?If(this,t):Lf(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport(bf),this.material.uniforms.resolution.value.set(bf.z,bf.w))}},zf={color:``,lineWidth:1,opacity:1,depthWrite:!0,transparent:!1},Bf=class e extends oi{constructor(t,n={}){super();let r={...zf,...n};for(let n of t.meshes){let t=e.expandIndexedPositions(n.vertices,n.indices),i=new vf;i.setPositions(t);let a=new yf({color:r.color||Wd.edgeColor.getHex(),linewidth:r.lineWidth,transparent:r.transparent||r.opacity<1,opacity:r.opacity,side:2,depthWrite:r.depthWrite,depthTest:r.depthWrite});Kd.register(a);let o=new Rf(i,a);o.userData.isEdgeLine=!0,n.edgeIndex!==void 0&&(o.userData.edgeIndex=n.edgeIndex),this.add(o)}}static expandIndexedPositions(e,t){let n=new Float32Array(t.length*3);for(let r=0;r<t.length;r++){let i=t[r]*3;n[r*3]=e[i],n[r*3+1]=e[i+1],n[r*3+2]=e[i+2]}return n}},Vf={color:``,opacity:1},Hf=class extends oi{constructor(e,t={}){super();let n={...Vf,...t};for(let r of e.meshes){let e=new H;e.setAttribute(`position`,new V(new Float32Array(r.vertices),3)),e.setAttribute(`normal`,new V(new Float32Array(r.normals),3));let i=r.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new V(new i(r.indices),1)),e.computeBoundingBox();let a=t?.color??r.color??`#`+Wd.faceColor.getHexString(),o=t?.color!==void 0||t?.opacity!==void 0,s=new U(e,new va({color:a,transparent:o||n.opacity<1,opacity:n.opacity,depthWrite:!o,polygonOffset:!0,polygonOffsetFactor:o?-1:1,polygonOffsetUnits:1,side:2}));r.faceMapping&&(s.userData.faceMapping=r.faceMapping),this.add(s)}}},Uf=class extends oi{constructor(e,t){super();for(let n of e.meshes)if(n.label===`solid-faces`){let e=new Hf({shapeType:`face`,meshes:[n]},t?.face);e.renderOrder=1,this.add(e)}else if(n.label===`solid-edges`){let e=new Bf({shapeType:`edge`,meshes:[n]},t?.edge);e.renderOrder=2,this.add(e)}}},Wf=4,Gf=1.5,Kf=.6,qf=Wf+Gf+Kf+Gf,Jf=`
4645
4645
  attribute float lineDistance;
4646
4646
  varying float vLineDistance;
4647
4647
 
@@ -4649,7 +4649,7 @@ void main() {
4649
4649
  vLineDistance = lineDistance;
4650
4650
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
4651
4651
  }
4652
- `,Bf=`
4652
+ `,Yf=`
4653
4653
  uniform vec3 color;
4654
4654
  uniform float dashLength;
4655
4655
  uniform float gapLength;
@@ -4674,7 +4674,7 @@ void main() {
4674
4674
 
4675
4675
  gl_FragColor = vec4(color, 1.0);
4676
4676
  }
4677
- `,Vf=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=t.vertices,n=t.indices,r=[];for(let t=0;t<n.length;t+=2){let i=n[t]*3;r.push(e[i],e[i+1],e[i+2])}if(n.length>=2){let t=n[n.length-1]*3;r.push(e[t],e[t+1],e[t+2])}let i=new H;i.setAttribute(`position`,new V(new Float32Array(r),3));let a=new Gi(i,new Yr({uniforms:{color:{value:Wd.metaEdgeColor},dashLength:{value:Ff},gapLength:{value:If},dotLength:{value:Lf},patternLength:{value:Rf}},vertexShader:zf,fragmentShader:Bf,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},Hf=`#2297ff`,Uf=2,Wf=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=jf.expandIndexedPositions(t.vertices,t.indices),n=new lf;n.setPositions(e);let r=new uf({color:Hf,linewidth:Uf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});Kd.register(r),this.add(new kf(n,r))}}},Gf=`#2297ff`,Kf=`#2297ff`,qf=.15,Jf=.4,Yf=class extends oi{constructor(e,t){super(),this.userData.isMetaShape=!0,this.userData.isPickRegion=!0,this.userData.isPickRegionSelected=t,e.metaData&&(this.userData.metaData=e.metaData);let n=t?Kf:Gf,r=t?Jf:qf;for(let t of e.meshes){let e=new H;e.setAttribute(`position`,new V(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new V(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new V(new i(t.indices),1)),e.computeBoundingBox();let a=new U(e,new mr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},Xf=new L;function Zf(e){e.getSize(Xf);let t=Xf.y;return t>0?t:e.domElement.clientHeight||1}function Qf(e,t){if(e instanceof Ua)return(e.top-e.bottom)/e.zoom;if(e instanceof ei){let n=e.position.distanceTo(t),r=e.fov*Math.PI/180;return 2*n*Math.tan(r/2)}return 1}function $f(e,t,n,r){let i=Zf(e),a=Qf(t,n);return r/i*a}function ep(e,t,n,r,i){let a=$f(e,t,n,r)/i;return!Number.isFinite(a)||a<=0?1e-4:Math.min(Math.max(a,1e-4),1e6)}function tp(e,t,n,r,i){e.onBeforeRender=(e,a,o)=>{t.scale.setScalar(ep(e,o,n,r,i)),t.updateMatrixWorld(!0)}}var np=`#2297ff`,rp=2,ip=2,ap=16,op=6,sp=1e-8,cp=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;let t=new oa(ip,ap),n=new mr({color:np,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=jf.expandIndexedPositions(t.vertices,t.indices),n=new lf;n.setPositions(e);let i=new uf({color:np,linewidth:rp,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});Kd.register(i),this.add(new kf(n,i));let a=t.vertices,o=t.indices,s=new Map;for(let e of o)s.set(e,(s.get(e)||0)+1);for(let[e,t]of s)if(t===1){let t=new R(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<sp)||r.push(t)}}for(let e of r){let r=new U(t,n);r.renderOrder=2;let i=new oi;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),tp(r,i,e,op,ip),this.add(i)}}},lp={color:`#2297ff`,lineWidth:2},up={trim:e=>new Wf(e),"pick-edge":e=>new cp(e)};function dp(e){let t=e.metaType?up[e.metaType]:void 0;return t?t(e):new Vf(e)}var fp={"pick-region":e=>new Yf(e,!1),"pick-region-selected":e=>new Yf(e,!0)};function pp(e){let t=e.metaType?fp[e.metaType]:void 0;return t?t(e):new Nf(e)}var mp=class extends oi{constructor(e,t,n){if(super(),!e.sceneShapes)return;let r=e.sceneShapes.every(e=>e.isMetaShape||e.shapeType===`wire`||e.shapeType===`edge`),i=[`pick-region`,`pick-region-selected`,`pick-edge`];for(let a of e.sceneShapes){if(!t&&a.isMetaShape&&a.metaType&&i.includes(a.metaType))continue;let e;if(a.isMetaShape)switch(a.shapeType){case`wire`:case`edge`:e=dp(a);break;case`face`:e=pp(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new jf(a,n?.edge??(r?lp:void 0));break;case`face`:e=new Nf(a,n?.face);break;case`solid`:e=new Pf(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}},hp=new Set([`line-two-points`,`hline`,`vline`,`circle`,`arc`,`arc-from-center`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`tline`,`trim2d`,`rect`,`polygon`,`slot`]);function gp(e){return e?e.startsWith(`bezier-`)?!0:hp.has(e):!1}function _p(e,t,n){let r=[],i=n.origin.x,a=n.origin.y,o=n.origin.z,s=n.xDirection.x,c=n.xDirection.y,l=n.xDirection.z,u=n.yDirection.x,d=n.yDirection.y,f=n.yDirection.z,p=e.some(e=>e.parentId===t&&e.sceneShapes.some(e=>e.metaType===`trim`));for(let n of e)if(n.parentId===t&&gp(n.uniqueType))for(let e of n.sceneShapes){if(!e.shapeId)continue;if(p){if(e.metaType!==`trim`)continue}else if(e.isMetaShape||e.isGuide)continue;let t=[],n=[];for(let r of e.meshes){let e=r.vertices,p=r.indices;if(!p.length)continue;let m=new Map;for(let e of p)m.set(e,(m.get(e)||0)+1);for(let[t,r]of m)r===1&&n.push([e[t*3],e[t*3+1],e[t*3+2]]);for(let n=0;n<p.length;n+=2){let r=p[n]*3,m=p[n+1]*3,h=e[r]-i,g=e[r+1]-a,_=e[r+2]-o,v=h*s+g*c+_*l,y=h*u+g*d+_*f,b=e[m]-i,x=e[m+1]-a,S=e[m+2]-o,C=b*s+x*c+S*l,w=b*u+x*d+S*f;t.push({ax:v,ay:y,bx:C,by:w})}}t.length>0&&r.push({shapeId:e.shapeId,segments:t,endpoints:n})}return r}var vp=new Set([`arc`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`slot`]);function yp(e,t,n){let r=[],i=n.origin.x,a=n.origin.y,o=n.origin.z,s=n.xDirection.x,c=n.xDirection.y,l=n.xDirection.z,u=n.yDirection.x,d=n.yDirection.y,f=n.yDirection.z;for(let n of e){if(n.parentId!==t||!gp(n.uniqueType))continue;let e=null;for(let t of n.sceneShapes)if(!t.isMetaShape&&t.shapeId){e=t.shapeId;break}if(!e)continue;let p=n.uniqueType??``;if(p.startsWith(`bezier-`)){let t=n.object?.startPoint,i=n.object?.resolvedPoints;if(t&&r.push({shapeId:e,point2d:[t[0],t[1]]}),i)for(let t of i)r.push({shapeId:e,point2d:[t[0],t[1]]});continue}if(vp.has(p)){for(let t of n.sceneShapes)if(t.isMetaShape){for(let n of t.meshes)if(n.vertices.length===3&&n.indices.length===0){let t=n.vertices[0]-i,p=n.vertices[1]-a,m=n.vertices[2]-o,h=t*s+p*c+m*l,g=t*u+p*d+m*f;r.push({shapeId:e,point2d:[h,g]})}}}}return r}function bp(e,t,n,r,i,a){return xp(e,t,n,r,i,a).dist}function xp(e,t,n,r,i,a){let o=i-n,s=a-r,c=o*o+s*s,l,u;if(c===0)l=n,u=r;else{let i=((e-n)*o+(t-r)*s)/c;i<0?i=0:i>1&&(i=1),l=n+i*o,u=r+i*s}let d=l-e,f=u-t;return{x:l,y:u,dist:Math.sqrt(d*d+f*f)}}function Sp(e,t,n,r){let i=e.renderer.domElement.getBoundingClientRect(),a=(n-i.left)/i.width*2-1,o=-((r-i.top)/i.height)*2+1,s=e.createPickingRaycaster(a,o),c=s.ray.origin,l=s.ray.direction,u=Op(t.origin),d=Op(t.normal),f=l.dot(d);if(Math.abs(f)<1e-6)return null;let p=u.clone().sub(c).dot(d)/f;if(p<0)return null;let m=c.clone().add(l.clone().multiplyScalar(p)).clone().sub(u),h=Op(t.xDirection),g=Op(t.yDirection);return[m.dot(h),m.dot(g)]}function Cp(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}function wp(e,t,n){let r=Cp(n,t).project(e.camera),i=e.renderer.domElement.getBoundingClientRect();return{clientX:(r.x+1)/2*i.width+i.left,clientY:(1-r.y)/2*i.height+i.top}}function Tp(e,t){let n=new R(e.x-t.origin.x,e.y-t.origin.y,e.z-t.origin.z),r=Op(t.xDirection),i=Op(t.yDirection);return[n.dot(r),n.dot(i)]}function Y(e){return[Math.round(e[0]*100)/100,Math.round(e[1]*100)/100]}function Ep(e,t){let n=e.camera,r=e.renderer.domElement.getBoundingClientRect().height||1,i,a=n;if(a.isOrthographicCamera)i=(a.top-a.bottom)/(a.zoom||1);else{let t=new R;e.cameraControls.getTarget(t);let r=n.position.distanceTo(t),o=a.fov*Math.PI/180;i=2*r*Math.tan(o/2)}return i/r*t}function Dp(e,t){let n=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(n*n+r*r)}function Op(e){return new R(e.x,e.y,e.z)}var kp={hline:`H`,vline:`V`,"tarc-to-point":`T`,"tarc-to-point-tangent":`T`,"tarc-with-tangent":`T`},Ap=new Set([`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`]),jp=22,Mp=5,Np=16,Pp=64,Fp=3,Ip=new Map;function Lp(e,t){let n=`${e}|${t}`,r=Ip.get(n);if(r)return r;let i=document.createElement(`canvas`);i.width=Pp,i.height=Pp;let a=i.getContext(`2d`),o=Pp-8,s=Pp-8;a.beginPath(),a.moveTo(14,4),a.lineTo(4+o-10,4),a.quadraticCurveTo(4+o,4,4+o,14),a.lineTo(4+o,4+s-10),a.quadraticCurveTo(4+o,4+s,4+o-10,4+s),a.lineTo(14,4+s),a.quadraticCurveTo(4,4+s,4,4+s-10),a.lineTo(4,14),a.quadraticCurveTo(4,4,14,4),a.closePath(),a.lineWidth=4,a.strokeStyle=t,a.stroke(),a.fillStyle=t,a.font=`${Pp*.55}px sans-serif`,a.textAlign=`center`,a.textBaseline=`middle`,a.fillText(e,Pp/2,Pp/2);let c=new ra(i);return Ip.set(n,c),c}function Rp(e,t,n){let r=[],i=0;for(let t of e.meshes){let e=t.vertices,n=t.indices;for(let t=0;t<n.length;t+=2){let a=n[t]*3,o=n[t+1]*3,s=new R(e[a],e[a+1],e[a+2]),c=new R(e[o],e[o+1],e[o+2]),l=s.distanceTo(c);r.push({from:s,to:c,length:l}),i+=l}}if(i<1e-10||r.length===0)return null;let a=i*Math.max(0,Math.min(1,t)),o=0;for(let e of r){if(o+e.length>=a||e===r[r.length-1]){let t=e.length>1e-10?(a-o)/e.length:0,r=e.from.clone().lerp(e.to,t),i=Tp(e.from,n),s=Tp(e.to,n),c=s[0]-i[0],l=s[1]-i[1],u=Math.sqrt(c*c+l*l);return{position:r,tangent2d:u>1e-10?[c/u,l/u]:[1,0]}}o+=e.length}return null}function zp(e,t,n,r,i){let a=Lp(e,`#${Wd.constraintColor.getHexString()}`),o=new U(new ma(Mp,Mp),new mr({map:a,transparent:!0,depthTest:!1,side:2}));o.renderOrder=Fp;let s=new oi;s.renderOrder=Fp,s.userData.isConstraintIcon=!0;let c=new R(r.xDirection.x*n[0]+r.yDirection.x*n[1],r.xDirection.y*n[0]+r.yDirection.y*n[1],r.xDirection.z*n[0]+r.yDirection.z*n[1]);return s.position.copy(t),s.up.set(r.yDirection.x,r.yDirection.y,r.yDirection.z),s.lookAt(new R(t.x+i.x,t.y+i.y,t.z+i.z)),s.add(o),o.onBeforeRender=(e,n,r)=>{let i=$f(e,r,t,jp);s.position.set(t.x+c.x*i,t.y+c.y*i,t.z+c.z*i),s.scale.setScalar(ep(e,r,t,Np,Mp)),s.updateMatrixWorld(!0)},s}function Bp(e,t){let n=e.object?.plane?.normal,r=e.object?.plane;if(!n||!r)return[];let i=[];for(let a of t){if(a.parentId!==e.id||!a.sceneShapes.length)continue;let t=kp[a.uniqueType??``];if(!t)continue;let o=Ap.has(a.uniqueType??``);for(let e of a.sceneShapes){if(e.isMetaShape||e.isGuide)continue;let a=Rp(e,o?0:.5,r);if(!a)continue;let s=[-a.tangent2d[1],a.tangent2d[0]];i.push(zp(t,a.position,s,r,n))}}return i}var Vp=`#2297ff`,Hp=`#6a5acd`,Up=2,Wp=16,Gp=6,Kp=3,qp=.6,Jp=`#8899aa`,Yp=1.5,Xp=4.5,Zp=15954511,Qp=64,$p=3,em=9,tm=15954511,nm=.35,rm=.6,im=18,am=5,om=2.5,sm=im+am,cm=54,lm=class extends oi{constructor(e,t,n,r){super(),this.userData.isSketchRoot=!0,this.buildEdges(e,t),this.buildVertices(e,t),this.addConstraintIcons(e,t),n&&e.id===n&&(this.buildCursor(e),this.buildTangentArrow(e))}buildEdges(e,t){for(let n of t){if(n.parentId!==e.id||!n.sceneShapes.length)continue;let t=gp(n.uniqueType)?Vp:Hp;for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=dp(e);t.traverse(e=>{e.renderOrder=1}),e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let n=new jf(e,{color:t,lineWidth:2,depthWrite:!1,transparent:!0});n.traverse(e=>{e.renderOrder=1}),e.shapeId&&(n.userData.shapeId=e.shapeId),this.add(n)}}}buildVertices(e,t){let n=e.object?.plane?.normal,r=[],i=[],a=[];for(let n of t){if(n.parentId!==e.id||!n.sceneShapes.length)continue;let t=gp(n.uniqueType);for(let e of n.sceneShapes){if(e.isGuide)continue;if(e.isMetaShape){for(let t of e.meshes)t.vertices.length===3&&t.indices.length===0&&a.push(new R(t.vertices[0],t.vertices[1],t.vertices[2]));continue}let n=t?r:i;for(let t of e.meshes){if(!t.indices.length)continue;let e=new Map;for(let n of t.indices)e.set(n,(e.get(n)||0)+1);for(let[r,i]of e)i===1&&n.push(new R(t.vertices[r*3],t.vertices[r*3+1],t.vertices[r*3+2]))}}}let o=1e-12,s=this.dedup(r,o),c=this.dedup(i,o),l=this.dedup(a,o);this.addVertexDots(s,n,Up,Gp,Vp,1),this.addVertexDots(c,n,Up,Kp,Hp,qp),this.addVertexDots(l,n,Yp,Xp,Jp,.5)}addConstraintIcons(e,t){for(let n of Bp(e,t))this.add(n)}dedup(e,t){let n=[];for(let r of e)n.some(e=>e.distanceToSquared(r)<t)||n.push(r);return n}addVertexDots(e,t,n,r,i,a){let o=new oa(n,Wp),s=new mr({color:i,side:2,depthTest:!1,transparent:!0,opacity:a});for(let i of e){let e=new U(o,s);e.renderOrder=2;let a=new oi;a.renderOrder=2,a.userData.isVertexDot=!0,a.add(e),a.position.copy(i),t&&a.lookAt(new R(i.x+t.x,i.y+t.y,i.z+t.z)),tp(e,a,i,r,n),this.add(a)}}buildCursor(e){let t=e.object?.currentPosition;if(!t)return;let n=new oa($p,Qp),r=new mr({color:Zp,side:2,depthTest:!1});r.transparent=!0,r.opacity=.8;let i=new U(n,r);i.renderOrder=1;let a=new oi;a.renderOrder=1,a.add(i),a.position.set(t.x,t.y,t.z);let o=e.object?.plane?.normal;if(o){let e=new R(t.x+o.x,t.y+o.y,t.z+o.z);a.lookAt(e)}tp(i,a,a.position,em,$p),this.add(a)}buildTangentArrow(e){let t=e.object?.currentPosition,n=e.object?.currentTangent,r=e.object?.plane?.origin;if(!t||!n||!r)return;let i=new R(n.x-r.x,n.y-r.y,n.z-r.z).normalize(),a=new mr({color:tm,transparent:!0,opacity:nm,side:2,depthTest:!1,depthWrite:!1}),o=new sa(rm,rm,im,16);o.translate(0,im/2,0);let s=new U(o,a),c=new ca(om,am,16);c.translate(0,im+am/2,0);let l=new U(c,a),u=new oi;u.renderOrder=1,u.add(s),u.add(l);let d=new R(0,1,0),f=new gt().setFromUnitVectors(d,i);u.quaternion.copy(f),u.position.set(t.x,t.y,t.z),tp(s,u,u.position,cm,sm),this.add(u)}},um=`#ffc26c`,dm=`#c88f40`,fm=`#c88f40`,pm=.1,mm=20,hm=3,gm=1.5,_m=.4,vm=96,ym=class extends oi{constructor(e,t){super();let n=e.sceneShapes[0]?.meshes[0];if(!n)return;this.userData.isMetaShape=!0,this.userData.isConstructionPlane=!0;let r=e.object.normal,i=e.object.center,a=new H;a.setAttribute(`position`,new V(new Float32Array(n.vertices),3)),a.setAttribute(`normal`,new V(new Float32Array(n.normals),3)),a.setIndex(new V(new Uint16Array(n.indices),1)),a.computeBoundingBox();let o=new U(a,new mr({color:um,transparent:!0,opacity:pm,side:2,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}));this.add(o);let s=new Yi(new pa(a,18),new Li({color:dm,linewidth:1}));this.add(s);let c=new R(r.x,r.y,r.z).normalize(),l=new R(i.x,i.y,i.z),u=new mr({color:fm}),d=mm-hm,f=new sa(_m,_m,d,8);f.translate(0,d/2,0);let p=new U(f,u),m=new ca(gm,hm,8);m.translate(0,d+hm/2,0);let h=new U(m,u),g=new oi;g.add(p),g.add(h);let _=new R(0,1,0),v=new gt().setFromUnitVectors(_,c);g.quaternion.copy(v),g.position.copy(l),tp(p,g,g.position,vm,mm),this.add(g),this.position.z=.01}},bm=`#c88f40`,xm=class extends oi{constructor(e){super();let t=e.sceneShapes[0]?.meshes[0];if(!t)return;let n=new H;n.setAttribute(`position`,new V(new Float32Array(t.vertices),3));let r=new Yi(n,new xa({color:bm,dashSize:5,gapSize:5}));r.computeLineDistances(),this.add(r)}};function Sm(){let e=`#`+Wd.selectEdgeColor.getHexString(),t=`#`+Wd.selectFaceColor.getHexString();return{edge:{color:e,lineWidth:3,depthWrite:!1},face:{color:t,opacity:1}}}function Cm(e,t){if(t)return t;if(e===`select`)return Sm()}function wm(e,t,n,r,i,a){switch(e.type){case`sketch`:return new lm(e,t,n,r);case`plane`:return new ym(e,r);case`axis`:return new xm(e)}let o=e.uniqueType===`select`,s=Cm(e.uniqueType,a),c=t.filter(t=>t.parentId===e.id),l;if(c.length>0){let e=new oi;for(let a of c)e.add(wm(a,t,n,r,i,s));l=e}else l=new mp(e,i,s);return o&&l.traverse(e=>{e.renderOrder=999}),l}function Tm(e,t,n,r=!1){let i=new oi;i.name=`compiledMesh`;for(let a of e)a.parentId||!a.visible&&!(t&&a.type===`sketch`)||i.add(wm(a,e,t,n,r));return i}var Em={"Content-Type":`application/json`};function Dm(e,t){fetch(e,{method:`POST`,headers:t===void 0?void 0:Em,body:t===void 0?void 0:JSON.stringify(t)}).catch(t=>console.error(`POST ${e} failed:`,t))}async function Om(e,t,n){try{let r=await fetch(e,{method:`POST`,headers:Em,body:JSON.stringify(t),signal:n});return r.ok?await r.json():null}catch(t){return t?.name!==`AbortError`&&console.error(`POST ${e} failed:`,t),null}}async function km(e,t,n){try{let r=e;if(t){let e=new URLSearchParams;for(let[n,r]of Object.entries(t))e.set(n,String(r));r+=`?`+e.toString()}let i=await fetch(r,{signal:n});return i.ok?await i.json():null}catch(t){return t?.name!==`AbortError`&&console.error(`GET ${e} failed:`,t),null}}function Am(e,t){Dm(`/api/insert-point`,{point:e,sourceLocation:t})}function jm(e,t){Dm(`/api/set-pick-points`,{points:e,sourceLocation:t})}function Mm(e){Dm(`/api/add-pick`,{sourceLocation:e})}function Nm(e){Dm(`/api/remove-pick`,{sourceLocation:e})}function Pm(e,t,n){Dm(`/api/insert-geometry`,{statement:e,sketchSourceLocation:t,newVariable:n??null})}function Fm(e,t,n){Dm(`/api/set-line-position`,{newStart:e,newEnd:t,sourceLocation:n})}function Im(e,t,n){Dm(`/api/update-position`,{newPosition:e,sourceLocation:t,pointIndex:n})}function Lm(e,t){Dm(`/api/set-chain-positions`,{updates:e,sourceLocation:t})}function Rm(e,t,n,r){Dm(`/api/set-rect-dimensions`,{width:e,height:t,sourceLocation:n,startPoint:r??null})}function zm(e,t,n,r,i){Dm(`/api/update-dimension-expression`,{expression:e,sourceLocation:t,sketchSourceLine:n,newVariable:r??null,dimensionOffset:i??0})}async function Bm(e){return await Om(`/api/dimension-expression`,{sourceLine:e})??{expression:null}}async function Vm(e){return(await Om(`/api/scope-variables`,{sketchSourceLine:e}))?.variables??[]}function Hm(e,t,n){return km(`/api/face-properties`,{shapeId:e,faceIndex:t},n)}function Um(e,t,n){return km(`/api/edge-properties`,{shapeId:e,edgeIndex:t},n)}function Wm(e){return km(`/api/shape-properties`,{shapeId:e})}function Gm(e,t){return Om(`/api/measure`,{entities:e},t)}function Km(){return km(`/api/materials`)}function qm(){Dm(`/api/recompute`)}function Jm(e){Dm(`/api/rollback`,{index:e})}function Ym(e){Dm(`/api/add-breakpoint`,{sourceLocation:e})}function Xm(){Dm(`/api/clear-breakpoints`)}function Zm(e){Dm(`/api/code/goto-source`,e)}async function Qm(e,t){return await Om(`/api/import-file`,{fileName:e,data:t})??{success:!1,error:`Network error`}}async function $m(e){let t=await fetch(`/api/export`,{method:`POST`,headers:Em,body:JSON.stringify(e)});if(!t.ok){let e=await t.json();throw Error(e.error||`Export failed`)}return t.blob()}async function eh(){return km(`/api/preferences`)}function th(e,t){Dm(`/api/preferences`,{[e]:t})}var nh=`<svg
4677
+ `,Xf=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=t.vertices,n=t.indices,r=[];for(let t=0;t<n.length;t+=2){let i=n[t]*3;r.push(e[i],e[i+1],e[i+2])}if(n.length>=2){let t=n[n.length-1]*3;r.push(e[t],e[t+1],e[t+2])}let i=new H;i.setAttribute(`position`,new V(new Float32Array(r),3));let a=new Gi(i,new Yr({uniforms:{color:{value:Wd.metaEdgeColor},dashLength:{value:Wf},gapLength:{value:Gf},dotLength:{value:Kf},patternLength:{value:qf}},vertexShader:Jf,fragmentShader:Yf,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},Zf=`#2297ff`,Qf=2,$f=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=Bf.expandIndexedPositions(t.vertices,t.indices),n=new vf;n.setPositions(e);let r=new yf({color:Zf,linewidth:Qf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});Kd.register(r),this.add(new Rf(n,r))}}},ep=`#2297ff`,tp=`#2297ff`,np=.15,rp=.4,ip=class extends oi{constructor(e,t){super(),this.userData.isMetaShape=!0,this.userData.isPickRegion=!0,this.userData.isPickRegionSelected=t,e.metaData&&(this.userData.metaData=e.metaData);let n=t?tp:ep,r=t?rp:np;for(let t of e.meshes){let e=new H;e.setAttribute(`position`,new V(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new V(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new V(new i(t.indices),1)),e.computeBoundingBox();let a=new U(e,new mr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},ap=`#2297ff`,op=2,sp=2,cp=16,lp=6,up=1e-8,dp=class extends oi{constructor(e){super(),this.userData.isMetaShape=!0;let t=new oa(sp,cp),n=new mr({color:ap,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=Bf.expandIndexedPositions(t.vertices,t.indices),n=new vf;n.setPositions(e);let i=new yf({color:ap,linewidth:op,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});Kd.register(i),this.add(new Rf(n,i));let a=t.vertices,o=t.indices,s=new Map;for(let e of o)s.set(e,(s.get(e)||0)+1);for(let[e,t]of s)if(t===1){let t=new R(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<up)||r.push(t)}}for(let e of r){let r=new U(t,n);r.renderOrder=2;let i=new oi;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),tf(r,i,e,lp,sp),this.add(i)}}},fp={color:`#2297ff`,lineWidth:2},pp={trim:e=>new $f(e),"pick-edge":e=>new dp(e)};function mp(e){let t=e.metaType?pp[e.metaType]:void 0;return t?t(e):new Xf(e)}var hp={"pick-region":e=>new ip(e,!1),"pick-region-selected":e=>new ip(e,!0)};function gp(e){let t=e.metaType?hp[e.metaType]:void 0;return t?t(e):new Hf(e)}var _p=class extends oi{constructor(e,t,n){if(super(),!e.sceneShapes)return;let r=e.sceneShapes.every(e=>e.isMetaShape||e.shapeType===`wire`||e.shapeType===`edge`),i=[`pick-region`,`pick-region-selected`,`pick-edge`];for(let a of e.sceneShapes){if(!t&&a.isMetaShape&&a.metaType&&i.includes(a.metaType))continue;let e;if(a.isMetaShape)switch(a.shapeType){case`wire`:case`edge`:e=mp(a);break;case`face`:e=gp(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new Bf(a,n?.edge??(r?fp:void 0));break;case`face`:e=new Hf(a,n?.face);break;case`solid`:e=new Uf(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}},vp=new Set([`line-two-points`,`hline`,`vline`,`circle`,`arc`,`arc-from-center`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`tline`,`trim2d`,`rect`,`polygon`,`slot`]);function yp(e){return e?e.startsWith(`bezier-`)?!0:vp.has(e):!1}function bp(e,t,n){let r=[],i=n.origin.x,a=n.origin.y,o=n.origin.z,s=n.xDirection.x,c=n.xDirection.y,l=n.xDirection.z,u=n.yDirection.x,d=n.yDirection.y,f=n.yDirection.z,p=e.some(e=>e.parentId===t&&e.sceneShapes.some(e=>e.metaType===`trim`));for(let n of e)if(n.parentId===t&&yp(n.uniqueType))for(let e of n.sceneShapes){if(!e.shapeId)continue;if(p){if(e.metaType!==`trim`)continue}else if(e.isMetaShape||e.isGuide)continue;let t=[],n=[];for(let r of e.meshes){let e=r.vertices,p=r.indices;if(!p.length)continue;let m=new Map;for(let e of p)m.set(e,(m.get(e)||0)+1);for(let[t,r]of m)r===1&&n.push([e[t*3],e[t*3+1],e[t*3+2]]);for(let n=0;n<p.length;n+=2){let r=p[n]*3,m=p[n+1]*3,h=e[r]-i,g=e[r+1]-a,_=e[r+2]-o,v=h*s+g*c+_*l,y=h*u+g*d+_*f,b=e[m]-i,x=e[m+1]-a,S=e[m+2]-o,C=b*s+x*c+S*l,w=b*u+x*d+S*f;t.push({ax:v,ay:y,bx:C,by:w})}}t.length>0&&r.push({shapeId:e.shapeId,segments:t,endpoints:n})}return r}var xp=new Set([`arc`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`slot`]);function Sp(e,t,n){let r=[],i=n.origin.x,a=n.origin.y,o=n.origin.z,s=n.xDirection.x,c=n.xDirection.y,l=n.xDirection.z,u=n.yDirection.x,d=n.yDirection.y,f=n.yDirection.z;for(let n of e){if(n.parentId!==t||!yp(n.uniqueType))continue;let e=null;for(let t of n.sceneShapes)if(!t.isMetaShape&&t.shapeId){e=t.shapeId;break}if(!e)continue;let p=n.uniqueType??``;if(p.startsWith(`bezier-`)){let t=n.object?.startPoint,i=n.object?.resolvedPoints;if(t&&r.push({shapeId:e,point2d:[t[0],t[1]]}),i)for(let t of i)r.push({shapeId:e,point2d:[t[0],t[1]]});continue}if(xp.has(p)){for(let t of n.sceneShapes)if(t.isMetaShape){for(let n of t.meshes)if(n.vertices.length===3&&n.indices.length===0){let t=n.vertices[0]-i,p=n.vertices[1]-a,m=n.vertices[2]-o,h=t*s+p*c+m*l,g=t*u+p*d+m*f;r.push({shapeId:e,point2d:[h,g]})}}}}return r}function Cp(e,t,n,r,i,a){return wp(e,t,n,r,i,a).dist}function wp(e,t,n,r,i,a){let o=i-n,s=a-r,c=o*o+s*s,l,u;if(c===0)l=n,u=r;else{let i=((e-n)*o+(t-r)*s)/c;i<0?i=0:i>1&&(i=1),l=n+i*o,u=r+i*s}let d=l-e,f=u-t;return{x:l,y:u,dist:Math.sqrt(d*d+f*f)}}function Tp(e,t,n,r){let i=e.renderer.domElement.getBoundingClientRect(),a=(n-i.left)/i.width*2-1,o=-((r-i.top)/i.height)*2+1,s=e.createPickingRaycaster(a,o),c=s.ray.origin,l=s.ray.direction,u=jp(t.origin),d=jp(t.normal),f=l.dot(d);if(Math.abs(f)<1e-6)return null;let p=u.clone().sub(c).dot(d)/f;if(p<0)return null;let m=c.clone().add(l.clone().multiplyScalar(p)).clone().sub(u),h=jp(t.xDirection),g=jp(t.yDirection);return[m.dot(h),m.dot(g)]}function Ep(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}function Dp(e,t,n){let r=Ep(n,t).project(e.camera),i=e.renderer.domElement.getBoundingClientRect();return{clientX:(r.x+1)/2*i.width+i.left,clientY:(1-r.y)/2*i.height+i.top}}function Op(e,t){let n=new R(e.x-t.origin.x,e.y-t.origin.y,e.z-t.origin.z),r=jp(t.xDirection),i=jp(t.yDirection);return[n.dot(r),n.dot(i)]}function Y(e){return[Math.round(e[0]*100)/100,Math.round(e[1]*100)/100]}function kp(e,t){let n=e.camera,r=e.renderer.domElement.getBoundingClientRect().height||1,i,a=n;if(a.isOrthographicCamera)i=(a.top-a.bottom)/(a.zoom||1);else{let t=new R;e.cameraControls.getTarget(t);let r=n.position.distanceTo(t),o=a.fov*Math.PI/180;i=2*r*Math.tan(o/2)}return i/r*t}function Ap(e,t){let n=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(n*n+r*r)}function jp(e){return new R(e.x,e.y,e.z)}var Mp={hline:`H`,vline:`V`,"tarc-to-point":`T`,"tarc-to-point-tangent":`T`,"tarc-with-tangent":`T`},Np=new Set([`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`]),Pp=22,Fp=5,Ip=16,Lp=64,Rp=3,zp=new Map;function Bp(e,t){let n=`${e}|${t}`,r=zp.get(n);if(r)return r;let i=document.createElement(`canvas`);i.width=Lp,i.height=Lp;let a=i.getContext(`2d`),o=Lp-8,s=Lp-8;a.beginPath(),a.moveTo(14,4),a.lineTo(4+o-10,4),a.quadraticCurveTo(4+o,4,4+o,14),a.lineTo(4+o,4+s-10),a.quadraticCurveTo(4+o,4+s,4+o-10,4+s),a.lineTo(14,4+s),a.quadraticCurveTo(4,4+s,4,4+s-10),a.lineTo(4,14),a.quadraticCurveTo(4,4,14,4),a.closePath(),a.lineWidth=4,a.strokeStyle=t,a.stroke(),a.fillStyle=t,a.font=`${Lp*.55}px sans-serif`,a.textAlign=`center`,a.textBaseline=`middle`,a.fillText(e,Lp/2,Lp/2);let c=new ra(i);return zp.set(n,c),c}function Vp(e,t,n){let r=[],i=0;for(let t of e.meshes){let e=t.vertices,n=t.indices;for(let t=0;t<n.length;t+=2){let a=n[t]*3,o=n[t+1]*3,s=new R(e[a],e[a+1],e[a+2]),c=new R(e[o],e[o+1],e[o+2]),l=s.distanceTo(c);r.push({from:s,to:c,length:l}),i+=l}}if(i<1e-10||r.length===0)return null;let a=i*Math.max(0,Math.min(1,t)),o=0;for(let e of r){if(o+e.length>=a||e===r[r.length-1]){let t=e.length>1e-10?(a-o)/e.length:0,r=e.from.clone().lerp(e.to,t),i=Op(e.from,n),s=Op(e.to,n),c=s[0]-i[0],l=s[1]-i[1],u=Math.sqrt(c*c+l*l);return{position:r,tangent2d:u>1e-10?[c/u,l/u]:[1,0]}}o+=e.length}return null}function Hp(e,t,n,r,i){let a=Bp(e,`#${Wd.constraintColor.getHexString()}`),o=new U(new ma(Fp,Fp),new mr({map:a,transparent:!0,depthTest:!1,side:2}));o.renderOrder=Rp;let s=new oi;s.renderOrder=Rp,s.userData.isConstraintIcon=!0;let c=new R(r.xDirection.x*n[0]+r.yDirection.x*n[1],r.xDirection.y*n[0]+r.yDirection.y*n[1],r.xDirection.z*n[0]+r.yDirection.z*n[1]);return s.position.copy(t),s.up.set(r.yDirection.x,r.yDirection.y,r.yDirection.z),s.lookAt(new R(t.x+i.x,t.y+i.y,t.z+i.z)),s.add(o),o.onBeforeRender=(e,n,r)=>{let i=Xd(e,r,t,Pp);s.position.set(t.x+c.x*i,t.y+c.y*i,t.z+c.z*i),s.scale.setScalar(Zd(e,r,t,Ip,Fp)),s.updateMatrixWorld(!0)},s}function Up(e,t){let n=e.object?.plane?.normal,r=e.object?.plane;if(!n||!r)return[];let i=[];for(let a of t){if(a.parentId!==e.id||!a.sceneShapes.length)continue;let t=Mp[a.uniqueType??``];if(!t)continue;let o=Np.has(a.uniqueType??``);for(let e of a.sceneShapes){if(e.isMetaShape||e.isGuide)continue;let a=Vp(e,o?0:.5,r);if(!a)continue;let s=[-a.tangent2d[1],a.tangent2d[0]];i.push(Hp(t,a.position,s,r,n))}}return i}var Wp=`#2297ff`,Gp=`#6a5acd`,Kp=2,qp=16,Jp=6,Yp=3,Xp=.6,Zp=`#8899aa`,Qp=1.5,$p=4.5,em=15954511,tm=64,nm=3,rm=9,im=15954511,am=.35,om=.6,sm=18,cm=5,lm=2.5,um=sm+cm,dm=54,fm=class extends oi{constructor(e,t,n,r){super(),this.userData.isSketchRoot=!0,this.buildEdges(e,t),this.buildVertices(e,t),this.addConstraintIcons(e,t),n&&e.id===n&&(this.buildCursor(e),this.buildTangentArrow(e))}buildEdges(e,t){for(let n of t){if(n.parentId!==e.id||!n.sceneShapes.length)continue;let t=yp(n.uniqueType)?Wp:Gp;for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=mp(e);t.traverse(e=>{e.renderOrder=1}),e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let n=new Bf(e,{color:t,lineWidth:2,depthWrite:!1,transparent:!0});n.traverse(e=>{e.renderOrder=1}),e.shapeId&&(n.userData.shapeId=e.shapeId),this.add(n)}}}buildVertices(e,t){let n=e.object?.plane?.normal,r=[],i=[],a=[];for(let n of t){if(n.parentId!==e.id||!n.sceneShapes.length)continue;let t=yp(n.uniqueType);for(let e of n.sceneShapes){if(e.isGuide)continue;if(e.isMetaShape){for(let t of e.meshes)t.vertices.length===3&&t.indices.length===0&&a.push(new R(t.vertices[0],t.vertices[1],t.vertices[2]));continue}let n=t?r:i;for(let t of e.meshes){if(!t.indices.length)continue;let e=new Map;for(let n of t.indices)e.set(n,(e.get(n)||0)+1);for(let[r,i]of e)i===1&&n.push(new R(t.vertices[r*3],t.vertices[r*3+1],t.vertices[r*3+2]))}}}let o=1e-12,s=this.dedup(r,o),c=this.dedup(i,o),l=this.dedup(a,o);this.addVertexDots(s,n,Kp,Jp,Wp,1),this.addVertexDots(c,n,Kp,Yp,Gp,Xp),this.addVertexDots(l,n,Qp,$p,Zp,.5)}addConstraintIcons(e,t){for(let n of Up(e,t))this.add(n)}dedup(e,t){let n=[];for(let r of e)n.some(e=>e.distanceToSquared(r)<t)||n.push(r);return n}addVertexDots(e,t,n,r,i,a){let o=new oa(n,qp),s=new mr({color:i,side:2,depthTest:!1,transparent:!0,opacity:a});for(let i of e){let e=new U(o,s);e.renderOrder=2;let a=new oi;a.renderOrder=2,a.userData.isVertexDot=!0,a.add(e),a.position.copy(i),t&&a.lookAt(new R(i.x+t.x,i.y+t.y,i.z+t.z)),tf(e,a,i,r,n),this.add(a)}}buildCursor(e){let t=e.object?.currentPosition;if(!t)return;let n=new oa(nm,tm),r=new mr({color:em,side:2,depthTest:!1});r.transparent=!0,r.opacity=.8;let i=new U(n,r);i.renderOrder=1;let a=new oi;a.renderOrder=1,a.add(i),a.position.set(t.x,t.y,t.z);let o=e.object?.plane?.normal;if(o){let e=new R(t.x+o.x,t.y+o.y,t.z+o.z);a.lookAt(e)}tf(i,a,a.position,rm,nm),this.add(a)}buildTangentArrow(e){let t=e.object?.currentPosition,n=e.object?.currentTangent,r=e.object?.plane?.origin;if(!t||!n||!r)return;let i=new R(n.x-r.x,n.y-r.y,n.z-r.z).normalize(),a=new mr({color:im,transparent:!0,opacity:am,side:2,depthTest:!1,depthWrite:!1}),o=new sa(om,om,sm,16);o.translate(0,sm/2,0);let s=new U(o,a),c=new ca(lm,cm,16);c.translate(0,sm+cm/2,0);let l=new U(c,a),u=new oi;u.renderOrder=1,u.add(s),u.add(l);let d=new R(0,1,0),f=new gt().setFromUnitVectors(d,i);u.quaternion.copy(f),u.position.set(t.x,t.y,t.z),tf(s,u,u.position,dm,um),this.add(u)}},pm=`#ffc26c`,mm=`#c88f40`,hm=`#c88f40`,gm=.1,_m=20,vm=3,ym=1.5,bm=.4,xm=96,Sm=class extends oi{constructor(e,t){super();let n=e.sceneShapes[0]?.meshes[0];if(!n)return;this.userData.isMetaShape=!0,this.userData.isConstructionPlane=!0;let r=e.object.normal,i=e.object.center,a=new H;a.setAttribute(`position`,new V(new Float32Array(n.vertices),3)),a.setAttribute(`normal`,new V(new Float32Array(n.normals),3)),a.setIndex(new V(new Uint16Array(n.indices),1)),a.computeBoundingBox();let o=new U(a,new mr({color:pm,transparent:!0,opacity:gm,side:2,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}));this.add(o);let s=new Yi(new pa(a,18),new Li({color:mm,linewidth:1}));this.add(s);let c=new R(r.x,r.y,r.z).normalize(),l=new R(i.x,i.y,i.z),u=new mr({color:hm}),d=_m-vm,f=new sa(bm,bm,d,8);f.translate(0,d/2,0);let p=new U(f,u),m=new ca(ym,vm,8);m.translate(0,d+vm/2,0);let h=new U(m,u),g=new oi;g.add(p),g.add(h);let _=new R(0,1,0),v=new gt().setFromUnitVectors(_,c);g.quaternion.copy(v),g.position.copy(l),tf(p,g,g.position,xm,_m),this.add(g),this.position.z=.01}},Cm=`#c88f40`,wm=class extends oi{constructor(e){super();let t=e.sceneShapes[0]?.meshes[0];if(!t)return;let n=new H;n.setAttribute(`position`,new V(new Float32Array(t.vertices),3));let r=new Yi(n,new xa({color:Cm,dashSize:5,gapSize:5}));r.computeLineDistances(),this.add(r)}};function Tm(){let e=`#`+Wd.selectEdgeColor.getHexString(),t=`#`+Wd.selectFaceColor.getHexString();return{edge:{color:e,lineWidth:3,depthWrite:!1},face:{color:t,opacity:1}}}function Em(e,t){if(t)return t;if(e===`select`)return Tm()}function Dm(e,t,n,r,i,a){switch(e.type){case`sketch`:return new fm(e,t,n,r);case`plane`:return new Sm(e,r);case`axis`:return new wm(e)}let o=e.uniqueType===`select`,s=Em(e.uniqueType,a),c=t.filter(t=>t.parentId===e.id),l;if(c.length>0){let e=new oi;for(let a of c)e.add(Dm(a,t,n,r,i,s));l=e}else l=new _p(e,i,s);return o&&l.traverse(e=>{e.renderOrder=999}),l}function Om(e,t,n,r=!1){let i=new oi;i.name=`compiledMesh`;for(let a of e)a.parentId||!a.visible&&!(t&&a.type===`sketch`)||i.add(Dm(a,e,t,n,r));return i}var km={"Content-Type":`application/json`};function Am(e,t){fetch(e,{method:`POST`,headers:t===void 0?void 0:km,body:t===void 0?void 0:JSON.stringify(t)}).catch(t=>console.error(`POST ${e} failed:`,t))}async function jm(e,t,n){try{let r=await fetch(e,{method:`POST`,headers:km,body:JSON.stringify(t),signal:n});return r.ok?await r.json():null}catch(t){return t?.name!==`AbortError`&&console.error(`POST ${e} failed:`,t),null}}async function Mm(e,t,n){try{let r=e;if(t){let e=new URLSearchParams;for(let[n,r]of Object.entries(t))e.set(n,String(r));r+=`?`+e.toString()}let i=await fetch(r,{signal:n});return i.ok?await i.json():null}catch(t){return t?.name!==`AbortError`&&console.error(`GET ${e} failed:`,t),null}}function Nm(e,t){Am(`/api/insert-point`,{point:e,sourceLocation:t})}function Pm(e,t){Am(`/api/set-pick-points`,{points:e,sourceLocation:t})}function Fm(e){Am(`/api/add-pick`,{sourceLocation:e})}function Im(e){Am(`/api/remove-pick`,{sourceLocation:e})}function Lm(e,t,n){Am(`/api/insert-geometry`,{statement:e,sketchSourceLocation:t,newVariable:n??null})}function Rm(e,t,n){Am(`/api/set-line-position`,{newStart:e,newEnd:t,sourceLocation:n})}function zm(e,t,n){Am(`/api/update-position`,{newPosition:e,sourceLocation:t,pointIndex:n})}function Bm(e,t){Am(`/api/set-chain-positions`,{updates:e,sourceLocation:t})}function Vm(e,t,n,r){Am(`/api/set-rect-dimensions`,{width:e,height:t,sourceLocation:n,startPoint:r??null})}function Hm(e,t,n,r,i){Am(`/api/update-dimension-expression`,{expression:e,sourceLocation:t,sketchSourceLine:n,newVariable:r??null,dimensionOffset:i??0})}async function Um(e){return await jm(`/api/dimension-expression`,{sourceLine:e})??{expression:null}}async function Wm(e){return(await jm(`/api/scope-variables`,{sketchSourceLine:e}))?.variables??[]}function Gm(e,t,n){return Mm(`/api/face-properties`,{shapeId:e,faceIndex:t},n)}function Km(e,t,n){return Mm(`/api/edge-properties`,{shapeId:e,edgeIndex:t},n)}function qm(e){return Mm(`/api/shape-properties`,{shapeId:e})}function Jm(e,t){return jm(`/api/measure`,{entities:e},t)}function Ym(){return Mm(`/api/materials`)}function Xm(){Am(`/api/recompute`)}function Zm(e){Am(`/api/rollback`,{index:e})}function Qm(e){Am(`/api/add-breakpoint`,{sourceLocation:e})}function $m(){Am(`/api/clear-breakpoints`)}function eh(e){Am(`/api/code/goto-source`,e)}async function th(e,t){return await jm(`/api/import-file`,{fileName:e,data:t})??{success:!1,error:`Network error`}}async function nh(e){let t=await fetch(`/api/export`,{method:`POST`,headers:km,body:JSON.stringify(e)});if(!t.ok){let e=await t.json();throw Error(e.error||`Export failed`)}return t.blob()}async function rh(){return Mm(`/api/preferences`)}function ih(e,t){Am(`/api/preferences`,{[e]:t})}var ah=`<svg
4678
4678
  xmlns="http://www.w3.org/2000/svg"
4679
4679
  width="24"
4680
4680
  height="24"
@@ -4692,7 +4692,7 @@ void main() {
4692
4692
  <path d="M4 16a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v2a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -2" />
4693
4693
  <path d="M10 7h-7" />
4694
4694
  <path d="M21 7h-7" />
4695
- </svg>`,rh=`<svg
4695
+ </svg>`,oh=`<svg
4696
4696
  xmlns="http://www.w3.org/2000/svg"
4697
4697
  width="24"
4698
4698
  height="24"
@@ -4711,7 +4711,7 @@ void main() {
4711
4711
  <path d="M6 3v18" />
4712
4712
  <path d="M12 3v18" />
4713
4713
  <path d="M18 3v18" />
4714
- </svg>`,ih=`<svg
4714
+ </svg>`,sh=`<svg
4715
4715
  xmlns="http://www.w3.org/2000/svg"
4716
4716
  width="24"
4717
4717
  height="24"
@@ -4729,7 +4729,7 @@ void main() {
4729
4729
  <path d="M12 3l0 17" />
4730
4730
  <path d="M9 12l-3 -6l-3 6a3 3 0 0 0 6 0" />
4731
4731
  <path d="M21 12l-3 -6l-3 6a3 3 0 0 0 6 0" />
4732
- </svg>`,ah=`<svg
4732
+ </svg>`,ch=`<svg
4733
4733
  xmlns="http://www.w3.org/2000/svg"
4734
4734
  width="24"
4735
4735
  height="24"
@@ -4746,7 +4746,7 @@ void main() {
4746
4746
  <path d="M3 17a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
4747
4747
  <path d="M8.6 8.6l10.4 10.4" />
4748
4748
  <path d="M8.6 15.4l10.4 -10.4" />
4749
- </svg>`,oh=`<svg
4749
+ </svg>`,lh=`<svg
4750
4750
  xmlns="http://www.w3.org/2000/svg"
4751
4751
  width="24"
4752
4752
  height="24"
@@ -4761,7 +4761,7 @@ void main() {
4761
4761
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4762
4762
  <path d="M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666" />
4763
4763
  <path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />
4764
- </svg>`,sh=`<svg
4764
+ </svg>`,uh=`<svg
4765
4765
  xmlns="http://www.w3.org/2000/svg"
4766
4766
  width="24"
4767
4767
  height="24"
@@ -4776,7 +4776,7 @@ void main() {
4776
4776
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4777
4777
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
4778
4778
  <path d="M9 12l2 2l4 -4" />
4779
- </svg>`,ch=`<svg
4779
+ </svg>`,dh=`<svg
4780
4780
  xmlns="http://www.w3.org/2000/svg"
4781
4781
  width="24"
4782
4782
  height="24"
@@ -4791,7 +4791,7 @@ void main() {
4791
4791
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4792
4792
  <path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
4793
4793
  <path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
4794
- </svg>`,lh=`<svg
4794
+ </svg>`,fh=`<svg
4795
4795
  xmlns="http://www.w3.org/2000/svg"
4796
4796
  width="24"
4797
4797
  height="24"
@@ -4808,7 +4808,7 @@ void main() {
4808
4808
  <path d="M15 6l3 3" />
4809
4809
  <path d="M9 3a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2" />
4810
4810
  <path d="M19 13a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2" />
4811
- </svg>`,uh=`<svg
4811
+ </svg>`,ph=`<svg
4812
4812
  xmlns="http://www.w3.org/2000/svg"
4813
4813
  width="24"
4814
4814
  height="24"
@@ -4823,7 +4823,7 @@ void main() {
4823
4823
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4824
4824
  <path d="M8 12a4 4 0 1 0 8 0a4 4 0 1 0 -8 0" />
4825
4825
  <path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
4826
- </svg>`,dh=`<svg
4826
+ </svg>`,mh=`<svg
4827
4827
  xmlns="http://www.w3.org/2000/svg"
4828
4828
  width="24"
4829
4829
  height="24"
@@ -4837,7 +4837,7 @@ void main() {
4837
4837
  >
4838
4838
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4839
4839
  <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454l0 .008" />
4840
- </svg>`,fh=`<svg
4840
+ </svg>`,hh=`<svg
4841
4841
  xmlns="http://www.w3.org/2000/svg"
4842
4842
  width="24"
4843
4843
  height="24"
@@ -4852,7 +4852,7 @@ void main() {
4852
4852
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4853
4853
  <path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
4854
4854
  <path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" />
4855
- </svg>`,ph=`<svg
4855
+ </svg>`,gh=`<svg
4856
4856
  xmlns="http://www.w3.org/2000/svg"
4857
4857
  width="24"
4858
4858
  height="24"
@@ -4868,7 +4868,7 @@ void main() {
4868
4868
  <path d="M10.585 10.587a2 2 0 0 0 2.829 2.828" />
4869
4869
  <path d="M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87" />
4870
4870
  <path d="M3 3l18 18" />
4871
- </svg>`,mh=`<svg
4871
+ </svg>`,_h=`<svg
4872
4872
  xmlns="http://www.w3.org/2000/svg"
4873
4873
  width="24"
4874
4874
  height="24"
@@ -4886,7 +4886,7 @@ void main() {
4886
4886
  <path d="M12 14l7 -7" />
4887
4887
  <path d="M12 19l8.5 -8.5" />
4888
4888
  <path d="M12 9l4.5 -4.5" />
4889
- </svg>`,hh=`<svg
4889
+ </svg>`,vh=`<svg
4890
4890
  xmlns="http://www.w3.org/2000/svg"
4891
4891
  width="24"
4892
4892
  height="24"
@@ -4901,7 +4901,7 @@ void main() {
4901
4901
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4902
4902
  <path d="M6 6a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1l0 -12" />
4903
4903
  <path d="M14 6a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1l0 -12" />
4904
- </svg>`,gh=`<svg
4904
+ </svg>`,yh=`<svg
4905
4905
  xmlns="http://www.w3.org/2000/svg"
4906
4906
  width="24"
4907
4907
  height="24"
@@ -4917,7 +4917,7 @@ void main() {
4917
4917
  <path d="M12 9v4" />
4918
4918
  <path d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0" />
4919
4919
  <path d="M12 16h.01" />
4920
- </svg>`,_h=`<svg
4920
+ </svg>`,bh=`<svg
4921
4921
  xmlns="http://www.w3.org/2000/svg"
4922
4922
  width="24"
4923
4923
  height="24"
@@ -4939,7 +4939,7 @@ void main() {
4939
4939
  <path d="M16 7a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
4940
4940
  <path d="M18 4v1" />
4941
4941
  <path d="M18 9v11" />
4942
- </svg>`,vh=`<svg
4942
+ </svg>`,xh=`<svg
4943
4943
  xmlns="http://www.w3.org/2000/svg"
4944
4944
  width="24"
4945
4945
  height="24"
@@ -4954,7 +4954,7 @@ void main() {
4954
4954
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4955
4955
  <path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065" />
4956
4956
  <path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
4957
- </svg>`,yh=`<svg
4957
+ </svg>`,Sh=`<svg
4958
4958
  xmlns="http://www.w3.org/2000/svg"
4959
4959
  width="24"
4960
4960
  height="24"
@@ -4969,7 +4969,7 @@ void main() {
4969
4969
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4970
4970
  <path d="M15 10l4.553 -2.276a1 1 0 0 1 1.447 .894v6.764a1 1 0 0 1 -1.447 .894l-4.553 -2.276v-4" />
4971
4971
  <path d="M3 8a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2l0 -8" />
4972
- </svg>`,bh=`<svg
4972
+ </svg>`,Ch=`<svg
4973
4973
  xmlns="http://www.w3.org/2000/svg"
4974
4974
  width="24"
4975
4975
  height="24"
@@ -4991,18 +4991,18 @@ void main() {
4991
4991
  <path d="M3 3v4" />
4992
4992
  <path d="M3 5h18" />
4993
4993
  <path d="M21 3v4" />
4994
- </svg>`,xh=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
4994
+ </svg>`,wh=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
4995
4995
  <path d="M22 16C22 10.4772 17.5228 6 12 6C6.47715 6 2 10.4772 2 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
4996
4996
  <path d="M2 17C2.55228 17 3 16.5523 3 16C3 15.4477 2.55228 15 2 15C1.44772 15 1 15.4477 1 16C1 16.5523 1.44772 17 2 17Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
4997
4997
  <path d="M22 17C22.5523 17 23 16.5523 23 16C23 15.4477 22.5523 15 22 15C21.4477 15 21 15.4477 21 16C21 16.5523 21.4477 17 22 17Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
4998
4998
  </svg>
4999
- `,Sh=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
4999
+ `,Th=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
5000
5000
  <path d="M21.9999 16C21.9999 10.4772 17.5228 6 11.9999 6C7.89931 6 4.37514 8.46819 2.83203 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 3"/>
5001
5001
  <path d="M2 17C2.55228 17 3 16.5523 3 16C3 15.4477 2.55228 15 2 15C1.44772 15 1 15.4477 1 16C1 16.5523 1.44772 17 2 17Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5002
5002
  <path d="M2 16H12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5003
5003
  <path d="M12 17C12.5523 17 13 16.5523 13 16C13 15.4477 12.5523 15 12 15C11.4477 15 11 15.4477 11 16C11 16.5523 11.4477 17 12 17Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5004
5004
  </svg>
5005
- `,Ch=`<svg
5005
+ `,Eh=`<svg
5006
5006
  xmlns="http://www.w3.org/2000/svg"
5007
5007
  width="24"
5008
5008
  height="24"
@@ -5016,34 +5016,34 @@ void main() {
5016
5016
  >
5017
5017
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
5018
5018
  <path d="M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10" />
5019
- </svg>`,wh=`<svg width="24" height="24" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5019
+ </svg>`,Dh=`<svg width="24" height="24" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5020
5020
  <path d="M3 20L21 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5021
5021
  </svg>
5022
- `,Th=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
5022
+ `,Oh=`<svg width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
5023
5023
  <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5024
5024
  <path d="M12 13C12.5523 13 13 12.5523 13 12C13 11.4477 12.5523 11 12 11C11.4477 11 11 11.4477 11 12C11 12.5523 11.4477 13 12 13Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5025
5025
  <path d="M19 19L17.5 17.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5026
5026
  <path d="M15.5 15.5L14.5 14.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
5027
5027
  </svg>
5028
- `,Eh=nh,Dh=rh,Oh=ih,kh=ah,Ah=oh,jh=sh,Mh=ch,Nh=lh,Ph=uh,Fh=dh,Ih=fh,Lh=ph,Rh=mh,zh=hh,Bh=gh,Vh=_h,Hh=vh,Uh=yh,Wh=bh,Gh=wh,Kh=Th,qh=Sh,Jh=xh,Yh=Ch,Xh=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="5"/></svg>`,Zh=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5h6a5 5 0 0 1 0 10H9a5 5 0 0 1 0-10z"/><circle cx="9" cy="10" r="1.2" fill="currentColor" stroke="none"/><circle cx="15" cy="10" r="1.2" fill="currentColor" stroke="none"/></svg>`,Qh=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><polygon points="12,3 20,7.5 20,16.5 12,21 4,16.5 4,7.5"/></svg>`,$h=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 18 8 10 14 14 20 6"/><circle cx="4" cy="18" r="1.5" fill="currentColor" stroke="none"/><circle cx="8" cy="10" r="1.5" fill="currentColor" stroke="none"/><circle cx="14" cy="14" r="1.5" fill="currentColor" stroke="none"/><circle cx="20" cy="6" r="1.5" fill="currentColor" stroke="none"/></svg>`,eg=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 19 C 8 5, 16 5, 21 19"/><circle cx="3" cy="19" r="1.5" fill="currentColor" stroke="none"/><circle cx="21" cy="19" r="1.5" fill="currentColor" stroke="none"/></svg>`,tg=`<svg width="14" height="14" viewBox="0 0 10 10" fill="currentColor"><path d="M3 1l5 4-5 4z"/></svg>`,ng=`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>`,rg=`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>`,ig=`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>`,ag=`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>`,og=`<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="6"/></svg>`,sg=`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`,cg=`btn btn-ghost btn-circle btn-sm text-base-content/60`,lg=`btn btn-soft btn-primary btn-circle btn-sm`;function ug(){return document.documentElement.getAttribute(`data-theme`)||`fluidcad-dark`}function dg(){return ug()!==`fluidcad-light`}var fg=class{wrapper;fabEl;fitEl;paramsEl;sectionViewEl;onFitView=null;onParamsToggle=null;onSectionViewToggle=null;constructor(e,t){this.onCameraSwitch=t;let n=document.createElement(`style`);n.textContent=`
5028
+ `,kh=ah,Ah=oh,jh=sh,Mh=ch,Nh=lh,Ph=uh,Fh=dh,Ih=fh,Lh=ph,Rh=mh,zh=hh,Bh=gh,Vh=_h,Hh=vh,Uh=yh,Wh=bh,Gh=xh,Kh=Sh,qh=Ch,Jh=Dh,Yh=Oh,Xh=Th,Zh=wh,Qh=Eh,$h=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="5"/></svg>`,eg=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5h6a5 5 0 0 1 0 10H9a5 5 0 0 1 0-10z"/><circle cx="9" cy="10" r="1.2" fill="currentColor" stroke="none"/><circle cx="15" cy="10" r="1.2" fill="currentColor" stroke="none"/></svg>`,tg=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><polygon points="12,3 20,7.5 20,16.5 12,21 4,16.5 4,7.5"/></svg>`,ng=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 18 8 10 14 14 20 6"/><circle cx="4" cy="18" r="1.5" fill="currentColor" stroke="none"/><circle cx="8" cy="10" r="1.5" fill="currentColor" stroke="none"/><circle cx="14" cy="14" r="1.5" fill="currentColor" stroke="none"/><circle cx="20" cy="6" r="1.5" fill="currentColor" stroke="none"/></svg>`,rg=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 19 C 8 5, 16 5, 21 19"/><circle cx="3" cy="19" r="1.5" fill="currentColor" stroke="none"/><circle cx="21" cy="19" r="1.5" fill="currentColor" stroke="none"/></svg>`,ig=`<svg width="14" height="14" viewBox="0 0 10 10" fill="currentColor"><path d="M3 1l5 4-5 4z"/></svg>`,ag=`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>`,og=`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>`,sg=`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>`,cg=`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>`,lg=`<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="6"/></svg>`,ug=`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`,dg=`btn btn-ghost btn-circle btn-sm text-base-content/60`,fg=`btn btn-soft btn-primary btn-circle btn-sm`;function pg(){return document.documentElement.getAttribute(`data-theme`)||`fluidcad-dark`}function mg(){return pg()!==`fluidcad-light`}var hg=class{wrapper;fabEl;fitEl;paramsEl;sectionViewEl;onFitView=null;onParamsToggle=null;onSectionViewToggle=null;constructor(e,t){this.onCameraSwitch=t;let n=document.createElement(`style`);n.textContent=`
5029
5029
  .settings-fab:not(:focus-within) > :nth-child(n+3) {
5030
5030
  display: none !important;
5031
5031
  }
5032
- `,document.head.appendChild(n),this.wrapper=document.createElement(`div`),this.wrapper.className=`absolute right-7 top-[100px] z-[100] flex flex-col items-end select-none`,e.appendChild(this.wrapper);let r=this.wrapper;this.sectionViewEl=document.createElement(`div`),this.sectionViewEl.className=`mb-2`,this.sectionViewEl.style.display=`none`,this.sectionViewEl.innerHTML=`<button class="${lg}" data-action="section-view" title="Toggle section view">${Rh}</button>`,r.appendChild(this.sectionViewEl),this.fabEl=document.createElement(`div`),this.fabEl.className=`fab settings-fab !relative !bottom-auto !end-auto !flex-col`,this.fabEl.innerHTML=this.buildFabHTML(),r.appendChild(this.fabEl),this.fitEl=document.createElement(`button`),this.fitEl.className=`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`,this.fitEl.title=`Fit to view`,this.fitEl.innerHTML=Eh,r.appendChild(this.fitEl),this.paramsEl=document.createElement(`button`),this.paramsEl.className=`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`,this.paramsEl.title=`Toggle parameters`,this.paramsEl.innerHTML=Vh,this.paramsEl.style.display=`none`,r.appendChild(this.paramsEl),this.bindEvents(),$d.subscribe(()=>this.sync())}buildFabHTML(){let e=$d.current,t=dg()?Ph:Fh,n=dg()?`Light theme`:`Dark theme`,r=e.cameraMode===`orthographic`?`Orthographic`:`Perspective`;return`
5033
- <div tabindex="0" role="button" class="btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60" title="Scene settings">${Hh}</div>
5032
+ `,document.head.appendChild(n),this.wrapper=document.createElement(`div`),this.wrapper.className=`absolute right-7 top-[100px] z-[100] flex flex-col items-end select-none`,e.appendChild(this.wrapper);let r=this.wrapper;this.sectionViewEl=document.createElement(`div`),this.sectionViewEl.className=`mb-2`,this.sectionViewEl.style.display=`none`,this.sectionViewEl.innerHTML=`<button class="${fg}" data-action="section-view" title="Toggle section view">${Vh}</button>`,r.appendChild(this.sectionViewEl),this.fabEl=document.createElement(`div`),this.fabEl.className=`fab settings-fab !relative !bottom-auto !end-auto !flex-col`,this.fabEl.innerHTML=this.buildFabHTML(),r.appendChild(this.fabEl),this.fitEl=document.createElement(`button`),this.fitEl.className=`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`,this.fitEl.title=`Fit to view`,this.fitEl.innerHTML=kh,r.appendChild(this.fitEl),this.paramsEl=document.createElement(`button`),this.paramsEl.className=`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`,this.paramsEl.title=`Toggle parameters`,this.paramsEl.innerHTML=Wh,this.paramsEl.style.display=`none`,r.appendChild(this.paramsEl),this.bindEvents(),lf.subscribe(()=>this.sync())}buildFabHTML(){let e=lf.current,t=mg()?Lh:Rh,n=mg()?`Light theme`:`Dark theme`,r=e.cameraMode===`orthographic`?`Orthographic`:`Perspective`;return`
5033
+ <div tabindex="0" role="button" class="btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60" title="Scene settings">${Gh}</div>
5034
5034
  <div class="fab-close !top-0 !bottom-auto">
5035
- <span class="btn btn-circle btn-sm panel-bg border border-base-content/10">${sg}</span>
5035
+ <span class="btn btn-circle btn-sm panel-bg border border-base-content/10">${ug}</span>
5036
5036
  </div>
5037
- <div>Grid <button class="${e.showGrid?lg:cg}" data-action="grid" title="Toggle grid">${Dh}</button></div>
5037
+ <div>Grid <button class="${e.showGrid?fg:dg}" data-action="grid" title="Toggle grid">${Ah}</button></div>
5038
5038
  <div>
5039
5039
  <span data-camera-label>${r}</span>
5040
- <button class="${cg}" data-action="camera" title="Toggle projection">${Uh}</button>
5040
+ <button class="${dg}" data-action="camera" title="Toggle projection">${Kh}</button>
5041
5041
  </div>
5042
5042
  <div>
5043
5043
  <span data-theme-label>${n}</span>
5044
- <button class="${cg}" data-action="theme" title="${dg()?`Switch to light theme`:`Switch to dark theme`}">${t}</button>
5044
+ <button class="${dg}" data-action="theme" title="${mg()?`Switch to light theme`:`Switch to dark theme`}">${t}</button>
5045
5045
  </div>
5046
- `}bindEvents(){this.fitEl.addEventListener(`click`,()=>{this.onFitView?.()}),this.paramsEl.addEventListener(`click`,()=>{this.onParamsToggle?.()}),this.fabEl.querySelector(`[data-action="camera"]`)?.addEventListener(`click`,()=>{let e=$d.current.cameraMode===`perspective`?`orthographic`:`perspective`;$d.update({cameraMode:e}),th(`cameraMode`,e),this.onCameraSwitch(e)}),this.fabEl.querySelector(`[data-action="grid"]`)?.addEventListener(`click`,()=>{let e=!$d.current.showGrid;$d.update({showGrid:e}),th(`showGrid`,e)}),this.sectionViewEl.querySelector(`[data-action="section-view"]`)?.addEventListener(`click`,()=>{let e=!$d.current.sectionView;$d.update({sectionView:e}),this.onSectionViewToggle?.(e)}),this.fabEl.querySelector(`[data-action="theme"]`)?.addEventListener(`click`,()=>{let e=dg()?`fluidcad-light`:`fluidcad-dark`;document.documentElement.setAttribute(`data-theme`,e),this.syncThemeButton(),th(`theme`,e)})}get panelHost(){return this.wrapper}setFitHandler(e){this.onFitView=e}setFitButtonVisible(e){this.fitEl.style.display=e?``:`none`}setParamsToggleHandler(e){this.onParamsToggle=e}setParamsButtonVisible(e){this.paramsEl.style.display=e?``:`none`}setParamsButtonActive(e){this.paramsEl.className=e?lg+` mt-2`:`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`}setSectionViewToggleHandler(e){this.onSectionViewToggle=e}setSectionViewVisible(e){this.sectionViewEl.style.display=e?``:`none`}setSectionViewActive(e){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e?lg:cg)}setProjectionLocked(e){let t=this.fabEl.querySelector(`[data-action="camera"]`);t&&(t.disabled=e)}syncThemeButton(){let e=this.fabEl.querySelector(`[data-action="theme"]`);e&&(e.innerHTML=dg()?Ph:Fh,e.title=dg()?`Switch to light theme`:`Switch to dark theme`);let t=this.fabEl.querySelector(`[data-theme-label]`);t&&(t.textContent=dg()?`Light theme`:`Dark theme`)}sync(){let e=$d.current,t=this.fabEl.querySelector(`[data-action="grid"]`);t&&(t.className=e.showGrid?lg:cg);let n=this.fabEl.querySelector(`[data-camera-label]`);if(n&&(n.textContent=e.cameraMode===`orthographic`?`Orthographic`:`Perspective`),this.sectionViewEl.style.display!==`none`){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e.sectionView?lg:cg)}}},pg=class{mesh=null;show(e,t,n){this.clear(e);let r=new U(new ha(n,16,16),new mr({color:16729088,depthTest:!1}));r.position.set(t.x,t.y,t.z),r.renderOrder=999,r.userData.isMetaShape=!0,e.add(r),this.mesh=r}clear(e){this.mesh&&=(this.mesh.geometry.dispose(),this.mesh.material.dispose(),e.remove(this.mesh),null)}};function mg(e,t){if(t.userData.isMetaShape)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)mg(e,n)}var hg=2,gg=2,_g=.75,vg=class{ctx;modeManager;settingsPanel;sceneObjects=[];highlightedShapeId=null;faceHighlightMeshes=[];hasRendered=!1;lastFitBox=null;isTrimming=!1;isRegionPicking=!1;isDrawing=!1;selectionHandler=null;centroidIndicator=new pg;hoverState=null;hoverFaceOverlayMeshes=[];hoverRafId=null;isMouseDown=!1;highlightedEntities=[];activeSketchId=null;hiddenShapeIds=new Set;shapeOpacities=new Map;constructor(e){let t=document.getElementById(e);this.ctx=new Xd(t),this.modeManager=new of(this.ctx),this.settingsPanel=new fg(t,e=>this.ctx.switchCamera(e)),this.settingsPanel.setFitHandler(()=>this.fitViewToScene()),$d.current.cameraMode===`perspective`&&this.ctx.switchCamera(`perspective`),this.settingsPanel.setSectionViewToggleHandler(e=>{e?this.applySectionView():this.clearSectionView()}),this.initClickDetection(),this.initHoverDetection()}get sceneContext(){return this.ctx}get currentSceneObjects(){return this.sceneObjects}setSelectionHandler(e){this.selectionHandler=e}get settingsPanelHost(){return this.settingsPanel.panelHost}setParamsToggleHandler(e){this.settingsPanel.setParamsToggleHandler(e)}setParamsButtonVisible(e){this.settingsPanel.setParamsButtonVisible(e)}setParamsButtonActive(e){this.settingsPanel.setParamsButtonActive(e)}lookAlongSketchNormal(e){this.modeManager.enforceSketchNormal(e)}initClickDetection(){let e=this.ctx.renderer.domElement,t=0,n=0;e.addEventListener(`mousedown`,e=>{t=e.clientX,n=e.clientY}),e.addEventListener(`mouseup`,e=>{if(!this.selectionHandler||this.isTrimming||this.isRegionPicking||this.modeManager.isSketchMode)return;let r=e.clientX-t,i=e.clientY-n;if(r*r+i*i>64)return;this.clearHover();let a={additive:e.ctrlKey||e.metaKey||e.shiftKey},o=this.pickAt(e.clientX,e.clientY);o?this.selectionHandler(o.shapeId,o.sub,a):this.selectionHandler(null,null,a)})}pickAt(e,t){let n=this.ctx.camera,r=this.ctx.renderer.domElement.getBoundingClientRect(),i=(e-r.left)/r.width*2-1,a=-((t-r.top)/r.height)*2+1,o=this.ctx.createPickingRaycaster(i,a);o.params.Line={threshold:this.computeEdgePickThreshold()},o.params.Line2={threshold:8};let s=[],c=[];this.ctx.scene.traverse(e=>{e.userData.isMetaShape||(e.isMesh&&e.userData.faceMapping?s.push(e):(e.isLine||e.userData.isEdgeLine)&&e.userData.edgeIndex!==void 0&&c.push(e))});let l=s.length>0?o.intersectObjects(s,!1):[],u=c.length>0?o.intersectObjects(c,!1):[];if(l.length===0&&u.length===0)return null;let d=new R;n.getWorldDirection(d);let f;for(let e of l){if(!e.face){f=e;break}if(e.face.normal.clone().transformDirection(e.object.matrixWorld).dot(d)<0){f=e;break}}let p=f==null?1/0:f.distance,m=o.ray.origin,h=o.ray.direction,g=new R,_=new R;for(let e of u){let t=e.pointOnLine;if(t?g.copy(t):g.copy(e.point),h.dot(_.copy(g).sub(m))<=p+.001){let t=e.object.userData.edgeIndex,n=this.findShapeIdForObject(e.object);if(n)return{shapeId:n,sub:{type:`edge`,index:t}}}}if(f){let e=f.object.userData.faceMapping;if(!e||f.faceIndex==null)return null;let t=e[f.faceIndex];if(t==null)return null;let n=this.findShapeIdForObject(f.object);if(n)return{shapeId:n,sub:{type:`face`,index:t}}}return null}findShapeIdForObject(e){let t=e;for(;t;){if(t.userData.shapeId&&!t.userData.isMetaShape)return t.userData.shapeId;t=t.parent}return null}toggleSketchMode(e){this.modeManager.sketchEnabled=e}setFileName(e){}updateView(e,t=!1,n){if(this.sceneObjects=e,this.highlightedShapeId=null,this.highlightedEntities=[],this.faceHighlightMeshes=[],this.hoverState=null,this.hoverFaceOverlayMeshes=[],this.ctx.renderer.domElement.style.cursor=``,this.removeCompiledMesh(),t)this.activeSketchId=this.findRollbackActiveSketchId(e,n);else{let t=this.findActiveObject(e);t?.type===`sketch`&&t.object?.plane?(this.modeManager.isSketchMode?this.modeManager.enforceSketchNormal(t.object.plane):this.modeManager.enterSketchMode(t.object.plane),this.activeSketchId=t.id,this.settingsPanel.setProjectionLocked(!0),this.settingsPanel.setFitButtonVisible(!1)):(this.activeSketchId=null,this.modeManager.enterDefaultMode(),this.settingsPanel.setProjectionLocked(!1),this.settingsPanel.setFitButtonVisible(!0),this.lastFitBox=null)}let r=Tm(e,this.activeSketchId,this.ctx.camera,this.isRegionPicking);if(this.ctx.scene.add(r),this.applyShapeOverridesAndPrune(e),this.activeSketchId&&this.applySketchModeGhosting(),this.settingsPanel.setSectionViewVisible(this.modeManager.isSketchMode),this.modeManager.isSketchMode&&(this.settingsPanel.setSectionViewActive($d.current.sectionView),$d.current.sectionView&&this.applySectionView()),!this.hasRendered&&!this.modeManager.isSketchMode||this.modeManager.isSketchMode&&!t&&!this.isTrimming&&!this.isRegionPicking&&!this.isDrawing){let e=new Gt;mg(e,r),!e.isEmpty()&&!this.isBoxContained(e)&&(this.ctx.fitToBox(e,!0),this.lastFitBox=e.clone(),this.hasRendered=!0)}!this.hasRendered&&this.modeManager.isSketchMode&&(this.hasRendered=!0),this.ctx.requestRender()}highlightShape(e){this.clearHighlight();let t=this.findShapeById(e);if(!t)return;let n=this.findMeshByShapeId(e);if(!n)return;let r=t.shapeType===`solid`||t.shapeType===`face`;n.traverse(e=>{if(!e.material)return;let t=e.isLine||e.userData.isEdgeLine;if(r&&e instanceof U&&!t){let t=e.material;e.userData.originalColor=t.color.getHex(),t.color.set(Wd.highlightColor),(t.opacity<1||t.transparent)&&(e.userData.originalOpacity=t.opacity,e.userData.originalTransparent=t.transparent,t.opacity=1,t.transparent=!1)}else !r&&t&&(e.userData.originalColor=e.material.color.getHex(),e.material.color.set(Wd.highlightColor),e.userData.originalLineWidth=e.material.linewidth,e.material.linewidth=hg,e.material.opacity<1&&(e.userData.originalOpacity=e.material.opacity,e.material.opacity=1))}),this.highlightedShapeId=e,this.highlightedEntities=[],this.ctx.render()}clearHighlight(){if(!(!this.highlightedShapeId&&this.highlightedEntities.length===0&&this.faceHighlightMeshes.length===0)){this.ctx.scene.traverse(e=>{e.userData.originalColor!==void 0&&(e.material.color.setHex(e.userData.originalColor),delete e.userData.originalColor),e.userData.originalOpacity!==void 0&&(e.material.opacity=e.userData.originalOpacity,delete e.userData.originalOpacity),e.userData.originalTransparent!==void 0&&(e.material.transparent=e.userData.originalTransparent,delete e.userData.originalTransparent),e.userData.originalLineWidth!==void 0&&(e.material.linewidth=e.userData.originalLineWidth,delete e.userData.originalLineWidth)});for(let e of this.faceHighlightMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.faceHighlightMeshes=[],this.highlightedShapeId=null,this.highlightedEntities=[],this.ctx.render()}}highlightEntities(e){this.clearHighlight();for(let t of e)t.sub.type===`face`?this.applyFaceHighlight(t.shapeId,t.sub.index):this.applyEdgeHighlight(t.shapeId,t.sub.index);this.highlightedEntities=e,this.ctx.render()}highlightFace(e,t){this.highlightEntities([{shapeId:e,sub:{type:`face`,index:t}}])}highlightEdge(e,t){this.highlightEntities([{shapeId:e,sub:{type:`edge`,index:t}}])}applyFaceHighlight(e,t){this.ctx.scene.traverse(n=>{if(!n.isMesh)return;let r=n.userData.faceMapping;if(!r)return;let i=!1,a=n;for(;a;){if(a.userData.shapeId===e&&!a.userData.isMetaShape){i=!0;break}a=a.parent}if(!i)return;let o=n,s=o.geometry,c=s.index;if(!c)return;let l=c.array,u=s.getAttribute(`position`).array,d=[];for(let e=0;e<r.length;e++)if(r[e]===t){let t=l[e*3]*3,n=l[e*3+1]*3,r=l[e*3+2]*3;d.push(u[t],u[t+1],u[t+2]),d.push(u[n],u[n+1],u[n+2]),d.push(u[r],u[r+1],u[r+2])}if(d.length===0)return;let f=new H;f.setAttribute(`position`,new V(new Float32Array(d),3));let p=new U(f,new va({color:Wd.highlightColor,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.faceHighlightMeshes.push(p)})}applyEdgeHighlight(e,t){this.ctx.scene.traverse(n=>{if(!n.isLine&&!n.userData.isEdgeLine||n.userData.edgeIndex!==t)return;let r=!1,i=n;for(;i;){if(i.userData.shapeId===e&&!i.userData.isMetaShape){r=!0;break}i=i.parent}r&&n.userData.originalColor===void 0&&(n.userData.originalColor=n.material.color.getHex(),n.material.color.set(Wd.highlightColor),n.userData.originalLineWidth=n.material.linewidth,n.material.linewidth=hg)})}initHoverDetection(){let e=this.ctx.renderer.domElement;e.addEventListener(`mousedown`,()=>{this.isMouseDown=!0,this.clearHover()}),e.addEventListener(`mouseup`,()=>{this.isMouseDown=!1}),e.addEventListener(`mousemove`,e=>{this.isMouseDown||this.isTrimming||this.isRegionPicking||this.modeManager.isSketchMode||this.hoverRafId===null&&(this.hoverRafId=requestAnimationFrame(()=>{this.hoverRafId=null,this.updateHover(e.clientX,e.clientY)}))}),e.addEventListener(`mouseleave`,()=>{this.clearHover()})}updateHover(e,t){if(!this.selectionHandler)return;let n=this.pickAt(e,t);if(!(this.hoverState&&n&&this.hoverState.shapeId===n.shapeId&&this.hoverState.sub?.type===n.sub?.type&&this.hoverState.sub?.index===n.sub?.index)){if(!n){this.hoverState&&this.clearHover();return}if(this.highlightedEntities.some(e=>e.shapeId===n.shapeId&&e.sub.type===n.sub?.type&&e.sub.index===n.sub?.index)){this.hoverState&&this.clearHover();return}this.clearHover(),this.hoverState=n,this.ctx.renderer.domElement.style.cursor=`pointer`,n.sub?.type===`face`?this.applyHoverFace(n.shapeId,n.sub.index):n.sub?.type===`edge`&&this.applyHoverEdge(n.shapeId,n.sub.index)}}clearHover(){for(let e of this.hoverFaceOverlayMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.hoverFaceOverlayMeshes=[],this.ctx.scene.traverse(e=>{e.userData.hoverOriginalColor!==void 0&&(e.material.color.setHex(e.userData.hoverOriginalColor),delete e.userData.hoverOriginalColor),e.userData.hoverOriginalLineWidth!==void 0&&(e.material.linewidth=e.userData.hoverOriginalLineWidth,delete e.userData.hoverOriginalLineWidth)}),this.hoverState=null,this.ctx.renderer.domElement.style.cursor=``,this.ctx.requestRender()}applyHoverFace(e,t){this.ctx.scene.traverse(n=>{if(!n.isMesh)return;let r=n.userData.faceMapping;if(!r)return;let i=!1,a=n;for(;a;){if(a.userData.shapeId===e&&!a.userData.isMetaShape){i=!0;break}a=a.parent}if(!i)return;let o=n,s=o.geometry,c=s.index;if(!c)return;let l=c.array,u=s.getAttribute(`position`).array,d=[];for(let e=0;e<r.length;e++)if(r[e]===t){let t=l[e*3]*3,n=l[e*3+1]*3,r=l[e*3+2]*3;d.push(u[t],u[t+1],u[t+2]),d.push(u[n],u[n+1],u[n+2]),d.push(u[r],u[r+1],u[r+2])}if(d.length===0)return;let f=new H;f.setAttribute(`position`,new V(new Float32Array(d),3));let p=new U(f,new va({color:Wd.highlightColor,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.hoverFaceOverlayMeshes.push(p)}),this.ctx.requestRender()}applyHoverEdge(e,t){this.ctx.scene.traverse(n=>{if(!n.isLine&&!n.userData.isEdgeLine||n.userData.edgeIndex!==t)return;let r=!1,i=n;for(;i;){if(i.userData.shapeId===e&&!i.userData.isMetaShape){r=!0;break}i=i.parent}r&&(n.userData.hoverOriginalColor=n.material.color.getHex(),n.material.color.set(Wd.highlightColor),n.userData.hoverOriginalLineWidth=n.material.linewidth,n.material.linewidth=gg)}),this.ctx.requestRender()}showCentroid(e){let t=this.computeCentroidRadius();this.centroidIndicator.show(this.ctx.scene,e,t),this.ctx.requestRender()}clearCentroid(){this.centroidIndicator.clear(this.ctx.scene),this.ctx.requestRender()}dispose(){this.ctx.dispose()}computeEdgePickThreshold(){let e=this.ctx.camera,t=this.ctx.renderer.domElement.getBoundingClientRect().height||1,n,r=e;if(r.isOrthographicCamera)n=(r.top-r.bottom)/(r.zoom||1);else{let t=new R;this.ctx.cameraControls.getTarget(t);let i=e.position.distanceTo(t),a=r.fov*Math.PI/180;n=2*i*Math.tan(a/2)}return n/t*8}computeCentroidRadius(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(e){let t=new Gt;if(mg(t,e),!t.isEmpty())return t.getSize(new R).length()*.015}return 2}fitViewToScene(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=new Gt;mg(t,e),t.isEmpty()||this.ctx.fitToBox(t,!0)}findShapeById(e){for(let t of this.sceneObjects)for(let n of t.sceneShapes)if(n.shapeId===e)return n}findMeshByShapeId(e){let t;return this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&(t=n)}),t}findActiveObject(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n.parentId||e.find(e=>e.id===n.parentId)?.type===`part`)return n}}findRollbackActiveSketchId(e,t){if(t==null||t<0||t>=e.length)return null;let n=e[t];for(;n;){if(n.type===`sketch`)return n.id;if(!n.parentId)return null;n=e.find(e=>e.id===n.parentId)}return null}isBoxContained(e){if(!this.lastFitBox)return!1;let t=this.lastFitBox.getCenter(new R),n=this.lastFitBox.getSize(new R).length()/2*Yd;if(n===0)return!1;let r=e.getCenter(new R),i=e.getSize(new R).length()/2;return t.distanceTo(r)+i<=n}rebuildSceneMesh(){if(!this.sceneObjects)return;this.removeCompiledMesh();let e=Tm(this.sceneObjects,this.activeSketchId,this.ctx.camera,this.isRegionPicking);this.ctx.scene.add(e),this.applyShapeOverridesAndPrune(this.sceneObjects),this.modeManager.isSketchMode&&$d.current.sectionView&&this.applySectionView(),this.ctx.requestRender()}setShapeVisibility(e,t){t?this.hiddenShapeIds.delete(e):this.hiddenShapeIds.add(e),this.applyVisibilityForId(e,t),this.ctx.requestRender()}isShapeHidden(e){return this.hiddenShapeIds.has(e)}applyVisibilityForId(e,t){this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&(n.visible=t)})}setShapeTransparency(e,t){t>=1?this.shapeOpacities.delete(e):this.shapeOpacities.set(e,t),this.applyOpacityForId(e,t),this.ctx.requestRender()}getShapeTransparency(e){return this.shapeOpacities.get(e)??1}resetAllTransparency(){if(this.shapeOpacities.size===0)return;let e=Array.from(this.shapeOpacities.keys());this.shapeOpacities.clear();for(let t of e)this.applyOpacityForId(t,1);this.ctx.requestRender()}applyOpacityForId(e,t){let n=[];this.ctx.scene.traverse(t=>{t.userData.shapeId===e&&n.push(t)});for(let e of n)this.applyOpacityToSubtree(e,t)}applyOpacityToSubtree(e,t){e.traverse(e=>{let n=e.material;if(!n)return;let r=Array.isArray(n)?n:[n];for(let e of r)e.transparent=t<1,e.opacity=t,e.depthWrite=t>=1,e.needsUpdate=!0})}applyShapeOverridesAndPrune(e){let t=new Set;for(let n of e)if(n.sceneShapes)for(let e of n.sceneShapes)e.isMetaShape||e.shapeId&&t.add(e.shapeId);for(let e of this.hiddenShapeIds)t.has(e)||this.hiddenShapeIds.delete(e);for(let e of this.shapeOpacities.keys())t.has(e)||this.shapeOpacities.delete(e);this.ctx.scene.traverse(e=>{let t=e.userData.shapeId;if(typeof t!=`string`)return;this.hiddenShapeIds.has(t)&&(e.visible=!1);let n=this.shapeOpacities.get(t);n!==void 0&&this.applyOpacityToSubtree(e,n)})}applySketchModeGhosting(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=Wd.backgroundColor;for(let n of e.children)this.tintForGhosting(n,t)}tintForGhosting(e,t){if(e.userData.isSketchRoot||e.renderOrder>=999)return;let n=e.material;if(n){let e=Array.isArray(n)?n:[n];for(let n of e)!n.color||!(n.color instanceof B)||(n.userData.ghostOriginalColor||(n.userData.ghostOriginalColor=n.color.clone()),n.color.copy(n.userData.ghostOriginalColor).lerp(t,_g))}for(let n of e.children)this.tintForGhosting(n,t)}applySectionView(){let e=this.modeManager.sectionPlane;if(!e)return;let t=this.ctx.scene.getObjectByName(`compiledMesh`);t&&(this.forEachClippableMaterial(t,t=>{t.clippingPlanes=[e]}),this.ctx.requestRender())}clearSectionView(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(this.forEachClippableMaterial(e,e=>{e.clippingPlanes=[]}),this.ctx.requestRender())}forEachClippableMaterial(e,t){if(e.userData.isSketchRoot)return;let n=e.material;if(n){let e=Array.isArray(n)?n:[n];for(let n of e)t(n)}for(let n of e.children)this.forEachClippableMaterial(n,t)}removeCompiledMesh(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(e.traverse(e=>{e.geometry?.dispose(),Array.isArray(e.material)?e.material.forEach(e=>e.dispose()):e.material?.dispose()}),this.ctx.scene.remove(e))}};function yg(e){switch(e){case`inch`:return 16.387064;case`foot`:return 28316.846592;case`yard`:return 764554.857984;case`meter`:return 1e6;default:return .001}}function bg(e){switch(e){case`inch`:return`in`;case`foot`:return`ft`;case`yard`:return`yd`;case`meter`:return`m`;default:return`mm`}}function xg(e,t,n){let r=t===`kg`?1e3:t===`lbs`?453.592:1;return e*yg(n)/r}function Sg(e,t){switch(t){case`kg/m³`:return e*.001;case`g/mm³`:return e*1e3;case`lbs/in³`:return e*27.6799;default:return e}}function Cg(e,t){switch(t){case`kg/m³`:return e/.001;case`g/mm³`:return e/1e3;case`lbs/in³`:return e/27.6799;default:return e}}function wg(e){return e===0?`0`:parseFloat(e.toPrecision(6)).toString()}var Tg=class{btn;panel;placeholderEl;formEl;selectEl;densityEl;densityUnitSelectEl;lengthUnitEl;massUnitEl;calcBtn;resultsEl;errorEl;volVal;areaVal;massVal;centroidVal;selectedShapeId=null;rawProps=null;canonicalDensityGcm3=null;currentDensityUnit=`g/cm³`;centroidHandler=null;openHandler=null;constructor(e){this.btn=document.createElement(`button`),this.btn.className=`btn btn-ghost btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10 text-base-content/60`,this.btn.title=`Shape Properties`,this.btn.innerHTML=Oh,e.appendChild(this.btn),this.panel=document.createElement(`div`),this.panel.className=`absolute bottom-[68px] right-6 w-[300px] bg-base-100/95 backdrop-blur-xl border border-base-content/10 rounded-lg p-4 z-[200] shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-base-content text-[13px] hidden`,this.panel.innerHTML=this.buildHTML(),e.appendChild(this.panel),this.bindRefs(),this.bindEvents(),this.loadMaterials()}buildHTML(){return`
5046
+ `}bindEvents(){this.fitEl.addEventListener(`click`,()=>{this.onFitView?.()}),this.paramsEl.addEventListener(`click`,()=>{this.onParamsToggle?.()}),this.fabEl.querySelector(`[data-action="camera"]`)?.addEventListener(`click`,()=>{let e=lf.current.cameraMode===`perspective`?`orthographic`:`perspective`;lf.update({cameraMode:e}),ih(`cameraMode`,e),this.onCameraSwitch(e)}),this.fabEl.querySelector(`[data-action="grid"]`)?.addEventListener(`click`,()=>{let e=!lf.current.showGrid;lf.update({showGrid:e}),ih(`showGrid`,e)}),this.sectionViewEl.querySelector(`[data-action="section-view"]`)?.addEventListener(`click`,()=>{let e=!lf.current.sectionView;lf.update({sectionView:e}),this.onSectionViewToggle?.(e)}),this.fabEl.querySelector(`[data-action="theme"]`)?.addEventListener(`click`,()=>{let e=mg()?`fluidcad-light`:`fluidcad-dark`;document.documentElement.setAttribute(`data-theme`,e),this.syncThemeButton(),ih(`theme`,e)})}get panelHost(){return this.wrapper}setFitHandler(e){this.onFitView=e}setFitButtonVisible(e){this.fitEl.style.display=e?``:`none`}setParamsToggleHandler(e){this.onParamsToggle=e}setParamsButtonVisible(e){this.paramsEl.style.display=e?``:`none`}setParamsButtonActive(e){this.paramsEl.className=e?fg+` mt-2`:`btn btn-circle btn-sm panel-bg border border-base-content/10 text-base-content/60 mt-2`}setSectionViewToggleHandler(e){this.onSectionViewToggle=e}setSectionViewVisible(e){this.sectionViewEl.style.display=e?``:`none`}setSectionViewActive(e){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e?fg:dg)}setProjectionLocked(e){let t=this.fabEl.querySelector(`[data-action="camera"]`);t&&(t.disabled=e)}syncThemeButton(){let e=this.fabEl.querySelector(`[data-action="theme"]`);e&&(e.innerHTML=mg()?Lh:Rh,e.title=mg()?`Switch to light theme`:`Switch to dark theme`);let t=this.fabEl.querySelector(`[data-theme-label]`);t&&(t.textContent=mg()?`Light theme`:`Dark theme`)}sync(){let e=lf.current,t=this.fabEl.querySelector(`[data-action="grid"]`);t&&(t.className=e.showGrid?fg:dg);let n=this.fabEl.querySelector(`[data-camera-label]`);if(n&&(n.textContent=e.cameraMode===`orthographic`?`Orthographic`:`Perspective`),this.sectionViewEl.style.display!==`none`){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e.sectionView?fg:dg)}}},gg=class{mesh=null;show(e,t,n){this.clear(e);let r=new U(new ha(n,16,16),new mr({color:16729088,depthTest:!1}));r.position.set(t.x,t.y,t.z),r.renderOrder=999,r.userData.isMetaShape=!0,e.add(r),this.mesh=r}clear(e){this.mesh&&=(this.mesh.geometry.dispose(),this.mesh.material.dispose(),e.remove(this.mesh),null)}};function _g(e,t){if(t.userData.isMetaShape)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)_g(e,n)}var vg=2,yg=2,bg=.75,xg=class{ctx;modeManager;settingsPanel;sceneObjects=[];highlightedShapeId=null;faceHighlightMeshes=[];hasRendered=!1;lastFitBox=null;isTrimming=!1;isRegionPicking=!1;isDrawing=!1;selectionHandler=null;centroidIndicator=new gg;hoverState=null;hoverFaceOverlayMeshes=[];hoverRafId=null;isMouseDown=!1;highlightedEntities=[];activeSketchId=null;hiddenShapeIds=new Set;shapeOpacities=new Map;constructor(e){let t=document.getElementById(e);this.ctx=new of(t),this.modeManager=new hf(this.ctx),this.settingsPanel=new hg(t,e=>this.ctx.switchCamera(e)),this.settingsPanel.setFitHandler(()=>this.fitViewToScene()),lf.current.cameraMode===`perspective`&&this.ctx.switchCamera(`perspective`),this.settingsPanel.setSectionViewToggleHandler(e=>{e?this.applySectionView():this.clearSectionView()}),this.initClickDetection(),this.initHoverDetection()}get sceneContext(){return this.ctx}get currentSceneObjects(){return this.sceneObjects}setSelectionHandler(e){this.selectionHandler=e}get settingsPanelHost(){return this.settingsPanel.panelHost}setParamsToggleHandler(e){this.settingsPanel.setParamsToggleHandler(e)}setParamsButtonVisible(e){this.settingsPanel.setParamsButtonVisible(e)}setParamsButtonActive(e){this.settingsPanel.setParamsButtonActive(e)}lookAlongSketchNormal(e){this.modeManager.enforceSketchNormal(e)}initClickDetection(){let e=this.ctx.renderer.domElement,t=0,n=0;e.addEventListener(`mousedown`,e=>{t=e.clientX,n=e.clientY}),e.addEventListener(`mouseup`,e=>{if(!this.selectionHandler||this.isTrimming||this.isRegionPicking||this.modeManager.isSketchMode)return;let r=e.clientX-t,i=e.clientY-n;if(r*r+i*i>64)return;this.clearHover();let a={additive:e.ctrlKey||e.metaKey||e.shiftKey},o=this.pickAt(e.clientX,e.clientY);o?this.selectionHandler(o.shapeId,o.sub,a):this.selectionHandler(null,null,a)})}pickAt(e,t){let n=this.ctx.camera,r=this.ctx.renderer.domElement.getBoundingClientRect(),i=(e-r.left)/r.width*2-1,a=-((t-r.top)/r.height)*2+1,o=this.ctx.createPickingRaycaster(i,a);o.params.Line={threshold:this.computeEdgePickThreshold()},o.params.Line2={threshold:8};let s=[],c=[];this.ctx.scene.traverse(e=>{e.userData.isMetaShape||(e.isMesh&&e.userData.faceMapping?s.push(e):(e.isLine||e.userData.isEdgeLine)&&e.userData.edgeIndex!==void 0&&c.push(e))});let l=s.length>0?o.intersectObjects(s,!1):[],u=c.length>0?o.intersectObjects(c,!1):[];if(l.length===0&&u.length===0)return null;let d=new R;n.getWorldDirection(d);let f;for(let e of l){if(!e.face){f=e;break}if(e.face.normal.clone().transformDirection(e.object.matrixWorld).dot(d)<0){f=e;break}}let p=f==null?1/0:f.distance,m=o.ray.origin,h=o.ray.direction,g=new R,_=new R;for(let e of u){let t=e.pointOnLine;if(t?g.copy(t):g.copy(e.point),h.dot(_.copy(g).sub(m))<=p+.001){let t=e.object.userData.edgeIndex,n=this.findShapeIdForObject(e.object);if(n)return{shapeId:n,sub:{type:`edge`,index:t}}}}if(f){let e=f.object.userData.faceMapping;if(!e||f.faceIndex==null)return null;let t=e[f.faceIndex];if(t==null)return null;let n=this.findShapeIdForObject(f.object);if(n)return{shapeId:n,sub:{type:`face`,index:t}}}return null}findShapeIdForObject(e){let t=e;for(;t;){if(t.userData.shapeId&&!t.userData.isMetaShape)return t.userData.shapeId;t=t.parent}return null}toggleSketchMode(e){this.modeManager.sketchEnabled=e}setFileName(e){}updateView(e,t=!1,n){if(this.sceneObjects=e,this.highlightedShapeId=null,this.highlightedEntities=[],this.faceHighlightMeshes=[],this.hoverState=null,this.hoverFaceOverlayMeshes=[],this.ctx.renderer.domElement.style.cursor=``,this.removeCompiledMesh(),t)this.activeSketchId=this.findRollbackActiveSketchId(e,n);else{let t=this.findActiveObject(e);t?.type===`sketch`&&t.object?.plane?(this.modeManager.isSketchMode?this.modeManager.enforceSketchNormal(t.object.plane):this.modeManager.enterSketchMode(t.object.plane),this.activeSketchId=t.id,this.settingsPanel.setProjectionLocked(!0),this.settingsPanel.setFitButtonVisible(!1)):(this.activeSketchId=null,this.modeManager.enterDefaultMode(),this.settingsPanel.setProjectionLocked(!1),this.settingsPanel.setFitButtonVisible(!0),this.lastFitBox=null)}let r=Om(e,this.activeSketchId,this.ctx.camera,this.isRegionPicking);if(this.ctx.scene.add(r),this.applyShapeOverridesAndPrune(e),this.activeSketchId&&this.applySketchModeGhosting(),this.settingsPanel.setSectionViewVisible(this.modeManager.isSketchMode),this.modeManager.isSketchMode&&(this.settingsPanel.setSectionViewActive(lf.current.sectionView),lf.current.sectionView&&this.applySectionView()),!this.hasRendered&&!this.modeManager.isSketchMode||this.modeManager.isSketchMode&&!t&&!this.isTrimming&&!this.isRegionPicking&&!this.isDrawing){let e=new Gt;_g(e,r),!e.isEmpty()&&!this.isBoxContained(e)&&(this.ctx.fitToBox(e,!0),this.lastFitBox=e.clone(),this.hasRendered=!0)}!this.hasRendered&&this.modeManager.isSketchMode&&(this.hasRendered=!0),this.ctx.requestRender()}highlightShape(e){this.clearHighlight();let t=this.findShapeById(e);if(!t)return;let n=this.findMeshByShapeId(e);if(!n)return;let r=t.shapeType===`solid`||t.shapeType===`face`;n.traverse(e=>{if(!e.material)return;let t=e.isLine||e.userData.isEdgeLine;if(r&&e instanceof U&&!t){let t=e.material;e.userData.originalColor=t.color.getHex(),t.color.set(Wd.highlightColor),(t.opacity<1||t.transparent)&&(e.userData.originalOpacity=t.opacity,e.userData.originalTransparent=t.transparent,t.opacity=1,t.transparent=!1)}else !r&&t&&(e.userData.originalColor=e.material.color.getHex(),e.material.color.set(Wd.highlightColor),e.userData.originalLineWidth=e.material.linewidth,e.material.linewidth=vg,e.material.opacity<1&&(e.userData.originalOpacity=e.material.opacity,e.material.opacity=1))}),this.highlightedShapeId=e,this.highlightedEntities=[],this.ctx.render()}clearHighlight(){if(!(!this.highlightedShapeId&&this.highlightedEntities.length===0&&this.faceHighlightMeshes.length===0)){this.ctx.scene.traverse(e=>{e.userData.originalColor!==void 0&&(e.material.color.setHex(e.userData.originalColor),delete e.userData.originalColor),e.userData.originalOpacity!==void 0&&(e.material.opacity=e.userData.originalOpacity,delete e.userData.originalOpacity),e.userData.originalTransparent!==void 0&&(e.material.transparent=e.userData.originalTransparent,delete e.userData.originalTransparent),e.userData.originalLineWidth!==void 0&&(e.material.linewidth=e.userData.originalLineWidth,delete e.userData.originalLineWidth)});for(let e of this.faceHighlightMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.faceHighlightMeshes=[],this.highlightedShapeId=null,this.highlightedEntities=[],this.ctx.render()}}highlightEntities(e){this.clearHighlight();for(let t of e)t.sub.type===`face`?this.applyFaceHighlight(t.shapeId,t.sub.index):this.applyEdgeHighlight(t.shapeId,t.sub.index);this.highlightedEntities=e,this.ctx.render()}highlightFace(e,t){this.highlightEntities([{shapeId:e,sub:{type:`face`,index:t}}])}highlightEdge(e,t){this.highlightEntities([{shapeId:e,sub:{type:`edge`,index:t}}])}applyFaceHighlight(e,t){this.ctx.scene.traverse(n=>{if(!n.isMesh)return;let r=n.userData.faceMapping;if(!r)return;let i=!1,a=n;for(;a;){if(a.userData.shapeId===e&&!a.userData.isMetaShape){i=!0;break}a=a.parent}if(!i)return;let o=n,s=o.geometry,c=s.index;if(!c)return;let l=c.array,u=s.getAttribute(`position`).array,d=[];for(let e=0;e<r.length;e++)if(r[e]===t){let t=l[e*3]*3,n=l[e*3+1]*3,r=l[e*3+2]*3;d.push(u[t],u[t+1],u[t+2]),d.push(u[n],u[n+1],u[n+2]),d.push(u[r],u[r+1],u[r+2])}if(d.length===0)return;let f=new H;f.setAttribute(`position`,new V(new Float32Array(d),3));let p=new U(f,new va({color:Wd.highlightColor,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.faceHighlightMeshes.push(p)})}applyEdgeHighlight(e,t){this.ctx.scene.traverse(n=>{if(!n.isLine&&!n.userData.isEdgeLine||n.userData.edgeIndex!==t)return;let r=!1,i=n;for(;i;){if(i.userData.shapeId===e&&!i.userData.isMetaShape){r=!0;break}i=i.parent}r&&n.userData.originalColor===void 0&&(n.userData.originalColor=n.material.color.getHex(),n.material.color.set(Wd.highlightColor),n.userData.originalLineWidth=n.material.linewidth,n.material.linewidth=vg)})}initHoverDetection(){let e=this.ctx.renderer.domElement;e.addEventListener(`mousedown`,()=>{this.isMouseDown=!0,this.clearHover()}),e.addEventListener(`mouseup`,()=>{this.isMouseDown=!1}),e.addEventListener(`mousemove`,e=>{this.isMouseDown||this.isTrimming||this.isRegionPicking||this.modeManager.isSketchMode||this.hoverRafId===null&&(this.hoverRafId=requestAnimationFrame(()=>{this.hoverRafId=null,this.updateHover(e.clientX,e.clientY)}))}),e.addEventListener(`mouseleave`,()=>{this.clearHover()})}updateHover(e,t){if(!this.selectionHandler)return;let n=this.pickAt(e,t);if(!(this.hoverState&&n&&this.hoverState.shapeId===n.shapeId&&this.hoverState.sub?.type===n.sub?.type&&this.hoverState.sub?.index===n.sub?.index)){if(!n){this.hoverState&&this.clearHover();return}if(this.highlightedEntities.some(e=>e.shapeId===n.shapeId&&e.sub.type===n.sub?.type&&e.sub.index===n.sub?.index)){this.hoverState&&this.clearHover();return}this.clearHover(),this.hoverState=n,this.ctx.renderer.domElement.style.cursor=`pointer`,n.sub?.type===`face`?this.applyHoverFace(n.shapeId,n.sub.index):n.sub?.type===`edge`&&this.applyHoverEdge(n.shapeId,n.sub.index)}}clearHover(){for(let e of this.hoverFaceOverlayMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.hoverFaceOverlayMeshes=[],this.ctx.scene.traverse(e=>{e.userData.hoverOriginalColor!==void 0&&(e.material.color.setHex(e.userData.hoverOriginalColor),delete e.userData.hoverOriginalColor),e.userData.hoverOriginalLineWidth!==void 0&&(e.material.linewidth=e.userData.hoverOriginalLineWidth,delete e.userData.hoverOriginalLineWidth)}),this.hoverState=null,this.ctx.renderer.domElement.style.cursor=``,this.ctx.requestRender()}applyHoverFace(e,t){this.ctx.scene.traverse(n=>{if(!n.isMesh)return;let r=n.userData.faceMapping;if(!r)return;let i=!1,a=n;for(;a;){if(a.userData.shapeId===e&&!a.userData.isMetaShape){i=!0;break}a=a.parent}if(!i)return;let o=n,s=o.geometry,c=s.index;if(!c)return;let l=c.array,u=s.getAttribute(`position`).array,d=[];for(let e=0;e<r.length;e++)if(r[e]===t){let t=l[e*3]*3,n=l[e*3+1]*3,r=l[e*3+2]*3;d.push(u[t],u[t+1],u[t+2]),d.push(u[n],u[n+1],u[n+2]),d.push(u[r],u[r+1],u[r+2])}if(d.length===0)return;let f=new H;f.setAttribute(`position`,new V(new Float32Array(d),3));let p=new U(f,new va({color:Wd.highlightColor,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.hoverFaceOverlayMeshes.push(p)}),this.ctx.requestRender()}applyHoverEdge(e,t){this.ctx.scene.traverse(n=>{if(!n.isLine&&!n.userData.isEdgeLine||n.userData.edgeIndex!==t)return;let r=!1,i=n;for(;i;){if(i.userData.shapeId===e&&!i.userData.isMetaShape){r=!0;break}i=i.parent}r&&(n.userData.hoverOriginalColor=n.material.color.getHex(),n.material.color.set(Wd.highlightColor),n.userData.hoverOriginalLineWidth=n.material.linewidth,n.material.linewidth=yg)}),this.ctx.requestRender()}showCentroid(e){let t=this.computeCentroidRadius();this.centroidIndicator.show(this.ctx.scene,e,t),this.ctx.requestRender()}clearCentroid(){this.centroidIndicator.clear(this.ctx.scene),this.ctx.requestRender()}dispose(){this.ctx.dispose()}computeEdgePickThreshold(){let e=this.ctx.camera,t=this.ctx.renderer.domElement.getBoundingClientRect().height||1,n,r=e;if(r.isOrthographicCamera)n=(r.top-r.bottom)/(r.zoom||1);else{let t=new R;this.ctx.cameraControls.getTarget(t);let i=e.position.distanceTo(t),a=r.fov*Math.PI/180;n=2*i*Math.tan(a/2)}return n/t*8}computeCentroidRadius(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(e){let t=new Gt;if(_g(t,e),!t.isEmpty())return t.getSize(new R).length()*.015}return 2}fitViewToScene(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=new Gt;_g(t,e),t.isEmpty()||this.ctx.fitToBox(t,!0)}findShapeById(e){for(let t of this.sceneObjects)for(let n of t.sceneShapes)if(n.shapeId===e)return n}findMeshByShapeId(e){let t;return this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&(t=n)}),t}findActiveObject(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n.parentId||e.find(e=>e.id===n.parentId)?.type===`part`)return n}}findRollbackActiveSketchId(e,t){if(t==null||t<0||t>=e.length)return null;let n=e[t];for(;n;){if(n.type===`sketch`)return n.id;if(!n.parentId)return null;n=e.find(e=>e.id===n.parentId)}return null}isBoxContained(e){if(!this.lastFitBox)return!1;let t=this.lastFitBox.getCenter(new R),n=this.lastFitBox.getSize(new R).length()/2*af;if(n===0)return!1;let r=e.getCenter(new R),i=e.getSize(new R).length()/2;return t.distanceTo(r)+i<=n}rebuildSceneMesh(){if(!this.sceneObjects)return;this.removeCompiledMesh();let e=Om(this.sceneObjects,this.activeSketchId,this.ctx.camera,this.isRegionPicking);this.ctx.scene.add(e),this.applyShapeOverridesAndPrune(this.sceneObjects),this.modeManager.isSketchMode&&lf.current.sectionView&&this.applySectionView(),this.ctx.requestRender()}setShapeVisibility(e,t){t?this.hiddenShapeIds.delete(e):this.hiddenShapeIds.add(e),this.applyVisibilityForId(e,t),this.ctx.requestRender()}isShapeHidden(e){return this.hiddenShapeIds.has(e)}applyVisibilityForId(e,t){this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&(n.visible=t)})}setShapeTransparency(e,t){t>=1?this.shapeOpacities.delete(e):this.shapeOpacities.set(e,t),this.applyOpacityForId(e,t),this.ctx.requestRender()}getShapeTransparency(e){return this.shapeOpacities.get(e)??1}resetAllTransparency(){if(this.shapeOpacities.size===0)return;let e=Array.from(this.shapeOpacities.keys());this.shapeOpacities.clear();for(let t of e)this.applyOpacityForId(t,1);this.ctx.requestRender()}applyOpacityForId(e,t){let n=[];this.ctx.scene.traverse(t=>{t.userData.shapeId===e&&n.push(t)});for(let e of n)this.applyOpacityToSubtree(e,t)}applyOpacityToSubtree(e,t){e.traverse(e=>{let n=e.material;if(!n)return;let r=Array.isArray(n)?n:[n];for(let e of r)e.transparent=t<1,e.opacity=t,e.depthWrite=t>=1,e.needsUpdate=!0})}applyShapeOverridesAndPrune(e){let t=new Set;for(let n of e)if(n.sceneShapes)for(let e of n.sceneShapes)e.isMetaShape||e.shapeId&&t.add(e.shapeId);for(let e of this.hiddenShapeIds)t.has(e)||this.hiddenShapeIds.delete(e);for(let e of this.shapeOpacities.keys())t.has(e)||this.shapeOpacities.delete(e);this.ctx.scene.traverse(e=>{let t=e.userData.shapeId;if(typeof t!=`string`)return;this.hiddenShapeIds.has(t)&&(e.visible=!1);let n=this.shapeOpacities.get(t);n!==void 0&&this.applyOpacityToSubtree(e,n)})}applySketchModeGhosting(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=Wd.backgroundColor;for(let n of e.children)this.tintForGhosting(n,t)}tintForGhosting(e,t){if(e.userData.isSketchRoot||e.renderOrder>=999)return;let n=e.material;if(n){let e=Array.isArray(n)?n:[n];for(let n of e)!n.color||!(n.color instanceof B)||(n.userData.ghostOriginalColor||(n.userData.ghostOriginalColor=n.color.clone()),n.color.copy(n.userData.ghostOriginalColor).lerp(t,bg))}for(let n of e.children)this.tintForGhosting(n,t)}applySectionView(){let e=this.modeManager.sectionPlane;if(!e)return;let t=this.ctx.scene.getObjectByName(`compiledMesh`);t&&(this.forEachClippableMaterial(t,t=>{t.clippingPlanes=[e]}),this.ctx.requestRender())}clearSectionView(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(this.forEachClippableMaterial(e,e=>{e.clippingPlanes=[]}),this.ctx.requestRender())}forEachClippableMaterial(e,t){if(e.userData.isSketchRoot)return;let n=e.material;if(n){let e=Array.isArray(n)?n:[n];for(let n of e)t(n)}for(let n of e.children)this.forEachClippableMaterial(n,t)}removeCompiledMesh(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(e.traverse(e=>{e.geometry?.dispose(),Array.isArray(e.material)?e.material.forEach(e=>e.dispose()):e.material?.dispose()}),this.ctx.scene.remove(e))}};function Sg(e){switch(e){case`inch`:return 16.387064;case`foot`:return 28316.846592;case`yard`:return 764554.857984;case`meter`:return 1e6;default:return .001}}function Cg(e){switch(e){case`inch`:return`in`;case`foot`:return`ft`;case`yard`:return`yd`;case`meter`:return`m`;default:return`mm`}}function wg(e,t,n){let r=t===`kg`?1e3:t===`lbs`?453.592:1;return e*Sg(n)/r}function Tg(e,t){switch(t){case`kg/m³`:return e*.001;case`g/mm³`:return e*1e3;case`lbs/in³`:return e*27.6799;default:return e}}function Eg(e,t){switch(t){case`kg/m³`:return e/.001;case`g/mm³`:return e/1e3;case`lbs/in³`:return e/27.6799;default:return e}}function Dg(e){return e===0?`0`:parseFloat(e.toPrecision(6)).toString()}var Og=class{btn;panel;placeholderEl;formEl;selectEl;densityEl;densityUnitSelectEl;lengthUnitEl;massUnitEl;calcBtn;resultsEl;errorEl;volVal;areaVal;massVal;centroidVal;selectedShapeId=null;rawProps=null;canonicalDensityGcm3=null;currentDensityUnit=`g/cm³`;centroidHandler=null;openHandler=null;constructor(e){this.btn=document.createElement(`button`),this.btn.className=`btn btn-ghost btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10 text-base-content/60`,this.btn.title=`Shape Properties`,this.btn.innerHTML=jh,e.appendChild(this.btn),this.panel=document.createElement(`div`),this.panel.className=`absolute bottom-[68px] right-6 w-[300px] bg-base-100/95 backdrop-blur-xl border border-base-content/10 rounded-lg p-4 z-[200] shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-base-content text-[13px] hidden`,this.panel.innerHTML=this.buildHTML(),e.appendChild(this.panel),this.bindRefs(),this.bindEvents(),this.loadMaterials()}buildHTML(){return`
5047
5047
  <div class="flex items-center justify-between mb-3">
5048
5048
  <span class="text-xs font-semibold text-base-content/70 uppercase tracking-wider">Shape Properties</span>
5049
5049
  <button class="btn btn-ghost btn-xs btn-square" data-action="panel-close">×</button>
@@ -5107,20 +5107,20 @@ void main() {
5107
5107
  <span class="text-base-content/90 text-xs font-medium" data-ref="centroid">—</span>
5108
5108
  </div>
5109
5109
  </div>
5110
- `}bindRefs(){this.placeholderEl=this.panel.querySelector(`[data-ref="placeholder"]`),this.formEl=this.panel.querySelector(`[data-ref="form"]`),this.selectEl=this.panel.querySelector(`[data-ref="material"]`),this.densityEl=this.panel.querySelector(`[data-ref="density"]`),this.densityUnitSelectEl=this.panel.querySelector(`[data-ref="density-unit"]`),this.lengthUnitEl=this.panel.querySelector(`[data-ref="length-unit"]`),this.massUnitEl=this.panel.querySelector(`[data-ref="mass-unit"]`),this.calcBtn=this.panel.querySelector(`[data-action="calculate"]`),this.resultsEl=this.panel.querySelector(`[data-ref="results"]`),this.errorEl=this.panel.querySelector(`[data-ref="error"]`),this.volVal=this.panel.querySelector(`[data-ref="vol"]`),this.areaVal=this.panel.querySelector(`[data-ref="area"]`),this.massVal=this.panel.querySelector(`[data-ref="mass"]`),this.centroidVal=this.panel.querySelector(`[data-ref="centroid"]`)}get isOpen(){return!this.panel.classList.contains(`hidden`)}setCentroidHandler(e){this.centroidHandler=e}setOpenHandler(e){this.openHandler=e}bindEvents(){this.btn.addEventListener(`click`,()=>this.toggle()),this.panel.querySelector(`[data-action="panel-close"]`).addEventListener(`click`,()=>this.close()),this.selectEl.addEventListener(`change`,()=>{let e=this.selectEl.options[this.selectEl.selectedIndex];e?.dataset.density&&(this.currentDensityUnit=e.dataset.densityUnit||`g/cm³`,this.canonicalDensityGcm3=Sg(parseFloat(e.dataset.density),this.currentDensityUnit),this.updateDensityUnitSelect(),this.updateDensityDisplay())}),this.densityEl.addEventListener(`input`,()=>{let e=parseFloat(this.densityEl.value);isNaN(e)||(this.canonicalDensityGcm3=Sg(e,this.currentDensityUnit))}),this.densityUnitSelectEl.addEventListener(`change`,()=>{this.currentDensityUnit=this.densityUnitSelectEl.value,this.updateDensityDisplay()}),this.lengthUnitEl.addEventListener(`change`,()=>this.renderResults()),this.massUnitEl.addEventListener(`change`,()=>this.renderResults()),this.calcBtn.addEventListener(`click`,()=>this.calculate())}updateDensityUnitSelect(){if(Array.from(this.densityUnitSelectEl.options).find(e=>e.value===this.currentDensityUnit))this.densityUnitSelectEl.value=this.currentDensityUnit;else{let e=document.createElement(`option`);e.value=this.currentDensityUnit,e.textContent=this.currentDensityUnit,this.densityUnitSelectEl.appendChild(e),this.densityUnitSelectEl.value=this.currentDensityUnit}}updateDensityDisplay(){this.canonicalDensityGcm3!==null&&(this.densityEl.value=wg(Cg(this.canonicalDensityGcm3,this.currentDensityUnit)))}toggle(){this.panel.classList.contains(`hidden`)?this.open():this.close()}open(){this.openHandler?.(),this.panel.classList.remove(`hidden`),this.btn.className=`btn btn-soft btn-primary btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10`}close(){this.panel.classList.add(`hidden`),this.btn.className=`btn btn-ghost btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10 text-base-content/60`}async loadMaterials(){let e=await Km();if(!e)return;this.selectEl.innerHTML=``;for(let t of e){let e=document.createElement(`option`);e.textContent=t.name,e.dataset.density=String(t.density),e.dataset.densityUnit=t.densityUnit,this.selectEl.appendChild(e)}let t=this.selectEl.options[0];t?.dataset.density&&(this.currentDensityUnit=t.dataset.densityUnit||`g/cm³`,this.canonicalDensityGcm3=Sg(parseFloat(t.dataset.density),this.currentDensityUnit),this.updateDensityUnitSelect(),this.updateDensityDisplay())}async calculate(){if(this.selectedShapeId){this.calcBtn.disabled=!0,this.errorEl.classList.add(`hidden`),this.resultsEl.classList.add(`hidden`);try{if(this.rawProps=await Wm(this.selectedShapeId),!this.rawProps){this.showError(`Failed to calculate properties.`);return}this.renderResults()}catch{this.showError(`Network error while fetching properties.`)}finally{this.calcBtn.disabled=!1}}}renderResults(){if(!this.rawProps)return;let e=this.lengthUnitEl.value,t=this.massUnitEl.value,n=bg(e),r=`${this.rawProps.volumeMm3.toFixed(4)} ${n}\u00B3`,i=`${this.rawProps.surfaceAreaMm2.toFixed(4)} ${n}\u00B2`,a=xg(this.canonicalDensityGcm3??0,`g`,e),o=this.rawProps.volumeMm3*a,s;s=t===`kg`?`${(o/1e3).toFixed(4)} kg`:t===`lbs`?`${(o/453.592).toFixed(4)} lbs`:`${o.toFixed(4)} g`;let{centroid:c}=this.rawProps,l=e=>e.toFixed(4),u=`(${l(c.x)}, ${l(c.y)}, ${l(c.z)}) ${n}`;this.volVal.textContent=r,this.areaVal.textContent=i,this.massVal.textContent=s,this.centroidVal.textContent=u,this.resultsEl.classList.remove(`hidden`),this.centroidHandler?.(c)}showError(e){this.errorEl.textContent=e,this.errorEl.classList.remove(`hidden`)}setSelectedShape(e){e!==this.selectedShapeId&&(this.rawProps=null,this.resultsEl.classList.add(`hidden`),this.errorEl.classList.add(`hidden`),this.centroidHandler?.(null),this.selectedShapeId=e,e?(this.placeholderEl.classList.add(`hidden`),this.formEl.classList.remove(`hidden`)):(this.placeholderEl.classList.remove(`hidden`),this.formEl.classList.add(`hidden`)))}show(e){this.setSelectedShape(e),this.open()}},Eg={plane:`Plane`,circle:`Circle`,cylinder:`Cylinder`,sphere:`Sphere`,torus:`Torus`,cone:`Cone`,other:`Surface`},Dg={line:`Line`,circle:`Circle`,arc:`Arc`,ellipse:`Ellipse`,other:`Curve`},Og=class{el;abortController=null;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute bottom-6 right-[76px] w-[200px] panel-bg border border-base-content/10 rounded-lg p-3 z-[150] shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-base-content text-xs pointer-events-none select-none hidden`,e.appendChild(this.el)}async showForFace(e,t){this.abortController&&this.abortController.abort(),this.abortController=new AbortController,this.el.innerHTML=`<div class="text-base-content/50 text-[11px] text-center py-1">Loading…</div>`,this.el.classList.remove(`hidden`);let n=this.abortController.signal,r=await Hm(e,t,n);if(!r){n.aborted||this.el.classList.add(`hidden`);return}this.renderFace(r)}async showForEdge(e,t){this.abortController&&this.abortController.abort(),this.abortController=new AbortController,this.el.innerHTML=`<div class="text-base-content/50 text-[11px] text-center py-1">Loading…</div>`,this.el.classList.remove(`hidden`);let n=this.abortController.signal,r=await Um(e,t,n);if(!r){n.aborted||this.el.classList.add(`hidden`);return}this.renderEdge(r)}hide(){this.abortController&&=(this.abortController.abort(),null),this.el.classList.add(`hidden`)}renderFace(e){let t=Eg[e.surfaceType]??`Surface`,n=[];e.surfaceType===`plane`&&e.areaMm2!=null?n.push({label:`Area`,value:`${e.areaMm2.toFixed(4)} mm\u00B2`}):e.surfaceType===`circle`&&e.radius!=null||e.surfaceType===`cylinder`&&e.radius!=null||e.surfaceType===`sphere`&&e.radius!=null?n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}):e.surfaceType===`torus`?(e.majorRadius!=null&&n.push({label:`Major R`,value:`${e.majorRadius.toFixed(4)} mm`}),e.minorRadius!=null&&n.push({label:`Minor R`,value:`${e.minorRadius.toFixed(4)} mm`})):e.surfaceType===`cone`&&e.halfAngleDeg!=null?n.push({label:`Half-angle`,value:`${e.halfAngleDeg.toFixed(2)}\u00B0`}):e.areaMm2!=null&&n.push({label:`Area`,value:`${e.areaMm2.toFixed(4)} mm\u00B2`}),this.renderPanel(t,n)}renderEdge(e){let t=Dg[e.curveType]??`Curve`,n=[];e.curveType===`line`?e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`}):e.curveType===`circle`?e.radius!=null&&n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}):e.curveType===`arc`?(e.radius!=null&&n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}),e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`})):e.curveType===`ellipse`?(e.majorRadius!=null&&n.push({label:`Major R`,value:`${e.majorRadius.toFixed(4)} mm`}),e.minorRadius!=null&&n.push({label:`Minor R`,value:`${e.minorRadius.toFixed(4)} mm`})):e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`}),this.renderPanel(t,n)}renderPanel(e,t){let n=t.map(e=>`<div class="flex justify-between items-baseline py-0.5"><span class="text-base-content/50 text-[11px]">${e.label}</span><span class="text-base-content/90 text-xs font-medium">${e.value}</span></div>`).join(``);this.el.innerHTML=`<div class="badge badge-primary badge-outline badge-sm mb-2">${e}</div>${n}<div class="text-[10px] text-base-content/40 mt-1.5 pt-1.5 border-t border-base-content/10">Ctrl+click another face/edge to measure</div>`,this.el.classList.remove(`hidden`)}},kg={aline:`aline`,"axis-from-edge":`axis`,"axis-middle":`axis`,"copy-circular-2d":`copy-circular2d`,"copy-linear-2d":`copy-linear2d`,cut:`cut`,"cut-symmetric":`cut`,"extrude-by-distance":`extrude`,"extrude-by-two-distance":`extrude`,"extrude-symmetric":`extrude`,"extrude-to-face":`extrude`,hline:`hline`,"lazy-select":`select`,"line-two-points":`line`,"mirror-feature":`mirror`,"mirror-shape":`mirror`,"mirror-shape-2d":`mirror2d`,"one-object-tline":`tline`,"plane-from-face":`plane`,"repeat-circular":`copy-circular`,"repeat-linear":`copy-linear`,"repeat-matrix":`copy-linear`,"slot-from-edge":`slot`,"tarc-to-point":`tarc`,"tarc-to-point-tangent":`tarc`,"tarc-with-tangent":`tarc`,tline:`tline`,"two-objects-tarc":`tarc`,"two-objects-tcircle":`arc`,"two-objects-tline":`tline`,vline:`vline`};function Ag(e,t){return e&&kg[e]?kg[e]:t||`solid`}var jg=`onerror="this.onerror=null;this.src='/icons/solid.png'"`,Mg=`flex items-center gap-2 px-3 py-2 panel-bg border border-base-content/10 rounded-md cursor-pointer select-none shrink-0`,Ng=class{header;body;panel;sceneObjects=[];collapsedGroups=new Set;selectedIds=new Set;expanded=!0;activeDropdown=null;dropdownCleanup=null;activeTransparencyPopover=null;onHighlightShape;onExportShapes;onToggleVisibility;isShapeHidden;onSetTransparency;getTransparency;onResetAllTransparency;constructor(e,t,n,r,i,a,o,s){this.panel=e,this.onHighlightShape=t,this.onExportShapes=n,this.onToggleVisibility=r,this.isShapeHidden=i,this.onSetTransparency=a,this.getTransparency=o,this.onResetAllTransparency=s,this.header=document.createElement(`div`),this.header.className=Mg,this.header.innerHTML=`
5111
- <span class="flex items-center justify-center w-5 h-5 opacity-50 transition-transform rotate-90">${tg}</span>
5110
+ `}bindRefs(){this.placeholderEl=this.panel.querySelector(`[data-ref="placeholder"]`),this.formEl=this.panel.querySelector(`[data-ref="form"]`),this.selectEl=this.panel.querySelector(`[data-ref="material"]`),this.densityEl=this.panel.querySelector(`[data-ref="density"]`),this.densityUnitSelectEl=this.panel.querySelector(`[data-ref="density-unit"]`),this.lengthUnitEl=this.panel.querySelector(`[data-ref="length-unit"]`),this.massUnitEl=this.panel.querySelector(`[data-ref="mass-unit"]`),this.calcBtn=this.panel.querySelector(`[data-action="calculate"]`),this.resultsEl=this.panel.querySelector(`[data-ref="results"]`),this.errorEl=this.panel.querySelector(`[data-ref="error"]`),this.volVal=this.panel.querySelector(`[data-ref="vol"]`),this.areaVal=this.panel.querySelector(`[data-ref="area"]`),this.massVal=this.panel.querySelector(`[data-ref="mass"]`),this.centroidVal=this.panel.querySelector(`[data-ref="centroid"]`)}get isOpen(){return!this.panel.classList.contains(`hidden`)}setCentroidHandler(e){this.centroidHandler=e}setOpenHandler(e){this.openHandler=e}bindEvents(){this.btn.addEventListener(`click`,()=>this.toggle()),this.panel.querySelector(`[data-action="panel-close"]`).addEventListener(`click`,()=>this.close()),this.selectEl.addEventListener(`change`,()=>{let e=this.selectEl.options[this.selectEl.selectedIndex];e?.dataset.density&&(this.currentDensityUnit=e.dataset.densityUnit||`g/cm³`,this.canonicalDensityGcm3=Tg(parseFloat(e.dataset.density),this.currentDensityUnit),this.updateDensityUnitSelect(),this.updateDensityDisplay())}),this.densityEl.addEventListener(`input`,()=>{let e=parseFloat(this.densityEl.value);isNaN(e)||(this.canonicalDensityGcm3=Tg(e,this.currentDensityUnit))}),this.densityUnitSelectEl.addEventListener(`change`,()=>{this.currentDensityUnit=this.densityUnitSelectEl.value,this.updateDensityDisplay()}),this.lengthUnitEl.addEventListener(`change`,()=>this.renderResults()),this.massUnitEl.addEventListener(`change`,()=>this.renderResults()),this.calcBtn.addEventListener(`click`,()=>this.calculate())}updateDensityUnitSelect(){if(Array.from(this.densityUnitSelectEl.options).find(e=>e.value===this.currentDensityUnit))this.densityUnitSelectEl.value=this.currentDensityUnit;else{let e=document.createElement(`option`);e.value=this.currentDensityUnit,e.textContent=this.currentDensityUnit,this.densityUnitSelectEl.appendChild(e),this.densityUnitSelectEl.value=this.currentDensityUnit}}updateDensityDisplay(){this.canonicalDensityGcm3!==null&&(this.densityEl.value=Dg(Eg(this.canonicalDensityGcm3,this.currentDensityUnit)))}toggle(){this.panel.classList.contains(`hidden`)?this.open():this.close()}open(){this.openHandler?.(),this.panel.classList.remove(`hidden`),this.btn.className=`btn btn-soft btn-primary btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10`}close(){this.panel.classList.add(`hidden`),this.btn.className=`btn btn-ghost btn-square btn-sm rounded-md absolute bottom-6 right-8 z-[100] panel-bg border border-base-content/10 text-base-content/60`}async loadMaterials(){let e=await Ym();if(!e)return;this.selectEl.innerHTML=``;for(let t of e){let e=document.createElement(`option`);e.textContent=t.name,e.dataset.density=String(t.density),e.dataset.densityUnit=t.densityUnit,this.selectEl.appendChild(e)}let t=this.selectEl.options[0];t?.dataset.density&&(this.currentDensityUnit=t.dataset.densityUnit||`g/cm³`,this.canonicalDensityGcm3=Tg(parseFloat(t.dataset.density),this.currentDensityUnit),this.updateDensityUnitSelect(),this.updateDensityDisplay())}async calculate(){if(this.selectedShapeId){this.calcBtn.disabled=!0,this.errorEl.classList.add(`hidden`),this.resultsEl.classList.add(`hidden`);try{if(this.rawProps=await qm(this.selectedShapeId),!this.rawProps){this.showError(`Failed to calculate properties.`);return}this.renderResults()}catch{this.showError(`Network error while fetching properties.`)}finally{this.calcBtn.disabled=!1}}}renderResults(){if(!this.rawProps)return;let e=this.lengthUnitEl.value,t=this.massUnitEl.value,n=Cg(e),r=`${this.rawProps.volumeMm3.toFixed(4)} ${n}\u00B3`,i=`${this.rawProps.surfaceAreaMm2.toFixed(4)} ${n}\u00B2`,a=wg(this.canonicalDensityGcm3??0,`g`,e),o=this.rawProps.volumeMm3*a,s;s=t===`kg`?`${(o/1e3).toFixed(4)} kg`:t===`lbs`?`${(o/453.592).toFixed(4)} lbs`:`${o.toFixed(4)} g`;let{centroid:c}=this.rawProps,l=e=>e.toFixed(4),u=`(${l(c.x)}, ${l(c.y)}, ${l(c.z)}) ${n}`;this.volVal.textContent=r,this.areaVal.textContent=i,this.massVal.textContent=s,this.centroidVal.textContent=u,this.resultsEl.classList.remove(`hidden`),this.centroidHandler?.(c)}showError(e){this.errorEl.textContent=e,this.errorEl.classList.remove(`hidden`)}setSelectedShape(e){e!==this.selectedShapeId&&(this.rawProps=null,this.resultsEl.classList.add(`hidden`),this.errorEl.classList.add(`hidden`),this.centroidHandler?.(null),this.selectedShapeId=e,e?(this.placeholderEl.classList.add(`hidden`),this.formEl.classList.remove(`hidden`)):(this.placeholderEl.classList.remove(`hidden`),this.formEl.classList.add(`hidden`)))}show(e){this.setSelectedShape(e),this.open()}},kg={plane:`Plane`,circle:`Circle`,cylinder:`Cylinder`,sphere:`Sphere`,torus:`Torus`,cone:`Cone`,other:`Surface`},Ag={line:`Line`,circle:`Circle`,arc:`Arc`,ellipse:`Ellipse`,other:`Curve`},jg=class{el;abortController=null;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute bottom-6 right-[76px] w-[200px] panel-bg border border-base-content/10 rounded-lg p-3 z-[150] shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-base-content text-xs pointer-events-none select-none hidden`,e.appendChild(this.el)}async showForFace(e,t){this.abortController&&this.abortController.abort(),this.abortController=new AbortController,this.el.innerHTML=`<div class="text-base-content/50 text-[11px] text-center py-1">Loading…</div>`,this.el.classList.remove(`hidden`);let n=this.abortController.signal,r=await Gm(e,t,n);if(!r){n.aborted||this.el.classList.add(`hidden`);return}this.renderFace(r)}async showForEdge(e,t){this.abortController&&this.abortController.abort(),this.abortController=new AbortController,this.el.innerHTML=`<div class="text-base-content/50 text-[11px] text-center py-1">Loading…</div>`,this.el.classList.remove(`hidden`);let n=this.abortController.signal,r=await Km(e,t,n);if(!r){n.aborted||this.el.classList.add(`hidden`);return}this.renderEdge(r)}hide(){this.abortController&&=(this.abortController.abort(),null),this.el.classList.add(`hidden`)}renderFace(e){let t=kg[e.surfaceType]??`Surface`,n=[];e.surfaceType===`plane`&&e.areaMm2!=null?n.push({label:`Area`,value:`${e.areaMm2.toFixed(4)} mm\u00B2`}):e.surfaceType===`circle`&&e.radius!=null||e.surfaceType===`cylinder`&&e.radius!=null||e.surfaceType===`sphere`&&e.radius!=null?n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}):e.surfaceType===`torus`?(e.majorRadius!=null&&n.push({label:`Major R`,value:`${e.majorRadius.toFixed(4)} mm`}),e.minorRadius!=null&&n.push({label:`Minor R`,value:`${e.minorRadius.toFixed(4)} mm`})):e.surfaceType===`cone`&&e.halfAngleDeg!=null?n.push({label:`Half-angle`,value:`${e.halfAngleDeg.toFixed(2)}\u00B0`}):e.areaMm2!=null&&n.push({label:`Area`,value:`${e.areaMm2.toFixed(4)} mm\u00B2`}),this.renderPanel(t,n)}renderEdge(e){let t=Ag[e.curveType]??`Curve`,n=[];e.curveType===`line`?e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`}):e.curveType===`circle`?e.radius!=null&&n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}):e.curveType===`arc`?(e.radius!=null&&n.push({label:`Radius`,value:`${e.radius.toFixed(4)} mm`}),e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`})):e.curveType===`ellipse`?(e.majorRadius!=null&&n.push({label:`Major R`,value:`${e.majorRadius.toFixed(4)} mm`}),e.minorRadius!=null&&n.push({label:`Minor R`,value:`${e.minorRadius.toFixed(4)} mm`})):e.length!=null&&n.push({label:`Length`,value:`${e.length.toFixed(4)} mm`}),this.renderPanel(t,n)}renderPanel(e,t){let n=t.map(e=>`<div class="flex justify-between items-baseline py-0.5"><span class="text-base-content/50 text-[11px]">${e.label}</span><span class="text-base-content/90 text-xs font-medium">${e.value}</span></div>`).join(``);this.el.innerHTML=`<div class="badge badge-primary badge-outline badge-sm mb-2">${e}</div>${n}<div class="text-[10px] text-base-content/40 mt-1.5 pt-1.5 border-t border-base-content/10">Ctrl+click another face/edge to measure</div>`,this.el.classList.remove(`hidden`)}},Mg={aline:`aline`,"axis-from-edge":`axis`,"axis-middle":`axis`,"copy-circular-2d":`copy-circular2d`,"copy-linear-2d":`copy-linear2d`,cut:`cut`,"cut-symmetric":`cut`,"extrude-by-distance":`extrude`,"extrude-by-two-distance":`extrude`,"extrude-symmetric":`extrude`,"extrude-to-face":`extrude`,hline:`hline`,"lazy-select":`select`,"line-two-points":`line`,"mirror-feature":`mirror`,"mirror-shape":`mirror`,"mirror-shape-2d":`mirror2d`,"one-object-tline":`tline`,"plane-from-face":`plane`,"repeat-circular":`copy-circular`,"repeat-linear":`copy-linear`,"repeat-matrix":`copy-linear`,"slot-from-edge":`slot`,"tarc-to-point":`tarc`,"tarc-to-point-tangent":`tarc`,"tarc-with-tangent":`tarc`,tline:`tline`,"two-objects-tarc":`tarc`,"two-objects-tcircle":`arc`,"two-objects-tline":`tline`,vline:`vline`};function Ng(e,t){return e&&Mg[e]?Mg[e]:t||`solid`}var Pg=`onerror="this.onerror=null;this.src='/icons/solid.png'"`,Fg=`flex items-center gap-2 px-3 py-2 panel-bg border border-base-content/10 rounded-md cursor-pointer select-none shrink-0`,Ig=class{header;body;panel;sceneObjects=[];collapsedGroups=new Set;selectedIds=new Set;expanded=!0;activeDropdown=null;dropdownCleanup=null;activeTransparencyPopover=null;onHighlightShape;onExportShapes;onToggleVisibility;isShapeHidden;onSetTransparency;getTransparency;onResetAllTransparency;constructor(e,t,n,r,i,a,o,s){this.panel=e,this.onHighlightShape=t,this.onExportShapes=n,this.onToggleVisibility=r,this.isShapeHidden=i,this.onSetTransparency=a,this.getTransparency=o,this.onResetAllTransparency=s,this.header=document.createElement(`div`),this.header.className=Fg,this.header.innerHTML=`
5111
+ <span class="flex items-center justify-center w-5 h-5 opacity-50 transition-transform rotate-90">${ig}</span>
5112
5112
  <span class="text-sm font-medium text-base-content/70">Shapes</span>
5113
5113
  `,this.body=document.createElement(`div`),this.body.className=`py-1 overflow-y-auto min-h-[33vh] flex-1`,this.header.addEventListener(`click`,()=>{this.expanded=!this.expanded,this.body.classList.toggle(`hidden`,!this.expanded),this.header.querySelector(`span`).classList.toggle(`rotate-90`,this.expanded)})}update(e){this.sceneObjects=e,this.render()}render(){let e=new Map;for(let t of this.sceneObjects)for(let n of t.sceneShapes){if(n.isMetaShape)continue;let r=n.shapeType||`unknown`;e.has(r)||e.set(r,[]),e.get(r).push({shapeId:n.shapeId||``,shapeType:r,sceneObjectName:t.name})}let t=``;for(let[n,r]of e){let e=n.charAt(0).toUpperCase()+n.slice(1),i=this.collapsedGroups.has(n);if(t+=`
5114
5114
  <div class="flex items-center gap-1 px-3 py-1.5 cursor-pointer hover:bg-base-content/[0.06] text-sm text-base-content/70 font-medium" data-shape-group="${n}">
5115
5115
  <span class="flex items-center justify-center w-5 h-5 opacity-50 hover:opacity-100 transition-transform ${i?``:`rotate-90`}">
5116
- ${tg}
5116
+ ${ig}
5117
5117
  </span>
5118
5118
  <span>${e}</span>
5119
5119
  <span class="text-base-content/40 ml-1">${r.length}</span>
5120
5120
  </div>
5121
- `,!i){let e=new Map;for(let t of r)e.set(t.sceneObjectName,(e.get(t.sceneObjectName)??0)+1);let n=new Map;for(let i=0;i<r.length;i++){let a=r[i],o=(n.get(a.sceneObjectName)??0)+1;n.set(a.sceneObjectName,o);let s=(e.get(a.sceneObjectName)??1)>1?`${a.sceneObjectName} ${o}`:a.sceneObjectName,c=this.selectedIds.has(a.shapeId)?` bg-primary/10`:``,l=this.isShapeHidden(a.shapeId),u=l?Lh:Ih,d=`<button class="ml-auto btn btn-ghost btn-square btn-xs ${l?`opacity-100 text-base-content/70`:`opacity-0 group-hover:opacity-100 text-base-content/40`} hover:text-base-content/70 shrink-0 [&>svg]:size-3.5" data-eye="${a.shapeId}">${u}</button>`,f=`<button class="opacity-0 group-hover:opacity-100 btn btn-ghost btn-square btn-xs text-base-content/40 hover:text-base-content/70 shrink-0" data-dots="${a.shapeId}">${rg}</button>`;t+=`
5121
+ `,!i){let e=new Map;for(let t of r)e.set(t.sceneObjectName,(e.get(t.sceneObjectName)??0)+1);let n=new Map;for(let i=0;i<r.length;i++){let a=r[i],o=(n.get(a.sceneObjectName)??0)+1;n.set(a.sceneObjectName,o);let s=(e.get(a.sceneObjectName)??1)>1?`${a.sceneObjectName} ${o}`:a.sceneObjectName,c=this.selectedIds.has(a.shapeId)?` bg-primary/10`:``,l=this.isShapeHidden(a.shapeId),u=l?Bh:zh,d=`<button class="ml-auto btn btn-ghost btn-square btn-xs ${l?`opacity-100 text-base-content/70`:`opacity-0 group-hover:opacity-100 text-base-content/40`} hover:text-base-content/70 shrink-0 [&>svg]:size-3.5" data-eye="${a.shapeId}">${u}</button>`,f=`<button class="opacity-0 group-hover:opacity-100 btn btn-ghost btn-square btn-xs text-base-content/40 hover:text-base-content/70 shrink-0" data-dots="${a.shapeId}">${og}</button>`;t+=`
5122
5122
  <div class="group flex items-center gap-2 pl-9 pr-3 py-1 cursor-pointer hover:bg-base-content/[0.06] text-sm text-base-content/70${c}" data-shape-id="${a.shapeId}" data-shape-type="${a.shapeType}">
5123
- <img src="/icons/${a.shapeType}.png" ${jg} class="w-4 h-4 object-contain" alt="" />
5123
+ <img src="/icons/${a.shapeType}.png" ${Pg} class="w-4 h-4 object-contain" alt="" />
5124
5124
  <span class="truncate">${s}</span>
5125
5125
  ${d}
5126
5126
  ${f}
@@ -5139,44 +5139,44 @@ void main() {
5139
5139
  <input type="range" min="0" max="100" value="${o}" class="range range-xs flex-1" data-ref="slider" />
5140
5140
  <span class="text-xs text-base-content/60 w-10 text-right" data-ref="value">${o}%</span>
5141
5141
  </div>
5142
- `,this.panel.appendChild(n),this.activeTransparencyPopover=n;let s=n.querySelector(`[data-ref="slider"]`),c=n.querySelector(`[data-ref="value"]`);s.addEventListener(`input`,()=>{let e=parseInt(s.value,10),n=e/100;c.textContent=`${e}%`;for(let e of t)this.onSetTransparency(e,n)}),n.querySelector(`[data-action="close"]`).addEventListener(`click`,()=>{this.closeTransparencyPopover()})}closeDropdown(){this.activeDropdown&&=(this.activeDropdown.remove(),null),this.dropdownCleanup&&=(this.dropdownCleanup(),null)}closeTransparencyPopover(){this.activeTransparencyPopover&&(this.activeTransparencyPopover.remove(),this.activeTransparencyPopover=null,this.onResetAllTransparency())}},Pg=`flex items-center gap-2 px-3 py-2 panel-bg border border-base-content/10 rounded-md cursor-pointer select-none shrink-0`;function Fg(e){return e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}var Ig=class{panel;fileLabel;timelineBody;contentWrapper;positioner;shapesPanel;loaded=!1;sceneObjects=[];rollbackStop=-1;collapsedIds=new Set;timelineExpanded=!0;activeDropdown=null;dropdownCleanup=null;showBuildTimings=!1;historyTotalLabel;hoverPopover=null;onImportFile;constructor(e,t,n,r,i,a,o,s,c){this.onImportFile=c,this.panel=document.createElement(`div`),this.panel.className=`absolute left-6 top-6 bottom-6 w-[220px] z-[99] flex flex-col gap-1 select-none hidden`,e.appendChild(this.panel),this.applyPanelWidth();let l=document.createElement(`div`);l.className=`flex items-center gap-1.5 px-1 pb-1 shrink-0`,l.innerHTML=`<img src="/logo.png" alt="FluidCAD" class="h-6 w-auto opacity-70" /><span class="text-[18px] font-bold text-base-content/70">FluidCAD</span>`,this.panel.appendChild(l);let u=document.createElement(`div`);u.className=`flex items-center gap-2 px-1 pb-1 shrink-0`,u.innerHTML=`
5143
- <span class="text-base-content/50 [&>svg]:size-4">${ig}</span>
5142
+ `,this.panel.appendChild(n),this.activeTransparencyPopover=n;let s=n.querySelector(`[data-ref="slider"]`),c=n.querySelector(`[data-ref="value"]`);s.addEventListener(`input`,()=>{let e=parseInt(s.value,10),n=e/100;c.textContent=`${e}%`;for(let e of t)this.onSetTransparency(e,n)}),n.querySelector(`[data-action="close"]`).addEventListener(`click`,()=>{this.closeTransparencyPopover()})}closeDropdown(){this.activeDropdown&&=(this.activeDropdown.remove(),null),this.dropdownCleanup&&=(this.dropdownCleanup(),null)}closeTransparencyPopover(){this.activeTransparencyPopover&&(this.activeTransparencyPopover.remove(),this.activeTransparencyPopover=null,this.onResetAllTransparency())}},Lg=`flex items-center gap-2 px-3 py-2 panel-bg border border-base-content/10 rounded-md cursor-pointer select-none shrink-0`;function Rg(e){return e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}var zg=class{panel;fileLabel;timelineBody;contentWrapper;positioner;shapesPanel;loaded=!1;sceneObjects=[];rollbackStop=-1;collapsedIds=new Set;timelineExpanded=!0;activeDropdown=null;dropdownCleanup=null;showBuildTimings=!1;historyTotalLabel;hoverPopover=null;onImportFile;constructor(e,t,n,r,i,a,o,s,c){this.onImportFile=c,this.panel=document.createElement(`div`),this.panel.className=`absolute left-6 top-6 bottom-6 w-[220px] z-[99] flex flex-col gap-1 select-none hidden`,e.appendChild(this.panel),this.applyPanelWidth();let l=document.createElement(`div`);l.className=`flex items-center gap-1.5 px-1 pb-1 shrink-0`,l.innerHTML=`<img src="/logo.png" alt="FluidCAD" class="h-6 w-auto opacity-70" /><span class="text-[18px] font-bold text-base-content/70">FluidCAD</span>`,this.panel.appendChild(l);let u=document.createElement(`div`);u.className=`flex items-center gap-2 px-1 pb-1 shrink-0`,u.innerHTML=`
5143
+ <span class="text-base-content/50 [&>svg]:size-4">${sg}</span>
5144
5144
  <span data-ref="filename" class="text-base text-base-content/70 truncate"></span>
5145
5145
  <button data-ref="import-btn" class="ml-auto w-5 h-5 min-h-0 btn btn-circle btn-ghost border border-base-content/30 hover:border-base-content/50 p-0 text-base-content/40 hover:text-base-content/70 shrink-0 tooltip tooltip-right" data-tip="Import File">
5146
5146
  <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
5147
5147
  </button>
5148
- `,this.panel.appendChild(u),this.fileLabel=u.querySelector(`[data-ref="filename"]`),u.querySelector(`[data-ref="import-btn"]`).addEventListener(`click`,()=>this.onImportFile()),this.positioner=document.createElement(`div`),this.positioner.className=`relative flex-1 min-h-0 overflow-hidden`,this.panel.appendChild(this.positioner),this.contentWrapper=document.createElement(`div`),this.contentWrapper.className=`absolute inset-0 flex flex-col gap-1 overflow-y-auto`,this.contentWrapper.style.transition=`transform 0.25s ease, opacity 0.25s ease`,this.positioner.appendChild(this.contentWrapper);let d=document.createElement(`div`);d.className=Pg,d.innerHTML=`
5149
- <span data-ref="chevron" class="flex items-center justify-center w-5 h-5 opacity-50 transition-transform rotate-90">${tg}</span>
5148
+ `,this.panel.appendChild(u),this.fileLabel=u.querySelector(`[data-ref="filename"]`),u.querySelector(`[data-ref="import-btn"]`).addEventListener(`click`,()=>this.onImportFile()),this.positioner=document.createElement(`div`),this.positioner.className=`relative flex-1 min-h-0 overflow-hidden`,this.panel.appendChild(this.positioner),this.contentWrapper=document.createElement(`div`),this.contentWrapper.className=`absolute inset-0 flex flex-col gap-1 overflow-y-auto`,this.contentWrapper.style.transition=`transform 0.25s ease, opacity 0.25s ease`,this.positioner.appendChild(this.contentWrapper);let d=document.createElement(`div`);d.className=Lg,d.innerHTML=`
5149
+ <span data-ref="chevron" class="flex items-center justify-center w-5 h-5 opacity-50 transition-transform rotate-90">${ig}</span>
5150
5150
  <span class="text-sm font-medium text-base-content/70">History</span>
5151
5151
  <span data-ref="history-total" class="text-xs text-base-content/40 tabular-nums hidden"></span>
5152
- <button data-ref="history-dots" class="ml-auto btn btn-ghost btn-square btn-xs text-base-content/40 hover:text-base-content/70 shrink-0">${rg}</button>
5153
- `,this.contentWrapper.appendChild(d),this.historyTotalLabel=d.querySelector(`[data-ref="history-total"]`);let f=d.querySelector(`[data-ref="history-dots"]`);f.addEventListener(`click`,e=>{e.stopPropagation(),this.showHistoryDropdown(f)}),this.timelineBody=document.createElement(`div`),this.timelineBody.className=`py-1 overflow-y-auto min-h-0`,this.contentWrapper.appendChild(this.timelineBody),d.addEventListener(`click`,()=>{this.timelineExpanded=!this.timelineExpanded,this.timelineBody.classList.toggle(`hidden`,!this.timelineExpanded),d.querySelector(`[data-ref="chevron"]`).classList.toggle(`rotate-90`,this.timelineExpanded)}),this.shapesPanel=new Ng(this.panel,t,n,r,i,a,o,s),this.contentWrapper.appendChild(this.shapesPanel.header),this.contentWrapper.appendChild(this.shapesPanel.body)}update(e,t,n){if(this.sceneObjects=e,this.rollbackStop=t,n){let e=n.split(`/`).pop()||n;this.fileLabel.textContent=e}this.loaded||(this.loaded=!0,this.panel.classList.remove(`hidden`)),this.renderTimeline(!0),this.shapesPanel.update(e),this.updateHistoryTotal()}setShowBuildTimings(e){this.showBuildTimings!==e&&(this.showBuildTimings=e,this.applyPanelWidth(),this.updateHistoryTotal(),this.loaded&&this.renderTimeline())}slideOut(){this.contentWrapper.style.transform=`translateX(-100%)`,this.contentWrapper.style.opacity=`0`,this.contentWrapper.style.pointerEvents=`none`}slideIn(){this.contentWrapper.style.transform=``,this.contentWrapper.style.opacity=``,this.contentWrapper.style.pointerEvents=``}get toolbarHost(){return this.positioner}renderTimeline(e=!1){let t=this.sceneObjects,n=this.rollbackStop,r=new Set,i=new Map;for(let e of t)e.uniqueType!==`lazy-select`&&e.parentId&&(r.add(e.parentId),e.hasError&&i.set(e.parentId,!0));let a=``;for(let e=0;e<t.length;e++){let o=t[e];if(o.parentId||o.uniqueType===`lazy-select`)continue;let s=o.id!=null&&r.has(o.id),c=o.id!=null&&this.collapsedIds.has(o.id),l=o.id!=null&&i.get(o.id)===!0,u=o.hasError===!0||l;if(a+=this.renderTimelineItem(o,e,n,!1,s,c,u),s&&!c)for(let e=0;e<t.length;e++)t[e].uniqueType!==`lazy-select`&&t[e].parentId===o.id&&(a+=this.renderTimelineItem(t[e],e,n,!0,!1,!1,t[e].hasError===!0))}if(this.timelineBody.innerHTML=a,this.timelineBody.querySelectorAll(`[data-index]`).forEach(e=>{e.addEventListener(`click`,t=>{if(t.target.closest(`[data-toggle]`))return;let n=parseInt(e.dataset.index,10);this.rollbackTo(n),this.goToSource(this.sceneObjects[n])}),e.addEventListener(`dblclick`,t=>{if(t.target.closest(`[data-toggle]`))return;let n=parseInt(e.dataset.index,10);this.addBreakpointAfter(n),this.goToSource(this.sceneObjects[n])})}),this.timelineBody.querySelectorAll(`[data-toggle]`).forEach(e=>{e.addEventListener(`click`,t=>{t.stopPropagation();let n=e.dataset.toggle;this.collapsedIds.has(n)?this.collapsedIds.delete(n):this.collapsedIds.add(n),this.renderTimeline()})}),this.showBuildTimings&&this.timelineBody.querySelectorAll(`[data-index]`).forEach(e=>{let t=parseInt(e.dataset.index,10),n=this.sceneObjects[t];!n||!n.profileCategories||n.profileCategories.length===0||(e.addEventListener(`mouseenter`,()=>{this.showProfilePopover(e,n.profileCategories,n.buildDurationMs)}),e.addEventListener(`mouseleave`,()=>{this.closeProfilePopover()}))}),e){let e=this.timelineBody.querySelector(`[data-current="true"]`);e&&e.scrollIntoView({block:`nearest`})}}renderTimelineItem(e,t,n,r,i,a,o){let s=t===n,c=t>n,l=e.visible===!1,u=e.name||`Unknown`,d=e.type===`part`?`/icons/box.png`:`/icons/${Ag(e.uniqueType,e.type)}.png`,f=`flex items-center gap-1 px-3 py-1.5 cursor-pointer hover:bg-base-content/[0.06] text-sm`;r&&(f+=` pl-7`),s&&(f+=` border-l-2 border-primary bg-primary/10`),o?f+=` text-error`:s?f+=` text-primary`:c||l?f+=` text-base-content/60`:f+=` text-base-content/80`;let p=l?`w-4 h-4 object-contain grayscale opacity-60`:`w-4 h-4 object-contain`,m=o?`<span class="text-error shrink-0 [&>svg]:w-2.5 [&>svg]:h-2.5">${og}</span>`:``,h=``;if(i){let t=a?``:`rotate-90`;h=`<span data-toggle="${e.id}" class="flex items-center justify-center w-5 h-5 opacity-50 hover:opacity-100 transition-transform ${t}">
5154
- ${tg}
5155
- </span>`}else h=`<span class="w-4"></span>`;let g=this.showBuildTimings&&!e.fromCache&&e.buildDurationMs!=null,_=g?`<span class="ml-auto shrink-0 text-xs text-base-content/40 tabular-nums">${Fg(e.buildDurationMs)}</span>`:``,v=g?`shrink-0 text-base-content/40 [&>svg]:w-4 [&>svg]:h-4`:`ml-auto shrink-0 text-base-content/40 [&>svg]:w-4 [&>svg]:h-4`,y=e.fromCache?`<span class="${v}">${jh}</span>`:`<span class="${v}">${Mh}</span>`;return`
5152
+ <button data-ref="history-dots" class="ml-auto btn btn-ghost btn-square btn-xs text-base-content/40 hover:text-base-content/70 shrink-0">${og}</button>
5153
+ `,this.contentWrapper.appendChild(d),this.historyTotalLabel=d.querySelector(`[data-ref="history-total"]`);let f=d.querySelector(`[data-ref="history-dots"]`);f.addEventListener(`click`,e=>{e.stopPropagation(),this.showHistoryDropdown(f)}),this.timelineBody=document.createElement(`div`),this.timelineBody.className=`py-1 overflow-y-auto min-h-0`,this.contentWrapper.appendChild(this.timelineBody),d.addEventListener(`click`,()=>{this.timelineExpanded=!this.timelineExpanded,this.timelineBody.classList.toggle(`hidden`,!this.timelineExpanded),d.querySelector(`[data-ref="chevron"]`).classList.toggle(`rotate-90`,this.timelineExpanded)}),this.shapesPanel=new Ig(this.panel,t,n,r,i,a,o,s),this.contentWrapper.appendChild(this.shapesPanel.header),this.contentWrapper.appendChild(this.shapesPanel.body)}update(e,t,n){if(this.sceneObjects=e,this.rollbackStop=t,n){let e=n.split(`/`).pop()||n;this.fileLabel.textContent=e}this.loaded||(this.loaded=!0,this.panel.classList.remove(`hidden`)),this.renderTimeline(!0),this.shapesPanel.update(e),this.updateHistoryTotal()}setShowBuildTimings(e){this.showBuildTimings!==e&&(this.showBuildTimings=e,this.applyPanelWidth(),this.updateHistoryTotal(),this.loaded&&this.renderTimeline())}slideOut(){this.contentWrapper.style.transform=`translateX(-100%)`,this.contentWrapper.style.opacity=`0`,this.contentWrapper.style.pointerEvents=`none`}slideIn(){this.contentWrapper.style.transform=``,this.contentWrapper.style.opacity=``,this.contentWrapper.style.pointerEvents=``}get toolbarHost(){return this.positioner}renderTimeline(e=!1){let t=this.sceneObjects,n=this.rollbackStop,r=new Set,i=new Map;for(let e of t)e.uniqueType!==`lazy-select`&&e.parentId&&(r.add(e.parentId),e.hasError&&i.set(e.parentId,!0));let a=``;for(let e=0;e<t.length;e++){let o=t[e];if(o.parentId||o.uniqueType===`lazy-select`)continue;let s=o.id!=null&&r.has(o.id),c=o.id!=null&&this.collapsedIds.has(o.id),l=o.id!=null&&i.get(o.id)===!0,u=o.hasError===!0||l;if(a+=this.renderTimelineItem(o,e,n,!1,s,c,u),s&&!c)for(let e=0;e<t.length;e++)t[e].uniqueType!==`lazy-select`&&t[e].parentId===o.id&&(a+=this.renderTimelineItem(t[e],e,n,!0,!1,!1,t[e].hasError===!0))}if(this.timelineBody.innerHTML=a,this.timelineBody.querySelectorAll(`[data-index]`).forEach(e=>{e.addEventListener(`click`,t=>{if(t.target.closest(`[data-toggle]`))return;let n=parseInt(e.dataset.index,10);this.rollbackTo(n),this.goToSource(this.sceneObjects[n])}),e.addEventListener(`dblclick`,t=>{if(t.target.closest(`[data-toggle]`))return;let n=parseInt(e.dataset.index,10);this.addBreakpointAfter(n),this.goToSource(this.sceneObjects[n])})}),this.timelineBody.querySelectorAll(`[data-toggle]`).forEach(e=>{e.addEventListener(`click`,t=>{t.stopPropagation();let n=e.dataset.toggle;this.collapsedIds.has(n)?this.collapsedIds.delete(n):this.collapsedIds.add(n),this.renderTimeline()})}),this.showBuildTimings&&this.timelineBody.querySelectorAll(`[data-index]`).forEach(e=>{let t=parseInt(e.dataset.index,10),n=this.sceneObjects[t];!n||!n.profileCategories||n.profileCategories.length===0||(e.addEventListener(`mouseenter`,()=>{this.showProfilePopover(e,n.profileCategories,n.buildDurationMs)}),e.addEventListener(`mouseleave`,()=>{this.closeProfilePopover()}))}),e){let e=this.timelineBody.querySelector(`[data-current="true"]`);e&&e.scrollIntoView({block:`nearest`})}}renderTimelineItem(e,t,n,r,i,a,o){let s=t===n,c=t>n,l=e.visible===!1,u=e.name||`Unknown`,d=e.type===`part`?`/icons/box.png`:`/icons/${Ng(e.uniqueType,e.type)}.png`,f=`flex items-center gap-1 px-3 py-1.5 cursor-pointer hover:bg-base-content/[0.06] text-sm`;r&&(f+=` pl-7`),s&&(f+=` border-l-2 border-primary bg-primary/10`),o?f+=` text-error`:s?f+=` text-primary`:c||l?f+=` text-base-content/60`:f+=` text-base-content/80`;let p=l?`w-4 h-4 object-contain grayscale opacity-60`:`w-4 h-4 object-contain`,m=o?`<span class="text-error shrink-0 [&>svg]:w-2.5 [&>svg]:h-2.5">${lg}</span>`:``,h=``;if(i){let t=a?``:`rotate-90`;h=`<span data-toggle="${e.id}" class="flex items-center justify-center w-5 h-5 opacity-50 hover:opacity-100 transition-transform ${t}">
5154
+ ${ig}
5155
+ </span>`}else h=`<span class="w-4"></span>`;let g=this.showBuildTimings&&!e.fromCache&&e.buildDurationMs!=null,_=g?`<span class="ml-auto shrink-0 text-xs text-base-content/40 tabular-nums">${Rg(e.buildDurationMs)}</span>`:``,v=g?`shrink-0 text-base-content/40 [&>svg]:w-4 [&>svg]:h-4`:`ml-auto shrink-0 text-base-content/40 [&>svg]:w-4 [&>svg]:h-4`,y=e.fromCache?`<span class="${v}">${Ph}</span>`:`<span class="${v}">${Fh}</span>`;return`
5156
5156
  <div class="${f}" data-index="${t}" data-container="${e.isContainer??!1}" data-current="${s}">
5157
5157
  ${h}
5158
5158
  ${m}
5159
- <img src="${d}" ${jg} class="${p}" alt="" />
5159
+ <img src="${d}" ${Pg} class="${p}" alt="" />
5160
5160
  <span class="truncate">${u}</span>
5161
5161
  ${_}
5162
5162
  ${y}
5163
5163
  </div>
5164
- `}updateHistoryTotal(){if(!this.showBuildTimings){this.historyTotalLabel.classList.add(`hidden`);return}let e=0,t=!1;for(let n of this.sceneObjects)n.parentId||n.fromCache||n.buildDurationMs==null||(e+=n.buildDurationMs,t=!0);if(!t){this.historyTotalLabel.classList.add(`hidden`);return}this.historyTotalLabel.textContent=`· ${Fg(e)}`,this.historyTotalLabel.classList.remove(`hidden`)}applyPanelWidth(){this.panel.classList.toggle(`w-[220px]`,!this.showBuildTimings),this.panel.classList.toggle(`w-[270px]`,this.showBuildTimings)}showHistoryDropdown(e){this.closeDropdown();let t=document.createElement(`div`);t.className=`absolute z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)]`;let n=e.getBoundingClientRect(),r=this.panel.getBoundingClientRect();t.style.top=`${n.bottom-r.top+2}px`,t.style.right=`${r.right-n.right}px`,t.innerHTML=`
5164
+ `}hasBuildTimings(){return this.sceneObjects.some(e=>!e.parentId&&!e.fromCache&&e.buildDurationMs!=null)}updateHistoryTotal(){if(!this.showBuildTimings){this.historyTotalLabel.classList.add(`hidden`);return}let e=0,t=!1;for(let n of this.sceneObjects)n.parentId||n.fromCache||n.buildDurationMs==null||(e+=n.buildDurationMs,t=!0);if(!t){this.historyTotalLabel.classList.add(`hidden`);return}this.historyTotalLabel.textContent=`· ${Rg(e)}`,this.historyTotalLabel.classList.remove(`hidden`)}applyPanelWidth(){this.panel.classList.toggle(`w-[220px]`,!this.showBuildTimings),this.panel.classList.toggle(`w-[270px]`,this.showBuildTimings)}showHistoryDropdown(e){this.closeDropdown();let t=document.createElement(`div`);t.className=`absolute z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)]`;let n=e.getBoundingClientRect(),r=this.panel.getBoundingClientRect();t.style.top=`${n.bottom-r.top+2}px`,t.style.right=`${r.right-n.right}px`,t.innerHTML=`
5165
5165
  <ul class="menu menu-xs p-1 min-w-[180px]">
5166
5166
  <li><button data-action="recompute" class="flex items-center gap-2">
5167
- <span class="flex items-center justify-center w-4 h-4 shrink-0 [&>svg]:size-3.5">${Mh}</span>
5167
+ <span class="flex items-center justify-center w-4 h-4 shrink-0 [&>svg]:size-3.5">${Fh}</span>
5168
5168
  <span>Recompute scene</span>
5169
5169
  </button></li>
5170
5170
  <li><button data-action="toggle-timings" class="flex items-center gap-2">
5171
- ${this.showBuildTimings?`<span class="flex items-center justify-center w-4 h-4 shrink-0 text-primary [&>svg]:size-3">${ag}</span>`:`<span class="w-4 h-4 shrink-0"></span>`}
5171
+ ${this.showBuildTimings?`<span class="flex items-center justify-center w-4 h-4 shrink-0 text-primary [&>svg]:size-3">${cg}</span>`:`<span class="w-4 h-4 shrink-0"></span>`}
5172
5172
  <span>Show execution time</span>
5173
5173
  </button></li>
5174
5174
  </ul>
5175
- `,this.panel.appendChild(t),this.activeDropdown=t,t.querySelector(`[data-action="toggle-timings"]`).addEventListener(`click`,()=>{let e=!this.showBuildTimings;this.showBuildTimings=e,this.applyPanelWidth(),this.updateHistoryTotal(),th(`showBuildTimings`,e),this.closeDropdown(),this.renderTimeline()}),t.querySelector(`[data-action="recompute"]`).addEventListener(`click`,()=>{this.closeDropdown(),this.recomputeScene()});let i=n=>{!t.contains(n.target)&&!e.contains(n.target)&&this.closeDropdown()};setTimeout(()=>document.addEventListener(`click`,i),0),this.dropdownCleanup=()=>document.removeEventListener(`click`,i)}closeDropdown(){this.activeDropdown&&=(this.activeDropdown.remove(),null),this.dropdownCleanup&&=(this.dropdownCleanup(),null)}showProfilePopover(e,t,n){this.closeProfilePopover();let r=document.createElement(`div`);r.className=`absolute z-[201] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)] p-3 min-w-[200px] max-w-[280px]`;let i=e.getBoundingClientRect(),a=this.panel.getBoundingClientRect();r.style.left=`${i.right-a.left+8}px`,r.style.top=`${Math.max(0,i.top-a.top-4)}px`;let o=t.reduce((e,t)=>e+t.durationMs,0),s=t.map(e=>({...e}));n!==void 0&&n-o>.5&&s.push({category:`Other`,durationMs:Math.round((n-o)*10)/10,isOther:!0});let c=Math.max(...s.map(e=>e.durationMs),.1),l=``;for(let e of s){let t=c>0?e.durationMs/c*100:0,n=e.isOther?`bg-base-content/25`:t>60?`bg-warning/60`:`bg-primary/40`;l+=`
5175
+ `,this.panel.appendChild(t),this.activeDropdown=t,t.querySelector(`[data-action="toggle-timings"]`).addEventListener(`click`,()=>{let e=!this.showBuildTimings;this.showBuildTimings=e,this.applyPanelWidth(),this.updateHistoryTotal(),ih(`showBuildTimings`,e),this.closeDropdown(),this.renderTimeline(),e&&!this.hasBuildTimings()&&this.recomputeScene()}),t.querySelector(`[data-action="recompute"]`).addEventListener(`click`,()=>{this.closeDropdown(),this.recomputeScene()});let i=n=>{!t.contains(n.target)&&!e.contains(n.target)&&this.closeDropdown()};setTimeout(()=>document.addEventListener(`click`,i),0),this.dropdownCleanup=()=>document.removeEventListener(`click`,i)}closeDropdown(){this.activeDropdown&&=(this.activeDropdown.remove(),null),this.dropdownCleanup&&=(this.dropdownCleanup(),null)}showProfilePopover(e,t,n){this.closeProfilePopover();let r=document.createElement(`div`);r.className=`absolute z-[201] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)] p-3 min-w-[200px] max-w-[280px]`;let i=e.getBoundingClientRect(),a=this.panel.getBoundingClientRect();r.style.left=`${i.right-a.left+8}px`,r.style.top=`${Math.max(0,i.top-a.top-4)}px`;let o=t.reduce((e,t)=>e+t.durationMs,0),s=t.map(e=>({...e}));n!==void 0&&n-o>.5&&s.push({category:`Other`,durationMs:Math.round((n-o)*10)/10,isOther:!0});let c=Math.max(...s.map(e=>e.durationMs),.1),l=``;for(let e of s){let t=c>0?e.durationMs/c*100:0,n=e.isOther?`bg-base-content/25`:t>60?`bg-warning/60`:`bg-primary/40`;l+=`
5176
5176
  <div class="mb-1.5">
5177
5177
  <div class="flex justify-between text-xs mb-0.5">
5178
5178
  <span class="text-base-content/80 truncate mr-2">${this.escapeHtml(e.category)}</span>
5179
- <span class="text-base-content/50 tabular-nums shrink-0">${Fg(e.durationMs)}</span>
5179
+ <span class="text-base-content/50 tabular-nums shrink-0">${Rg(e.durationMs)}</span>
5180
5180
  </div>
5181
5181
  <div class="h-1 rounded-full bg-base-content/10 overflow-hidden">
5182
5182
  <div class="h-full rounded-full ${n}" style="width:${t}%"></div>
@@ -5184,12 +5184,12 @@ void main() {
5184
5184
  </div>
5185
5185
  `}let u=n===void 0?``:`<div class="flex justify-between text-xs text-base-content/40 mt-1 pt-1 border-t border-base-content/10">
5186
5186
  <span>Total</span>
5187
- <span class="tabular-nums">${Fg(n)}</span>
5187
+ <span class="tabular-nums">${Rg(n)}</span>
5188
5188
  </div>`;r.innerHTML=`
5189
5189
  <div class="text-xs font-medium text-base-content/60 mb-2">Build Time Breakdown</div>
5190
5190
  ${l}
5191
5191
  ${u}
5192
- `,this.panel.appendChild(r),this.hoverPopover=r}closeProfilePopover(){this.hoverPopover&&=(this.hoverPopover.remove(),null)}recomputeScene(){qm()}rollbackTo(e){Jm(e)}addBreakpointAfter(e){let t=this.sceneObjects[e];!t||!t.sourceLocation||Ym(t.sourceLocation)}goToSource(e){!e||!e.sourceLocation||Zm(e.sourceLocation)}escapeHtml(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}},Lg=class{root;body;hasParams=!1;visible=!1;currentParams=[];debounceTimers=new Map;collapsedGroups=new Set;constructor(e){this.root=document.createElement(`div`),this.root.className=`w-[220px] mt-2 select-none hidden`,e.appendChild(this.root);let t=document.createElement(`div`);t.className=`panel-bg border border-base-content/10 rounded-md overflow-y-auto max-h-[60vh]`,this.root.appendChild(t);let n=document.createElement(`div`);n.className=`flex items-center justify-between px-3 pt-2 pb-1`,n.innerHTML=`
5192
+ `,this.panel.appendChild(r),this.hoverPopover=r}closeProfilePopover(){this.hoverPopover&&=(this.hoverPopover.remove(),null)}recomputeScene(){Xm()}rollbackTo(e){Zm(e)}addBreakpointAfter(e){let t=this.sceneObjects[e];!t||!t.sourceLocation||Qm(t.sourceLocation)}goToSource(e){!e||!e.sourceLocation||eh(e.sourceLocation)}escapeHtml(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}},Bg=class{root;body;hasParams=!1;visible=!1;currentParams=[];debounceTimers=new Map;collapsedGroups=new Set;constructor(e){this.root=document.createElement(`div`),this.root.className=`w-[220px] mt-2 select-none hidden`,e.appendChild(this.root);let t=document.createElement(`div`);t.className=`panel-bg border border-base-content/10 rounded-md overflow-y-auto max-h-[60vh]`,this.root.appendChild(t);let n=document.createElement(`div`);n.className=`flex items-center justify-between px-3 pt-2 pb-1`,n.innerHTML=`
5193
5193
  <span class="text-xs font-medium text-base-content/50 uppercase tracking-wider">Parameters</span>
5194
5194
  <button class="btn btn-ghost btn-xs btn-circle text-base-content/40 hover:text-base-content/70" title="Reset all to defaults" data-reset-params>
5195
5195
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-3.5 h-3.5">
@@ -5274,12 +5274,12 @@ void main() {
5274
5274
  ${r}
5275
5275
  ${a}
5276
5276
  </div>
5277
- `}bindParamHandlers(){this.body.querySelectorAll(`[data-param-label]`).forEach(e=>{let t=e.dataset.paramLabel,n=e.dataset.paramType,r=e=>{let n=this.currentParams.find(e=>e.label===t),r=n&&typeof n.defaultValue==`number`?Number(e):e;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:r})}).catch(e=>console.error(`Set param failed:`,e))},i=e=>{let n=this.currentParams.find(e=>e.label===t),r=n?.options?.[0]&&typeof n.options[0].value==`number`?e.map(Number):e;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:r})}).catch(e=>console.error(`Set param failed:`,e))};n===`slider`?(e.addEventListener(`input`,()=>{let n=this.body.querySelector(`[data-param-display="${t}"]`);n&&(n.textContent=e.value)}),e.addEventListener(`change`,()=>{r(e.value)})):n===`number`||n===`text`?(e.addEventListener(`input`,()=>{this.debounceParam(t,()=>r(e.value))}),e.addEventListener(`blur`,()=>{this.flushParam(t,()=>r(e.value))})):n===`checkbox`?e.addEventListener(`change`,()=>{let n=e.checked;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:n})}).catch(e=>console.error(`Set param failed:`,e))}):n===`select`?e.addEventListener(`change`,()=>{r(e.value)}):n===`multi-select`?e.addEventListener(`change`,()=>{i(Array.from(e.selectedOptions,e=>e.value))}):n===`multi-checkboxes`?e.addEventListener(`change`,()=>{i(Array.from(e.querySelectorAll(`input[type="checkbox"]:checked`),e=>e.value))}):n===`color`?e.addEventListener(`input`,()=>{r(e.value)}):n===`multi-chips`&&e.addEventListener(`click`,t=>{let n=t.target.closest(`[data-chip-value]`);n&&(n.classList.toggle(`badge-primary`),n.classList.toggle(`badge-outline`),i(Array.from(e.querySelectorAll(`.badge-primary[data-chip-value]`),e=>e.dataset.chipValue)))})})}debounceParam(e,t){let n=this.debounceTimers.get(e);n&&clearTimeout(n),this.debounceTimers.set(e,setTimeout(()=>{this.debounceTimers.delete(e),t()},500))}flushParam(e,t){let n=this.debounceTimers.get(e);n&&(clearTimeout(n),this.debounceTimers.delete(e),t())}escapeHtml(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}},Rg={front:new R(0,-1,0),back:new R(0,1,0),left:new R(-1,0,0),right:new R(1,0,0),top:new R(0,0,1),bottom:new R(0,0,-1),"iso-ftr":new R(1,-1,1).normalize(),"iso-fbr":new R(1,-1,-1).normalize(),"iso-ftl":new R(-1,-1,1).normalize(),"iso-fbl":new R(-1,-1,-1).normalize(),"iso-btr":new R(1,1,1).normalize(),"iso-bbr":new R(1,1,-1).normalize(),"iso-btl":new R(-1,1,1).normalize(),"iso-bbl":new R(-1,1,-1).normalize()};function zg(e,t,n){let r=Rg[e],i=Math.max(n,1);return{eye:t.clone().add(r.clone().multiplyScalar(i)),target:t.clone()}}function Bg(e,t,n,r){let i=e.clone().sub(t),a=i.length(),o=Math.acos(ht.clamp(i.z/Math.max(a,1e-9),-1,1)),s=Math.atan2(i.y,i.x);s+=n*ht.DEG2RAD,o=ht.clamp(o-r*ht.DEG2RAD,.001,Math.PI-.001);let c=Math.sin(o),l=new R(a*c*Math.cos(s),a*c*Math.sin(s),a*Math.cos(o));return{eye:t.clone().add(l),target:t.clone()}}function Vg(e,t,n,r,i){switch(e.kind){case`current`:return null;case`named`:return zg(e.name,t,n);case`orbit-from-current`:return Bg(r,i,e.azimuthDeg,e.elevationDeg);case`look-from`:return{eye:new R(e.eye[0],e.eye[1],e.eye[2]),target:e.target?new R(e.target[0],e.target[1],e.target[2]):t.clone()}}}function Hg(e){let t=new Gt;return Ug(t,e),t}function Ug(e,t){if(t.userData.isConstructionPlane||!t.visible)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)Ug(e,n)}var Wg={width:800,height:800,showGrid:!1,showAxes:!1,transparent:!1,autoCrop:!1,fitToModel:!1,margin:0,view:{kind:`current`}};function Gg(e,t={}){return Jg(qg(e,{...Wg,...t}))}function Kg(e,t={}){let n={...Wg,...t},r=Math.max(1,Math.floor(n.width/2)),i=Math.max(1,Math.floor(n.height/2)),a=[{x:0,y:0,view:{kind:`named`,name:`front`}},{x:r,y:0,view:{kind:`named`,name:`top`}},{x:0,y:i,view:{kind:`named`,name:`right`}},{x:r,y:i,view:{kind:`named`,name:`iso-ftr`}}],o=document.createElement(`canvas`);o.width=r*2,o.height=i*2;let s=o.getContext(`2d`);if(!s)return Promise.reject(Error(`Failed to get composite 2d context.`));n.transparent||(s.fillStyle=`#ffffff`,s.fillRect(0,0,o.width,o.height));for(let t of a){let a=qg(e,{...n,width:r,height:i,view:t.view,autoCrop:!1,fitToModel:!0});s.drawImage(a,t.x,t.y)}return Jg(o)}function qg(e,t){let{width:n,height:r,showGrid:i,showAxes:a,transparent:o,autoCrop:s,fitToModel:c,margin:l,view:u}=t,d=e.scene,f=e.camera,p=e.cameraControls,m=d.getObjectByName(`grid`),h=d.getObjectByName(`defaultAxesHelper`),g=d.getObjectByName(`sketchAxesHelper`),_=m?.visible,v=h?.visible,y=g?.visible,b=d.background,x=new R,S=new R;p.getPosition(x),p.getTarget(S);let C=f.zoom;m&&(m.visible=i),h&&(h.visible=a),g&&(g.visible=a),o&&(d.background=null);let w=n/r,T=f,E;if(T.isOrthographicCamera){E={left:T.left,right:T.right,top:T.top,bottom:T.bottom};let e=T.top-T.bottom;T.left=-w*e/2,T.right=w*e/2,T.updateProjectionMatrix()}else E={aspect:T.aspect},T.aspect=w,T.updateProjectionMatrix();let D=Xg(e);if(u.kind!==`current`){let e=Vg(u,D.center,D.diameter,x,S);if(e){if(f.position.copy(e.eye),f.lookAt(e.target),T.isOrthographicCamera&&D.diameter>0){let e=T.right-T.left,t=T.top-T.bottom;T.zoom=Math.min(e/D.diameter,t/D.diameter)}else if(T.isPerspectiveCamera&&D.diameter>0){let t=T.fov*Math.PI/360,n=Math.atan(Math.tan(t)*T.aspect),r=Math.min(t,n),i=D.diameter/2/Math.sin(r),a=f.position.clone().sub(e.target).normalize();f.position.copy(e.target).add(a.multiplyScalar(i)),f.lookAt(e.target)}T.updateProjectionMatrix()}}else if(s||c){let e=d.getObjectByName(`compiledMesh`);if(e){let t=new Gt;if(Qg(t,e),!t.isEmpty()){let e=t.getCenter(new R),n=t.getSize(new R).length()*Yd;if(n>0){let t=new R;if(f.getWorldDirection(t),f.position.copy(e).sub(t.clone().multiplyScalar(1e3)),f.lookAt(e),T.isOrthographicCamera){let e=T.right-T.left,t=T.top-T.bottom;T.zoom=Math.min(e/n,t/n)}T.updateProjectionMatrix()}}}}let ee=new Dl({antialias:!0,alpha:!0,preserveDrawingBuffer:!0});ee.setSize(n,r),ee.setPixelRatio(1),ee.toneMapping=4,ee.outputColorSpace=Ie;let O=new R;f.getWorldDirection(O),d.traverse(e=>{e.isDirectionalLight&&e.position.copy(O.clone().multiplyScalar(-10))}),ee.render(d,f);let k=ee.domElement;if(s){let t=Zg(e,n,r,l);if(t){let e=document.createElement(`canvas`);e.width=t.w,e.height=t.h,e.getContext(`2d`).drawImage(ee.domElement,t.x,t.y,t.w,t.h,0,0,t.w,t.h),k=e}}let te=Yg(k,n,r);return m&&(m.visible=_),h&&(h.visible=v),g&&(g.visible=y),d.background=b,T.isOrthographicCamera?(T.left=E.left,T.right=E.right,T.top=E.top,T.bottom=E.bottom):T.aspect=E.aspect,f.zoom=C,f.position.copy(x),f.lookAt(S),T.updateProjectionMatrix(),p.setLookAt(x.x,x.y,x.z,S.x,S.y,S.z,!1),ee.dispose(),e.requestRender(),te}function Jg(e){return new Promise((t,n)=>{e.toBlob(e=>{e?t(e):n(Error(`Failed to create PNG blob.`))},`image/png`)})}function Yg(e,t,n){let r=document.createElement(`canvas`);r.width=e.width||t,r.height=e.height||n;let i=r.getContext(`2d`);return i?(i.drawImage(e,0,0),r):e}function Xg(e){let t=Hg(e.scene.getObjectByName(`compiledMesh`)??e.scene);return t.isEmpty()?{center:new R,diameter:100}:{center:t.getCenter(new R),diameter:t.getSize(new R).length()*Yd}}function Zg(e,t,n,r){let i=e.scene.getObjectByName(`compiledMesh`);if(!i)return null;let a=new Gt;if(Qg(a,i),a.isEmpty())return null;let o=e.camera,s=[new R(a.min.x,a.min.y,a.min.z),new R(a.max.x,a.min.y,a.min.z),new R(a.min.x,a.max.y,a.min.z),new R(a.max.x,a.max.y,a.min.z),new R(a.min.x,a.min.y,a.max.z),new R(a.max.x,a.min.y,a.max.z),new R(a.min.x,a.max.y,a.max.z),new R(a.max.x,a.max.y,a.max.z)],c=1/0,l=1/0,u=-1/0,d=-1/0;for(let e of s){e.project(o);let r=(e.x+1)/2*t,i=(1-e.y)/2*n;c=Math.min(c,r),l=Math.min(l,i),u=Math.max(u,r),d=Math.max(d,i)}let f=Math.max(0,Math.floor(c-r)),p=Math.max(0,Math.floor(l-r)),m=Math.min(t,Math.ceil(u+r)),h=Math.min(n,Math.ceil(d+r)),g=m-f,_=h-p;return g<=0||_<=0?null:{x:f,y:p,w:g,h:_}}function Qg(e,t){if(t.userData.isConstructionPlane||!t.visible)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)Qg(e,n)}var $g=class{overlay;pillsContainer;stepSection;stlSection;pngSection;includeColorsToggle;resolutionSelect;customSection;angularInput;linearInput;showGridToggle;showAxesToggle;transparentToggle;autoCropToggle;marginSection;marginInput;widthInput;heightInput;exportBtn;statusEl;shapeIds=[];selectedFormat=`step`;constructor(e,t){this.sceneCtx=t,this.overlay=document.createElement(`div`),this.overlay.className=`fixed inset-0 z-[300] bg-black/50 flex items-center justify-center hidden`,this.overlay.innerHTML=this.buildHTML(),e.appendChild(this.overlay),this.pillsContainer=this.overlay.querySelector(`[data-ref="format-pills"]`),this.stepSection=this.overlay.querySelector(`[data-ref="step-section"]`),this.stlSection=this.overlay.querySelector(`[data-ref="stl-section"]`),this.pngSection=this.overlay.querySelector(`[data-ref="png-section"]`),this.includeColorsToggle=this.overlay.querySelector(`[data-ref="include-colors"]`),this.resolutionSelect=this.overlay.querySelector(`[data-ref="resolution"]`),this.customSection=this.overlay.querySelector(`[data-ref="custom-section"]`),this.angularInput=this.overlay.querySelector(`[data-ref="angular"]`),this.linearInput=this.overlay.querySelector(`[data-ref="linear"]`),this.showGridToggle=this.overlay.querySelector(`[data-ref="show-grid"]`),this.showAxesToggle=this.overlay.querySelector(`[data-ref="show-axes"]`),this.transparentToggle=this.overlay.querySelector(`[data-ref="transparent"]`),this.autoCropToggle=this.overlay.querySelector(`[data-ref="auto-crop"]`),this.marginSection=this.overlay.querySelector(`[data-ref="margin-section"]`),this.marginInput=this.overlay.querySelector(`[data-ref="margin"]`),this.widthInput=this.overlay.querySelector(`[data-ref="png-width"]`),this.heightInput=this.overlay.querySelector(`[data-ref="png-height"]`),this.exportBtn=this.overlay.querySelector(`[data-ref="export-btn"]`),this.statusEl=this.overlay.querySelector(`[data-ref="status"]`),this.bindEvents()}show(e){this.shapeIds=e,this.statusEl.classList.add(`hidden`),this.exportBtn.disabled=!1,this.overlay.classList.remove(`hidden`)}hide(){this.overlay.classList.add(`hidden`)}buildHTML(){return`
5277
+ `}bindParamHandlers(){this.body.querySelectorAll(`[data-param-label]`).forEach(e=>{let t=e.dataset.paramLabel,n=e.dataset.paramType,r=e=>{let n=this.currentParams.find(e=>e.label===t),r=n&&typeof n.defaultValue==`number`?Number(e):e;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:r})}).catch(e=>console.error(`Set param failed:`,e))},i=e=>{let n=this.currentParams.find(e=>e.label===t),r=n?.options?.[0]&&typeof n.options[0].value==`number`?e.map(Number):e;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:r})}).catch(e=>console.error(`Set param failed:`,e))};n===`slider`?(e.addEventListener(`input`,()=>{let n=this.body.querySelector(`[data-param-display="${t}"]`);n&&(n.textContent=e.value)}),e.addEventListener(`change`,()=>{r(e.value)})):n===`number`||n===`text`?(e.addEventListener(`input`,()=>{this.debounceParam(t,()=>r(e.value))}),e.addEventListener(`blur`,()=>{this.flushParam(t,()=>r(e.value))})):n===`checkbox`?e.addEventListener(`change`,()=>{let n=e.checked;fetch(`/api/set-param`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,value:n})}).catch(e=>console.error(`Set param failed:`,e))}):n===`select`?e.addEventListener(`change`,()=>{r(e.value)}):n===`multi-select`?e.addEventListener(`change`,()=>{i(Array.from(e.selectedOptions,e=>e.value))}):n===`multi-checkboxes`?e.addEventListener(`change`,()=>{i(Array.from(e.querySelectorAll(`input[type="checkbox"]:checked`),e=>e.value))}):n===`color`?e.addEventListener(`input`,()=>{r(e.value)}):n===`multi-chips`&&e.addEventListener(`click`,t=>{let n=t.target.closest(`[data-chip-value]`);n&&(n.classList.toggle(`badge-primary`),n.classList.toggle(`badge-outline`),i(Array.from(e.querySelectorAll(`.badge-primary[data-chip-value]`),e=>e.dataset.chipValue)))})})}debounceParam(e,t){let n=this.debounceTimers.get(e);n&&clearTimeout(n),this.debounceTimers.set(e,setTimeout(()=>{this.debounceTimers.delete(e),t()},500))}flushParam(e,t){let n=this.debounceTimers.get(e);n&&(clearTimeout(n),this.debounceTimers.delete(e),t())}escapeHtml(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}},Vg={front:new R(0,-1,0),back:new R(0,1,0),left:new R(-1,0,0),right:new R(1,0,0),top:new R(0,0,1),bottom:new R(0,0,-1),"iso-ftr":new R(1,-1,1).normalize(),"iso-fbr":new R(1,-1,-1).normalize(),"iso-ftl":new R(-1,-1,1).normalize(),"iso-fbl":new R(-1,-1,-1).normalize(),"iso-btr":new R(1,1,1).normalize(),"iso-bbr":new R(1,1,-1).normalize(),"iso-btl":new R(-1,1,1).normalize(),"iso-bbl":new R(-1,1,-1).normalize()};function Hg(e,t,n){let r=Vg[e],i=Math.max(n,1);return{eye:t.clone().add(r.clone().multiplyScalar(i)),target:t.clone()}}function Ug(e,t,n,r){let i=e.clone().sub(t),a=i.length(),o=Math.acos(ht.clamp(i.z/Math.max(a,1e-9),-1,1)),s=Math.atan2(i.y,i.x);s+=n*ht.DEG2RAD,o=ht.clamp(o-r*ht.DEG2RAD,.001,Math.PI-.001);let c=Math.sin(o),l=new R(a*c*Math.cos(s),a*c*Math.sin(s),a*Math.cos(o));return{eye:t.clone().add(l),target:t.clone()}}function Wg(e,t,n,r,i){switch(e.kind){case`current`:return null;case`named`:return Hg(e.name,t,n);case`orbit-from-current`:return Ug(r,i,e.azimuthDeg,e.elevationDeg);case`look-from`:return{eye:new R(e.eye[0],e.eye[1],e.eye[2]),target:e.target?new R(e.target[0],e.target[1],e.target[2]):t.clone()}}}function Gg(e){let t=new Gt;return Kg(t,e),t}function Kg(e,t){if(t.userData.isConstructionPlane||!t.visible)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)Kg(e,n)}var qg={width:800,height:800,showGrid:!1,showAxes:!1,transparent:!1,autoCrop:!1,fitToModel:!1,margin:0,view:{kind:`current`}};function Jg(e,t={}){return Zg(Xg(e,{...qg,...t}))}function Yg(e,t={}){let n={...qg,...t},r=Math.max(1,Math.floor(n.width/2)),i=Math.max(1,Math.floor(n.height/2)),a=[{x:0,y:0,view:{kind:`named`,name:`front`}},{x:r,y:0,view:{kind:`named`,name:`top`}},{x:0,y:i,view:{kind:`named`,name:`right`}},{x:r,y:i,view:{kind:`named`,name:`iso-ftr`}}],o=document.createElement(`canvas`);o.width=r*2,o.height=i*2;let s=o.getContext(`2d`);if(!s)return Promise.reject(Error(`Failed to get composite 2d context.`));n.transparent||(s.fillStyle=`#ffffff`,s.fillRect(0,0,o.width,o.height));for(let t of a){let a=Xg(e,{...n,width:r,height:i,view:t.view,autoCrop:!1,fitToModel:!0});s.drawImage(a,t.x,t.y)}return Zg(o)}function Xg(e,t){let{width:n,height:r,showGrid:i,showAxes:a,transparent:o,autoCrop:s,fitToModel:c,margin:l,view:u}=t,d=e.scene,f=e.camera,p=e.cameraControls,m=d.getObjectByName(`grid`),h=d.getObjectByName(`defaultAxesHelper`),g=d.getObjectByName(`sketchAxesHelper`),_=m?.visible,v=h?.visible,y=g?.visible,b=d.background,x=new R,S=new R;p.getPosition(x),p.getTarget(S);let C=f.zoom;m&&(m.visible=i),h&&(h.visible=a),g&&(g.visible=a),o&&(d.background=null);let w=n/r,T=f,E;if(T.isOrthographicCamera){E={left:T.left,right:T.right,top:T.top,bottom:T.bottom};let e=T.top-T.bottom;T.left=-w*e/2,T.right=w*e/2,T.updateProjectionMatrix()}else E={aspect:T.aspect},T.aspect=w,T.updateProjectionMatrix();let D=$g(e);if(u.kind!==`current`){let e=Wg(u,D.center,D.diameter,x,S);if(e){if(f.position.copy(e.eye),f.lookAt(e.target),T.isOrthographicCamera&&D.diameter>0){let e=T.right-T.left,t=T.top-T.bottom;T.zoom=Math.min(e/D.diameter,t/D.diameter)}else if(T.isPerspectiveCamera&&D.diameter>0){let t=T.fov*Math.PI/360,n=Math.atan(Math.tan(t)*T.aspect),r=Math.min(t,n),i=D.diameter/2/Math.sin(r),a=f.position.clone().sub(e.target).normalize();f.position.copy(e.target).add(a.multiplyScalar(i)),f.lookAt(e.target)}T.updateProjectionMatrix()}}else if(s||c){let e=d.getObjectByName(`compiledMesh`);if(e){let t=new Gt;if(t_(t,e),!t.isEmpty()){let e=t.getCenter(new R),n=t.getSize(new R).length()*af;if(n>0){let t=new R;if(f.getWorldDirection(t),f.position.copy(e).sub(t.clone().multiplyScalar(1e3)),f.lookAt(e),T.isOrthographicCamera){let e=T.right-T.left,t=T.top-T.bottom;T.zoom=Math.min(e/n,t/n)}T.updateProjectionMatrix()}}}}let ee=new Dl({antialias:!0,alpha:!0,preserveDrawingBuffer:!0});ee.setSize(n,r),ee.setPixelRatio(1),ee.toneMapping=4,ee.outputColorSpace=Ie;let O=new R;f.getWorldDirection(O),d.traverse(e=>{e.isDirectionalLight&&e.position.copy(O.clone().multiplyScalar(-10))}),ee.render(d,f);let k=ee.domElement;if(s){let t=e_(e,n,r,l);if(t){let e=document.createElement(`canvas`);e.width=t.w,e.height=t.h,e.getContext(`2d`).drawImage(ee.domElement,t.x,t.y,t.w,t.h,0,0,t.w,t.h),k=e}}let te=Qg(k,n,r);return m&&(m.visible=_),h&&(h.visible=v),g&&(g.visible=y),d.background=b,T.isOrthographicCamera?(T.left=E.left,T.right=E.right,T.top=E.top,T.bottom=E.bottom):T.aspect=E.aspect,f.zoom=C,f.position.copy(x),f.lookAt(S),T.updateProjectionMatrix(),p.setLookAt(x.x,x.y,x.z,S.x,S.y,S.z,!1),ee.dispose(),e.requestRender(),te}function Zg(e){return new Promise((t,n)=>{e.toBlob(e=>{e?t(e):n(Error(`Failed to create PNG blob.`))},`image/png`)})}function Qg(e,t,n){let r=document.createElement(`canvas`);r.width=e.width||t,r.height=e.height||n;let i=r.getContext(`2d`);return i?(i.drawImage(e,0,0),r):e}function $g(e){let t=Gg(e.scene.getObjectByName(`compiledMesh`)??e.scene);return t.isEmpty()?{center:new R,diameter:100}:{center:t.getCenter(new R),diameter:t.getSize(new R).length()*af}}function e_(e,t,n,r){let i=e.scene.getObjectByName(`compiledMesh`);if(!i)return null;let a=new Gt;if(t_(a,i),a.isEmpty())return null;let o=e.camera,s=[new R(a.min.x,a.min.y,a.min.z),new R(a.max.x,a.min.y,a.min.z),new R(a.min.x,a.max.y,a.min.z),new R(a.max.x,a.max.y,a.min.z),new R(a.min.x,a.min.y,a.max.z),new R(a.max.x,a.min.y,a.max.z),new R(a.min.x,a.max.y,a.max.z),new R(a.max.x,a.max.y,a.max.z)],c=1/0,l=1/0,u=-1/0,d=-1/0;for(let e of s){e.project(o);let r=(e.x+1)/2*t,i=(1-e.y)/2*n;c=Math.min(c,r),l=Math.min(l,i),u=Math.max(u,r),d=Math.max(d,i)}let f=Math.max(0,Math.floor(c-r)),p=Math.max(0,Math.floor(l-r)),m=Math.min(t,Math.ceil(u+r)),h=Math.min(n,Math.ceil(d+r)),g=m-f,_=h-p;return g<=0||_<=0?null:{x:f,y:p,w:g,h:_}}function t_(e,t){if(t.userData.isConstructionPlane||!t.visible)return;let n=t;(n.isMesh||n.isLine||n.isPoints)&&n.geometry&&(n.geometry.computeBoundingBox(),n.geometry.boundingBox&&e.union(n.geometry.boundingBox.clone().applyMatrix4(n.matrixWorld)));for(let n of t.children)t_(e,n)}var n_=class{overlay;pillsContainer;stepSection;stlSection;pngSection;includeColorsToggle;resolutionSelect;customSection;angularInput;linearInput;showGridToggle;showAxesToggle;transparentToggle;autoCropToggle;marginSection;marginInput;widthInput;heightInput;exportBtn;statusEl;shapeIds=[];selectedFormat=`step`;constructor(e,t){this.sceneCtx=t,this.overlay=document.createElement(`div`),this.overlay.className=`fixed inset-0 z-[300] bg-black/50 flex items-center justify-center hidden`,this.overlay.innerHTML=this.buildHTML(),e.appendChild(this.overlay),this.pillsContainer=this.overlay.querySelector(`[data-ref="format-pills"]`),this.stepSection=this.overlay.querySelector(`[data-ref="step-section"]`),this.stlSection=this.overlay.querySelector(`[data-ref="stl-section"]`),this.pngSection=this.overlay.querySelector(`[data-ref="png-section"]`),this.includeColorsToggle=this.overlay.querySelector(`[data-ref="include-colors"]`),this.resolutionSelect=this.overlay.querySelector(`[data-ref="resolution"]`),this.customSection=this.overlay.querySelector(`[data-ref="custom-section"]`),this.angularInput=this.overlay.querySelector(`[data-ref="angular"]`),this.linearInput=this.overlay.querySelector(`[data-ref="linear"]`),this.showGridToggle=this.overlay.querySelector(`[data-ref="show-grid"]`),this.showAxesToggle=this.overlay.querySelector(`[data-ref="show-axes"]`),this.transparentToggle=this.overlay.querySelector(`[data-ref="transparent"]`),this.autoCropToggle=this.overlay.querySelector(`[data-ref="auto-crop"]`),this.marginSection=this.overlay.querySelector(`[data-ref="margin-section"]`),this.marginInput=this.overlay.querySelector(`[data-ref="margin"]`),this.widthInput=this.overlay.querySelector(`[data-ref="png-width"]`),this.heightInput=this.overlay.querySelector(`[data-ref="png-height"]`),this.exportBtn=this.overlay.querySelector(`[data-ref="export-btn"]`),this.statusEl=this.overlay.querySelector(`[data-ref="status"]`),this.bindEvents()}show(e){this.shapeIds=e,this.statusEl.classList.add(`hidden`),this.exportBtn.disabled=!1,this.overlay.classList.remove(`hidden`)}hide(){this.overlay.classList.add(`hidden`)}buildHTML(){return`
5278
5278
  <div class="w-[380px] bg-base-100 border border-base-content/10 rounded-lg p-5 shadow-[0_4px_24px_rgba(0,0,0,0.5)]">
5279
5279
  <div class="flex items-center justify-between mb-4">
5280
5280
  <h3 class="text-sm font-medium text-base-content/90">Export</h3>
5281
5281
  <button data-ref="close-btn" class="btn btn-ghost btn-square btn-xs text-base-content/60">
5282
- <span class="[&>svg]:size-4">${sg}</span>
5282
+ <span class="[&>svg]:size-4">${ug}</span>
5283
5283
  </button>
5284
5284
  </div>
5285
5285
 
@@ -5365,23 +5365,23 @@ void main() {
5365
5365
  <button data-ref="export-btn" class="btn btn-primary btn-sm">Export</button>
5366
5366
  </div>
5367
5367
  </div>
5368
- `}setFormat(e){this.selectedFormat=e,this.stepSection.classList.toggle(`hidden`,e!==`step`),this.stlSection.classList.toggle(`hidden`,e!==`stl`),this.pngSection.classList.toggle(`hidden`,e!==`png`)}bindEvents(){this.overlay.querySelector(`[data-ref="close-btn"]`).addEventListener(`click`,()=>this.hide()),this.overlay.querySelector(`[data-ref="cancel-btn"]`).addEventListener(`click`,()=>this.hide()),this.overlay.addEventListener(`click`,e=>{e.target===this.overlay&&this.hide()}),this.pillsContainer.querySelectorAll(`[data-format]`).forEach(e=>{e.addEventListener(`change`,()=>this.setFormat(e.dataset.format))}),this.resolutionSelect.addEventListener(`change`,()=>{this.customSection.classList.toggle(`hidden`,this.resolutionSelect.value!==`custom`)}),this.autoCropToggle.addEventListener(`change`,()=>{this.marginSection.classList.toggle(`hidden`,!this.autoCropToggle.checked)}),this.exportBtn.addEventListener(`click`,()=>this.onExport())}async onExport(){if(this.selectedFormat===`png`)return this.exportPng();let e=this.selectedFormat,t={format:e,shapeIds:this.shapeIds};e===`step`?t.includeColors=this.includeColorsToggle.checked:(t.resolution=this.resolutionSelect.value,t.resolution===`custom`&&(t.customAngularDeflectionDeg=parseFloat(this.angularInput.value),t.customLinearDeflection=parseFloat(this.linearInput.value))),this.exportBtn.disabled=!0,this.statusEl.classList.remove(`hidden`),this.statusEl.innerHTML=`<span class="loading loading-spinner loading-xs"></span><span>Exporting...</span>`;try{let n=await $m(t),r=e===`step`?`.step`:`.stl`,i=URL.createObjectURL(n),a=document.createElement(`a`);a.href=i,a.download=`export${r}`,a.click(),URL.revokeObjectURL(i),this.hide()}catch(e){this.statusEl.innerHTML=`<span class="text-error text-xs">${e.message}</span>`}finally{this.exportBtn.disabled=!1}}async exportPng(){this.exportBtn.disabled=!0;try{let e=await Gg(this.sceneCtx,{width:Math.max(1,Math.min(8192,parseInt(this.widthInput.value)||800)),height:Math.max(1,Math.min(8192,parseInt(this.heightInput.value)||800)),showGrid:this.showGridToggle.checked,showAxes:this.showAxesToggle.checked,transparent:this.transparentToggle.checked,autoCrop:this.autoCropToggle.checked,margin:this.autoCropToggle.checked?Math.max(0,parseInt(this.marginInput.value)||0):0}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`export.png`,n.click(),URL.revokeObjectURL(t),this.hide()}catch(e){this.statusEl.classList.remove(`hidden`),this.statusEl.innerHTML=`<span class="text-error text-xs">${e.message}</span>`}finally{this.exportBtn.disabled=!1}}},e_=class{element;constructor(e,t){this.element=document.createElement(`div`),this.element.id=`fluidcad-breakpoint-indicator`,this.element.className=`absolute bottom-6 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.element.innerHTML=`
5368
+ `}setFormat(e){this.selectedFormat=e,this.stepSection.classList.toggle(`hidden`,e!==`step`),this.stlSection.classList.toggle(`hidden`,e!==`stl`),this.pngSection.classList.toggle(`hidden`,e!==`png`)}bindEvents(){this.overlay.querySelector(`[data-ref="close-btn"]`).addEventListener(`click`,()=>this.hide()),this.overlay.querySelector(`[data-ref="cancel-btn"]`).addEventListener(`click`,()=>this.hide()),this.overlay.addEventListener(`click`,e=>{e.target===this.overlay&&this.hide()}),this.pillsContainer.querySelectorAll(`[data-format]`).forEach(e=>{e.addEventListener(`change`,()=>this.setFormat(e.dataset.format))}),this.resolutionSelect.addEventListener(`change`,()=>{this.customSection.classList.toggle(`hidden`,this.resolutionSelect.value!==`custom`)}),this.autoCropToggle.addEventListener(`change`,()=>{this.marginSection.classList.toggle(`hidden`,!this.autoCropToggle.checked)}),this.exportBtn.addEventListener(`click`,()=>this.onExport())}async onExport(){if(this.selectedFormat===`png`)return this.exportPng();let e=this.selectedFormat,t={format:e,shapeIds:this.shapeIds};e===`step`?t.includeColors=this.includeColorsToggle.checked:(t.resolution=this.resolutionSelect.value,t.resolution===`custom`&&(t.customAngularDeflectionDeg=parseFloat(this.angularInput.value),t.customLinearDeflection=parseFloat(this.linearInput.value))),this.exportBtn.disabled=!0,this.statusEl.classList.remove(`hidden`),this.statusEl.innerHTML=`<span class="loading loading-spinner loading-xs"></span><span>Exporting...</span>`;try{let n=await nh(t),r=e===`step`?`.step`:`.stl`,i=URL.createObjectURL(n),a=document.createElement(`a`);a.href=i,a.download=`export${r}`,a.click(),URL.revokeObjectURL(i),this.hide()}catch(e){this.statusEl.innerHTML=`<span class="text-error text-xs">${e.message}</span>`}finally{this.exportBtn.disabled=!1}}async exportPng(){this.exportBtn.disabled=!0;try{let e=await Jg(this.sceneCtx,{width:Math.max(1,Math.min(8192,parseInt(this.widthInput.value)||800)),height:Math.max(1,Math.min(8192,parseInt(this.heightInput.value)||800)),showGrid:this.showGridToggle.checked,showAxes:this.showAxesToggle.checked,transparent:this.transparentToggle.checked,autoCrop:this.autoCropToggle.checked,margin:this.autoCropToggle.checked?Math.max(0,parseInt(this.marginInput.value)||0):0}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`export.png`,n.click(),URL.revokeObjectURL(t),this.hide()}catch(e){this.statusEl.classList.remove(`hidden`),this.statusEl.innerHTML=`<span class="text-error text-xs">${e.message}</span>`}finally{this.exportBtn.disabled=!1}}},r_=class{element;constructor(e,t){this.element=document.createElement(`div`),this.element.id=`fluidcad-breakpoint-indicator`,this.element.className=`absolute bottom-6 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.element.innerHTML=`
5369
5369
  <div class="flex items-center gap-3 panel-bg border border-warning/40 rounded-lg px-5 py-2.5 text-sm leading-none select-none">
5370
- <span class="text-warning [&>svg]:size-5">${zh}</span>
5370
+ <span class="text-warning [&>svg]:size-5">${Hh}</span>
5371
5371
  <span class="text-base-content/80">Breakpoint Active</span>
5372
5372
  <div class="h-4 w-px bg-base-content/10"></div>
5373
5373
  <button class="text-base-content/60 hover:text-base-content transition-colors cursor-pointer fluidcad-breakpoint-continue">
5374
5374
  Continue
5375
5375
  </button>
5376
5376
  </div>
5377
- `,e.appendChild(this.element),this.element.querySelector(`.fluidcad-breakpoint-continue`).addEventListener(`click`,()=>{t?.(),Xm()})}setActive(e){this.element.classList.toggle(`hidden`,!e)}},t_=class{element;messageEl;countEl;toggleEl;listEl;expanded=!1;primaryLoc=null;onGotoSource;constructor(e,t){this.onGotoSource=t,this.element=document.createElement(`div`),this.element.id=`fluidcad-error-banner`,this.element.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1001] pointer-events-auto hidden max-w-[600px]`,this.element.innerHTML=`
5377
+ `,e.appendChild(this.element),this.element.querySelector(`.fluidcad-breakpoint-continue`).addEventListener(`click`,()=>{t?.(),$m()})}setActive(e){this.element.classList.toggle(`hidden`,!e)}},i_=class{element;messageEl;countEl;toggleEl;listEl;expanded=!1;primaryLoc=null;onGotoSource;constructor(e,t){this.onGotoSource=t,this.element=document.createElement(`div`),this.element.id=`fluidcad-error-banner`,this.element.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1001] pointer-events-auto hidden max-w-[600px]`,this.element.innerHTML=`
5378
5378
  <div class="panel-bg border border-error/40 rounded-lg shadow-md overflow-hidden">
5379
5379
  <div class="flex items-start gap-3 px-5 py-2.5 text-sm select-none">
5380
- <span class="text-error shrink-0 mt-0.5 [&>svg]:size-5">${Bh}</span>
5380
+ <span class="text-error shrink-0 mt-0.5 [&>svg]:size-5">${Uh}</span>
5381
5381
  <span data-ref="message" class="text-base-content/90 whitespace-pre-line break-words cursor-pointer hover:underline grow min-w-0"></span>
5382
5382
  <span data-ref="count" class="text-base-content/40 tabular-nums shrink-0 hidden mt-0.5"></span>
5383
5383
  <button data-ref="toggle" class="text-base-content/40 hover:text-base-content/70 shrink-0 hidden cursor-pointer transition-transform mt-0.5" aria-label="Toggle error list">
5384
- ${ng}
5384
+ ${ag}
5385
5385
  </button>
5386
5386
  </div>
5387
5387
  <div data-ref="list" class="hidden border-t border-base-content/10 max-h-[40vh] overflow-y-auto"></div>
@@ -5394,33 +5394,33 @@ void main() {
5394
5394
  <div class="text-base-content/90 break-words whitespace-pre-line">${a}</div>
5395
5395
  </div>
5396
5396
  </div>
5397
- `}this.listEl.innerHTML=t,this.listEl.querySelectorAll(`[data-error-index]`).forEach(t=>{t.addEventListener(`click`,()=>{let n=e[parseInt(t.dataset.errorIndex,10)]?.sourceLocation;n&&this.onGotoSource(n)})})}},n_=class{element;textEl;constructor(e){this.element=document.createElement(`div`),this.element.id=`fluidcad-loading`,this.element.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1000] pointer-events-none`,this.element.innerHTML=`
5397
+ `}this.listEl.innerHTML=t,this.listEl.querySelectorAll(`[data-error-index]`).forEach(t=>{t.addEventListener(`click`,()=>{let n=e[parseInt(t.dataset.errorIndex,10)]?.sourceLocation;n&&this.onGotoSource(n)})})}},a_=class{element;textEl;constructor(e){this.element=document.createElement(`div`),this.element.id=`fluidcad-loading`,this.element.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1000] pointer-events-none`,this.element.innerHTML=`
5398
5398
  <div class="flex items-center gap-3 panel-bg border border-base-content/10 rounded-lg px-6 py-3 text-base-content/70 text-sm leading-none select-none">
5399
5399
  <span class="loading loading-spinner loading-sm"></span>
5400
5400
  <span class="loading-text">Loading FluidCAD...</span>
5401
5401
  </div>
5402
- `,e.appendChild(this.element),this.textEl=this.element.querySelector(`.loading-text`)}show(e){this.textEl.textContent=e,this.element.classList.remove(`hidden`)}hide(){this.element.classList.add(`hidden`)}},r_=class{importToast;fileInput;importToastTimer=null;showLoading;hideLoading;constructor(e,t){this.showLoading=t.showLoading,this.hideLoading=t.hideLoading,this.importToast=document.createElement(`div`),this.importToast.className=`absolute bottom-16 left-6 z-[100] panel-bg border border-base-content/10 rounded-lg px-4 py-3 text-sm text-base-content/80 hidden`,e.appendChild(this.importToast),this.fileInput=document.createElement(`input`),this.fileInput.type=`file`,this.fileInput.accept=`.step,.stp`,this.fileInput.style.display=`none`,e.appendChild(this.fileInput),this.fileInput.addEventListener(`change`,()=>this.handleFileChange())}openPicker(){this.fileInput.click()}showToast(e,t){t?(this.importToast.innerHTML=`
5402
+ `,e.appendChild(this.element),this.textEl=this.element.querySelector(`.loading-text`)}show(e){this.textEl.textContent=e,this.element.classList.remove(`hidden`)}hide(){this.element.classList.add(`hidden`)}},o_=class{importToast;fileInput;importToastTimer=null;showLoading;hideLoading;constructor(e,t){this.showLoading=t.showLoading,this.hideLoading=t.hideLoading,this.importToast=document.createElement(`div`),this.importToast.className=`absolute bottom-16 left-6 z-[100] panel-bg border border-base-content/10 rounded-lg px-4 py-3 text-sm text-base-content/80 hidden`,e.appendChild(this.importToast),this.fileInput=document.createElement(`input`),this.fileInput.type=`file`,this.fileInput.accept=`.step,.stp`,this.fileInput.style.display=`none`,e.appendChild(this.fileInput),this.fileInput.addEventListener(`change`,()=>this.handleFileChange())}openPicker(){this.fileInput.click()}showToast(e,t){t?(this.importToast.innerHTML=`
5403
5403
  <div class="flex items-center gap-2">
5404
5404
  <span>${e} <code class="bg-base-content/10 px-1.5 py-0.5 rounded text-base-content/90">${t}</code></span>
5405
5405
  <button class="btn btn-ghost btn-square btn-xs text-base-content/60 import-toast-copy" title="Copy">
5406
- <span class="[&>svg]:size-3.5">${Ah}</span>
5406
+ <span class="[&>svg]:size-3.5">${Nh}</span>
5407
5407
  </button>
5408
5408
  </div>
5409
- `,this.importToast.querySelector(`.import-toast-copy`).addEventListener(`click`,()=>{navigator.clipboard.writeText(t);let e=this.importToast.querySelector(`.import-toast-copy`);e.setAttribute(`title`,`Copied!`),setTimeout(()=>e.setAttribute(`title`,`Copy`),1500)})):this.importToast.textContent=e,this.importToast.classList.remove(`hidden`),this.importToastTimer&&clearTimeout(this.importToastTimer),this.importToastTimer=setTimeout(()=>{this.importToast.classList.add(`hidden`),this.importToastTimer=null},6e3)}async handleFileChange(){let e=this.fileInput.files?.[0];if(e){this.fileInput.value=``,this.showLoading(`Importing file...`);try{let t=await e.arrayBuffer(),n=new Uint8Array(t),r=``;for(let e=0;e<n.length;e++)r+=String.fromCharCode(n[e]);let i=btoa(r),a=await Qm(e.name,i);a.success?this.showToast(`Imported! Use:`,`load('${a.fileName}')`):this.showToast(`Import failed: ${a.error||`Unknown error`}`)}catch{this.showToast(`Import failed: network error`)}finally{this.hideLoading()}}}},i_=12,a_=class{canvas;ctx;plane;snapManager;onPick;onHighlight;edges=[];highlightedShapeId=null;downX=0;downY=0;boundMouseDown;boundMouseUp;boundMouseMove;constructor(e,t,n,r,i,a,o){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.snapManager=n,this.onPick=a,this.onHighlight=o,this.edges=_p(r,i,t),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}updateEdges(e,t){this.edges=_p(e,t,this.plane),this.highlightedShapeId&&(this.edges.some(e=>e.shapeId===this.highlightedShapeId)||(this.onHighlight(null),this.highlightedShapeId=null))}activate(){this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.highlightedShapeId&&=(this.onHighlight(null),null)}getEdgeEntry(e){return this.edges.find(t=>t.shapeId===e)}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64||!this.highlightedShapeId)return;let r=this.projectToSketch(e.clientX,e.clientY);if(!r)return;let i=this.projectOntoEdge(r,this.highlightedShapeId)??r;this.onPick(Y(i))}handleMouseMove(e){let t=this.projectToSketch(e.clientX,e.clientY);if(!t){this.highlightedShapeId&&=(this.onHighlight(null),null);return}let n=this.computeSketchThreshold(),r=this.findNearestEdge(t,n);if(r!==this.highlightedShapeId){if(r){let e=this.getEdgeEntry(r);this.onHighlight({shapeId:r,endpoints:e?.endpoints??[]})}else this.onHighlight(null);this.highlightedShapeId=r}}computeSketchThreshold(){return Ep(this.ctx,i_)}findNearestEdge(e,t){let n=1/0,r=null;for(let t of this.edges)for(let i of t.segments){let a=bp(e[0],e[1],i.ax,i.ay,i.bx,i.by);a<n&&(n=a,r=t.shapeId)}return n<=t?r:null}projectOntoEdge(e,t){let n=this.edges.find(e=>e.shapeId===t);if(!n)return null;let r=1/0,i=null;for(let t of n.segments){let n=xp(e[0],e[1],t.ax,t.ay,t.bx,t.by);n.dist<r&&(r=n.dist,i=[n.x,n.y])}return i}projectToSketch(e,t){return Sp(this.ctx,this.plane,e,t)}},o_=1e-6,s_=class{vertices2d=[];excluded=[];plane;constructor(e,t){this.vertices2d=e,this.plane=t}setExcluded(e){this.excluded=e}isExcluded(e){for(let t of this.excluded){let n=e[0]-t[0],r=e[1]-t[1];if(n*n+r*r<o_)return!0}return!1}snap(e,t){let n=1/0,r=null;for(let i of this.vertices2d){if(this.isExcluded(i))continue;let a=e[0]-i[0],o=e[1]-i[1],s=Math.sqrt(a*a+o*o);s<t&&s<n&&(n=s,r=i)}return r?{point2d:r,worldPoint:c_(r,this.plane),snapType:`vertex`}:null}};function c_(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}var l_=.35,u_=[1,2,5];function d_(e,t=10,n=15){if(t/e>=n)return t;let r=t;for(;;){for(let t of u_){let i=r*t;if(i/e>=n)return i}r*=10}}var f_=class{spacing;plane;constructor(e,t=10){this.plane=e,this.spacing=t}setSpacing(e){this.spacing=e}snap(e,t){let n=Math.round(e[0]/this.spacing)*this.spacing,r=Math.round(e[1]/this.spacing)*this.spacing,i=e[0]-n,a=e[1]-r;if(Math.sqrt(i*i+a*a)>Math.min(t,this.spacing*l_))return null;let o=[n,r];return{point2d:o,worldPoint:p_(o,this.plane),snapType:`grid`}}};function p_(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}var m_=15,h_=class e{snappers=[];threshold;ctx;constructor(e,t=m_,n=null){this.snappers=e,this.threshold=t,this.ctx=n}setExcludedVertices(e){for(let t of this.snappers)t instanceof s_&&t.setExcluded(e)}snap(e,t){this.ctx&&this.updateGridSpacing();for(let t of this.snappers){let n=t.snap(e,this.threshold);if(n)return n}let n=t.origin,r=t.xDirection,i=t.yDirection;return{point2d:e,worldPoint:new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1]),snapType:`none`}}updateGridSpacing(){let e=this.ctx.camera,t=this.ctx.renderer.domElement.getBoundingClientRect().height||1,n,r=e;if(r.isOrthographicCamera)n=(r.top-r.bottom)/(r.zoom||1);else{let t=new R;this.ctx.cameraControls.getTarget(t);let i=e.position.distanceTo(t),a=r.fov*Math.PI/180;n=2*i*Math.tan(a/2)}let i=d_(n/t);for(let e of this.snappers)e instanceof f_&&e.setSpacing(i)}static fromSceneObjects(t,n,r,i){let a=[];for(let e of t)if(!(e.parentId!==n||!e.sceneShapes.length)){for(let t of e.sceneShapes)if(!(t.isMetaShape||t.isGuide))for(let e of t.meshes){if(!e.indices.length)continue;let t=new Map;for(let n of e.indices)t.set(n,(t.get(n)||0)+1);for(let[n,i]of t)if(i===1){let t=e.vertices[n*3],i=e.vertices[n*3+1],o=e.vertices[n*3+2],s=t-r.origin.x,c=i-r.origin.y,l=o-r.origin.z,u=s*r.xDirection.x+c*r.xDirection.y+l*r.xDirection.z,d=s*r.yDirection.x+c*r.yDirection.y+l*r.yDirection.z;a.some(e=>(e[0]-u)*(e[0]-u)+(e[1]-d)*(e[1]-d)<1e-6)||a.push([u,d])}}}return new e([new s_(a,r),new f_(r)],m_,i??null)}};function g_(e,t){return e.parentId?t.find(t=>t.id===e.parentId)?.type===`part`:!0}var __=16762232,v_=1e-4,y_=class{viewer;triggerBtn;activeBar;_state=`idle`;_lastPickInfo=null;lastSceneObjects=null;activePointPickMode=null;activePickSourceLine=null;_pendingActivation=!1;highlightedVertexDots=[];constructor(e,t){this.viewer=t,this.triggerBtn=document.createElement(`div`),this.triggerBtn.id=`fluidcad-trim-pick-trigger`,this.triggerBtn.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.triggerBtn.innerHTML=`
5409
+ `,this.importToast.querySelector(`.import-toast-copy`).addEventListener(`click`,()=>{navigator.clipboard.writeText(t);let e=this.importToast.querySelector(`.import-toast-copy`);e.setAttribute(`title`,`Copied!`),setTimeout(()=>e.setAttribute(`title`,`Copy`),1500)})):this.importToast.textContent=e,this.importToast.classList.remove(`hidden`),this.importToastTimer&&clearTimeout(this.importToastTimer),this.importToastTimer=setTimeout(()=>{this.importToast.classList.add(`hidden`),this.importToastTimer=null},6e3)}async handleFileChange(){let e=this.fileInput.files?.[0];if(e){this.fileInput.value=``,this.showLoading(`Importing file...`);try{let t=await e.arrayBuffer(),n=new Uint8Array(t),r=``;for(let e=0;e<n.length;e++)r+=String.fromCharCode(n[e]);let i=btoa(r),a=await th(e.name,i);a.success?this.showToast(`Imported! Use:`,`load('${a.fileName}')`):this.showToast(`Import failed: ${a.error||`Unknown error`}`)}catch{this.showToast(`Import failed: network error`)}finally{this.hideLoading()}}}},s_=12,c_=class{canvas;ctx;plane;snapManager;onPick;onHighlight;edges=[];highlightedShapeId=null;downX=0;downY=0;boundMouseDown;boundMouseUp;boundMouseMove;constructor(e,t,n,r,i,a,o){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.snapManager=n,this.onPick=a,this.onHighlight=o,this.edges=bp(r,i,t),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}updateEdges(e,t){this.edges=bp(e,t,this.plane),this.highlightedShapeId&&(this.edges.some(e=>e.shapeId===this.highlightedShapeId)||(this.onHighlight(null),this.highlightedShapeId=null))}activate(){this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.highlightedShapeId&&=(this.onHighlight(null),null)}getEdgeEntry(e){return this.edges.find(t=>t.shapeId===e)}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64||!this.highlightedShapeId)return;let r=this.projectToSketch(e.clientX,e.clientY);if(!r)return;let i=this.projectOntoEdge(r,this.highlightedShapeId)??r;this.onPick(Y(i))}handleMouseMove(e){let t=this.projectToSketch(e.clientX,e.clientY);if(!t){this.highlightedShapeId&&=(this.onHighlight(null),null);return}let n=this.computeSketchThreshold(),r=this.findNearestEdge(t,n);if(r!==this.highlightedShapeId){if(r){let e=this.getEdgeEntry(r);this.onHighlight({shapeId:r,endpoints:e?.endpoints??[]})}else this.onHighlight(null);this.highlightedShapeId=r}}computeSketchThreshold(){return kp(this.ctx,s_)}findNearestEdge(e,t){let n=1/0,r=null;for(let t of this.edges)for(let i of t.segments){let a=Cp(e[0],e[1],i.ax,i.ay,i.bx,i.by);a<n&&(n=a,r=t.shapeId)}return n<=t?r:null}projectOntoEdge(e,t){let n=this.edges.find(e=>e.shapeId===t);if(!n)return null;let r=1/0,i=null;for(let t of n.segments){let n=wp(e[0],e[1],t.ax,t.ay,t.bx,t.by);n.dist<r&&(r=n.dist,i=[n.x,n.y])}return i}projectToSketch(e,t){return Tp(this.ctx,this.plane,e,t)}},l_=1e-6,u_=class{vertices2d=[];excluded=[];plane;constructor(e,t){this.vertices2d=e,this.plane=t}setExcluded(e){this.excluded=e}isExcluded(e){for(let t of this.excluded){let n=e[0]-t[0],r=e[1]-t[1];if(n*n+r*r<l_)return!0}return!1}snap(e,t){let n=1/0,r=null;for(let i of this.vertices2d){if(this.isExcluded(i))continue;let a=e[0]-i[0],o=e[1]-i[1],s=Math.sqrt(a*a+o*o);s<t&&s<n&&(n=s,r=i)}return r?{point2d:r,worldPoint:d_(r,this.plane),snapType:`vertex`}:null}};function d_(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}var f_=.35,p_=[1,2,5];function m_(e,t=10,n=15){if(t/e>=n)return t;let r=t;for(;;){for(let t of p_){let i=r*t;if(i/e>=n)return i}r*=10}}var h_=class{spacing;plane;constructor(e,t=10){this.plane=e,this.spacing=t}setSpacing(e){this.spacing=e}snap(e,t){let n=Math.round(e[0]/this.spacing)*this.spacing,r=Math.round(e[1]/this.spacing)*this.spacing,i=e[0]-n,a=e[1]-r;if(Math.sqrt(i*i+a*a)>Math.min(t,this.spacing*f_))return null;let o=[n,r];return{point2d:o,worldPoint:g_(o,this.plane),snapType:`grid`}}};function g_(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1])}var __=15,v_=class e{snappers=[];threshold;ctx;constructor(e,t=__,n=null){this.snappers=e,this.threshold=t,this.ctx=n}setExcludedVertices(e){for(let t of this.snappers)t instanceof u_&&t.setExcluded(e)}snap(e,t){this.ctx&&this.updateGridSpacing();for(let t of this.snappers){let n=t.snap(e,this.threshold);if(n)return n}let n=t.origin,r=t.xDirection,i=t.yDirection;return{point2d:e,worldPoint:new R(n.x+r.x*e[0]+i.x*e[1],n.y+r.y*e[0]+i.y*e[1],n.z+r.z*e[0]+i.z*e[1]),snapType:`none`}}updateGridSpacing(){let e=this.ctx.camera,t=this.ctx.renderer.domElement.getBoundingClientRect().height||1,n,r=e;if(r.isOrthographicCamera)n=(r.top-r.bottom)/(r.zoom||1);else{let t=new R;this.ctx.cameraControls.getTarget(t);let i=e.position.distanceTo(t),a=r.fov*Math.PI/180;n=2*i*Math.tan(a/2)}let i=m_(n/t);for(let e of this.snappers)e instanceof h_&&e.setSpacing(i)}static fromSceneObjects(t,n,r,i){let a=[];for(let e of t)if(!(e.parentId!==n||!e.sceneShapes.length)){for(let t of e.sceneShapes)if(!(t.isMetaShape||t.isGuide))for(let e of t.meshes){if(!e.indices.length)continue;let t=new Map;for(let n of e.indices)t.set(n,(t.get(n)||0)+1);for(let[n,i]of t)if(i===1){let t=e.vertices[n*3],i=e.vertices[n*3+1],o=e.vertices[n*3+2],s=t-r.origin.x,c=i-r.origin.y,l=o-r.origin.z,u=s*r.xDirection.x+c*r.xDirection.y+l*r.xDirection.z,d=s*r.yDirection.x+c*r.yDirection.y+l*r.yDirection.z;a.some(e=>(e[0]-u)*(e[0]-u)+(e[1]-d)*(e[1]-d)<1e-6)||a.push([u,d])}}}return new e([new u_(a,r),new h_(r)],__,i??null)}};function y_(e,t){return e.parentId?t.find(t=>t.id===e.parentId)?.type===`part`:!0}var b_=16762232,x_=1e-4,S_=class{viewer;triggerBtn;activeBar;_state=`idle`;_lastPickInfo=null;lastSceneObjects=null;activePointPickMode=null;activePickSourceLine=null;_pendingActivation=!1;highlightedVertexDots=[];constructor(e,t){this.viewer=t,this.triggerBtn=document.createElement(`div`),this.triggerBtn.id=`fluidcad-trim-pick-trigger`,this.triggerBtn.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.triggerBtn.innerHTML=`
5410
5410
  <button class="flex items-center gap-3 panel-bg border border-base-content/10 rounded-lg px-6 py-3 text-base-content/70 text-sm leading-none select-none cursor-pointer hover:border-base-content/20 transition-colors">
5411
- <span class="[&>svg]:size-5">${kh}</span>
5411
+ <span class="[&>svg]:size-5">${Mh}</span>
5412
5412
  <span>Interactive Trimming</span>
5413
5413
  </button>
5414
5414
  `,e.appendChild(this.triggerBtn),this.activeBar=document.createElement(`div`),this.activeBar.id=`fluidcad-trim-pick-active`,this.activeBar.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.activeBar.innerHTML=`
5415
5415
  <div class="flex items-center gap-3 panel-bg border border-base-content/10 rounded-lg px-6 py-3 text-base-content/70 text-sm leading-none select-none">
5416
- <span class="[&>svg]:size-5">${kh}</span>
5416
+ <span class="[&>svg]:size-5">${Mh}</span>
5417
5417
  <span>Trimming Mode</span>
5418
5418
  <div class="h-4 w-px bg-base-content/10"></div>
5419
5419
  <button class="text-base-content/60 hover:text-base-content transition-colors cursor-pointer" id="exit-trim-pick">Exit</button>
5420
5420
  </div>
5421
- `,e.appendChild(this.activeBar),this.triggerBtn.querySelector(`button`).addEventListener(`click`,()=>{this.enter()}),this.activeBar.querySelector(`#exit-trim-pick`).addEventListener(`click`,()=>{this.exit()})}get state(){return this._state}get lastPickInfo(){return this._lastPickInfo}get pendingActivation(){return this._pendingActivation}set pendingActivation(e){this._pendingActivation=e}update(e){let t=this.hasTrimPickingTrigger(e);if(!t.hasTrigger){this._pendingActivation||this.reset();return}this._lastPickInfo={trimObj:t.trimObj,sketchObj:t.sketchObj},this.lastSceneObjects=e;let n=t.trimObj.object?.picking;if(this._pendingActivation){this._pendingActivation=!1,this.enter(),this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`);return}if(this._state===`picking-active`){if(n){let n=this._lastPickInfo.trimObj.sourceLocation.line;if(this.activePointPickMode&&this.activePickSourceLine===n){this.activePointPickMode.updateEdges(e,t.sketchObj.id);return}this.activateInteractive(this._lastPickInfo,e)}return}this._state=`icon-visible`,this.triggerBtn.classList.remove(`hidden`),this.activeBar.classList.add(`hidden`)}enter(){if(this._lastPickInfo){if(!this._lastPickInfo.trimObj.object?.picking){Mm(this._lastPickInfo.trimObj.sourceLocation),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isTrimming=!0;return}this.lastSceneObjects&&this.activateInteractive(this._lastPickInfo,this.lastSceneObjects),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isTrimming=!0}}exit(){this.deactivateHandler(),this.viewer.isTrimming=!1;let e=this._lastPickInfo?.trimObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Nm(e.sourceLocation),this._lastPickInfo?(this._state=`icon-visible`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.remove(`hidden`)):(this._state=`idle`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`))}reset(){this.deactivateHandler(),this._state=`idle`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.add(`hidden`),this._lastPickInfo=null,this.lastSceneObjects=null,this.viewer.isTrimming=!1}hideBars(){this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`)}activateInteractive(e,t){this.deactivateHandler();let n=e.sketchObj.object.plane,r=e.trimObj.sourceLocation,i=e.sketchObj.id,a=h_.fromSceneObjects(t,i,n,this.viewer.sceneContext);this.activePointPickMode=new a_(this.viewer.sceneContext,n,a,t,i,e=>{Am(e,r)},e=>{this.viewer.clearHighlight(),this.clearVertexHighlights(),e&&(this.viewer.highlightShape(e.shapeId),this.highlightVerticesAt(e.endpoints))}),this.activePickSourceLine=r.line,this.activePointPickMode.activate()}deactivateHandler(){this.activePointPickMode&&(this.activePointPickMode.deactivate(),this.activePointPickMode=null,this.activePickSourceLine=null),this.clearVertexHighlights()}highlightVerticesAt(e){this.clearVertexHighlights(),e.length!==0&&(this.viewer.sceneContext.scene.traverse(t=>{if(!t.userData.isVertexDot)return;let n=t.children[0];if(!n||!n.isMesh)return;let r=t.position;for(let t of e){let e=r.x-t[0],i=r.y-t[1],a=r.z-t[2];if(e*e+i*i+a*a<v_){let e=n.material,t=e.clone();t.color.setHex(__),n.material=t,this.highlightedVertexDots.push({mesh:n,originalMaterial:e});break}}}),this.viewer.sceneContext.requestRender())}clearVertexHighlights(){for(let{mesh:e,originalMaterial:t}of this.highlightedVertexDots)e.material.dispose(),e.material=t;this.highlightedVertexDots.length>0&&(this.highlightedVertexDots.length=0,this.viewer.sceneContext.requestRender())}hasTrimPickingTrigger(e){let t=null;for(let n=e.length-1;n>=0;n--)if(g_(e[n],e)){t=e[n];break}if(!t||t.type!==`sketch`||!t.id||!t.object?.plane)return{hasTrigger:!1};let n=null;for(let r=e.length-1;r>=0;r--)if(e[r].parentId===t.id){n=e[r];break}let r=n;return!r||r.type!==`trim2d`||r.object?.trigger!==`trim-picking`||!r.sourceLocation?{hasTrigger:!1}:{hasTrigger:!0,trimObj:n,sketchObj:t}}},b_=`#64B5F6`,x_=.35,S_=class{canvas;ctx;plane;onPick;onRemove;onHighlight;highlightedMesh=null;highlightedOriginalColor=null;highlightedOriginalOpacity=null;downX=0;downY=0;boundMouseDown;boundMouseUp;boundMouseMove;constructor(e,t,n,r,i){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.onPick=n,this.onRemove=r,this.onHighlight=i,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}activate(){this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.restoreHighlight()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=this.projectToSketch(e.clientX,e.clientY);if(!r)return;let i=this.raycastRegions(e.clientX,e.clientY);if(!i)return;let a=i.mesh.parent;if(a?.userData.isPickRegionSelected===!0){let e=this.collectSelectedPickPoints(a);this.onRemove(e)}else{let e=[Math.round(r[0]*100)/100,Math.round(r[1]*100)/100];this.onPick(e)}}collectSelectedPickPoints(e){let t=[];return this.ctx.scene.traverse(n=>{n!==e&&n.userData.isPickRegion&&n.userData.isPickRegionSelected&&n.userData.metaData?.pickPoint&&t.push(n.userData.metaData.pickPoint)}),t}handleMouseMove(e){let t=this.raycastRegions(e.clientX,e.clientY)?.mesh??null;if(t!==this.highlightedMesh)if(this.restoreHighlight(),t){let e=t.material;this.highlightedOriginalColor=e.color.getHex(),this.highlightedOriginalOpacity=e.opacity,e.color.set(b_),e.opacity=x_,this.highlightedMesh=t;let n=null,r=t;for(;r;){if(r.userData.shapeId){n=r.userData.shapeId;break}r=r.parent}this.onHighlight(n),this.ctx.requestRender()}else this.highlightedMesh=null,this.onHighlight(null),this.ctx.requestRender()}restoreHighlight(){if(this.highlightedMesh){let e=this.highlightedMesh.material;this.highlightedOriginalColor!==null&&e.color.setHex(this.highlightedOriginalColor),this.highlightedOriginalOpacity!==null&&(e.opacity=this.highlightedOriginalOpacity),this.highlightedMesh=null,this.highlightedOriginalColor=null,this.highlightedOriginalOpacity=null}}raycastRegions(e,t){let n=this.ctx.renderer.domElement.getBoundingClientRect(),r=(e-n.left)/n.width*2-1,i=-((t-n.top)/n.height)*2+1,a=this.ctx.createPickingRaycaster(r,i),o=[];if(this.ctx.scene.traverse(e=>{if(e.userData.isPickRegion&&e.children)for(let t of e.children)t.isMesh&&o.push(t)}),o.length===0)return null;let s=a.intersectObjects(o,!1);return s.length===0?null:{mesh:s[0].object,point:s[0].point}}projectToSketch(e,t){let n=this.ctx.renderer.domElement.getBoundingClientRect(),r=(e-n.left)/n.width*2-1,i=-((t-n.top)/n.height)*2+1,a=this.ctx.createPickingRaycaster(r,i),o=a.ray.origin,s=a.ray.direction,c=new R(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),l=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),u=s.dot(l);if(Math.abs(u)<1e-6)return null;let d=c.clone().sub(o).dot(l)/u;if(d<0)return null;let f=o.clone().add(s.clone().multiplyScalar(d)).clone().sub(c),p=new R(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),m=new R(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[f.dot(p),f.dot(m)]}},C_=[`extrude`,`cut`,`cut-symmetric`,`revolve`,`sweep`,`wrap`],w_=class{viewer;triggerBtn;activeBar;_state=`idle`;lastInfo=null;activeMode=null;activeSourceLine=null;constructor(e,t){this.viewer=t,this.triggerBtn=document.createElement(`div`),this.triggerBtn.id=`fluidcad-region-pick-trigger`,this.triggerBtn.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.triggerBtn.innerHTML=`
5421
+ `,e.appendChild(this.activeBar),this.triggerBtn.querySelector(`button`).addEventListener(`click`,()=>{this.enter()}),this.activeBar.querySelector(`#exit-trim-pick`).addEventListener(`click`,()=>{this.exit()})}get state(){return this._state}get lastPickInfo(){return this._lastPickInfo}get pendingActivation(){return this._pendingActivation}set pendingActivation(e){this._pendingActivation=e}update(e){let t=this.hasTrimPickingTrigger(e);if(!t.hasTrigger){this._pendingActivation||this.reset();return}this._lastPickInfo={trimObj:t.trimObj,sketchObj:t.sketchObj},this.lastSceneObjects=e;let n=t.trimObj.object?.picking;if(this._pendingActivation){this._pendingActivation=!1,this.enter(),this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`);return}if(this._state===`picking-active`){if(n){let n=this._lastPickInfo.trimObj.sourceLocation.line;if(this.activePointPickMode&&this.activePickSourceLine===n){this.activePointPickMode.updateEdges(e,t.sketchObj.id);return}this.activateInteractive(this._lastPickInfo,e)}return}this._state=`icon-visible`,this.triggerBtn.classList.remove(`hidden`),this.activeBar.classList.add(`hidden`)}enter(){if(this._lastPickInfo){if(!this._lastPickInfo.trimObj.object?.picking){Fm(this._lastPickInfo.trimObj.sourceLocation),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isTrimming=!0;return}this.lastSceneObjects&&this.activateInteractive(this._lastPickInfo,this.lastSceneObjects),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isTrimming=!0}}exit(){this.deactivateHandler(),this.viewer.isTrimming=!1;let e=this._lastPickInfo?.trimObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Im(e.sourceLocation),this._lastPickInfo?(this._state=`icon-visible`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.remove(`hidden`)):(this._state=`idle`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`))}reset(){this.deactivateHandler(),this._state=`idle`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.add(`hidden`),this._lastPickInfo=null,this.lastSceneObjects=null,this.viewer.isTrimming=!1}hideBars(){this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`)}activateInteractive(e,t){this.deactivateHandler();let n=e.sketchObj.object.plane,r=e.trimObj.sourceLocation,i=e.sketchObj.id,a=v_.fromSceneObjects(t,i,n,this.viewer.sceneContext);this.activePointPickMode=new c_(this.viewer.sceneContext,n,a,t,i,e=>{Nm(e,r)},e=>{this.viewer.clearHighlight(),this.clearVertexHighlights(),e&&(this.viewer.highlightShape(e.shapeId),this.highlightVerticesAt(e.endpoints))}),this.activePickSourceLine=r.line,this.activePointPickMode.activate()}deactivateHandler(){this.activePointPickMode&&(this.activePointPickMode.deactivate(),this.activePointPickMode=null,this.activePickSourceLine=null),this.clearVertexHighlights()}highlightVerticesAt(e){this.clearVertexHighlights(),e.length!==0&&(this.viewer.sceneContext.scene.traverse(t=>{if(!t.userData.isVertexDot)return;let n=t.children[0];if(!n||!n.isMesh)return;let r=t.position;for(let t of e){let e=r.x-t[0],i=r.y-t[1],a=r.z-t[2];if(e*e+i*i+a*a<x_){let e=n.material,t=e.clone();t.color.setHex(b_),n.material=t,this.highlightedVertexDots.push({mesh:n,originalMaterial:e});break}}}),this.viewer.sceneContext.requestRender())}clearVertexHighlights(){for(let{mesh:e,originalMaterial:t}of this.highlightedVertexDots)e.material.dispose(),e.material=t;this.highlightedVertexDots.length>0&&(this.highlightedVertexDots.length=0,this.viewer.sceneContext.requestRender())}hasTrimPickingTrigger(e){let t=null;for(let n=e.length-1;n>=0;n--)if(y_(e[n],e)){t=e[n];break}if(!t||t.type!==`sketch`||!t.id||!t.object?.plane)return{hasTrigger:!1};let n=null;for(let r=e.length-1;r>=0;r--)if(e[r].parentId===t.id){n=e[r];break}let r=n;return!r||r.type!==`trim2d`||r.object?.trigger!==`trim-picking`||!r.sourceLocation?{hasTrigger:!1}:{hasTrigger:!0,trimObj:n,sketchObj:t}}},C_=`#64B5F6`,w_=.35,T_=class{canvas;ctx;plane;onPick;onRemove;onHighlight;highlightedMesh=null;highlightedOriginalColor=null;highlightedOriginalOpacity=null;downX=0;downY=0;boundMouseDown;boundMouseUp;boundMouseMove;constructor(e,t,n,r,i){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.onPick=n,this.onRemove=r,this.onHighlight=i,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}activate(){this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.restoreHighlight()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=this.projectToSketch(e.clientX,e.clientY);if(!r)return;let i=this.raycastRegions(e.clientX,e.clientY);if(!i)return;let a=i.mesh.parent;if(a?.userData.isPickRegionSelected===!0){let e=this.collectSelectedPickPoints(a);this.onRemove(e)}else{let e=[Math.round(r[0]*100)/100,Math.round(r[1]*100)/100];this.onPick(e)}}collectSelectedPickPoints(e){let t=[];return this.ctx.scene.traverse(n=>{n!==e&&n.userData.isPickRegion&&n.userData.isPickRegionSelected&&n.userData.metaData?.pickPoint&&t.push(n.userData.metaData.pickPoint)}),t}handleMouseMove(e){let t=this.raycastRegions(e.clientX,e.clientY)?.mesh??null;if(t!==this.highlightedMesh)if(this.restoreHighlight(),t){let e=t.material;this.highlightedOriginalColor=e.color.getHex(),this.highlightedOriginalOpacity=e.opacity,e.color.set(C_),e.opacity=w_,this.highlightedMesh=t;let n=null,r=t;for(;r;){if(r.userData.shapeId){n=r.userData.shapeId;break}r=r.parent}this.onHighlight(n),this.ctx.requestRender()}else this.highlightedMesh=null,this.onHighlight(null),this.ctx.requestRender()}restoreHighlight(){if(this.highlightedMesh){let e=this.highlightedMesh.material;this.highlightedOriginalColor!==null&&e.color.setHex(this.highlightedOriginalColor),this.highlightedOriginalOpacity!==null&&(e.opacity=this.highlightedOriginalOpacity),this.highlightedMesh=null,this.highlightedOriginalColor=null,this.highlightedOriginalOpacity=null}}raycastRegions(e,t){let n=this.ctx.renderer.domElement.getBoundingClientRect(),r=(e-n.left)/n.width*2-1,i=-((t-n.top)/n.height)*2+1,a=this.ctx.createPickingRaycaster(r,i),o=[];if(this.ctx.scene.traverse(e=>{if(e.userData.isPickRegion&&e.children)for(let t of e.children)t.isMesh&&o.push(t)}),o.length===0)return null;let s=a.intersectObjects(o,!1);return s.length===0?null:{mesh:s[0].object,point:s[0].point}}projectToSketch(e,t){let n=this.ctx.renderer.domElement.getBoundingClientRect(),r=(e-n.left)/n.width*2-1,i=-((t-n.top)/n.height)*2+1,a=this.ctx.createPickingRaycaster(r,i),o=a.ray.origin,s=a.ray.direction,c=new R(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),l=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),u=s.dot(l);if(Math.abs(u)<1e-6)return null;let d=c.clone().sub(o).dot(l)/u;if(d<0)return null;let f=o.clone().add(s.clone().multiplyScalar(d)).clone().sub(c),p=new R(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),m=new R(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[f.dot(p),f.dot(m)]}},E_=[`extrude`,`cut`,`cut-symmetric`,`revolve`,`sweep`,`wrap`],D_=class{viewer;triggerBtn;activeBar;_state=`idle`;lastInfo=null;activeMode=null;activeSourceLine=null;constructor(e,t){this.viewer=t,this.triggerBtn=document.createElement(`div`),this.triggerBtn.id=`fluidcad-region-pick-trigger`,this.triggerBtn.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.triggerBtn.innerHTML=`
5422
5422
  <button class="flex items-center gap-3 panel-bg border border-base-content/10 rounded-lg px-6 py-3 text-base-content/70 text-sm leading-none select-none cursor-pointer hover:border-base-content/20 transition-colors">
5423
- <span class="[&>svg]:size-5">${Nh}</span>
5423
+ <span class="[&>svg]:size-5">${Ih}</span>
5424
5424
  <span>Pick Regions</span>
5425
5425
  </button>
5426
5426
  `,e.appendChild(this.triggerBtn),this.activeBar=document.createElement(`div`),this.activeBar.id=`fluidcad-region-pick-active`,this.activeBar.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,this.activeBar.innerHTML=`
@@ -5429,20 +5429,20 @@ void main() {
5429
5429
  <div class="h-4 w-px bg-base-content/10"></div>
5430
5430
  <button class="text-base-content/60 hover:text-base-content transition-colors cursor-pointer" id="exit-region-pick">Exit</button>
5431
5431
  </div>
5432
- `,e.appendChild(this.activeBar),this.triggerBtn.querySelector(`button`).addEventListener(`click`,()=>{this.enter()}),this.activeBar.querySelector(`#exit-region-pick`).addEventListener(`click`,()=>{this.exit()})}get state(){return this._state}update(e){let t=this.hasRegionPickingTrigger(e),n=t.extrudeObj?.object?.pickPlane||t.sketchObj?.object?.plane;if(!t.hasTrigger||!t.extrudeObj?.sourceLocation||!n){this.reset();return}this.lastInfo={extrudeObj:t.extrudeObj,sketchObj:t.sketchObj};let r=t.extrudeObj.object?.picking;if(this._state===`picking-active`){if(r){let e=this.lastInfo.extrudeObj.sourceLocation.line;if(this.activeMode&&this.activeSourceLine===e)return;this.activateInteractive(this.lastInfo)}return}this._state=`icon-visible`,this.triggerBtn.classList.remove(`hidden`),this.activeBar.classList.add(`hidden`)}enter(){if(this.lastInfo){if(!this.lastInfo.extrudeObj.object?.picking){Mm(this.lastInfo.extrudeObj.sourceLocation),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isRegionPicking=!0,this.viewer.toggleSketchMode(!1);return}this.activateInteractive(this.lastInfo),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isRegionPicking=!0,this.viewer.toggleSketchMode(!1),this.viewer.rebuildSceneMesh()}}exit(){this.deactivateHandler(),this.viewer.isRegionPicking=!1,this.viewer.toggleSketchMode(!0),this.viewer.rebuildSceneMesh();let e=this.lastInfo?.extrudeObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Nm(e.sourceLocation),this.lastInfo?(this._state=`icon-visible`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.remove(`hidden`)):(this._state=`idle`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`))}reset(){this.deactivateHandler(),this._state=`idle`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.add(`hidden`),this.lastInfo=null,this.viewer.isRegionPicking=!1,this.viewer.toggleSketchMode(!0)}activateInteractive(e){this.deactivateHandler();let t=e.extrudeObj.object?.pickPlane??e.sketchObj.object.plane,n=e.extrudeObj.sourceLocation;this.activeMode=new S_(this.viewer.sceneContext,t,e=>{Am(e,n)},e=>{jm(e,n)},e=>{}),this.activeSourceLine=n.line,this.activeMode.activate()}deactivateHandler(){this.activeMode&&(this.activeMode.deactivate(),this.activeMode=null,this.activeSourceLine=null)}hasRegionPickingTrigger(e){let t=[`plane`,`axis`],n;for(let r=e.length-1;r>=0;r--){let i=e[r];if(!i.parentId&&!t.includes(i.type)){n=i;break}}if(!n)return{hasTrigger:!1};let r=n;if(!C_.includes(r.type)||r.object?.trigger!==`region-picking`||r.object?.thin)return{hasTrigger:!1};let i=e.indexOf(n),a;for(let t=i-1;t>=0;t--)if(e[t].type===`sketch`&&e[t].parentId===r.parentId){a=e[t];break}return{hasTrigger:!0,extrudeObj:n,sketchObj:a}}},T_=/^F([1-9]|1[0-9])$/;function E_(e){return!1}function D_(e){if(!(e instanceof Element))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`?!0:e instanceof HTMLElement&&e.isContentEditable}function O_(e){return!(e.defaultPrevented||E_(e)||e.key===`Control`||e.key===`Alt`||e.key===`Meta`||e.key===`Shift`||D_(e.target)||!(e.ctrlKey||e.metaKey||e.altKey)&&!T_.test(e.key))}function k_(){window.parent!==window&&window.addEventListener(`keydown`,e=>{O_(e)&&window.parent.postMessage({type:`fluidcad-keydown`,key:e.key,code:e.code,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,repeat:e.repeat},`*`)},!1)}function A_(){return{children:new Map,action:null}}var j_=class{root=A_();buffer=``;timerId=null;pendingAction=null;enabled=!1;timeout;boundHandler;constructor(e){this.timeout=e?.timeout??300,this.boundHandler=this.handleKeyDown.bind(this)}register(e,t){let n=this.root;for(let t of e){let e=n.children.get(t);e||(e=A_(),n.children.set(t,e)),n=e}n.action=t}enable(){this.enabled||(this.enabled=!0,this.resetState(),window.addEventListener(`keydown`,this.boundHandler))}disable(){if(this.enabled){if(this.enabled=!1,this.pendingAction){let e=this.pendingAction;this.resetState(),e()}else this.resetState();window.removeEventListener(`keydown`,this.boundHandler)}}destroy(){this.disable(),this.root=A_()}handleKeyDown(e){if(e.repeat)return;if(e.ctrlKey||e.metaKey||e.altKey){this.firePendingAndReset();return}if(D_(e.target))return;let t=e.key.toLowerCase();if(t===`escape`){this.resetState();return}if(t.length!==1||t<`a`||t>`z`){this.firePendingAndReset();return}this.clearTimer();let n=this.buffer+t,{exactMatch:r,hasLongerPrefix:i}=this.lookupTrie(n);if(r&&!i){e.preventDefault();let t=r;this.resetState(),t()}else if(r&&i)e.preventDefault(),this.buffer=n,this.pendingAction=r,this.startTimer();else if(i)e.preventDefault(),this.buffer=n,this.startTimer();else if(this.pendingAction){e.preventDefault();let t=this.pendingAction;this.resetState(),t()}else this.resetState()}lookupTrie(e){let t=this.root;for(let n of e){let e=t.children.get(n);if(!e)return{exactMatch:null,hasLongerPrefix:!1};t=e}return{exactMatch:t.action,hasLongerPrefix:t.children.size>0}}firePendingAndReset(){if(this.pendingAction){let e=this.pendingAction;this.resetState(),e()}else this.resetState()}resetState(){this.clearTimer(),this.buffer=``,this.pendingAction=null}clearTimer(){this.timerId!==null&&(clearTimeout(this.timerId),this.timerId=null)}startTimer(){this.clearTimer(),this.timerId=setTimeout(()=>{this.timerId=null,this.firePendingAndReset()},this.timeout)}};function M_(e){return`tools`in e}var N_=[{tools:[{id:`line`,label:`Line`,icon:Gh},{id:`polyline`,label:`Polyline`,icon:$h},{id:`bezier`,label:`Bezier`,icon:eg}]},{tools:[{id:`circle`,label:`Circle`,icon:Kh},{id:`polygon`,label:`Polygon`,icon:Qh}]},{tools:[{id:`rect`,label:`Rectangle`,icon:Yh},{id:`rounded-rect`,label:`Rounded Rectangle`,icon:Xh}]},{tools:[{id:`arc3`,label:`3-Point Arc`,icon:Jh},{id:`arc2`,label:`Center Arc`,icon:qh}]},{tools:[{id:`slot`,label:`Slot`,icon:Zh}]},{tools:[{id:`trim`,label:`Trim`,icon:kh}]}],P_={circle:`c`,rect:`r`,"rounded-rect":`rr`,line:`l`,polygon:`p`,polyline:`ll`,arc3:`a`,arc2:`ca`,bezier:`b`,trim:`t`},F_=`btn btn-ghost btn-square btn-sm text-base-content/60`,I_=`btn btn-soft btn-primary btn-square btn-sm`,L_=class{el;inner;snapMenu=null;onToolSelect;activeToolId=null;buttons=new Map;shortcutManager;boundKeyDown;boundCloseSnapMenu;snapVertexCheckedState=!0;snapGridCheckedState=!0;onSnapVerticesChange=null;onSnapGridChange=null;constructor(e,t){this.onToolSelect=t,this.el=document.createElement(`div`),this.el.className=`absolute top-1/2 -translate-y-1/2 left-0 select-none pointer-events-auto flex flex-col items-center gap-1.5`,this.el.style.transition=`transform 0.25s ease, opacity 0.25s ease`,this.el.style.transform=`translateX(-100%)`,this.el.style.opacity=`0`,this.inner=document.createElement(`div`),this.inner.className=`flex flex-col gap-0.5 panel-bg border border-base-content/10 rounded-md p-1`,this.el.appendChild(this.inner),this.buildSnapButton(),this.renderTools(),e.appendChild(this.el),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundCloseSnapMenu=this.handleCloseSnapMenu.bind(this),this.shortcutManager=new j_({timeout:200});for(let[e,t]of Object.entries(P_))this.shortcutManager.register(t,()=>this.handleToolClick(e))}show(){this.el.style.transform=``,this.el.style.opacity=``,window.addEventListener(`keydown`,this.boundKeyDown),this.shortcutManager.enable()}hide(){this.el.style.transform=`translateX(-100%)`,this.el.style.opacity=`0`,this.closeSnapMenu(),window.removeEventListener(`keydown`,this.boundKeyDown),this.shortcutManager.disable(),this.activeToolId&&this.setActiveTool(null)}get isVisible(){return this.el.style.transform===``}setActiveTool(e){this.activeToolId!==e&&(this.activeToolId=e,this.syncButtonStates())}get activeTool(){return this.activeToolId}get snapVerticesChecked(){return this.snapVertexCheckedState}get snapGridChecked(){return this.snapGridCheckedState}buildSnapButton(){let e=document.createElement(`div`);e.className=`relative`;let t=document.createElement(`button`);t.className=F_,t.innerHTML=`<span class="[&>svg]:size-5">${Hh}</span>`,t.addEventListener(`click`,t=>{t.stopPropagation(),this.snapMenu?this.closeSnapMenu():this.openSnapMenu(e)}),e.appendChild(t),this.el.appendChild(e)}openSnapMenu(e){this.closeSnapMenu();let t=document.createElement(`div`);t.className=`absolute left-full top-1/2 -translate-y-1/2 ml-2 z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)] p-2 flex flex-col gap-2 whitespace-nowrap`;let n=document.createElement(`input`);n.type=`checkbox`,n.className=`checkbox checkbox-xs checkbox-primary`,n.checked=this.snapVertexCheckedState,n.addEventListener(`change`,()=>{this.snapVertexCheckedState=n.checked,this.onSnapVerticesChange?.(n.checked)});let r=document.createElement(`label`);r.className=`flex items-center gap-2 cursor-pointer`,r.appendChild(n);let i=document.createElement(`span`);i.className=`text-xs text-base-content/70`,i.textContent=`Snap to vertices`,r.appendChild(i);let a=document.createElement(`input`);a.type=`checkbox`,a.className=`checkbox checkbox-xs checkbox-primary`,a.checked=this.snapGridCheckedState,a.addEventListener(`change`,()=>{this.snapGridCheckedState=a.checked,this.onSnapGridChange?.(a.checked)});let o=document.createElement(`label`);o.className=`flex items-center gap-2 cursor-pointer`,o.appendChild(a);let s=document.createElement(`span`);s.className=`text-xs text-base-content/70`,s.textContent=`Snap to grid`,o.appendChild(s),t.appendChild(r),t.appendChild(o),e.appendChild(t),this.snapMenu=t,setTimeout(()=>document.addEventListener(`click`,this.boundCloseSnapMenu),0)}closeSnapMenu(){this.snapMenu&&(this.snapMenu.remove(),this.snapMenu=null,document.removeEventListener(`click`,this.boundCloseSnapMenu))}handleCloseSnapMenu(e){this.snapMenu&&!this.snapMenu.contains(e.target)&&!this.snapMenu.parentElement?.contains(e.target)&&this.closeSnapMenu()}renderTools(){this.inner.innerHTML=``,this.buttons.clear();for(let e=0;e<N_.length;e++){if(e>0){let e=document.createElement(`div`);e.className=`h-px bg-base-content/[0.08] my-0.5`,this.inner.appendChild(e)}let t=N_[e];M_(t)?this.renderGroup(t):this.inner.appendChild(this.createToolButton(t))}}renderGroup(e){if(e.tools.length===1){this.inner.appendChild(this.createToolButton(e.tools[0]));return}let t=document.createElement(`div`);t.className=`flex flex-col items-center`;for(let n of e.tools)t.appendChild(this.createToolButton(n));this.inner.appendChild(t)}createToolButton(e){let t=document.createElement(`div`);t.className=`relative group`;let n=document.createElement(`button`);n.className=e.id===this.activeToolId?I_:F_,n.innerHTML=`<span class="[&>svg]:size-5">${e.icon}</span>`,n.addEventListener(`click`,()=>this.handleToolClick(e.id));let r=P_[e.id],i=document.createElement(`div`);return i.className=`absolute left-full top-1/2 -translate-y-1/2 ml-2 px-2 py-1 rounded bg-base-300 text-base-content text-xs whitespace-nowrap opacity-0 pointer-events-none group-hover:opacity-100 transition-opacity flex items-center gap-1.5`,i.innerHTML=r?`${e.label} <kbd class="kbd kbd-xs">${r}</kbd>`:e.label,t.appendChild(n),t.appendChild(i),this.buttons.set(e.id,n),t}syncButtonStates(){for(let[e,t]of this.buttons)t.className=e===this.activeToolId?I_:F_}handleToolClick(e){this.activeToolId===e?this.onToolSelect(null):this.onToolSelect(e)}handleKeyDown(e){e.key===`Escape`&&this.activeToolId&&(e.preventDefault(),e.stopPropagation(),this.onToolSelect(null))}},R_=class{ctx;plane;snapController;previewGroup;insertGeometry;canvas;currentPosition=null;constructor(e,t,n,r){this.ctx=e,this.plane=t,this.snapController=n,this.insertGeometry=r,this.canvas=e.renderer.domElement,this.previewGroup=new oi,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=3}updatePlane(e){this.plane=e}updateSnapManager(e){this.snapController.updateSnapManager(e)}updateCurrentPosition(e){e?this.currentPosition=Tp(e,this.plane):this.currentPosition=null}isAtCurrentPosition(e){if(!this.currentPosition)return!1;let t=Ep(this.ctx,15);return Dp(e,this.currentPosition)<=t}disposePreview(){for(;this.previewGroup.children.length>0;){let e=this.previewGroup.children[0];this.previewGroup.remove(e);let t=e;t.geometry&&t.geometry.dispose(),t.material&&t.material.dispose()}}addPreviewToScene(){this.ctx.scene.add(this.previewGroup)}removePreviewFromScene(){this.ctx.scene.remove(this.previewGroup),this.disposePreview(),this.ctx.requestRender()}requestRender(){this.ctx.requestRender()}formatPoint(e){return`[${e[0]}, ${e[1]}]`}},z_=16,B_=-36,V_=/^[a-zA-Z_$][\w$]*$/,H_=/^([a-zA-Z_$][\w$]*)\s*=\s*(.+?)\s*;?\s*$/,U_=new Set(`const.let.var.if.else.for.while.do.return.function.class.new.this.true.false.null.undefined.typeof.instanceof.switch.case.break.continue.default.try.catch.finally.throw.in.of.delete.void.yield.async.await.import.export.from.as.extends.super.static.enum.interface.implements.package.private.protected.public`.split(`.`));function W_(e){return V_.test(e)&&!U_.has(e)}var G_=class{el;wrapperEl;input;label;dropdown;errorEl;onCommit=null;visible=!1;userIsTyping=!1;variables=[];filteredVars=[];selectedIndex=-1;seedValue=``;errorVisible=!1;numericOnly=!1;onSpaceOverride=null;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute z-[1000] pointer-events-auto hidden`,this.el.innerHTML=`
5432
+ `,e.appendChild(this.activeBar),this.triggerBtn.querySelector(`button`).addEventListener(`click`,()=>{this.enter()}),this.activeBar.querySelector(`#exit-region-pick`).addEventListener(`click`,()=>{this.exit()})}get state(){return this._state}update(e){let t=this.hasRegionPickingTrigger(e),n=t.extrudeObj?.object?.pickPlane||t.sketchObj?.object?.plane;if(!t.hasTrigger||!t.extrudeObj?.sourceLocation||!n){this.reset();return}this.lastInfo={extrudeObj:t.extrudeObj,sketchObj:t.sketchObj};let r=t.extrudeObj.object?.picking;if(this._state===`picking-active`){if(r){let e=this.lastInfo.extrudeObj.sourceLocation.line;if(this.activeMode&&this.activeSourceLine===e)return;this.activateInteractive(this.lastInfo)}return}this._state=`icon-visible`,this.triggerBtn.classList.remove(`hidden`),this.activeBar.classList.add(`hidden`)}enter(){if(this.lastInfo){if(!this.lastInfo.extrudeObj.object?.picking){Fm(this.lastInfo.extrudeObj.sourceLocation),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isRegionPicking=!0,this.viewer.toggleSketchMode(!1);return}this.activateInteractive(this.lastInfo),this._state=`picking-active`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.remove(`hidden`),this.viewer.isRegionPicking=!0,this.viewer.toggleSketchMode(!1),this.viewer.rebuildSceneMesh()}}exit(){this.deactivateHandler(),this.viewer.isRegionPicking=!1,this.viewer.toggleSketchMode(!0),this.viewer.rebuildSceneMesh();let e=this.lastInfo?.extrudeObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Im(e.sourceLocation),this.lastInfo?(this._state=`icon-visible`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.remove(`hidden`)):(this._state=`idle`,this.activeBar.classList.add(`hidden`),this.triggerBtn.classList.add(`hidden`))}reset(){this.deactivateHandler(),this._state=`idle`,this.triggerBtn.classList.add(`hidden`),this.activeBar.classList.add(`hidden`),this.lastInfo=null,this.viewer.isRegionPicking=!1,this.viewer.toggleSketchMode(!0)}activateInteractive(e){this.deactivateHandler();let t=e.extrudeObj.object?.pickPlane??e.sketchObj.object.plane,n=e.extrudeObj.sourceLocation;this.activeMode=new T_(this.viewer.sceneContext,t,e=>{Nm(e,n)},e=>{Pm(e,n)},e=>{}),this.activeSourceLine=n.line,this.activeMode.activate()}deactivateHandler(){this.activeMode&&(this.activeMode.deactivate(),this.activeMode=null,this.activeSourceLine=null)}hasRegionPickingTrigger(e){let t=[`plane`,`axis`],n;for(let r=e.length-1;r>=0;r--){let i=e[r];if(!i.parentId&&!t.includes(i.type)){n=i;break}}if(!n)return{hasTrigger:!1};let r=n;if(!E_.includes(r.type)||r.object?.trigger!==`region-picking`||r.object?.thin)return{hasTrigger:!1};let i=e.indexOf(n),a;for(let t=i-1;t>=0;t--)if(e[t].type===`sketch`&&e[t].parentId===r.parentId){a=e[t];break}return{hasTrigger:!0,extrudeObj:n,sketchObj:a}}},O_=/^F([1-9]|1[0-9])$/;function k_(e){return!1}function A_(e){if(!(e instanceof Element))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`?!0:e instanceof HTMLElement&&e.isContentEditable}function j_(e){return!(e.defaultPrevented||k_(e)||e.key===`Control`||e.key===`Alt`||e.key===`Meta`||e.key===`Shift`||A_(e.target)||!(e.ctrlKey||e.metaKey||e.altKey)&&!O_.test(e.key))}function M_(){window.parent!==window&&window.addEventListener(`keydown`,e=>{j_(e)&&window.parent.postMessage({type:`fluidcad-keydown`,key:e.key,code:e.code,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,repeat:e.repeat},`*`)},!1)}function N_(){return{children:new Map,action:null}}var P_=class{root=N_();buffer=``;timerId=null;pendingAction=null;enabled=!1;timeout;boundHandler;constructor(e){this.timeout=e?.timeout??300,this.boundHandler=this.handleKeyDown.bind(this)}register(e,t){let n=this.root;for(let t of e){let e=n.children.get(t);e||(e=N_(),n.children.set(t,e)),n=e}n.action=t}enable(){this.enabled||(this.enabled=!0,this.resetState(),window.addEventListener(`keydown`,this.boundHandler))}disable(){if(this.enabled){if(this.enabled=!1,this.pendingAction){let e=this.pendingAction;this.resetState(),e()}else this.resetState();window.removeEventListener(`keydown`,this.boundHandler)}}destroy(){this.disable(),this.root=N_()}handleKeyDown(e){if(e.repeat)return;if(e.ctrlKey||e.metaKey||e.altKey){this.firePendingAndReset();return}if(A_(e.target))return;let t=e.key.toLowerCase();if(t===`escape`){this.resetState();return}if(t.length!==1||t<`a`||t>`z`){this.firePendingAndReset();return}this.clearTimer();let n=this.buffer+t,{exactMatch:r,hasLongerPrefix:i}=this.lookupTrie(n);if(r&&!i){e.preventDefault();let t=r;this.resetState(),t()}else if(r&&i)e.preventDefault(),this.buffer=n,this.pendingAction=r,this.startTimer();else if(i)e.preventDefault(),this.buffer=n,this.startTimer();else if(this.pendingAction){e.preventDefault();let t=this.pendingAction;this.resetState(),t()}else this.resetState()}lookupTrie(e){let t=this.root;for(let n of e){let e=t.children.get(n);if(!e)return{exactMatch:null,hasLongerPrefix:!1};t=e}return{exactMatch:t.action,hasLongerPrefix:t.children.size>0}}firePendingAndReset(){if(this.pendingAction){let e=this.pendingAction;this.resetState(),e()}else this.resetState()}resetState(){this.clearTimer(),this.buffer=``,this.pendingAction=null}clearTimer(){this.timerId!==null&&(clearTimeout(this.timerId),this.timerId=null)}startTimer(){this.clearTimer(),this.timerId=setTimeout(()=>{this.timerId=null,this.firePendingAndReset()},this.timeout)}};function F_(e){return`tools`in e}var I_=[{tools:[{id:`line`,label:`Line`,icon:Jh},{id:`polyline`,label:`Polyline`,icon:ng},{id:`bezier`,label:`Bezier`,icon:rg}]},{tools:[{id:`circle`,label:`Circle`,icon:Yh},{id:`polygon`,label:`Polygon`,icon:tg}]},{tools:[{id:`rect`,label:`Rectangle`,icon:Qh},{id:`rounded-rect`,label:`Rounded Rectangle`,icon:$h}]},{tools:[{id:`arc3`,label:`3-Point Arc`,icon:Zh},{id:`arc2`,label:`Center Arc`,icon:Xh}]},{tools:[{id:`slot`,label:`Slot`,icon:eg}]},{tools:[{id:`trim`,label:`Trim`,icon:Mh}]}],L_={circle:`c`,rect:`r`,"rounded-rect":`rr`,line:`l`,polygon:`p`,polyline:`ll`,arc3:`a`,arc2:`ca`,bezier:`b`,trim:`t`},R_=`btn btn-ghost btn-square btn-sm text-base-content/60`,z_=`btn btn-soft btn-primary btn-square btn-sm`,B_=class{el;inner;snapMenu=null;onToolSelect;activeToolId=null;buttons=new Map;shortcutManager;boundKeyDown;boundCloseSnapMenu;snapVertexCheckedState=!0;snapGridCheckedState=!0;onSnapVerticesChange=null;onSnapGridChange=null;constructor(e,t){this.onToolSelect=t,this.el=document.createElement(`div`),this.el.className=`absolute top-1/2 -translate-y-1/2 left-0 select-none pointer-events-auto flex flex-col items-center gap-1.5`,this.el.style.transition=`transform 0.25s ease, opacity 0.25s ease`,this.el.style.transform=`translateX(-100%)`,this.el.style.opacity=`0`,this.inner=document.createElement(`div`),this.inner.className=`flex flex-col gap-0.5 panel-bg border border-base-content/10 rounded-md p-1`,this.el.appendChild(this.inner),this.buildSnapButton(),this.renderTools(),e.appendChild(this.el),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundCloseSnapMenu=this.handleCloseSnapMenu.bind(this),this.shortcutManager=new P_({timeout:200});for(let[e,t]of Object.entries(L_))this.shortcutManager.register(t,()=>this.handleToolClick(e))}show(){this.el.style.transform=``,this.el.style.opacity=``,window.addEventListener(`keydown`,this.boundKeyDown),this.shortcutManager.enable()}hide(){this.el.style.transform=`translateX(-100%)`,this.el.style.opacity=`0`,this.closeSnapMenu(),window.removeEventListener(`keydown`,this.boundKeyDown),this.shortcutManager.disable(),this.activeToolId&&this.setActiveTool(null)}get isVisible(){return this.el.style.transform===``}setActiveTool(e){this.activeToolId!==e&&(this.activeToolId=e,this.syncButtonStates())}get activeTool(){return this.activeToolId}get snapVerticesChecked(){return this.snapVertexCheckedState}get snapGridChecked(){return this.snapGridCheckedState}buildSnapButton(){let e=document.createElement(`div`);e.className=`relative`;let t=document.createElement(`button`);t.className=R_,t.innerHTML=`<span class="[&>svg]:size-5">${Gh}</span>`,t.addEventListener(`click`,t=>{t.stopPropagation(),this.snapMenu?this.closeSnapMenu():this.openSnapMenu(e)}),e.appendChild(t),this.el.appendChild(e)}openSnapMenu(e){this.closeSnapMenu();let t=document.createElement(`div`);t.className=`absolute left-full top-1/2 -translate-y-1/2 ml-2 z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)] p-2 flex flex-col gap-2 whitespace-nowrap`;let n=document.createElement(`input`);n.type=`checkbox`,n.className=`checkbox checkbox-xs checkbox-primary`,n.checked=this.snapVertexCheckedState,n.addEventListener(`change`,()=>{this.snapVertexCheckedState=n.checked,this.onSnapVerticesChange?.(n.checked)});let r=document.createElement(`label`);r.className=`flex items-center gap-2 cursor-pointer`,r.appendChild(n);let i=document.createElement(`span`);i.className=`text-xs text-base-content/70`,i.textContent=`Snap to vertices`,r.appendChild(i);let a=document.createElement(`input`);a.type=`checkbox`,a.className=`checkbox checkbox-xs checkbox-primary`,a.checked=this.snapGridCheckedState,a.addEventListener(`change`,()=>{this.snapGridCheckedState=a.checked,this.onSnapGridChange?.(a.checked)});let o=document.createElement(`label`);o.className=`flex items-center gap-2 cursor-pointer`,o.appendChild(a);let s=document.createElement(`span`);s.className=`text-xs text-base-content/70`,s.textContent=`Snap to grid`,o.appendChild(s),t.appendChild(r),t.appendChild(o),e.appendChild(t),this.snapMenu=t,setTimeout(()=>document.addEventListener(`click`,this.boundCloseSnapMenu),0)}closeSnapMenu(){this.snapMenu&&(this.snapMenu.remove(),this.snapMenu=null,document.removeEventListener(`click`,this.boundCloseSnapMenu))}handleCloseSnapMenu(e){this.snapMenu&&!this.snapMenu.contains(e.target)&&!this.snapMenu.parentElement?.contains(e.target)&&this.closeSnapMenu()}renderTools(){this.inner.innerHTML=``,this.buttons.clear();for(let e=0;e<I_.length;e++){if(e>0){let e=document.createElement(`div`);e.className=`h-px bg-base-content/[0.08] my-0.5`,this.inner.appendChild(e)}let t=I_[e];F_(t)?this.renderGroup(t):this.inner.appendChild(this.createToolButton(t))}}renderGroup(e){if(e.tools.length===1){this.inner.appendChild(this.createToolButton(e.tools[0]));return}let t=document.createElement(`div`);t.className=`flex flex-col items-center`;for(let n of e.tools)t.appendChild(this.createToolButton(n));this.inner.appendChild(t)}createToolButton(e){let t=document.createElement(`div`);t.className=`relative group`;let n=document.createElement(`button`);n.className=e.id===this.activeToolId?z_:R_,n.innerHTML=`<span class="[&>svg]:size-5">${e.icon}</span>`,n.addEventListener(`click`,()=>this.handleToolClick(e.id));let r=L_[e.id],i=document.createElement(`div`);return i.className=`absolute left-full top-1/2 -translate-y-1/2 ml-2 px-2 py-1 rounded bg-base-300 text-base-content text-xs whitespace-nowrap opacity-0 pointer-events-none group-hover:opacity-100 transition-opacity flex items-center gap-1.5`,i.innerHTML=r?`${e.label} <kbd class="kbd kbd-xs">${r}</kbd>`:e.label,t.appendChild(n),t.appendChild(i),this.buttons.set(e.id,n),t}syncButtonStates(){for(let[e,t]of this.buttons)t.className=e===this.activeToolId?z_:R_}handleToolClick(e){this.activeToolId===e?this.onToolSelect(null):this.onToolSelect(e)}handleKeyDown(e){e.key===`Escape`&&this.activeToolId&&(e.preventDefault(),e.stopPropagation(),this.onToolSelect(null))}},V_=class{ctx;plane;snapController;previewGroup;insertGeometry;canvas;currentPosition=null;constructor(e,t,n,r){this.ctx=e,this.plane=t,this.snapController=n,this.insertGeometry=r,this.canvas=e.renderer.domElement,this.previewGroup=new oi,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=3}updatePlane(e){this.plane=e}updateSnapManager(e){this.snapController.updateSnapManager(e)}updateCurrentPosition(e){e?this.currentPosition=Op(e,this.plane):this.currentPosition=null}isAtCurrentPosition(e){if(!this.currentPosition)return!1;let t=kp(this.ctx,15);return Ap(e,this.currentPosition)<=t}disposePreview(){for(;this.previewGroup.children.length>0;){let e=this.previewGroup.children[0];this.previewGroup.remove(e);let t=e;t.geometry&&t.geometry.dispose(),t.material&&t.material.dispose()}}addPreviewToScene(){this.ctx.scene.add(this.previewGroup)}removePreviewFromScene(){this.ctx.scene.remove(this.previewGroup),this.disposePreview(),this.ctx.requestRender()}requestRender(){this.ctx.requestRender()}formatPoint(e){return`[${e[0]}, ${e[1]}]`}},H_=16,U_=-36,W_=/^[a-zA-Z_$][\w$]*$/,G_=/^([a-zA-Z_$][\w$]*)\s*=\s*(.+?)\s*;?\s*$/,K_=new Set(`const.let.var.if.else.for.while.do.return.function.class.new.this.true.false.null.undefined.typeof.instanceof.switch.case.break.continue.default.try.catch.finally.throw.in.of.delete.void.yield.async.await.import.export.from.as.extends.super.static.enum.interface.implements.package.private.protected.public`.split(`.`));function q_(e){return W_.test(e)&&!K_.has(e)}var J_=class{el;wrapperEl;input;label;dropdown;errorEl;onCommit=null;visible=!1;userIsTyping=!1;variables=[];filteredVars=[];selectedIndex=-1;seedValue=``;errorVisible=!1;numericOnly=!1;onSpaceOverride=null;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute z-[1000] pointer-events-auto hidden`,this.el.innerHTML=`
5433
5433
  <div class="expression-wrapper flex items-center gap-1.5 panel-bg border border-base-content/10 rounded-md px-2 py-1 shadow-lg">
5434
5434
  <span class="text-xs text-base-content/50 select-none expression-label"></span>
5435
5435
  <input type="text" class="bg-transparent border-none outline-none text-sm text-base-content w-24 font-mono expression-input" />
5436
5436
  </div>
5437
5437
  <div class="mt-1 panel-bg border border-base-content/10 rounded-md shadow-lg max-h-[150px] overflow-y-auto hidden expression-dropdown"></div>
5438
5438
  <div class="mt-1 bg-red-500/90 text-white text-xs rounded-md px-2 py-1 shadow-lg hidden expression-error"></div>
5439
- `,e.appendChild(this.el),this.wrapperEl=this.el.querySelector(`.expression-wrapper`),this.input=this.el.querySelector(`.expression-input`),this.label=this.el.querySelector(`.expression-label`),this.dropdown=this.el.querySelector(`.expression-dropdown`),this.errorEl=this.el.querySelector(`.expression-error`),this.input.addEventListener(`keydown`,e=>{if(e.key!==`Escape`&&e.stopPropagation(),e.key===`ArrowDown`){e.preventDefault(),this.moveSelection(1);return}if(e.key===`ArrowUp`){e.preventDefault(),this.moveSelection(-1);return}if(e.key===`Tab`){e.preventDefault(),this.fillSelected();return}if(e.key===`Enter`){e.preventDefault(),this.selectedIndex>=0&&this.selectedIndex<this.filteredVars.length&&(this.input.value=this.filteredVars[this.selectedIndex].name),this.commit();return}if(e.key===` `&&this.onSpaceOverride){e.preventDefault(),this.onSpaceOverride();return}if(e.key===`Escape`){e.preventDefault(),this.userIsTyping=!1,this.input.blur(),this.hide();return}}),this.input.addEventListener(`input`,()=>{this.userIsTyping=!0,this.errorVisible&&this.clearInlineError(),this.filterAndRender()}),this.input.addEventListener(`focus`,()=>{this.filterAndRender()}),this.input.addEventListener(`mousedown`,e=>e.stopPropagation()),this.input.addEventListener(`mouseup`,e=>e.stopPropagation()),this.input.addEventListener(`click`,e=>e.stopPropagation()),this.dropdown.addEventListener(`mousedown`,e=>e.stopPropagation())}show(e){this.label.textContent=e.label,this.onCommit=e.onCommit,this.variables=e.variables,this.numericOnly=e.numericOnly??!1,this.visible=!0,this.userIsTyping=!1,this.selectedIndex=-1,this.seedValue=e.value,this.el.classList.remove(`hidden`),this.updatePosition(e.clientX,e.clientY),this.input.value=e.value,this.input.focus(),this.input.select(),this.clearInlineError(),this.filterAndRender()}hide(){this.visible&&(this.visible=!1,this.userIsTyping=!1,this.el.classList.add(`hidden`),this.dropdown.classList.add(`hidden`),this.clearInlineError(),this.onCommit=null,this.input.blur())}get isVisible(){return this.visible}containsElement(e){return e instanceof Node&&this.el.contains(e)}updateValue(e){if(!this.visible||this.userIsTyping)return;let t=typeof e==`string`?e:String(Math.round(e*100)/100);this.input.value=t,this.seedValue=t,this.input.select()}updatePosition(e,t){if(!this.visible)return;let n=this.el.parentElement.getBoundingClientRect();this.el.style.left=`${e-n.left+z_}px`,this.el.style.top=`${t-n.top+B_}px`}commitCurrentValue(){let e=this.input.value.trim();return e?this.runCommit(e):!1}commit(){let e=this.input.value.trim();e?this.runCommit(e):this.hide()}runCommit(e){if(!this.onCommit)return!1;let t=this.classifyCommit(e);return t.kind===`error`?(this.showInlineError(t.message),!1):(t.kind===`declare`?this.onCommit({expression:t.name,newVariable:{name:t.name,initializer:t.initializer}}):this.onCommit({expression:t.expression}),this.hide(),!0)}classifyCommit(e){if(this.numericOnly)return isNaN(parseFloat(e))?{kind:`error`,message:`Enter a numeric value`}:{kind:`expression`,expression:e};let t=e.match(H_);if(t){let e=t[1],n=t[2].trim();return W_(e)?this.variables.some(t=>t.name===e)?{kind:`error`,message:`'${e}' is already defined`}:n?{kind:`declare`,name:e,initializer:n}:{kind:`error`,message:`Missing value`}:{kind:`error`,message:`'${e}' is not a valid name`}}if(V_.test(e)){if(this.variables.some(t=>t.name===e)||!W_(e))return{kind:`expression`,expression:e};let t=this.seedValue.trim();return t?{kind:`declare`,name:e,initializer:t}:{kind:`error`,message:`No value to assign`}}return{kind:`expression`,expression:e}}showInlineError(e){this.errorVisible=!0,this.errorEl.textContent=e,this.errorEl.classList.remove(`hidden`),this.wrapperEl.classList.add(`border-red-500/70`),this.wrapperEl.classList.remove(`border-base-content/10`)}clearInlineError(){if(!this.errorVisible){this.errorEl.classList.add(`hidden`);return}this.errorVisible=!1,this.errorEl.classList.add(`hidden`),this.errorEl.textContent=``,this.wrapperEl.classList.remove(`border-red-500/70`),this.wrapperEl.classList.add(`border-base-content/10`)}moveSelection(e){this.filteredVars.length!==0&&(this.selectedIndex+=e,this.selectedIndex<0?this.selectedIndex=this.filteredVars.length-1:this.selectedIndex>=this.filteredVars.length&&(this.selectedIndex=0),this.renderDropdown())}fillSelected(){this.selectedIndex>=0&&this.selectedIndex<this.filteredVars.length&&(this.input.value=this.filteredVars[this.selectedIndex].name,this.userIsTyping=!0,this.filterAndRender())}filterAndRender(){if(this.numericOnly){this.filteredVars=[],this.selectedIndex=-1,this.renderDropdown();return}if(!this.userIsTyping)this.filteredVars=[...this.variables];else{let e=this.input.value.trim().toLowerCase();e?this.filteredVars=this.variables.filter(t=>t.name.toLowerCase().includes(e)):this.filteredVars=[...this.variables]}this.selectedIndex=-1,this.renderDropdown()}renderDropdown(){if(this.filteredVars.length===0){this.dropdown.classList.add(`hidden`);return}if(this.dropdown.classList.remove(`hidden`),this.dropdown.innerHTML=this.filteredVars.map((e,t)=>{let n=t===this.selectedIndex?`bg-primary/10`:``,r=e.initializer?`<span class="text-base-content/40 ml-2">= ${this.escapeHtml(this.truncate(e.initializer,20))}</span>`:``;return`<div class="px-2 py-1 text-sm font-mono cursor-pointer hover:bg-primary/10 ${n}" data-idx="${t}">${this.escapeHtml(e.name)}${r}</div>`}).join(``),this.dropdown.querySelectorAll(`[data-idx]`).forEach(e=>{e.addEventListener(`mousedown`,t=>{t.preventDefault(),t.stopPropagation();let n=parseInt(e.dataset.idx,10);this.input.value=this.filteredVars[n].name,this.commit()})}),this.selectedIndex>=0){let e=this.dropdown.children[this.selectedIndex];e&&e.scrollIntoView({block:`nearest`})}}escapeHtml(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}truncate(e,t){return e.length>t?e.slice(0,t)+`...`:e}},X=2280550,K_=11579568,Z=16762232,q_=8947848,J_=2.5,Y_=7.5;function X_(e){return e===`vertex`?Z:q_}function Q(e,t,n,r,i,a,o=1,s=4,c=J_,l=Y_){let u=new U(new oa(c,16),new mr({color:n,side:2,depthTest:!1,transparent:o<1,opacity:o}));u.renderOrder=s;let d=new oi;d.renderOrder=s;let f=Cp(t,a);d.position.copy(f),d.lookAt(f.clone().add(i)),tp(u,d,f,l,c),d.add(u),e.add(d)}function Z_(e,t,n,r,i=3){let a=Cp(t,r),o=Cp(n,r),s=new Float32Array(6);s[0]=a.x,s[1]=a.y,s[2]=a.z,s[3]=o.x,s[4]=o.y,s[5]=o.z;let c=new H;c.setAttribute(`position`,new V(s,3));let l=new Gi(c,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));l.computeLineDistances(),l.renderOrder=i,e.add(l)}function Q_(e,t,n,r,i=3){let a=new Float32Array(195);for(let e=0;e<=64;e++){let i=e/64*Math.PI*2,o=Cp([t[0]+Math.cos(i)*n,t[1]+Math.sin(i)*n],r);a[e*3]=o.x,a[e*3+1]=o.y,a[e*3+2]=o.z}let o=new H;o.setAttribute(`position`,new V(a,3));let s=new Gi(o,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));s.computeLineDistances(),s.renderOrder=i,e.add(s)}function $_(e,t,n,r,i=3){let a=t[0],o=t[1],s=n[0],c=n[1],l=[[a,o],[s,o],[s,c],[a,c],[a,o]],u=new Float32Array(l.length*3);for(let e=0;e<l.length;e++){let t=Cp(l[e],r);u[e*3]=t.x,u[e*3+1]=t.y,u[e*3+2]=t.z}let d=new H;d.setAttribute(`position`,new V(u,3));let f=new Gi(d,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));f.computeLineDistances(),f.renderOrder=i,e.add(f)}var ev=8;function tv(e,t,n,r,i,a=3){let o=Math.min(t[0],n[0]),s=Math.max(t[0],n[0]),c=Math.min(t[1],n[1]),l=Math.max(t[1],n[1]),u=s-o,d=l-c,f=Math.min(r,u/2,d/2);if(f<=0){$_(e,t,n,i,a);return}let p=[];p.push([o+f,c]),p.push([s-f,c]);for(let e=0;e<=ev;e++){let t=-Math.PI/2+e/ev*(Math.PI/2);p.push([s-f+f*Math.cos(t),c+f+f*Math.sin(t)])}p.push([s,c+f]),p.push([s,l-f]);for(let e=0;e<=ev;e++){let t=0+e/ev*(Math.PI/2);p.push([s-f+f*Math.cos(t),l-f+f*Math.sin(t)])}p.push([s-f,l]),p.push([o+f,l]);for(let e=0;e<=ev;e++){let t=Math.PI/2+e/ev*(Math.PI/2);p.push([o+f+f*Math.cos(t),l-f+f*Math.sin(t)])}p.push([o,l-f]),p.push([o,c+f]);for(let e=0;e<=ev;e++){let t=Math.PI+e/ev*(Math.PI/2);p.push([o+f+f*Math.cos(t),c+f+f*Math.sin(t)])}p.push([o+f,c]);let m=new Float32Array(p.length*3);for(let e=0;e<p.length;e++){let t=Cp(p[e],i);m[e*3]=t.x,m[e*3+1]=t.y,m[e*3+2]=t.z}let h=new H;h.setAttribute(`position`,new V(m,3));let g=new Gi(h,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));g.computeLineDistances(),g.renderOrder=a,e.add(g)}function nv(e,t,n,r,i,a=3){let o=new Float32Array((r+1)*3);for(let e=0;e<=r;e++){let a=e/r*Math.PI*2,s=Cp([t[0]+Math.cos(a)*n,t[1]+Math.sin(a)*n],i);o[e*3]=s.x,o[e*3+1]=s.y,o[e*3+2]=s.z}let s=new H;s.setAttribute(`position`,new V(o,3));let c=new Gi(s,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));c.computeLineDistances(),c.renderOrder=a,e.add(c)}function rv(e,t,n,r,i,a,o,s=3){let c=i-r;a?c<=0&&(c+=Math.PI*2):c>=0&&(c-=Math.PI*2);let l=Math.max(Math.round(Math.abs(c)/(Math.PI*2)*64),2),u=new Float32Array((l+1)*3);for(let e=0;e<=l;e++){let i=e/l,a=r+c*i,s=Cp([t[0]+Math.cos(a)*n,t[1]+Math.sin(a)*n],o);u[e*3]=s.x,u[e*3+1]=s.y,u[e*3+2]=s.z}let d=new H;d.setAttribute(`position`,new V(u,3));let f=new Gi(d,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));f.computeLineDistances(),f.renderOrder=s,e.add(f)}function iv(e,t){let n=e.slice();for(;n.length>1;){let e=[];for(let r=0;r<n.length-1;r++)e.push([(1-t)*n[r][0]+t*n[r+1][0],(1-t)*n[r][1]+t*n[r+1][1]]);n=e}return n[0]}function av(e,t,n,r=3){if(t.length<2)return;let i=new Float32Array(195);for(let e=0;e<=64;e++){let r=Cp(iv(t,e/64),n);i[e*3]=r.x,i[e*3+1]=r.y,i[e*3+2]=r.z}let a=new H;a.setAttribute(`position`,new V(i,3));let o=new Gi(a,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));o.computeLineDistances(),o.renderOrder=r,e.add(o)}var ov=16;function sv(e,t,n,r,i,a=3){let o=n[0]-t[0],s=n[1]-t[1],c=Math.sqrt(o*o+s*s),l,u;c>1e-10?(l=o/c,u=s/c):(l=1,u=0);let d=-u,f=l,p=[],m=Math.atan2(f,d);for(let e=0;e<=ov;e++){let n=m+e/ov*Math.PI;p.push([t[0]+r*Math.cos(n),t[1]+r*Math.sin(n)])}p.push([n[0]-r*d,n[1]-r*f]);let h=Math.atan2(-f,-d);for(let e=0;e<=ov;e++){let t=h+e/ov*Math.PI;p.push([n[0]+r*Math.cos(t),n[1]+r*Math.sin(t)])}p.push([t[0]+r*d,t[1]+r*f]);let g=new Float32Array(p.length*3);for(let e=0;e<p.length;e++){let t=Cp(p[e],i);g[e*3]=t.x,g[e*3+1]=t.y,g[e*3+2]=t.z}let _=new H;_.setAttribute(`position`,new V(g,3));let v=new Gi(_,new xa({color:K_,dashSize:3,gapSize:2,depthTest:!1}));v.computeLineDistances(),v.renderOrder=a,e.add(v)}function cv(e,t){return Math.atan2(t[1]-e[1],t[0]-e[0])}function lv(e,t,n){return[e[0]+t*Math.cos(n),e[1]+t*Math.sin(n)]}function uv(e,t,n){let r=2*(e[0]*(t[1]-n[1])+t[0]*(n[1]-e[1])+n[0]*(e[1]-t[1]));if(Math.abs(r)<1e-10)return null;let i=e[0]*e[0]+e[1]*e[1],a=t[0]*t[0]+t[1]*t[1],o=n[0]*n[0]+n[1]*n[1];return[(i*(t[1]-n[1])+a*(n[1]-e[1])+o*(e[1]-t[1]))/r,(i*(n[0]-t[0])+a*(e[0]-n[0])+o*(t[0]-e[0]))/r]}function dv(e,t,n){let r=cv(e,t),i=cv(e,n)-r;return i<0&&(i+=Math.PI*2),i<Math.PI}function fv(e,t,n,r){let i=(e[0]+t[0])/2,a=(e[1]+t[1])/2,o=t[0]-e[0],s=t[1]-e[1],c=Math.sqrt(o*o+s*s)/2;if(Math.abs(n)<c-1e-10)return null;let l=Math.sqrt(Math.max(n*n-c*c,0)),u=-s,d=o,f=Math.sqrt(u*u+d*d);if(f<1e-10)return null;let p=r?1:-1;return[i+p*l*u/f,a+p*l*d/f]}var pv=new Set([`line-two-points`,`hline`,`vline`,`arc`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`tline`]);function mv(e,t){let n=t.origin.x,r=t.origin.y,i=t.origin.z,a=t.xDirection.x,o=t.xDirection.y,s=t.xDirection.z,c=t.yDirection.x,l=t.yDirection.y,u=t.yDirection.z,d=[];for(let t=0;t<e.length;t+=3){let f=e[t]-n,p=e[t+1]-r,m=e[t+2]-i;d.push([f*a+p*o+m*s,f*c+p*l+m*u])}return d}function hv(e,t){let n,r;if(t===`end`){let t=e[e.length-2],i=e[e.length-1];n=i[0]-t[0],r=i[1]-t[1]}else{let t=e[0],i=e[1];n=t[0]-i[0],r=t[1]-i[1]}let i=Math.sqrt(n*n+r*r);return i<1e-10?null:[n/i,r/i]}var gv=class extends R_{id=`line`;label=`Line`;icon=Gh;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;ctrlHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;sceneObjects=[];sketchId=``;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.startPoint=null,this.mousePoint=null,this.shiftHeld=!1,this.ctrlHeld=!1,this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){this.sceneObjects=e,this.sketchId=t;let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY,this.syncModifiers(e)}handleMouseUp(e){this.syncModifiers(e);let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.rebuildPreview();return}this.isTLineMode()&&this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.isTLineMode()?this.commitTLineDirect():this.shiftHeld&&this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitLine(this.startPoint,i),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}syncModifiers(e){let t=this.isTLineMode();this.shiftHeld=e.shiftKey,this.ctrlHeld=e.ctrlKey||e.metaKey,this.isTLineMode()!==t&&this.expressionInput.hide()}handleKeyDown(e){this.syncModifiers(e),(e.key===`Shift`||e.key===`Control`||e.key===`Meta`)&&(this.rebuildPreview(),this.updateDimensionInput()),e.key===`Escape`&&this.startPoint&&(this.startPoint=null,this.expressionInput.hide(),this.rebuildPreview())}handleKeyUp(e){this.syncModifiers(e),(e.key===`Shift`||e.key===`Control`||e.key===`Meta`)&&(this.shiftHeld||this.expressionInput.hide(),this.rebuildPreview(),this.updateDimensionInput())}isTLineMode(){return this.shiftHeld&&this.ctrlHeld}findTangentAtStart(){if(!this.startPoint||!this.isAtCurrentPosition(Y(this.startPoint)))return null;let e=null;for(let t of this.sceneObjects)t.parentId!==this.sketchId||!t.sourceLocation||pv.has(t.uniqueType??``)&&(e=t);if(!e)return null;for(let t of e.sceneShapes)if(!t.isMetaShape)for(let e of t.meshes){let t=mv(e.vertices,this.plane);if(!(t.length<2))return hv(t,`end`)}return null}getEffectiveEndPoint(){if(!this.startPoint||!this.mousePoint)return null;if(this.isTLineMode()){let e=this.findTangentAtStart();if(e){let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=t*e[0]+n*e[1];return[this.startPoint[0]+e[0]*r,this.startPoint[1]+e[1]*r]}return this.mousePoint}if(this.shiftHeld){let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1];return Math.abs(e)>=Math.abs(t)?[this.mousePoint[0],this.startPoint[1]]:[this.startPoint[0],this.mousePoint[1]]}return this.mousePoint}updateDimensionInput(){if(!this.startPoint||!this.mousePoint||!this.shiftHeld){this.expressionInput.hide();return}if(this.isTLineMode()){this.updateTLineDimensionInput();return}let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1],n=Math.abs(e)>=Math.abs(t),r=Math.abs(n?e:t);this.expressionInput.isVisible?(this.expressionInput.updateValue(r),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:n?`H:`:`V:`,value:String(Math.round(r*100)/100),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.commitWithDimension(e)})}updateTLineDimensionInput(){let e=this.findTangentAtStart();if(!e){this.expressionInput.hide();return}let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=t*e[0]+n*e[1];this.expressionInput.isVisible?(this.expressionInput.updateValue(Math.abs(r)),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`T:`,value:String(Math.round(Math.abs(r)*100)/100),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.commitTLine(e,r)})}commitWithDimension(e){if(!this.startPoint||!this.mousePoint)return;let{expression:t,newVariable:n}=e,r=Y(this.startPoint),i=this.isAtCurrentPosition(r),a=this.mousePoint[0]-this.startPoint[0],o=this.mousePoint[1]-this.startPoint[1],s=Math.abs(a)>=Math.abs(o),c=Math.sign(s?a:o),l=parseFloat(t),u=!isNaN(l)&&String(l)===t?String(Math.round(c*l*100)/100):t,d=s?`hLine`:`vLine`,f=i?`${d}(${u})`:`${d}(${this.formatPoint(r)}, ${u})`;this.insertGeometry(f,n),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitTLine(e,t){if(!this.startPoint)return;let{expression:n,newVariable:r}=e,i=Math.sign(t),a=parseFloat(n),o=!isNaN(a)&&String(a)===n?String(Math.round(i*a*100)/100):n;this.insertGeometry(`tLine(${o})`,r),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitTLineDirect(){if(!this.startPoint||!this.mousePoint)return;let e=this.findTangentAtStart();if(!e)return;let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=Math.round((t*e[0]+n*e[1])*100)/100;this.insertGeometry(`tLine(${r})`),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitLine(e,t){let n=Y(e),r=Y(t),i=this.isAtCurrentPosition(n);if(this.shiftHeld){let e=r[0]-n[0],t=r[1]-n[1],a=Math.abs(e)>=Math.abs(t),o=a?Y([e,0])[0]:Y([0,t])[1];a?i?this.insertGeometry(`hLine(${o})`):this.insertGeometry(`hLine(${this.formatPoint(n)}, ${o})`):i?this.insertGeometry(`vLine(${o})`):this.insertGeometry(`vLine(${this.formatPoint(n)}, ${o})`);return}i?this.insertGeometry(`line(${this.formatPoint(r)})`):this.insertGeometry(`line(${this.formatPoint(n)}, ${this.formatPoint(r)})`)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){Q(this.previewGroup,this.startPoint,X,e,t,this.plane);let n=this.getEffectiveEndPoint();if(n&&(Z_(this.previewGroup,this.startPoint,n,this.plane),this.lastSnapType!==`none`)){let r=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,n,r,e,t,this.plane,.6)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},_v=class extends R_{id=`circle`;label=`Circle`;icon=Kh;centerPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.centerPoint=null,this.mousePoint=null,this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.centerPoint){this.centerPoint=i,this.rebuildPreview();return}if(this.expressionInput.isVisible)this.expressionInput.commitCurrentValue();else{let e=Math.round(Dp(this.centerPoint,i)*2*100)/100;if(e<=0)return;this.commitCircle(this.centerPoint,{expression:String(e)})}this.expressionInput.hide(),this.centerPoint=null,this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&this.centerPoint&&(this.centerPoint=null,this.expressionInput.hide(),this.rebuildPreview())}updateDimensionInput(){if(!this.centerPoint||!this.mousePoint)return;let e=Math.round(Dp(this.centerPoint,this.mousePoint)*2*100)/100;e<=0||(this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`⌀`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>{this.centerPoint&&(this.commitCircle(this.centerPoint,e),this.expressionInput.hide(),this.centerPoint=null,this.rebuildPreview())}}))}commitCircle(e,t){let{expression:n,newVariable:r}=t,i=this.isAtCurrentPosition(e)?`circle(${n})`:`circle(${this.formatPoint(e)}, ${n})`;this.insertGeometry(i,r)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.centerPoint){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint){let e=Dp(this.centerPoint,this.mousePoint);e>0&&Q_(this.previewGroup,this.centerPoint,e,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},vv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.CENTER_PLACED=1]=`CENTER_PLACED`,e[e.START_PLACED=2]=`START_PLACED`,e}(vv||{}),yv=class extends R_{id=`arc2`;label=`Center Arc`;icon=qh;state=vv.IDLE;centerPoint=null;startPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;lastCCW=!0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.resetState(),this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.state=vv.IDLE,this.centerPoint=null,this.startPoint=null,this.mousePoint=null}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(this.state===vv.IDLE){this.centerPoint=i,this.state=vv.CENTER_PLACED,this.rebuildPreview();return}if(this.state===vv.CENTER_PLACED){if(Dp(this.centerPoint,i)<=0)return;this.startPoint=i,this.state=vv.START_PLACED,this.rebuildPreview();return}this.state===vv.START_PLACED&&(this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromMouse())}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.state===vv.START_PLACED&&this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&(this.state===vv.START_PLACED?(this.startPoint=null,this.state=vv.CENTER_PLACED,this.expressionInput.hide()):this.state===vv.CENTER_PLACED&&(this.centerPoint=null,this.state=vv.IDLE),this.rebuildPreview())}getSweepDeg(){if(!this.centerPoint||!this.startPoint||!this.mousePoint)return null;let e=cv(this.centerPoint,this.startPoint),t=cv(this.centerPoint,this.mousePoint);this.lastCCW=dv(this.centerPoint,this.startPoint,this.mousePoint);let n;return this.lastCCW?(n=t-e,n<=0&&(n+=Math.PI*2)):(n=e-t,n<=0&&(n+=Math.PI*2)),n===0?null:Math.round(180/Math.PI*n*100)/100}updateDimensionInput(){let e=this.getSweepDeg();e===null||e<=0||(this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`∠`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,numericOnly:!0,onCommit:e=>this.commitFromExpression(e)}))}commitFromMouse(){if(!this.centerPoint||!this.startPoint||!this.mousePoint)return;let e=dv(this.centerPoint,this.startPoint,this.mousePoint),t=Dp(this.centerPoint,this.startPoint),n=cv(this.centerPoint,this.mousePoint),r=lv(this.centerPoint,t,n);this.emitArc(this.startPoint,r,this.centerPoint,e)}commitFromExpression(e){if(!this.centerPoint||!this.startPoint)return;let{expression:t,newVariable:n}=e,r=parseFloat(t);if(isNaN(r)||r<=0)return;let i=Math.PI/180*r,a=Dp(this.centerPoint,this.startPoint),o=cv(this.centerPoint,this.startPoint)+(this.lastCCW?1:-1)*i,s=lv(this.centerPoint,a,o);this.emitArc(this.startPoint,s,this.centerPoint,this.lastCCW,n)}emitArc(e,t,n,r,i){let a=Y(e),o=Y(t),s=Y(n),c=r?``:`.cw()`,l=this.isAtCurrentPosition(a)?`arc(${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`:`arc(${this.formatPoint(a)}, ${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`;this.insertGeometry(l,i),this.expressionInput.hide(),this.resetState(),this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.state===vv.IDLE){if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===vv.CENTER_PLACED){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===vv.START_PLACED&&this.centerPoint&&this.startPoint&&(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),Q(this.previewGroup,this.startPoint,X,e,t,this.plane),Z_(this.previewGroup,this.centerPoint,this.startPoint,this.plane),this.mousePoint)){let n=Dp(this.centerPoint,this.startPoint),r=cv(this.centerPoint,this.startPoint),i=cv(this.centerPoint,this.mousePoint),a=lv(this.centerPoint,n,i);Z_(this.previewGroup,this.centerPoint,a,this.plane);let o=dv(this.centerPoint,this.startPoint,this.mousePoint);if(rv(this.previewGroup,this.centerPoint,n,r,i,o,this.plane),this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}this.requestRender()}},bv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.START_PLACED=1]=`START_PLACED`,e[e.END_PLACED=2]=`END_PLACED`,e}(bv||{}),xv=class extends R_{id=`arc3`;label=`3-Point Arc`;icon=Jh;state=bv.IDLE;startPoint=null;endPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;lastCCW=!0;lastCenterOnLeft=!0;shiftHeld=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.state=bv.IDLE,this.startPoint=null,this.endPoint=null,this.mousePoint=null}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){this.shiftHeld=e.shiftKey;let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(this.state===bv.IDLE){this.startPoint=i,this.state=bv.START_PLACED,this.rebuildPreview();return}if(this.state===bv.START_PLACED){if(Dp(this.startPoint,i)<=0)return;this.endPoint=i,this.state=bv.END_PLACED,this.rebuildPreview();return}this.state===bv.END_PLACED&&(this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromMouse())}handleMouseMove(e){this.shiftHeld=e.shiftKey,this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.state===bv.END_PLACED&&this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&(this.state===bv.END_PLACED?(this.endPoint=null,this.state=bv.START_PLACED,this.expressionInput.hide()):this.state===bv.START_PLACED&&(this.startPoint=null,this.state=bv.IDLE),this.rebuildPreview()),e.key===`Shift`&&!this.shiftHeld&&(this.shiftHeld=!0,this.rebuildPreview(),this.state===bv.END_PLACED&&this.updateDimensionInput())}handleKeyUp(e){e.key===`Shift`&&this.shiftHeld&&(this.shiftHeld=!1,this.rebuildPreview(),this.state===bv.END_PLACED&&this.updateDimensionInput())}snapCenterToCollinear(e){if(!this.startPoint||!this.endPoint)return null;let t=this.endPoint[0]-this.startPoint[0],n=this.endPoint[1]-this.startPoint[1],r=t*t+n*n;if(r<1e-10)return null;let i=e[0]-this.startPoint[0],a=e[1]-this.startPoint[1],o=Math.abs(i*n-a*t)/Math.sqrt(r),s=Cp([(this.startPoint[0]+this.endPoint[0])/2,(this.startPoint[1]+this.endPoint[1])/2],this.plane);return o>=$f(this.ctx.renderer,this.ctx.camera,s,10)?null:[(this.startPoint[0]+this.endPoint[0])/2,(this.startPoint[1]+this.endPoint[1])/2]}computeCenter(){if(!this.startPoint||!this.endPoint||!this.mousePoint)return null;let e=uv(this.startPoint,this.endPoint,this.mousePoint);return e?this.shiftHeld?e:this.snapCenterToCollinear(e)??e:null}isMouseCCW(){if(!this.startPoint||!this.endPoint||!this.mousePoint)return!0;let e=this.computeCenter();if(!e)return!0;let t=cv(e,this.startPoint),n=cv(e,this.endPoint),r=cv(e,this.mousePoint)-t;r<0&&(r+=Math.PI*2);let i=n-t;return i<0&&(i+=Math.PI*2),r<i}updateDimensionInput(){let e=this.computeCenter();if(!e||!this.startPoint)return;let t=Math.round(Dp(e,this.startPoint)*100)/100;if(t<=0)return;this.lastCCW=this.isMouseCCW();let n=this.endPoint[0]-this.startPoint[0],r=this.endPoint[1]-this.startPoint[1],i=e[0]-this.startPoint[0];this.lastCenterOnLeft=n*(e[1]-this.startPoint[1])-r*i>0,this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`R`,value:String(t),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,numericOnly:!0,onCommit:e=>this.commitFromExpression(e)})}commitFromMouse(){if(!this.startPoint||!this.endPoint)return;let e=this.computeCenter();e&&this.emitArc(this.startPoint,this.endPoint,e,this.isMouseCCW())}commitFromExpression(e){if(!this.startPoint||!this.endPoint)return;let{expression:t,newVariable:n}=e,r=parseFloat(t);if(isNaN(r)||r<=0)return;let i=fv(this.startPoint,this.endPoint,r,this.lastCenterOnLeft);i&&this.emitArc(this.startPoint,this.endPoint,i,this.lastCCW,n)}emitArc(e,t,n,r,i){let a=Y(e),o=Y(t),s=Y(n),c=r?``:`.cw()`,l=this.isAtCurrentPosition(a)?`arc(${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`:`arc(${this.formatPoint(a)}, ${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`;this.insertGeometry(l,i),this.expressionInput.hide(),this.resetState(),this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.state===bv.IDLE){if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===bv.START_PLACED){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===bv.END_PLACED&&this.startPoint&&this.endPoint&&(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),Q(this.previewGroup,this.endPoint,X,e,t,this.plane),Z_(this.previewGroup,this.startPoint,this.endPoint,this.plane),this.mousePoint)){let n=this.computeCenter();if(n){let r=Dp(n,this.startPoint),i=cv(n,this.startPoint),a=cv(n,this.endPoint),o=this.isMouseCCW();rv(this.previewGroup,n,r,i,a,o,this.plane),Q(this.previewGroup,n,K_,e,t,this.plane,.7),Z_(this.previewGroup,n,this.startPoint,this.plane),Z_(this.previewGroup,n,this.endPoint,this.plane)}if(this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}this.requestRender()}},Sv=class extends R_{id=`rect`;label=`Rectangle`;icon=Yh;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`width`;widthExpression=null;lockedWidth=null;widthIsNumeric=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.startPoint=null,this.mousePoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.shiftHeld=!1,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.rebuildPreview();return}this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromGeometry(i)}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.startPoint&&(this.resetState(),this.rebuildPreview());return}e.key===`Shift`&&(this.shiftHeld=!0,this.rebuildPreview())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.rebuildPreview())}syncModifiers(e){this.shiftHeld=e.shiftKey}computeDimensions(e){let t=this.startPoint;if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{width:Math.round(n*2*100)/100,height:Math.round(r*2*100)/100}}return{width:Math.round((e[0]-t[0])*100)/100,height:Math.round((e[1]-t[1])*100)/100}}computePreviewCorners(e){let t=this.startPoint;if(this.lockedWidth!==null){if(this.shiftHeld){let n=this.lockedWidth/2,r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}let n=e[0]>=t[0]?1:-1;return{c1:t,c2:[t[0]+n*this.lockedWidth,e[1]]}}if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}return{c1:t,c2:e}}dimensionInputAnchor(){if(!this.startPoint||!this.mousePoint)return{clientX:this.lastClientX,clientY:this.lastClientY};let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint),n=this.expressionPhase===`width`?[(e[0]+t[0])/2,e[1]]:[t[0],(e[1]+t[1])/2];return wp(this.ctx,this.plane,n)}updateDimensionInput(){if(!this.startPoint||!this.mousePoint)return;let{width:e,height:t}=this.computeDimensions(this.mousePoint),n=this.dimensionInputAnchor();if(this.expressionPhase===`width`){let t=Math.round(Math.abs(e)*100)/100;if(t<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(n.clientX,n.clientY)):this.expressionInput.show({label:`W`,value:String(t),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onWidthCommit(e)})}else if(this.expressionPhase===`height`){let e=Math.round(Math.abs(t)*100)/100;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(n.clientX,n.clientY)):this.expressionInput.show({label:`H`,value:String(e),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e)})}}onWidthCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.widthIsNumeric=n,n?(this.widthExpression=e,this.lockedWidth=t):(this.widthExpression=e,this.lockedWidth=null),this.expressionPhase=`height`,queueMicrotask(()=>{if(this.mousePoint&&this.startPoint){let{height:e}=this.computeDimensions(this.mousePoint),t=Math.round(Math.abs(e)*100)/100,n=this.dimensionInputAnchor();this.expressionInput.show({label:`H`,value:String(t),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e)})}this.rebuildPreview()})}onHeightCommit(e){if(!this.startPoint||!this.widthExpression)return;let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression,r=this.resolveSignedDim(this.widthExpression,this.widthIsNumeric,this.lockedWidth,0),i;if(n&&this.mousePoint&&!this.shiftHeld){let n=this.mousePoint[1]>=this.startPoint[1]?1:-1;i={expression:String(Math.round(n*t*100)/100),newVariable:e.newVariable}}else i=e;this.commitRect(this.startPoint,r,i),this.expressionInput.hide(),this.startPoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.rebuildPreview()}commitFromGeometry(e){if(!this.startPoint)return;let{width:t,height:n}=this.computeDimensions(e);t===0||n===0||(this.commitRect(this.startPoint,{expression:String(t)},{expression:String(n)}),this.expressionInput.hide(),this.startPoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.rebuildPreview())}resolveSignedDim(e,t,n,r){if(!t||n===null||!this.mousePoint||!this.startPoint||this.shiftHeld)return e;let i=r===0?this.mousePoint[0]>=this.startPoint[0]?1:-1:this.mousePoint[1]>=this.startPoint[1]?1:-1;return{expression:String(Math.round(i*n*100)/100),newVariable:e.newVariable}}commitRect(e,t,n){let r=this.isAtCurrentPosition(e),i;i=r?`rect(${t.expression}, ${n.expression})`:`rect(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,this.shiftHeld&&(i+=`.centered()`);let a=t.newVariable??n.newVariable;this.insertGeometry(i,a)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.mousePoint){let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint);$_(this.previewGroup,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},Cv=class extends R_{id=`rounded-rect`;label=`Rounded Rectangle`;icon=Xh;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`width`;widthExpression=null;heightExpression=null;lockedWidth=null;lockedHeight=null;widthIsNumeric=!1;heightIsNumeric=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.startPoint=null,this.mousePoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.heightExpression=null,this.lockedWidth=null,this.lockedHeight=null,this.widthIsNumeric=!1,this.heightIsNumeric=!1,this.shiftHeld=!1,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.rebuildPreview();return}if(this.expressionInput.isVisible)this.expressionInput.commitCurrentValue();else if(this.expressionPhase===`width`||this.expressionPhase===`height`)this.commitDimensionsFromGeometry(i);else if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(i);this.commitRoundedRect(this.startPoint,this.widthExpression,this.heightExpression,{expression:String(e)}),this.resetState(),this.rebuildPreview()}}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.startPoint&&(this.resetState(),this.rebuildPreview());return}e.key===`Shift`&&(this.shiftHeld=!0,this.rebuildPreview())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.rebuildPreview())}syncModifiers(e){this.shiftHeld=e.shiftKey}computeDimensions(e){let t=this.startPoint;if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{width:Math.round(n*2*100)/100,height:Math.round(r*2*100)/100}}return{width:Math.round((e[0]-t[0])*100)/100,height:Math.round((e[1]-t[1])*100)/100}}computePreviewCorners(e){let t=this.startPoint,n=this.lockedWidth!==null,r=this.lockedHeight!==null;if(n&&r)return this.getLockedPreviewCorners();if(n){if(this.shiftHeld){let n=this.lockedWidth/2,r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}let n=e[0]>=t[0]?1:-1;return{c1:t,c2:[t[0]+n*this.lockedWidth,e[1]]}}if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}return{c1:t,c2:e}}getLockedPreviewCorners(){if(!this.startPoint||this.lockedWidth===null||this.lockedHeight===null)return null;if(this.shiftHeld){let e=this.lockedWidth/2,t=this.lockedHeight/2;return{c1:[this.startPoint[0]-e,this.startPoint[1]-t],c2:[this.startPoint[0]+e,this.startPoint[1]+t]}}let e=this.mousePoint?this.mousePoint[0]>=this.startPoint[0]?1:-1:1,t=this.mousePoint?this.mousePoint[1]>=this.startPoint[1]?1:-1:1;return{c1:this.startPoint,c2:[this.startPoint[0]+e*this.lockedWidth,this.startPoint[1]+t*this.lockedHeight]}}computeRadiusFromMouse(e){let t=this.getLockedPreviewCorners();if(!t)return 0;let{c1:n,c2:r}=t,i=[[n[0],n[1]],[r[0],n[1]],[r[0],r[1]],[n[0],r[1]]],a=1/0;for(let t of i){let n=Dp(e,t);n<a&&(a=n)}let o=Math.min(Math.abs(r[0]-n[0])/2,Math.abs(r[1]-n[1])/2);return Math.round(Math.min(a,o)*100)/100}dimensionInputAnchor(){let e={clientX:this.lastClientX,clientY:this.lastClientY};if(!this.startPoint||!this.mousePoint)return e;if(this.expressionPhase===`radius`){let t=this.getLockedPreviewCorners();if(!t)return e;let{c1:n,c2:r}=t;return wp(this.ctx,this.plane,[(n[0]+r[0])/2,(n[1]+r[1])/2])}let{c1:t,c2:n}=this.computePreviewCorners(this.mousePoint),r=this.expressionPhase===`width`?[(t[0]+n[0])/2,t[1]]:[n[0],(t[1]+n[1])/2];return wp(this.ctx,this.plane,r)}updateDimensionInput(){if(!this.startPoint||!this.mousePoint)return;let e=this.dimensionInputAnchor();if(this.expressionPhase===`width`){let{width:t}=this.computeDimensions(this.mousePoint),n=Math.round(Math.abs(t)*100)/100;if(n<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(n),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`W`,value:String(n),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onWidthCommit(e)})}else if(this.expressionPhase===`height`){let{height:t}=this.computeDimensions(this.mousePoint),n=Math.round(Math.abs(t)*100)/100,r=t>=0?1:-1;this.expressionInput.isVisible?(this.expressionInput.updateValue(n),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`H`,value:String(n),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e,r)})}else if(this.expressionPhase===`radius`){let t=this.computeRadiusFromMouse(this.mousePoint);this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`R`,value:String(t),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}}onWidthCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.widthIsNumeric=n,n?(this.widthExpression=e,this.lockedWidth=t):(this.widthExpression=e,this.lockedWidth=null),this.expressionPhase=`height`,queueMicrotask(()=>{if(this.mousePoint&&this.startPoint){let{height:e}=this.computeDimensions(this.mousePoint),t=Math.round(Math.abs(e)*100)/100,n=e>=0?1:-1,r=this.dimensionInputAnchor();this.expressionInput.show({label:`H`,value:String(t),clientX:r.clientX,clientY:r.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e,n)})}this.rebuildPreview()})}onHeightCommit(e,t){if(!this.startPoint||!this.widthExpression)return;let n=parseFloat(e.expression),r=!isNaN(n)&&String(n)===e.expression;this.heightIsNumeric=r,r?(this.heightExpression=e,this.lockedHeight=n):(this.heightExpression=e,this.lockedHeight=null),this.expressionPhase=`radius`,queueMicrotask(()=>{if(this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint),t=this.dimensionInputAnchor();this.expressionInput.show({label:`R`,value:String(e),clientX:t.clientX,clientY:t.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()})}onRadiusCommit(e){if(!this.startPoint||!this.widthExpression||!this.heightExpression)return;let t=this.resolveSignedExpression(this.widthExpression,this.widthIsNumeric,this.lockedWidth,0),n=this.resolveSignedExpression(this.heightExpression,this.heightIsNumeric,this.lockedHeight,1);this.commitRoundedRect(this.startPoint,t,n,e),this.resetState(),this.rebuildPreview()}resolveSignedExpression(e,t,n,r){if(!t||n===null||!this.mousePoint||!this.startPoint||this.shiftHeld)return e;let i=r===0?this.mousePoint[0]>=this.startPoint[0]?1:-1:this.mousePoint[1]>=this.startPoint[1]?1:-1,a=Math.round(i*n*100)/100;return{expression:String(a),newVariable:e.newVariable}}commitDimensionsFromGeometry(e){if(!this.startPoint)return;let{width:t,height:n}=this.computeDimensions(e);if(!(t===0||n===0)){if(this.widthExpression={expression:String(t)},this.lockedWidth=Math.abs(t),this.widthIsNumeric=!0,this.heightExpression={expression:String(n)},this.lockedHeight=Math.abs(n),this.heightIsNumeric=!0,this.expressionPhase=`radius`,this.expressionInput.hide(),this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint),t=this.dimensionInputAnchor();this.expressionInput.show({label:`R`,value:String(e),clientX:t.clientX,clientY:t.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()}}commitRoundedRect(e,t,n,r){let i=this.isAtCurrentPosition(e),a;a=i?`rect(${t.expression}, ${n.expression})`:`rect(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,a+=`.radius(${r.expression})`,this.shiftHeld&&(a+=`.centered()`);let o=t.newVariable??n.newVariable??r.newVariable;this.insertGeometry(a,o)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.expressionPhase===`radius`){let e=this.getLockedPreviewCorners();if(e){let t=this.mousePoint?this.computeRadiusFromMouse(this.mousePoint):0;t>0?tv(this.previewGroup,e.c1,e.c2,t,this.plane):$_(this.previewGroup,e.c1,e.c2,this.plane)}}else if(this.mousePoint){let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint);$_(this.previewGroup,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},wv=class extends R_{id=`slot`;label=`Slot`;icon=Zh;startPoint=null;endPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;horizontalMode=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`endpoint`;distanceExpression=null;lockedDistance=null;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleEscape(){return this.startPoint?this.expressionPhase===`radius`?(this.expressionPhase=this.horizontalMode?`distance`:`endpoint`,this.endPoint=null,this.distanceExpression=null,this.lockedDistance=null,this.expressionInput.hide(),this.rebuildPreview(),!0):this.expressionPhase===`distance`?(this.expressionPhase=`endpoint`,this.horizontalMode=!1,this.expressionInput.hide(),this.rebuildPreview(),!0):(this.resetState(),this.rebuildPreview(),!0):!1}resetState(){this.startPoint=null,this.endPoint=null,this.mousePoint=null,this.expressionPhase=`endpoint`,this.horizontalMode=!1,this.distanceExpression=null,this.lockedDistance=null,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.shiftHeld&&(this.horizontalMode=!0,this.expressionPhase=`distance`),this.rebuildPreview();return}if(this.expressionInput.isVisible){this.expressionInput.commitCurrentValue();return}if(this.expressionPhase===`endpoint`){if(Dp(this.startPoint,i)<=0)return;this.endPoint=i,this.expressionPhase=`radius`,this.expressionInput.hide(),this.rebuildPreview(),this.updateDimensionInput();return}if(this.expressionPhase===`distance`){let e=Math.round((i[0]-this.startPoint[0])*100)/100;if(e===0)return;this.onDistanceCommit({expression:String(e)});return}if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(i);if(e<=0)return;this.onRadiusCommit({expression:String(e)})}}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.handleEscape()&&e.stopPropagation();return}e.key===`Shift`&&(this.shiftHeld=!0,this.startPoint&&this.expressionPhase===`endpoint`&&!this.horizontalMode&&(this.horizontalMode=!0,this.expressionPhase=`distance`,this.expressionInput.hide()),this.rebuildPreview(),this.updateDimensionInput())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.expressionPhase===`distance`&&!this.distanceExpression&&(this.horizontalMode=!1,this.expressionPhase=`endpoint`,this.expressionInput.hide()),this.rebuildPreview(),this.updateDimensionInput())}syncModifiers(e){this.shiftHeld=e.shiftKey}getSlotAxis(){if(!this.startPoint)return null;if(this.horizontalMode){let e=this.lockedDistance??(this.mousePoint?this.mousePoint[0]-this.startPoint[0]:0);return{dir:e>=0?[1,0]:[-1,0],leftCenter:this.startPoint,rightCenter:[this.startPoint[0]+e,this.startPoint[1]]}}if(this.endPoint){let e=this.endPoint[0]-this.startPoint[0],t=this.endPoint[1]-this.startPoint[1],n=Math.sqrt(e*e+t*t);return n<1e-10?null:{dir:[e/n,t/n],leftCenter:this.startPoint,rightCenter:this.endPoint}}if(this.mousePoint){let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1],n=Math.sqrt(e*e+t*t);return n<1e-10?null:{dir:[e/n,t/n],leftCenter:this.startPoint,rightCenter:this.mousePoint}}return null}computeRadiusFromMouse(e){let t=this.getSlotAxis();if(!t)return 0;let n=e[0]-t.leftCenter[0],r=e[1]-t.leftCenter[1],i=Math.abs(-t.dir[1]*n+t.dir[0]*r);return Math.round(i*100)/100}updateDimensionInput(){if(!(!this.startPoint||!this.mousePoint)){if(this.expressionPhase===`distance`){let e=Math.round((this.mousePoint[0]-this.startPoint[0])*100)/100;if(e===0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`D`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onDistanceCommit(e)});return}if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(this.mousePoint);if(e<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`R`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}}}onDistanceCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.distanceExpression=e,this.lockedDistance=n?t:null,this.expressionPhase=`radius`,queueMicrotask(()=>{if(this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint);this.expressionInput.show({label:`R`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()})}onRadiusCommit(e){this.startPoint&&(this.horizontalMode&&this.distanceExpression?this.commitHorizontalSlot(this.startPoint,this.distanceExpression,e):this.endPoint&&this.commitTwoPointSlot(this.startPoint,this.endPoint,e),this.resetState(),this.rebuildPreview())}commitTwoPointSlot(e,t,n){let r=`slot(${this.formatPoint(e)}, ${this.formatPoint(t)}, ${n.expression})`;this.insertGeometry(r,n.newVariable)}commitHorizontalSlot(e,t,n){let r=this.isAtCurrentPosition(e)?`slot(${t.expression}, ${n.expression})`:`slot(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,i=t.newVariable??n.newVariable;this.insertGeometry(r,i)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){Q(this.previewGroup,this.startPoint,X,e,t,this.plane);let n=this.getSlotAxis();if(n){let r=Dp(n.leftCenter,n.rightCenter);if(r>0)if(this.expressionPhase===`radius`&&this.mousePoint){let r=this.computeRadiusFromMouse(this.mousePoint);r>0?sv(this.previewGroup,n.leftCenter,n.rightCenter,r,this.plane):Z_(this.previewGroup,n.leftCenter,n.rightCenter,this.plane),Q(this.previewGroup,n.rightCenter,X,e,t,this.plane)}else sv(this.previewGroup,n.leftCenter,n.rightCenter,r/6,this.plane),Q(this.previewGroup,n.rightCenter,Z,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},Tv={line:`Line`,hLine:`H-Line`,vLine:`V-Line`,arc:`Arc`,tArc:`T-Arc`,tLine:`T-Line`},Ev=class{el;labelSpan;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute z-[999] pointer-events-none hidden`;let t=document.createElement(`div`);t.className=`panel-bg border border-base-content/10 rounded-md px-2 py-0.5 shadow-sm flex items-center gap-1.5`,this.labelSpan=document.createElement(`span`),this.labelSpan.className=`text-xs font-mono text-base-content/70`;let n=document.createElement(`span`);n.className=`text-[10px] text-base-content/30`,n.textContent=`Space`,t.appendChild(this.labelSpan),t.appendChild(n),this.el.appendChild(t),e.appendChild(this.el)}show(e){this.labelSpan.textContent=Tv[e],this.el.classList.remove(`hidden`)}hide(){this.el.classList.add(`hidden`)}update(e){this.labelSpan.textContent=Tv[e]}updatePosition(e,t){this.el.style.left=`${e+16}px`,this.el.style.top=`${t+16}px`}dispose(){this.el.remove()}},Dv=class{id=`line`;label=`Line`;requiresTangent=!1;mousePoint=null;lastSnapType=`none`;enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null}handleClick(e,t,n){let r=Y(n.startPoint),i=Y(e),a=n.isAtCurrentPosition(r)?`line(${n.formatPoint(i)})`:`line(${n.formatPoint(r)}, ${n.formatPoint(i)})`;n.insertGeometry(a);let o=i[0]-r[0],s=i[1]-r[1],c=Math.sqrt(o*o+s*s);return{kind:`committed`,result:{endpoint:i,exitTangent:c>1e-10?{direction:[o/c,s/c],point:i}:null}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return!1}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint&&(Z_(e.previewGroup,e.startPoint,this.mousePoint,e.plane),this.lastSnapType!==`none`)){let t=this.lastSnapType===`vertex`?Z:q_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}},Ov=class{id;label;requiresTangent=!1;axis;mousePoint=null;lastSnapType=`none`;constructor(e){this.axis=e,this.id=e===`h`?`hLine`:`vLine`,this.label=e===`h`?`H-Line`:`V-Line`}enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null,e.hideExpressionInput()}getEffectiveEnd(e,t){return this.axis===`h`?[t[0],e[1]]:[e[0],t[1]]}getDistance(e,t){return this.axis===`h`?t[0]-e[0]:t[1]-e[1]}handleClick(e,t,n){if(n.isExpressionVisible())return n.commitExpressionValue(),{kind:`ignored`};let r=Y(n.startPoint),i=this.getDistance(r,e),a=Math.round(i*100)/100;if(a===0)return{kind:`ignored`};let o=n.isAtCurrentPosition(r),s=this.axis===`h`?`hLine`:`vLine`,c=o?`${s}(${a})`:`${s}(${n.formatPoint(r)}, ${a})`;n.insertGeometry(c),n.hideExpressionInput();let l=Y(this.axis===`h`?[r[0]+a,r[1]]:[r[0],r[1]+a]);return{kind:`committed`,result:{endpoint:l,exitTangent:{direction:this.axis===`h`?[Math.sign(a)||1,0]:[0,Math.sign(a)||1],point:l}}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType;let a=Math.abs(this.getDistance(i.startPoint,e)),o=this.axis===`h`?`H:`:`V:`;i.isExpressionVisible()?(i.updateExpressionValue(a),i.updateExpressionPosition(n,r)):i.showExpressionInput({label:o,value:String(Math.round(a*100)/100),clientX:n,clientY:r,onCommit:e=>this.commitWithDimension(e,i)})}handleEscape(e){return e.isExpressionVisible()?(e.hideExpressionInput(),!0):!1}commitWithDimension(e,t){let n=Y(t.startPoint);if(!this.mousePoint)return;let{expression:r,newVariable:i}=e,a=this.getDistance(n,this.mousePoint),o=Math.sign(a),s=parseFloat(r),c=!isNaN(s)&&String(s)===r?String(Math.round(o*s*100)/100):r,l=t.isAtCurrentPosition(n),u=this.axis===`h`?`hLine`:`vLine`,d=l?`${u}(${c})`:`${u}(${t.formatPoint(n)}, ${c})`;t.insertGeometry(d,i),t.hideExpressionInput();let f=parseFloat(c),p=isNaN(f)?Math.round(o*Math.abs(this.getDistance(n,this.mousePoint))*100)/100:f,m=this.axis===`h`?[n[0]+p,n[1]]:[n[0],n[1]+p],h=this.axis===`h`?[Math.sign(p)||1,0]:[0,Math.sign(p)||1];t.onSegmentCommitted({endpoint:Y(m),exitTangent:{direction:h,point:Y(m)}})}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint){let t=this.getEffectiveEnd(e.startPoint,this.mousePoint);if(Z_(e.previewGroup,e.startPoint,t,e.plane),this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(e.previewGroup,t,n,e.camera,e.planeNormal,e.plane,.6)}}}},kv=function(e){return e[e.AWAITING_END=0]=`AWAITING_END`,e[e.AWAITING_THROUGH=1]=`AWAITING_THROUGH`,e}(kv||{}),Av=class{id=`arc`;label=`Arc`;requiresTangent=!1;subState=kv.AWAITING_END;endPoint=null;mousePoint=null;lastSnapType=`none`;enter(e){this.subState=kv.AWAITING_END,this.endPoint=null,this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.subState=kv.AWAITING_END,this.endPoint=null,this.mousePoint=null}handleClick(e,t,n){if(this.subState===kv.AWAITING_END)return Dp(n.startPoint,e)<1e-6?{kind:`ignored`}:(this.endPoint=e,this.subState=kv.AWAITING_THROUGH,{kind:`consumed`});if(!this.endPoint)return{kind:`ignored`};let r=uv(n.startPoint,this.endPoint,e);if(!r)return{kind:`ignored`};let i=this.isMouseCCW(n.startPoint,this.endPoint,e,r),a=Y(n.startPoint),o=Y(this.endPoint),s=Y(r),c=i?``:`.cw()`,l=n.isAtCurrentPosition(a)?`arc(${n.formatPoint(o)}).center(${n.formatPoint(s)})${c}`:`arc(${n.formatPoint(a)}, ${n.formatPoint(o)}).center(${n.formatPoint(s)})${c}`;return n.insertGeometry(l),{kind:`committed`,result:{endpoint:o,exitTangent:this.computeExitTangent(o,s,i)}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return this.subState===kv.AWAITING_THROUGH?(this.endPoint=null,this.subState=kv.AWAITING_END,!0):!1}isMouseCCW(e,t,n,r){let i=cv(r,e),a=cv(r,t),o=cv(r,n)-i;o<0&&(o+=Math.PI*2);let s=a-i;return s<0&&(s+=Math.PI*2),o<s}semicirclePreview(e,t){let n=t[0]-e[0],r=t[1]-e[1],i=Math.sqrt(n*n+r*r);if(i<1e-6)return null;let a=[(e[0]+t[0])/2,(e[1]+t[1])/2];return{center:a,radius:i/2,startAngle:cv(a,e),endAngle:cv(a,t)}}computeExitTangent(e,t,n){let r=e[0]-t[0],i=e[1]-t[1],a=Math.sqrt(r*r+i*i);return a<1e-10?null:{direction:[n?-i/a:i/a,n?r/a:-r/a],point:e}}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.subState===kv.AWAITING_END){if(this.mousePoint){let t=this.semicirclePreview(e.startPoint,this.mousePoint);if(t&&rv(e.previewGroup,t.center,t.radius,t.startAngle,t.endAngle,!0,e.plane),this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:q_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}else if(this.endPoint&&(Q(e.previewGroup,this.endPoint,X,e.camera,e.planeNormal,e.plane),Z_(e.previewGroup,e.startPoint,this.endPoint,e.plane),this.mousePoint)){let t=uv(e.startPoint,this.endPoint,this.mousePoint);if(t){let n=Dp(t,e.startPoint),r=cv(t,e.startPoint),i=cv(t,this.endPoint),a=this.isMouseCCW(e.startPoint,this.endPoint,this.mousePoint,t);rv(e.previewGroup,t,n,r,i,a,e.plane)}if(this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:q_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}},jv=class{id=`tArc`;label=`T-Arc`;requiresTangent=!0;mousePoint=null;lastSnapType=`none`;enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null}handleClick(e,t,n){if(!n.tangent)return{kind:`ignored`};let r=Y(e);n.insertGeometry(`tArc(${n.formatPoint(r)})`);let i=this.computeArcPreview(n.startPoint,e,n.tangent.direction),a=null;if(i){let e=r[0]-i.center[0],t=r[1]-i.center[1],n=Math.sqrt(e*e+t*t);n>1e-10&&(a={direction:[i.ccw?-t/n:t/n,i.ccw?e/n:-e/n],point:r})}return{kind:`committed`,result:{endpoint:r,exitTangent:a}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return!1}computeArcPreview(e,t,n){let r=-n[1],i=n[0],a=e[0]-t[0],o=e[1]-t[1],s=a*a+o*o,c=a*r+o*i;if(Math.abs(c)<1e-10)return null;let l=-s/(2*c),u=Math.abs(l),d=[e[0]+r*l,e[1]+i*l];return{center:d,radius:u,startAngle:cv(d,e),endAngle:cv(d,t),ccw:l>=0}}rebuildPreview(e){if(e.tangent&&(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint)){let t=this.computeArcPreview(e.startPoint,this.mousePoint,e.tangent.direction);if(t&&rv(e.previewGroup,t.center,t.radius,t.startAngle,t.endAngle,t.ccw,e.plane),this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:q_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}},Mv=class{id=`tLine`;label=`T-Line`;requiresTangent=!0;mousePoint=null;enter(e){this.mousePoint=null}exit(e){this.mousePoint=null,e.hideExpressionInput()}projectOnTangent(e,t,n){let r=t[0]-e[0],i=t[1]-e[1],a=r*n[0]+i*n[1];return{projected:[e[0]+n[0]*a,e[1]+n[1]*a],distance:a}}handleClick(e,t,n){if(!n.tangent)return{kind:`ignored`};if(n.isExpressionVisible())return n.commitExpressionValue(),{kind:`ignored`};if(!this.mousePoint)return{kind:`ignored`};let{distance:r}=this.projectOnTangent(n.startPoint,this.mousePoint,n.tangent.direction),i=Math.round(r*100)/100;if(i===0)return{kind:`ignored`};n.insertGeometry(`tLine(${i})`),n.hideExpressionInput();let a=Y([n.startPoint[0]+n.tangent.direction[0]*r,n.startPoint[1]+n.tangent.direction[1]*r]);return{kind:`committed`,result:{endpoint:a,exitTangent:{direction:n.tangent.direction,point:a}}}}handleMouseMove(e,t,n,r,i){if(this.mousePoint=e,!i.tangent)return;let{distance:a}=this.projectOnTangent(i.startPoint,e,i.tangent.direction),o=Math.abs(a);i.isExpressionVisible()?(i.updateExpressionValue(o),i.updateExpressionPosition(n,r)):i.showExpressionInput({label:`T:`,value:String(Math.round(o*100)/100),clientX:n,clientY:r,onCommit:e=>this.commitWithDimension(e,i)})}handleEscape(e){return e.isExpressionVisible()?(e.hideExpressionInput(),!0):!1}commitWithDimension(e,t){if(!t.tangent||!this.mousePoint)return;let{expression:n,newVariable:r}=e,{distance:i}=this.projectOnTangent(t.startPoint,this.mousePoint,t.tangent.direction),a=Math.sign(i),o=parseFloat(n),s=!isNaN(o)&&String(o)===n?String(Math.round(a*o*100)/100):n;t.insertGeometry(`tLine(${s})`,r),t.hideExpressionInput();let c=Y([t.startPoint[0]+t.tangent.direction[0]*i,t.startPoint[1]+t.tangent.direction[1]*i]);t.onSegmentCommitted({endpoint:c,exitTangent:{direction:t.tangent.direction,point:c}})}rebuildPreview(e){if(e.tangent&&(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint)){let{projected:t}=this.projectOnTangent(e.startPoint,this.mousePoint,e.tangent.direction);Z_(e.previewGroup,e.startPoint,t,e.plane)}}},Nv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.DRAWING=1]=`DRAWING`,e}({}),Pv=[`line`,`hLine`,`vLine`,`arc`,`tArc`,`tLine`],Fv=class extends R_{id=`polyline`;label=`Polyline`;icon=$h;phase=Nv.IDLE;startPoint=null;currentModeIndex=0;tangent=null;modes;expressionInput;fetchVariables;cachedVariables=[];modeIndicator;sceneObjects=[];sketchId=``;mousePoint=null;lastSnapType=`none`;lastSnapResult=null;lastClientX=0;lastClientY=0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.modeIndicator=new Ev(i),this.modes=[new Dv,new Ov(`h`),new Ov(`v`),new Av,new jv,new Mv],this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.expressionInput.onSpaceOverride=()=>{this.cycleMode(1)}}get currentMode(){return this.modes[this.currentModeIndex]}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e}),this.modeIndicator.show(this.currentMode.id)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.expressionInput.hide(),this.modeIndicator.dispose(),this.phase=Nv.IDLE,this.startPoint=null,this.tangent=null,this.removePreviewFromScene()}onSceneUpdate(e,t){this.sceneObjects=e,this.sketchId=t;let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e}),this.phase===Nv.DRAWING&&this.startPoint&&this.updateTangentFromScene()}handleEscape(){return!1}buildModeContext(){if(!this.startPoint)return null;let e=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);return{plane:this.plane,previewGroup:this.previewGroup,camera:this.ctx.camera,planeNormal:e,tangent:this.tangent,sceneObjects:this.sceneObjects,sketchId:this.sketchId,startPoint:this.startPoint,isAtCurrentPosition:e=>this.isAtCurrentPosition(e),formatPoint:e=>this.formatPoint(e),insertGeometry:(e,t)=>this.insertGeometry(e,t),requestRender:()=>this.requestRender(),showExpressionInput:e=>{this.expressionInput.isVisible||this.expressionInput.show({...e,variables:this.cachedVariables})},updateExpressionValue:e=>this.expressionInput.updateValue(e),updateExpressionPosition:(e,t)=>this.expressionInput.updatePosition(e,t),hideExpressionInput:()=>this.expressionInput.hide(),isExpressionVisible:()=>this.expressionInput.isVisible,commitExpressionValue:()=>this.expressionInput.commitCurrentValue(),onSegmentCommitted:e=>this.handleModeCommit(e)}}handleModeCommit(e){let{endpoint:t,exitTangent:n}=e;this.startPoint=t,this.tangent=n,this.currentMode.requiresTangent&&!this.tangent&&(this.advanceToNextValidMode(),this.modeIndicator.update(this.currentMode.id));let r=this.buildModeContext();this.currentMode.enter(r),this.rebuildPreview()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=this.snapController.snap(r),a=Y(i.point2d);if(this.phase===Nv.IDLE){this.startPoint=a,this.phase=Nv.DRAWING,this.tangent=this.findTangentAtPoint(a),this.currentMode.requiresTangent&&!this.tangent&&this.advanceToNextValidMode();let e=this.buildModeContext();this.currentMode.enter(e),this.modeIndicator.update(this.currentMode.id),this.rebuildPreview();return}let o=this.buildModeContext();if(!o)return;let s=this.currentMode.handleClick(a,i,o);s.kind===`committed`?this.handleModeCommit(s.result):this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);if(this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.lastSnapResult=n,this.modeIndicator.updatePosition(e.clientX,e.clientY),this.phase===Nv.DRAWING){let t=this.buildModeContext();t&&this.currentMode.handleMouseMove(n.point2d,n,e.clientX,e.clientY,t)}this.rebuildPreview()}handleKeyDown(e){if(e.key===` `){e.preventDefault(),this.cycleMode(e.shiftKey?-1:1);return}}cycleMode(e){let t=this.buildModeContext();t&&(this.expressionInput.hide(),this.currentMode.exit(t));let n=this.currentModeIndex;for(let t=0;t<Pv.length&&(this.currentModeIndex=(this.currentModeIndex+e+Pv.length)%Pv.length,!(!this.modes[this.currentModeIndex].requiresTangent||this.tangent||this.currentModeIndex===n));t++);if(this.modeIndicator.update(this.currentMode.id),this.phase===Nv.DRAWING){let e=this.buildModeContext();e&&(this.currentMode.enter(e),this.mousePoint&&this.lastSnapResult&&this.currentMode.handleMouseMove(this.mousePoint,this.lastSnapResult,this.lastClientX,this.lastClientY,e))}this.rebuildPreview()}advanceToNextValidMode(){let e=this.currentModeIndex;for(let t=0;t<Pv.length;t++)if(this.currentModeIndex=(this.currentModeIndex+1)%Pv.length,!this.modes[this.currentModeIndex].requiresTangent||this.tangent||this.currentModeIndex===e)return}findTangentAtPoint(e){if(!this.isAtCurrentPosition(Y(e)))return null;let t=null;for(let e of this.sceneObjects)e.parentId!==this.sketchId||!e.sourceLocation||pv.has(e.uniqueType??``)&&(t=e);if(!t)return null;for(let n of t.sceneShapes)if(!n.isMetaShape)for(let t of n.meshes){let n=mv(t.vertices,this.plane);if(n.length<2)continue;let r=hv(n,`end`);if(r)return{direction:r,point:e}}return null}updateTangentFromScene(){if(!this.startPoint||this.tangent)return;let e=this.findTangentAtPoint(this.startPoint);e&&(this.tangent=e)}rebuildPreview(){this.disposePreview();let e=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.phase===Nv.DRAWING){let e=this.buildModeContext();e&&this.currentMode.rebuildPreview(e)}else if(this.mousePoint&&this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,t,this.ctx.camera,e,this.plane,.6)}this.requestRender()}},Iv=class extends R_{id=`bezier`;label=`Bezier`;icon=eg;activeSourceLocation=null;existingPoles=[];mousePoint=null;lastSnapType=`none`;pendingFirstClick=!1;pendingStart=null;boundMouseDown;boundMouseUp;boundMouseMove;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.activeSourceLocation=null,this.existingPoles=[],this.mousePoint=null,this.lastSnapType=`none`,this.pendingFirstClick=!1,this.pendingStart=null,this.removePreviewFromScene()}handleEscape(){return!1}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);if(this.updateSnapManager(n),!this.activeSourceLocation&&!this.pendingFirstClick){this.rebuildPreview();return}let r=null;for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.parentId===t&&i.type===`bezier`){r=i;break}}if(r&&r.sourceLocation){let e=r.object?.startPoint,t=r.object?.resolvedPoints;this.activeSourceLocation=r.sourceLocation,this.existingPoles=e?[e,...t??[]]:[],this.pendingFirstClick=!1,this.pendingStart=null}this.rebuildPreview()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64||this.pendingFirstClick)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.activeSourceLocation){this.insertGeometry(`bezier(${this.formatPoint(i)})`),this.pendingFirstClick=!0,this.pendingStart=i,this.rebuildPreview();return}Am(i,this.activeSourceLocation)}handleMouseMove(e){let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),n=[...this.existingPoles];if(n.length===0&&this.pendingStart&&n.push(this.pendingStart),this.mousePoint&&(this.activeSourceLocation||this.pendingStart)&&n.push(this.mousePoint),n.length>=2){for(let e=1;e<n.length;e++)Z_(this.previewGroup,n[e-1],n[e],this.plane);av(this.previewGroup,n,this.plane)}for(let r=0;r<n.length;r++){let i=r===0?X:K_,a=r===0?1:.85;Q(this.previewGroup,n[r],i,e,t,this.plane,a)}this.mousePoint&&this.lastSnapType!==`none`&&Q(this.previewGroup,this.mousePoint,X_(this.lastSnapType),e,t,this.plane,.6),this.requestRender()}},Lv=3,Rv=24,zv=6,Bv=25,Vv=class extends R_{id=`polygon`;label=`Polygon`;icon=Qh;centerPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`diameter`;diameterExpression=null;lockedDiameter=null;currentSides=zv;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new G_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=h_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.centerPoint=null,this.mousePoint=null,this.expressionPhase=`diameter`,this.diameterExpression=null,this.lockedDiameter=null,this.currentSides=zv,this.expressionInput.hide()}sidesFromDistance(e){if(this.lockedDiameter!==null&&this.lockedDiameter>0){let t=e/(this.lockedDiameter/2);return Math.max(Lv,Math.min(Rv,Math.round(t*zv)))}let t=Ep(this.ctx,Bv);return t<=0?zv:Math.max(Lv,Math.min(Rv,Math.round(e/t)))}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.centerPoint){this.centerPoint=i,this.rebuildPreview();return}if(this.expressionInput.isVisible){this.expressionInput.commitCurrentValue();return}if(this.expressionPhase===`diameter`){let e=Math.round(Dp(this.centerPoint,i)*2*100)/100;if(e<=0)return;this.onDiameterCommit({expression:String(e)})}else this.onSidesCommit({expression:String(this.currentSides)})}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);if(this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.centerPoint&&this.expressionPhase===`sides`){let e=Dp(this.centerPoint,this.mousePoint);this.currentSides=this.sidesFromDistance(e)}this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&this.centerPoint&&(this.resetState(),this.rebuildPreview())}updateDimensionInput(){if(!(!this.centerPoint||!this.mousePoint))if(this.expressionPhase===`diameter`){let e=Math.round(Dp(this.centerPoint,this.mousePoint)*2*100)/100;if(e<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`⌀`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onDiameterCommit(e)})}else this.expressionInput.isVisible?(this.expressionInput.updateValue(this.currentSides),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`N`,value:String(this.currentSides),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onSidesCommit(e)})}onDiameterCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.diameterExpression=e,this.lockedDiameter=n?t:null,this.expressionPhase=`sides`,queueMicrotask(()=>{if(this.mousePoint&&this.centerPoint){let e=Dp(this.centerPoint,this.mousePoint);this.currentSides=this.sidesFromDistance(e)}this.expressionInput.show({label:`N`,value:String(this.currentSides),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onSidesCommit(e)}),this.rebuildPreview()})}onSidesCommit(e){!this.centerPoint||!this.diameterExpression||(this.commitPolygon(this.centerPoint,this.diameterExpression,e),this.resetState(),this.rebuildPreview())}commitPolygon(e,t,n){let r=this.isAtCurrentPosition(e)?`polygon(${n.expression}, ${t.expression})`:`polygon(${this.formatPoint(e)}, ${n.expression}, ${t.expression})`,i=n.newVariable??t.newVariable;this.insertGeometry(r,i)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.centerPoint){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint)if(this.expressionPhase===`diameter`){let e=Dp(this.centerPoint,this.mousePoint);e>0&&Q_(this.previewGroup,this.centerPoint,e,this.plane)}else{let e=this.lockedDiameter===null?Dp(this.centerPoint,this.mousePoint):this.lockedDiameter/2;if(e>0&&this.currentSides>=Lv){let t=e/Math.cos(Math.PI/this.currentSides);nv(this.previewGroup,this.centerPoint,t,this.currentSides,this.plane)}}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:q_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}};function Hv(e,t,n,r,i){let a=t.filter(e=>e.parentId===n),o=Ep(i,12),s=o*o,c=null,l=1/0;for(let t of a){if(!t.sourceLocation||!gp(t.uniqueType))continue;let n=t.uniqueType,i=t.sourceLocation;if(n&&n.startsWith(`bezier-`)){let r=Jv(e,t,i,n,s,l);r&&(c=r.hit,l=r.distSq);continue}if(n===`polygon`){let n=[];for(let e of t.sceneShapes)if(!e.isMetaShape)for(let t of e.meshes){let e=mv(t.vertices,r);for(let t of e)n.push(t)}if(n.length>0){let r=Xv(e,n,i,t,s,l);r&&(c=r.hit,l=r.distSq)}continue}if(n===`slot`){let n=[];for(let e of t.sceneShapes)if(e.isMetaShape){for(let t of e.meshes)if(t.vertices.length===3&&t.indices.length===0){let e=mv(t.vertices,r);e.length===1&&n.push(e[0])}}if(n.length===2){let a=Zv(e,n,i,t,r,s,l);a&&(c=a.hit,l=a.distSq)}continue}if(n===`rect`){let n=[];for(let e of t.sceneShapes)if(!e.isMetaShape)for(let t of e.meshes){let e=mv(t.vertices,r);for(let t of e)n.push(t)}if(n.length>0){let r=Yv(e,n,i,t,s,l);r&&(c=r.hit,l=r.distSq)}continue}for(let a of t.sceneShapes)if(!a.isMetaShape)for(let o of a.meshes){let a=mv(o.vertices,r);if(a.length!==0)if(n===`circle`){let t=Uv(e,a,i,s,l);t&&(c=t.hit,l=t.distSq)}else if(n===`line-two-points`||n===`hline`||n===`vline`||n===`tline`){let r=Wv(e,a,i,n,t,s,l);r&&(c=r.hit,l=r.distSq)}else if(n===`arc`&&a.length>=3){let n=Kv(e,a,i,t,r,s,l);n&&(c=n.hit,l=n.distSq)}else if((n===`tarc-to-point`||n===`tarc-to-point-tangent`)&&a.length>=2){let o=qv(e,a,i,n,t,r,s,l);o&&(c=o.hit,l=o.distSq)}else for(let t of a){let r=t[0]-e[0],a=t[1]-e[1],o=r*r+a*a;o<s&&o<l&&(c={sourceLocation:i,uniqueType:n||``,hitZone:`body`},l=o)}}}return c}function Uv(e,t,n,r,i){let a=[];for(let e of t){let t=!1;for(let n of a){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||a.push(e)}let o=0,s=0;for(let e of a)o+=e[0],s+=e[1];o/=a.length,s/=a.length;let c=a[0],l=c[0]-o,u=c[1]-s,d=Math.sqrt(l*l+u*u),f=Math.round(2*d*100)/100,p=null;for(let a of t){let t=a[0]-e[0],c=a[1]-e[1],l=t*t+c*c;l<r&&l<i&&(p={hit:{sourceLocation:n,uniqueType:`circle`,hitZone:`body`,anchorPoint:[o,s],initialValue:f},distSq:l},i=l)}return p}function Wv(e,t,n,r,i,a,o){let s=t[0],c=t[t.length-1],l=s[0]-e[0],u=s[1]-e[1],d=l*l+u*u,f=c[0]-e[0],p=c[1]-e[1],m=f*f+p*p,h=r===`hline`||r===`vline`||r===`tline`,g,_;if(r===`tline`){let e=c[0]-s[0],n=c[1]-s[1],r=Math.sqrt(e*e+n*n);if(r>1e-10){if(_=[e/r,n/r],g=r,t.length>=2){let e=t[t.length-2],n=t[t.length-1],r=n[0]-e[0],i=n[1]-e[1],a=Math.sqrt(r*r+i*i);a>1e-10&&(_=[r/a,i/a])}let i=c[0]-s[0],a=c[1]-s[1];g=i*_[0]+a*_[1]}}else (r===`hline`||r===`vline`)&&(g=r===`hline`?c[0]-s[0]:c[1]-s[1]);let v=h?Math.round((g??0)*100)/100:void 0,y=d<a||m<a,b=null;if(m<a&&m<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`end`,anchorPoint:s,fixedVertex:s,initialValue:v,draggedVertices:[c],tangentDir:_},distSq:m},o=m),r!==`tline`&&i.object?.hasExplicitStart===!0&&!(h&&i.object?.centered===!0)&&d<a&&d<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`start`,anchorPoint:s,fixedVertex:c,originalDistance:g,draggedVertices:[s]},distSq:d},o=d),!y&&r===`line-two-points`){let t=bp(e[0],e[1],s[0],s[1],c[0],c[1]),i=t*t;i<a&&i<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`body`,anchorPoint:s,fixedVertex:c,originalDistance:g,initialValue:v,draggedVertices:[s,c]},distSq:i})}return b}function Gv(e,t){for(let n of e.sceneShapes)if(n.isMetaShape){for(let e of n.meshes)if(e.vertices.length===3&&e.indices.length===0){let n=mv(e.vertices,t);if(n.length===1)return n[0]}}return null}function Kv(e,t,n,r,i,a,o){let s=t[0],c=t[t.length-1],l=r.object?.startPoint!==void 0,u=l?3:2,d=Gv(r,i);if(!d){let e=t[Math.floor(t.length/2)];d=uv(s,e,c)}if(!d)return null;let f=t[Math.floor(t.length/2)],p=dv(d,s,f),m=s[0]-e[0],h=s[1]-e[1],g=m*m+h*h,_=c[0]-e[0],v=c[1]-e[1],y=_*_+v*v,b=d[0]-e[0],x=d[1]-e[1],S=b*b+x*x,C=Math.min(g,y,S),w=null;return l&&g<a&&g<o&&g===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`start`,anchorPoint:d,fixedVertex:c,draggedVertices:[s],arcCCW:p,arcArgCount:u},distSq:g},o=g),y<a&&y<o&&y===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`end`,anchorPoint:d,fixedVertex:s,draggedVertices:[c],arcCCW:p,arcArgCount:u},distSq:y},o=y),S<a&&S<o&&S===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`center`,anchorPoint:d,fixedVertex:s,fixedVertex2:c,draggedVertices:[d],arcCCW:p,arcArgCount:u},distSq:S}),w}function qv(e,t,n,r,i,a,o,s){let c=t[0],l=t[t.length-1],u=t[1][0]-c[0],d=t[1][1]-c[1],f=Math.sqrt(u*u+d*d),p=f>1e-10?[u/f,d/f]:[1,0],m=Gv(i,a);if(!m){let e=t[Math.floor(t.length/2)];m=uv(c,e,l)}let h=t[Math.floor(t.length/2)],g=m?dv(m,c,h):!0,_=l[0]-e[0],v=l[1]-e[1],y=_*_+v*v,b=null;if(y<o&&y<s&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`end`,anchorPoint:c,fixedVertex:c,draggedVertices:[l],tangentDir:p,arcCCW:g},distSq:y},s=y),m){let t=m[0]-e[0],i=m[1]-e[1],a=t*t+i*i;a<o&&a<s&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`center`,anchorPoint:c,fixedVertex:c,fixedVertex2:l,draggedVertices:[m],tangentDir:p,arcCCW:g},distSq:a})}return b}function Jv(e,t,n,r,i,a){let o=t.object?.startPoint,s=t.object?.resolvedPoints??[],c=o?[o,...s]:s;if(c.length===0)return null;let l=null;for(let t=0;t<c.length;t++){let o=c[t],s=o[0]-e[0],u=o[1]-e[1],d=s*s+u*u;d<i&&d<a&&(l={hit:{sourceLocation:n,uniqueType:r,hitZone:`end`,anchorPoint:o,draggedVertices:[o],bezierPoleIndex:t,bezierPoles:c},distSq:d},a=d)}return l}function Yv(e,t,n,r,i,a){if(r.object?.radius)return null;let o=[];for(let e of t){let t=!1;for(let n of o){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||o.push(e)}if(o.length<4)return null;let s=r.object?.centered===!0,c;if(s){let e=0,t=0;for(let n of o)e+=n[0],t+=n[1];c=[e/o.length,t/o.length]}let l=null;for(let t of o){let r=t[0]-e[0],u=t[1]-e[1],d=r*r+u*u;if(d<i&&d<a){let e;if(s&&c)e=c;else{let n=-1;e=o[0];for(let r of o){let i=r[0]-t[0],a=r[1]-t[1],o=i*i+a*a;o>n&&(n=o,e=r)}}l={hit:{sourceLocation:n,uniqueType:`rect`,hitZone:`end`,anchorPoint:e,fixedVertex:e,draggedVertices:[t],rectCentered:s},distSq:d},a=d}}return l}function Xv(e,t,n,r,i,a){let o=[];for(let e of t){let t=!1;for(let n of o){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||o.push(e)}let s=0,c=0;for(let e of o)s+=e[0],c+=e[1];s/=o.length,c/=o.length;let l=o[0],u=l[0]-s,d=l[1]-c,f=Math.sqrt(u*u+d*d),p=r.object?.numberOfSides??o.length,m=r.object?.diameter??Math.round(2*f*100)/100,h=null;for(let r of t){let t=r[0]-e[0],o=r[1]-e[1],l=t*t+o*o;l<i&&l<a&&(h={hit:{sourceLocation:n,uniqueType:`polygon`,hitZone:`body`,anchorPoint:[s,c],initialValue:m,originalDistance:f,polygonSides:p},distSq:l},a=l)}return h}function Zv(e,t,n,r,i,a,o){let s=t[0],c=t[1],l=r.object?.hasTwoPoints??!1,u=r.object?.radius??0,d=c[0]-s[0],f=c[1]-s[1],p=Math.sqrt(d*d+f*f),m;if(l)m=p>1e-10?[d/p,f/p]:[1,0];else{let e=(r.object?.angle??0)*Math.PI/180;m=[Math.cos(e),Math.sin(e)]}let h={sourceLocation:n,uniqueType:`slot`,initialValue:u,slotHasTwoPoints:l,slotAxisDir:m,slotRadius:u};function g(){return{...h,hitZone:`start`,anchorPoint:s,fixedVertex:c,slotOtherCenter:c,slotPointIndex:0,draggedVertices:[s]}}function _(){return{...h,hitZone:`end`,anchorPoint:c,fixedVertex:s,slotOtherCenter:s,slotPointIndex:1,draggedVertices:[c]}}let v=null,y=s[0]-e[0],b=s[1]-e[1],x=y*y+b*b,S=c[0]-e[0],C=c[1]-e[1],w=S*S+C*C;x<a&&x<o&&x<=w&&(v={hit:g(),distSq:x},o=x),w<a&&w<o&&(v={hit:_(),distSq:w},o=w);for(let t of r.sceneShapes)if(!t.isMetaShape)for(let n of t.meshes){let t=mv(n.vertices,i);for(let n of t){let t=n[0]-e[0],r=n[1]-e[1],i=t*t+r*r;i<a&&i<o&&(v={hit:{...h,hitZone:`body`,anchorPoint:s,fixedVertex:c,slotOtherCenter:c,slotRadius:u},distSq:i},o=i)}}return v}function Qv(e,t,n){let r=(t[0]+n[0])/2,i=(t[1]+n[1])/2,a=n[0]-t[0],o=-(n[1]-t[1]),s=a,c=o*o+s*s;if(c<1e-10)return e;let l=((e[0]-r)*o+(e[1]-i)*s)/c;return[r+l*o,i+l*s]}function $v(e,t,n){let r=-n[1],i=n[0],a=(e[0]-t[0])*r+(e[1]-t[1])*i;return[t[0]+a*r,t[1]+a*i]}function ey(e,t,n){let r=-n[1],i=n[0],a=e[0]-t[0],o=e[1]-t[1],s=a*a+o*o,c=a*r+o*i;if(Math.abs(c)<1e-10)return null;let l=-s/(2*c),u=Math.abs(l),d=[e[0]+r*l,e[1]+i*l];return{center:d,radius:u,startAngle:cv(d,e),endAngle:cv(d,t),ccw:l>=0}}function ty(e,t,n){let r=(t[0]+n[0])/2,i=(t[1]+n[1])/2,a=n[0]-t[0],o=-(n[1]-t[1]),s=a,c=o*o+s*s;if(c<1e-10)return e;let l=e[0]-r,u=e[1]-i,d=(l*o+u*s)/c;return[r+d*o,i+d*s]}var $=5;function ny(e,t,n,r,i,a){let o=new R(a.normal.x,a.normal.y,a.normal.z),{uniqueType:s,hitZone:c,anchorPoint:l,fixedVertex:u}=r;if(s===`polygon`&&l&&r.polygonSides){let n=l,s=t[0]-n[0],c=t[1]-n[1],u=Math.sqrt(s*s+c*c);Q(e,n,X,i,o,a,1,$),nv(e,n,u,r.polygonSides,a,$),Q(e,t,Z,i,o,a,1,$)}else if(s===`circle`&&l){let n=l,r=t[0]-n[0],s=t[1]-n[1],c=Math.sqrt(r*r+s*s);Q(e,n,X,i,o,a,1,$),Q_(e,n,c,a,$)}else if(s===`tline`&&l&&r.tangentDir){let n=l,s=r.tangentDir,c=t[0]-n[0],u=t[1]-n[1],d=c*s[0]+u*s[1],f=[n[0]+s[0]*d,n[1]+s[1]*d];Q(e,n,X,i,o,a,1,$),Z_(e,n,f,a,$),Q(e,f,Z,i,o,a,1,$)}else if(s===`hline`||s===`vline`)if(c===`end`){let n=l,r=s===`hline`?[t[0],n[1]]:[n[0],t[1]];Q(e,n,X,i,o,a,1,$),Z_(e,n,r,a,$),Q(e,r,Z,i,o,a,1,$)}else{let n=r.originalDistance??0,c=s===`hline`?[t[0]+n,t[1]]:[t[0],t[1]+n];Q(e,t,X,i,o,a,1,$),Z_(e,t,c,a,$),Q(e,c,Z,i,o,a,1,$)}else if(s===`line-two-points`&&u&&l)if(c===`body`){let n=u[0]-l[0],r=u[1]-l[1],s=[t[0]+n,t[1]+r];Q(e,t,X,i,o,a,1,$),Z_(e,t,s,a,$),Q(e,s,Z,i,o,a,1,$)}else c===`start`?(Q(e,t,Z,i,o,a,1,$),Z_(e,t,u,a,$),Q(e,u,X,i,o,a,1,$)):(Q(e,u,X,i,o,a,1,$),Z_(e,u,t,a,$),Q(e,t,Z,i,o,a,1,$));else if(s===`arc`&&l&&u)ry(e,t,r,i,o,a);else if(s===`rect`&&l)if(r.rectCentered){let n=[2*l[0]-t[0],2*l[1]-t[1]];Q(e,l,X,i,o,a,1,$),$_(e,n,t,a,$),Q(e,t,Z,i,o,a,1,$)}else Q(e,l,X,i,o,a,1,$),$_(e,l,t,a,$),Q(e,t,Z,i,o,a,1,$);else if(s===`slot`&&r.slotRadius!==void 0)if(c===`body`){let n=l,s=u,c=r.slotAxisDir?.[0]??1,d=r.slotAxisDir?.[1]??0,f=t[0]-n[0],p=t[1]-n[1],m=Math.abs(-d*f+c*p);Q(e,n,X,i,o,a,1,$),Q(e,s,X,i,o,a,1,$),m>0?sv(e,n,s,m,a,$):Z_(e,n,s,a,$),Q(e,t,Z,i,o,a,1,$)}else{let n=r.slotOtherCenter,s=r.slotRadius,l=c===`start`?t:n,u=c===`start`?n:t;Q(e,n,X,i,o,a,1,$),s>0?sv(e,l,u,s,a,$):Z_(e,l,u,a,$),Q(e,t,Z,i,o,a,1,$)}else if((s===`tarc-to-point`||s===`tarc-to-point-tangent`)&&u&&r.tangentDir)iy(e,t,r,i,o,a);else if(s.startsWith(`bezier-`)&&r.bezierPoles&&r.bezierPoleIndex!==void 0){let n=r.bezierPoles.slice();n[r.bezierPoleIndex]=t;for(let t=1;t<n.length;t++)Z_(e,n[t-1],n[t],a,$);av(e,n,a,$);for(let t=0;t<n.length;t++)t!==r.bezierPoleIndex&&Q(e,n[t],K_,i,o,a,.85,$);Q(e,t,Z,i,o,a,1,$)}else Q(e,t,Z,i,o,a,1,$),n&&Z_(e,n,t,a,$)}function ry(e,t,n,r,i,a){let{hitZone:o,anchorPoint:s,fixedVertex:c}=n,l=n.arcCCW!==!1;if(o===`center`){let o=c,s=n.fixedVertex2,u=t,d=Math.sqrt((o[0]-u[0])**2+(o[1]-u[1])**2),f=cv(u,o),p=cv(u,s),m=[u[0]+d*Math.cos(p),u[1]+d*Math.sin(p)];Q(e,o,X,r,i,a,1,$),rv(e,u,d,f,p,l,a,$),Q(e,m,X,r,i,a,1,$),Q(e,u,Z,r,i,a,1,$)}else{let n=ty(s,c,t),u=Math.sqrt((t[0]-n[0])**2+(t[1]-n[1])**2);if(o===`start`){let o=cv(n,t),s=cv(n,c);Q(e,t,Z,r,i,a,1,$),rv(e,n,u,o,s,l,a,$),Q(e,c,X,r,i,a,1,$)}else{let o=cv(n,c),s=cv(n,t);Q(e,c,X,r,i,a,1,$),rv(e,n,u,o,s,l,a,$),Q(e,t,Z,r,i,a,1,$)}}}function iy(e,t,n,r,i,a){let{hitZone:o,fixedVertex:s,tangentDir:c}=n,l=s,u=c;if(o===`center`){let o=t,s=n.fixedVertex2,c=Math.sqrt((l[0]-o[0])**2+(l[1]-o[1])**2),u=cv(o,l),d=cv(o,s),f=n.arcCCW!==!1,p=[o[0]+c*Math.cos(d),o[1]+c*Math.sin(d)];Q(e,l,X,r,i,a,1,$),rv(e,o,c,u,d,f,a,$),Q(e,p,X,r,i,a,1,$),Q(e,o,Z,r,i,a,1,$)}else{let n=ey(l,t,u);n?(Q(e,l,X,r,i,a,1,$),rv(e,n.center,n.radius,n.startAngle,n.endAngle,n.ccw,a,$),Q(e,t,Z,r,i,a,1,$)):(Q(e,l,X,r,i,a,1,$),Z_(e,l,t,a,$),Q(e,t,Z,r,i,a,1,$))}}function ay(e){for(;e.children.length>0;){let t=e.children[0];e.remove(t);let n=t;n.geometry&&n.geometry.dispose(),n.material&&n.material.dispose()}}function oy(e,t,n){let r=Y(e),{sourceLocation:i,uniqueType:a,hitZone:o,anchorPoint:s,fixedVertex:c}=t;if(a===`line-two-points`&&o===`body`&&s&&c){let e=c[0]-s[0],t=c[1]-s[1];Fm(r,Y([r[0]+e,r[1]+t]),i);return}if(a===`line-two-points`)Im(r,i,o===`start`?0:-1);else if(a===`arc`&&s&&c){let e=t.arcArgCount===2,n=+!e,a=e?1:2;if(o===`center`){let e=c,o=t.fixedVertex2,s=Math.sqrt((e[0]-r[0])**2+(e[1]-r[1])**2),l=Math.atan2(o[1]-r[1],o[0]-r[0]);Lm([{pointIndex:n,position:Y([r[0]+s*Math.cos(l),r[1]+s*Math.sin(l)])},{pointIndex:a,position:r}],i)}else{let e=Y(ty(s,c,r));Lm([{pointIndex:o===`start`?0:n,position:r},{pointIndex:a,position:e}],i)}}else if((a===`hline`||a===`vline`)&&(o===`start`||o===`body`))Im(r,i,0);else if(a===`tline`&&o===`end`&&s&&t.tangentDir){let e=t.tangentDir,a=r[0]-s[0],o=r[1]-s[1],c=Math.round((a*e[0]+o*e[1])*100)/100,l=n();zm(String(c),i,l)}else if(a===`polygon`&&s&&t.originalDistance&&t.initialValue){let e=r[0]-s[0],a=r[1]-s[1],o=Math.sqrt(e*e+a*a),c=Math.round(t.initialValue*o/t.originalDistance*100)/100,l=n();zm(String(c),i,l)}else if(a===`rect`&&s)if(t.rectCentered)Rm(Math.round(Math.abs(r[0]-s[0])*2*100)/100,Math.round(Math.abs(r[1]-s[1])*2*100)/100,i);else{let e=Math.min(s[0],r[0]),t=Math.min(s[1],r[1]);Rm(Math.round(Math.abs(r[0]-s[0])*100)/100,Math.round(Math.abs(r[1]-s[1])*100)/100,i,Y([e,t]))}else if(a===`tarc-to-point`||a===`tarc-to-point-tangent`){let e=a===`tarc-to-point`?0:1;if(o===`center`&&c&&t.fixedVertex2){let n=c,a=t.fixedVertex2,o=Math.sqrt((n[0]-r[0])**2+(n[1]-r[1])**2),s=Math.atan2(a[1]-r[1],a[0]-r[0]);Im(Y([r[0]+o*Math.cos(s),r[1]+o*Math.sin(s)]),i,e)}else Im(r,i,e)}else if(a===`slot`){if(o===`body`){let e=t.anchorPoint,a=t.slotAxisDir?.[0]??1,o=t.slotAxisDir?.[1]??0,s=r[0]-e[0],c=r[1]-e[1],l=Math.round(Math.abs(-o*s+a*c)*100)/100,u=n();zm(String(l),i,u)}else if(t.slotHasTwoPoints)Im(r,i,t.slotPointIndex??0);else if(o===`start`)Im(r,i,0);else if(t.slotOtherCenter&&t.slotAxisDir){let e=t.slotOtherCenter,a=t.slotAxisDir,o=r[0]-e[0],s=r[1]-e[1],c=Math.round((o*a[0]+s*a[1])*100)/100,l=n();zm(String(c),i,l,void 0,1)}}else a.startsWith(`bezier-`)&&t.bezierPoleIndex!==void 0?Im(r,i,t.bezierPoleIndex):Im(r,i)}var sy=class{expressionInput;fetchVariables;getSketchSourceLine;cachedVariables=[];standaloneInputActive=!1;onRequestEndResize=null;onRequestCloseStandalone=null;constructor(e,t,n){this.expressionInput=new G_(e),this.fetchVariables=t,this.getSketchSourceLine=n}get isVisible(){return this.expressionInput.isVisible}containsElement(e){return this.expressionInput.containsElement(e)}refreshVariables(){return this.fetchVariables().then(e=>{this.cachedVariables=e})}showForDrag(e,t,n,r){let{uniqueType:i,hitZone:a}=e,o=null,s=0;if(i===`polygon`){o=`⌀`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1],a=Math.sqrt(r*r+i*i);s=e.originalDistance&&e.initialValue?Math.round(e.initialValue*a/e.originalDistance*100)/100:Math.round(2*a*100)/100}else if(i===`circle`){o=`⌀`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1];s=Math.round(2*Math.sqrt(r*r+i*i)*100)/100}else if((i===`hline`||i===`vline`)&&a===`end`){o=i===`hline`?`H:`:`V:`;let n=e.anchorPoint;s=i===`hline`?Math.round(Math.abs(t[0]-n[0])*100)/100:Math.round(Math.abs(t[1]-n[1])*100)/100}else if(i===`tline`&&a===`end`&&e.tangentDir){o=`T:`;let n=e.anchorPoint,r=e.tangentDir,i=t[0]-n[0],a=t[1]-n[1];s=Math.round(Math.abs(i*r[0]+a*r[1])*100)/100}else if(i===`slot`&&!e.slotHasTwoPoints&&e.slotOtherCenter&&e.slotAxisDir&&a===`end`){o=`D`;let n=e.slotOtherCenter,r=e.slotAxisDir,i=t[0]-n[0],a=t[1]-n[1];s=Math.round((i*r[0]+a*r[1])*100)/100}else if(i===`slot`&&a===`body`){o=`R`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1];s=Math.round(Math.sqrt(r*r+i*i)*100)/100}o!==null&&this.openInput(o,s,e,n,r,!0)}showForDoubleClick(e,t,n){let r,i;if(e.uniqueType===`polygon`||e.uniqueType===`circle`)r=`⌀`,i=e.initialValue??0;else if(e.uniqueType===`hline`||e.uniqueType===`vline`)r=e.uniqueType===`hline`?`H:`:`V:`,i=Math.abs(e.initialValue??0);else if(e.uniqueType===`tline`)r=`T:`,i=Math.abs(e.initialValue??0);else if(e.uniqueType===`slot`)if(e.hitZone===`start`||e.hitZone===`end`){if(e.slotHasTwoPoints)return!1;r=`D`;let t=e.anchorPoint,n=e.fixedVertex,a=e.slotAxisDir??[1,0];i=Math.round(((n[0]-t[0])*a[0]+(n[1]-t[1])*a[1])*100)/100}else r=`R`,i=e.slotRadius??0;else return!1;return this.standaloneInputActive=!0,this.openInput(r,i,e,t,n,!1),!0}updateValue(e,t){if(!this.expressionInput.isVisible)return;let{uniqueType:n,anchorPoint:r}=e,i;if(n===`polygon`){let n=r,a=t[0]-n[0],o=t[1]-n[1],s=Math.sqrt(a*a+o*o);i=e.originalDistance&&e.initialValue?Math.round(e.initialValue*s/e.originalDistance*100)/100:Math.round(2*s*100)/100}else if(n===`circle`){let e=r,n=t[0]-e[0],a=t[1]-e[1];i=Math.round(2*Math.sqrt(n*n+a*a)*100)/100}else if(n===`tline`&&e.tangentDir){let n=r,a=e.tangentDir,o=t[0]-n[0],s=t[1]-n[1];i=Math.round(Math.abs(o*a[0]+s*a[1])*100)/100}else if(n===`slot`&&e.hitZone===`body`){let n=r,a=e.slotAxisDir?.[0]??1,o=e.slotAxisDir?.[1]??0,s=t[0]-n[0],c=t[1]-n[1];i=Math.round(Math.abs(-o*s+a*c)*100)/100}else if(n===`slot`&&e.slotOtherCenter&&e.slotAxisDir){let n=e.slotOtherCenter,r=e.slotAxisDir,a=t[0]-n[0],o=t[1]-n[1];i=Math.round((a*r[0]+o*r[1])*100)/100}else{let e=r,a=n===`hline`?t[0]-e[0]:t[1]-e[1];i=Math.round(Math.abs(a)*100)/100}this.expressionInput.updateValue(i)}updatePosition(e,t){this.expressionInput.updatePosition(e,t)}updateValueIfUnmoved(e){this.expressionInput.updateValue(e)}commitIfVisible(e){this.expressionInput.isVisible&&e&&this.expressionInput.commitCurrentValue()}hide(){this.expressionInput.hide()}closeStandalone(){this.standaloneInputActive&&(this.standaloneInputActive=!1,this.expressionInput.hide())}openInput(e,t,n,r,i,a){let{sourceLocation:o}=n,s=String(t);this.expressionInput.show({label:e,value:s,clientX:r,clientY:i,variables:this.cachedVariables,onCommit:t=>{let{expression:r,newVariable:i}=t,s=parseFloat(r),c=!isNaN(s)&&String(s)===r,l=r;if(c&&n.uniqueType!==`circle`&&n.uniqueType!==`polygon`&&n.uniqueType!==`slot`){let e=this.computeDistanceSign(n,null);l=String(Math.round(e*s*100)/100)}else c&&(l=String(Math.round(s*100)/100));let u=this.getSketchSourceLine();zm(l,o,u,i,+(e===`D`)),a?this.onRequestEndResize?.():this.closeStandalone()}}),e!==`D`&&Bm(o.line).then(({expression:e})=>{e&&(a||this.standaloneInputActive)&&this.updateValueIfUnmoved(e)})}computeDistanceSign(e,t){if(t){let n=e.anchorPoint;if(e.uniqueType===`tline`&&e.tangentDir){let r=e.tangentDir,i=t[0]-n[0],a=t[1]-n[1];return i*r[0]+a*r[1]>=0?1:-1}return e.uniqueType===`hline`?t[0]>=n[0]?1:-1:t[1]>=n[1]?1:-1}return(e.initialValue??e.originalDistance??0)>=0?1:-1}},cy=class{ctx;plane;snapController;sceneObjects=[];sketchId=``;canvas;previewGroup;_isResizing=!1;hasMoved=!1;hitResult=null;startPoint=null;currentPoint=null;grabOffset=null;pendingHit=null;dimensionInput;getSketchSourceLine;boundCanvasPointerDown;boundPointerMove;boundPointerUp;boundKeyDown;boundCanvasDoubleClick;constructor(e,t,n,r,i,a){this.ctx=e,this.plane=t,this.snapController=n,this.canvas=e.renderer.domElement,this.getSketchSourceLine=a,this.previewGroup=new oi,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=5,this.dimensionInput=new sy(r,i,a),this.dimensionInput.onRequestEndResize=()=>this.endResize(),this.dimensionInput.onRequestCloseStandalone=()=>{this.dimensionInput.closeStandalone(),this.hitResult=null},this.boundCanvasPointerDown=this.handleCanvasPointerDown.bind(this),this.boundPointerMove=this.handlePointerMove.bind(this),this.boundPointerUp=this.handlePointerUp.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundCanvasDoubleClick=this.handleCanvasDoubleClick.bind(this)}get isResizing(){return this._isResizing}activate(){this.ctx.scene.add(this.previewGroup),this.canvas.addEventListener(`pointerdown`,this.boundCanvasPointerDown,{capture:!0}),this.canvas.addEventListener(`dblclick`,this.boundCanvasDoubleClick),window.addEventListener(`pointermove`,this.boundPointerMove),window.addEventListener(`pointerup`,this.boundPointerUp,{capture:!0}),window.addEventListener(`keydown`,this.boundKeyDown)}deactivate(){this.canvas.removeEventListener(`pointerdown`,this.boundCanvasPointerDown,{capture:!0}),this.canvas.removeEventListener(`dblclick`,this.boundCanvasDoubleClick),window.removeEventListener(`pointermove`,this.boundPointerMove),window.removeEventListener(`pointerup`,this.boundPointerUp,{capture:!0}),window.removeEventListener(`keydown`,this.boundKeyDown),this.endResize(),this.dimensionInput.closeStandalone(),this.pendingHit=null,this.ctx.scene.remove(this.previewGroup),ay(this.previewGroup)}updatePlane(e){this.plane=e}updateSnapController(e){this.snapController=e,this._isResizing&&this.hitResult?.draggedVertices&&this.snapController.setExcludedVertices(this.hitResult.draggedVertices)}updateSceneData(e,t){this.sceneObjects=e,this.sketchId=t,this.dimensionInput.refreshVariables()}handleCanvasPointerDown(e){if(e.button!==0||this._isResizing||this.dimensionInput.standaloneInputActive&&this.dimensionInput.containsElement(e.target))return;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t)return;let n=Hv(t,this.sceneObjects,this.sketchId,this.plane,this.ctx);n&&(this.pendingHit={hit:n,point2d:t,clientX:e.clientX,clientY:e.clientY},this.ctx.cameraControls.enabled=!1,e.stopPropagation())}handlePointerUp(e){if(e.button===0){if(this._isResizing){this.commitResize(),e.stopPropagation(),e.preventDefault();return}this.pendingHit&&(this.pendingHit=null,this.ctx.cameraControls.enabled=!0)}}startResize(e){this._isResizing=!0,this.hasMoved=!1,this.hitResult=e.hit,this.startPoint=e.point2d,this.currentPoint=e.point2d;let t=e.hit;t.hitZone===`body`&&t.anchorPoint&&(t.uniqueType===`hline`||t.uniqueType===`vline`||t.uniqueType===`line-two-points`)?this.grabOffset=[e.point2d[0]-t.anchorPoint[0],e.point2d[1]-t.anchorPoint[1]]:this.grabOffset=null,this.ctx.cameraControls.enabled=!1,this.canvas.style.cursor=`crosshair`,this.snapController.setExcludedVertices(t.draggedVertices??[]),this.dimensionInput.showForDrag(t,e.point2d,e.clientX,e.clientY)}commitResize(){this.dimensionInput.isVisible&&this.hasMoved?this.dimensionInput.commitIfVisible(this.hasMoved):this.currentPoint&&this.hitResult&&oy(this.currentPoint,this.hitResult,this.getSketchSourceLine),this.endResize()}handleKeyDown(e){e.key===`Escape`&&(this._isResizing?this.endResize():this.dimensionInput.standaloneInputActive&&(this.dimensionInput.closeStandalone(),this.hitResult=null))}handlePointerMove(e){if(this.pendingHit&&!this._isResizing){let t=e.clientX-this.pendingHit.clientX,n=e.clientY-this.pendingHit.clientY;if(t*t+n*n>=16){let e=this.pendingHit;this.pendingHit=null,this.startResize(e)}else return}if(!this._isResizing)return;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(t){if(this.hasMoved=!0,this.grabOffset&&this.hitResult?.hitZone===`body`){let e=[t[0]-this.grabOffset[0],t[1]-this.grabOffset[1]];this.currentPoint=this.snapController.snap(e).point2d}else this.currentPoint=this.snapController.snap(t).point2d;if(this.hitResult?.hitZone===`start`&&this.hitResult.anchorPoint&&(this.hitResult.uniqueType===`hline`||this.hitResult.uniqueType===`vline`)&&(this.hitResult.uniqueType===`hline`?this.currentPoint=[this.currentPoint[0],this.hitResult.anchorPoint[1]]:this.currentPoint=[this.hitResult.anchorPoint[0],this.currentPoint[1]]),this.hitResult?.uniqueType===`tline`&&this.hitResult.hitZone===`end`&&this.hitResult.anchorPoint&&this.hitResult.tangentDir){let e=this.hitResult.anchorPoint,t=this.hitResult.tangentDir,n=this.currentPoint[0]-e[0],r=this.currentPoint[1]-e[1],i=n*t[0]+r*t[1];this.currentPoint=[e[0]+t[0]*i,e[1]+t[1]*i]}if(this.hitResult?.hitZone===`center`&&this.hitResult.uniqueType===`arc`&&this.hitResult.fixedVertex&&this.hitResult.fixedVertex2&&e.shiftKey&&(this.currentPoint=Qv(this.currentPoint,this.hitResult.fixedVertex,this.hitResult.fixedVertex2)),this.hitResult?.hitZone===`center`&&this.hitResult.tangentDir&&this.hitResult.fixedVertex&&(this.currentPoint=$v(this.currentPoint,this.hitResult.fixedVertex,this.hitResult.tangentDir)),this.hitResult?.uniqueType===`slot`&&!this.hitResult.slotHasTwoPoints&&(this.hitResult.hitZone===`start`||this.hitResult.hitZone===`end`)&&this.hitResult.slotAxisDir&&this.hitResult.slotOtherCenter){let e=this.hitResult.slotAxisDir,t=this.hitResult.slotOtherCenter,n=this.currentPoint[0]-t[0],r=this.currentPoint[1]-t[1],i=n*e[0]+r*e[1];this.currentPoint=[t[0]+e[0]*i,t[1]+e[1]*i]}ay(this.previewGroup),this.currentPoint&&this.hitResult&&ny(this.previewGroup,this.currentPoint,this.startPoint,this.hitResult,this.ctx.camera,this.plane),this.ctx.requestRender(),this.currentPoint&&this.hitResult&&this.dimensionInput.updateValue(this.hitResult,this.currentPoint),this.dimensionInput.updatePosition(e.clientX,e.clientY)}}handleCanvasDoubleClick(e){if(this._isResizing)return;let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t)return;let n=Hv(t,this.sceneObjects,this.sketchId,this.plane,this.ctx);n&&n.uniqueType!==`line-two-points`&&(this.hitResult=n,this.startPoint=null,this.currentPoint=null,this.dimensionInput.showForDoubleClick(n,e.clientX,e.clientY)||(this.hitResult=null))}endResize(){this._isResizing=!1,this.hasMoved=!1,this.hitResult=null,this.startPoint=null,this.currentPoint=null,this.grabOffset=null,this.pendingHit=null,this.ctx.cameraControls.enabled=!0,this.canvas.style.cursor=``,this.snapController.setExcludedVertices([]),this.dimensionInput.hide(),ay(this.previewGroup),this.ctx.requestRender()}},ly=12,uy=2,dy=6,fy=class{ctx;plane;canvas;edges=[];centers=[];hoveredShapeId=null;hoveredCenterOverlay=null;hoveredCenterPoint=null;selectedShapeIds=new Set;isExternalResizing;boundMouseMove;boundMouseDown;boundMouseUp;downX=0;downY=0;constructor(e,t,n){this.ctx=e,this.plane=t,this.canvas=e.renderer.domElement,this.isExternalResizing=n,this.boundMouseMove=this.handleMouseMove.bind(this),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this)}activate(){this.canvas.addEventListener(`mousemove`,this.boundMouseMove),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp)}deactivate(){this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.clearHover(),this.clearSelection(),this.removeCenterOverlay()}updatePlane(e){this.plane=e}updateSceneData(e,t){this.edges=_p(e,t,this.plane),this.centers=yp(e,t,this.plane);let n=new Set(this.edges.map(e=>e.shapeId));for(let e of this.centers)n.add(e.shapeId);this.hoveredShapeId&&!n.has(this.hoveredShapeId)&&this.clearHover();for(let e of this.selectedShapeIds)n.has(e)||(this.removeSelectionHighlight(e),this.selectedShapeIds.delete(e))}get selectedIds(){return this.selectedShapeIds}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseMove(e){if(this.isExternalResizing()){this.hoveredShapeId&&this.clearHover();return}let t=Sp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.hoveredShapeId&&this.clearHover();return}let n=Ep(this.ctx,ly),r=this.findNearestEdge(t,n),i=r?.shapeId??null;i!==this.hoveredShapeId&&(this.hoveredShapeId&&this.removeHoverHighlight(this.hoveredShapeId),this.removeCenterOverlay(),i?(this.applyHoverHighlight(i),this.canvas.style.cursor=`pointer`):this.canvas.style.cursor=``,this.hoveredShapeId=i,this.ctx.requestRender()),r?.isCenter&&r.centerPoint?this.hoveredCenterPoint&&this.hoveredCenterPoint[0]===r.centerPoint[0]&&this.hoveredCenterPoint[1]===r.centerPoint[1]||(this.removeCenterOverlay(),this.addCenterOverlay(r.centerPoint),this.hoveredCenterPoint=r.centerPoint,this.ctx.requestRender()):this.hoveredCenterOverlay&&(this.removeCenterOverlay(),this.ctx.requestRender())}handleMouseUp(e){if(this.isExternalResizing())return;let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=e.ctrlKey||e.metaKey;if(!this.hoveredShapeId){r||(this.clearSelection(),this.ctx.requestRender());return}r?this.selectedShapeIds.has(this.hoveredShapeId)?(this.removeSelectionHighlight(this.hoveredShapeId),this.selectedShapeIds.delete(this.hoveredShapeId),this.applyHoverHighlight(this.hoveredShapeId)):(this.selectedShapeIds.add(this.hoveredShapeId),this.applySelectionHighlight(this.hoveredShapeId)):(this.clearSelection(),this.selectedShapeIds.add(this.hoveredShapeId),this.applySelectionHighlight(this.hoveredShapeId)),this.ctx.requestRender()}findNearestEdge(e,t){let n=1/0,r=null,i=!1,a=null;for(let t of this.edges)for(let o of t.segments){let s=bp(e[0],e[1],o.ax,o.ay,o.bx,o.by);s<n&&(n=s,r=t.shapeId,i=!1,a=null)}for(let t of this.centers){let o=t.point2d[0]-e[0],s=t.point2d[1]-e[1],c=Math.sqrt(o*o+s*s);c<n&&(n=c,r=t.shapeId,i=!0,a=t.point2d)}return n>t||!r?null:a?{shapeId:r,isCenter:i,centerPoint:a}:{shapeId:r,isCenter:i}}applyHoverHighlight(e){this.selectedShapeIds.has(e)||this.traverseShapeEdges(e,e=>{e.userData.selectOriginalColor===void 0&&(e.userData.hoverOriginalColor=e.material.color.getHex(),e.material.color.set(Wd.highlightColor))})}removeHoverHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.hoverOriginalColor!==void 0&&(e.material.color.setHex(e.userData.hoverOriginalColor),delete e.userData.hoverOriginalColor)})}applySelectionHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.hoverOriginalColor===void 0?e.userData.selectOriginalColor=e.material.color.getHex():(e.userData.selectOriginalColor=e.userData.hoverOriginalColor,delete e.userData.hoverOriginalColor),e.material.color.set(Wd.highlightColor)})}removeSelectionHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.selectOriginalColor!==void 0&&(e.material.color.setHex(e.userData.selectOriginalColor),delete e.userData.selectOriginalColor)})}clearHover(){this.hoveredShapeId&&(this.removeHoverHighlight(this.hoveredShapeId),this.hoveredShapeId=null,this.canvas.style.cursor=``,this.removeCenterOverlay(),this.ctx.requestRender())}clearSelection(){for(let e of this.selectedShapeIds)this.removeSelectionHighlight(e);this.selectedShapeIds.clear()}traverseShapeEdges(e,t){this.ctx.scene.traverse(n=>{n.userData.isMetaShape||(n.isLine||n.userData.isEdgeLine)&&this.findShapeId(n)===e&&t(n)})}findShapeId(e){let t=e;for(;t;){if(t.userData.shapeId&&!t.userData.isMetaShape)return t.userData.shapeId;t=t.parent}return null}addCenterOverlay(e){this.removeCenterOverlay();let t=Cp(e,this.plane),n=this.plane.normal,r=new R(n.x,n.y,n.z),i=new U(new oa(uy,16),new mr({color:Wd.highlightColor,side:2,depthTest:!1,transparent:!0,opacity:.9}));i.renderOrder=6;let a=new oi;a.renderOrder=6,a.userData.isCenterOverlay=!0,a.add(i),a.position.copy(t),a.lookAt(t.clone().add(r)),tp(i,a,t,dy,uy),this.ctx.scene.add(a),this.hoveredCenterOverlay=a}removeCenterOverlay(){if(this.hoveredCenterOverlay){this.ctx.scene.remove(this.hoveredCenterOverlay);let e=this.hoveredCenterOverlay.children[0];e.geometry.dispose(),e.material.dispose(),this.hoveredCenterOverlay=null,this.hoveredCenterPoint=null}}},py=`#8899aa`,my=1.5,hy=4.5,gy=.5,_y=2,vy=class{ctx;group;active=!1;constructor(e){this.ctx=e,this.group=new oi,this.group.userData.isMetaShape=!0,this.group.renderOrder=3}activate(){this.active||=(this.ctx.scene.add(this.group),!0)}deactivate(){this.active&&(this.ctx.scene.remove(this.group),this.disposeGroup(),this.active=!1,this.ctx.requestRender())}update(e,t,n){if(!this.active)return;this.disposeGroup();let r=this.ctx.camera,i=new R(n.normal.x,n.normal.y,n.normal.z);for(let a of e){if(a.parentId!==t||a.type!==`bezier`)continue;let e=a.object?.startPoint,o=a.object?.resolvedPoints,s=[];e&&s.push(e),o&&s.push(...o);for(let e=1;e<s.length;e++)Z_(this.group,s[e-1],s[e],n,_y);for(let e of s)Q(this.group,e,py,r,i,n,gy,_y,my,hy)}this.ctx.requestRender()}disposeGroup(){for(;this.group.children.length>0;){let e=this.group.children[0];this.group.remove(e);let t=e;t.geometry&&t.geometry.dispose(),t.material&&t.material.dispose();let n=e.children?.[0];n?.geometry&&n.geometry.dispose(),n?.material&&n.material.dispose()}}},yy=class{snapManager;plane;excludedVertices=[];snapToVertices=!0;snapToGrid=!0;constructor(e,t){this.snapManager=e,this.plane=t}updateSnapManager(e){this.snapManager=e,this.snapManager.setExcludedVertices(this.excludedVertices)}setExcludedVertices(e){this.excludedVertices=e,this.snapManager.setExcludedVertices(e)}snap(e){if(!this.snapToVertices&&!this.snapToGrid)return this.noSnapResult(e);let t=this.snapManager.snap(e,this.plane);return t.snapType===`vertex`&&!this.snapToVertices||t.snapType===`grid`&&!this.snapToGrid?this.noSnapResult(e):t}noSnapResult(e){let t=this.plane.origin,n=this.plane.xDirection,r=this.plane.yDirection;return{point2d:e,worldPoint:new R(t.x+n.x*e[0]+r.x*e[1],t.y+n.y*e[0]+r.y*e[1],t.z+n.z*e[0]+r.z*e[1]),snapType:`none`}}},by=class{viewer;container;trimService;timelinePanel;toolbar;activeSketchInfo=null;activeDrawingTool=null;activeDragHandler=null;activeHoverSelectHandler=null;bezierHandles;shortcuts;constructor(e,t,n,r){this.viewer=t,this.container=e,this.trimService=n,this.timelinePanel=r,this.toolbar=new L_(r.toolbarHost,e=>{this.handleToolSelect(e)}),this.shortcuts=new j_,this.shortcuts.register(`n`,()=>this.lookAlongSketchNormal()),this.bezierHandles=new vy(t.sceneContext),this.toolbar.onSnapVerticesChange=e=>{this.activeDrawingTool&&(this.activeDrawingTool.snapController.snapToVertices=e),this.activeDragHandler&&(this.activeDragHandler.snapController.snapToVertices=e)},this.toolbar.onSnapGridChange=e=>{this.activeDrawingTool&&(this.activeDrawingTool.snapController.snapToGrid=e),this.activeDragHandler&&(this.activeDragHandler.snapController.snapToGrid=e)}}get hasActiveDrawingTool(){return this.activeDrawingTool!==null}update(e){let t=null;for(let n=e.length-1;n>=0;n--)if(g_(e[n],e)){t=e[n];break}if(t?.type===`sketch`&&t.id&&t.object?.plane&&t.sourceLocation){let n=t.object.plane,r=this.activeSketchInfo?.sketchObj.id;if(this.activeSketchInfo={sketchObj:t,plane:n,sourceLocation:t.sourceLocation},this.toolbar.isVisible||(this.toolbar.show(),this.shortcuts.enable(),this.timelinePanel.slideOut()),this.bezierHandles.activate(),this.bezierHandles.update(e,t.id,n),this.activeDrawingTool)r===t.id?(this.activeDrawingTool.updatePlane(n),this.activeDrawingTool.onSceneUpdate(e,t.id),t.object?.currentPosition&&this.activeDrawingTool.updateCurrentPosition(t.object.currentPosition)):this.handleToolSelect(this.toolbar.activeTool);else if(this.activeDragHandler){this.activeDragHandler.updatePlane(n);let r=new yy(h_.fromSceneObjects(e,t.id,n,this.viewer.sceneContext),n);r.snapToVertices=this.toolbar.snapVerticesChecked,r.snapToGrid=this.toolbar.snapGridChecked,this.activeDragHandler.updateSnapController(r),this.activeDragHandler.updateSceneData(e,t.id),this.activeHoverSelectHandler&&(this.activeHoverSelectHandler.updatePlane(n),this.activeHoverSelectHandler.updateSceneData(e,t.id))}else this.toolbar.activeTool||this.activateDragHandler()}else this.activeDrawingTool&&=(this.activeDrawingTool.deactivate(),null),this.deactivateDragHandler(),this.bezierHandles.deactivate(),this.activeSketchInfo=null,this.toolbar.hide(),this.shortcuts.disable(),this.timelinePanel.slideIn()}async fetchScopeVariables(){return this.activeSketchInfo?Vm(this.activeSketchInfo.sourceLocation.line):[]}createTool(e,t,n,r){let i=new yy(h_.fromSceneObjects(n,r,t,this.viewer.sceneContext),t);i.snapToVertices=this.toolbar.snapVerticesChecked,i.snapToGrid=this.toolbar.snapGridChecked;let a=(e,t)=>{this.activeSketchInfo&&Pm(e,this.activeSketchInfo.sourceLocation,t)},o=()=>this.fetchScopeVariables();switch(e){case`line`:{let e=new gv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`circle`:return new _v(this.viewer.sceneContext,t,i,a,this.container,o);case`polygon`:return new Vv(this.viewer.sceneContext,t,i,a,this.container,o);case`arc2`:return new yv(this.viewer.sceneContext,t,i,a,this.container,o);case`arc3`:{let e=new xv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`polyline`:{let e=new Fv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`bezier`:{let e=new Iv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`rect`:return new Sv(this.viewer.sceneContext,t,i,a,this.container,o);case`rounded-rect`:return new Cv(this.viewer.sceneContext,t,i,a,this.container,o);case`slot`:return new wv(this.viewer.sceneContext,t,i,a,this.container,o);default:return null}}activateDragHandler(){if(this.activeDragHandler||!this.activeSketchInfo)return;let e=new yy(h_.fromSceneObjects(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id,this.activeSketchInfo.plane,this.viewer.sceneContext),this.activeSketchInfo.plane);e.snapToVertices=this.toolbar.snapVerticesChecked,e.snapToGrid=this.toolbar.snapGridChecked,this.activeDragHandler=new cy(this.viewer.sceneContext,this.activeSketchInfo.plane,e,this.container,()=>this.fetchScopeVariables(),()=>this.activeSketchInfo?.sourceLocation.line??null),this.activeDragHandler.updateSceneData(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id),this.activeDragHandler.activate(),this.activeHoverSelectHandler=new fy(this.viewer.sceneContext,this.activeSketchInfo.plane,()=>this.activeDragHandler?.isResizing??!1),this.activeHoverSelectHandler.updateSceneData(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id),this.activeHoverSelectHandler.activate()}deactivateDragHandler(){this.activeHoverSelectHandler&&=(this.activeHoverSelectHandler.deactivate(),null),this.activeDragHandler&&=(this.activeDragHandler.deactivate(),null)}handleToolSelect(e){if(!e&&this.activeDrawingTool?.handleEscape?.())return;if(this.activeDrawingTool&&=(this.activeDrawingTool.deactivate(),null),this.toolbar.activeTool===`trim`&&e!==`trim`&&this.exitTrimFromToolbar(),this.toolbar.setActiveTool(e),!e||!this.activeSketchInfo){!e&&this.activeSketchInfo&&this.activateDragHandler();return}if(this.deactivateDragHandler(),e===`trim`){this.enterTrimFromToolbar();return}let t=this.createTool(e,this.activeSketchInfo.plane,this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id);t&&(this.activeSketchInfo.sketchObj.object?.currentPosition&&t.updateCurrentPosition(this.activeSketchInfo.sketchObj.object.currentPosition),t.activate(),this.activeDrawingTool=t)}enterTrimFromToolbar(){if(this.activeSketchInfo){if(this.trimService.lastPickInfo){this.trimService.enter(),this.trimService.hideBars();return}this.trimService.pendingActivation=!0,Pm(`trim()`,this.activeSketchInfo.sourceLocation)}}exitTrimFromToolbar(){if(this.trimService.pendingActivation=!1,this.trimService.state===`picking-active`&&this.trimService.exit(),this.trimService.lastPickInfo){let e=this.trimService.lastPickInfo.trimObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Nm(e.sourceLocation)}this.trimService.reset()}lookAlongSketchNormal(){this.activeSketchInfo&&this.viewer.lookAlongSketchNormal(this.activeSketchInfo.plane)}},xy=class extends lf{constructor(){super(),this.isLineGeometry=!0,this.type=`LineGeometry`}setPositions(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setPositions(n),this}setColors(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setColors(n),this}setFromPoints(e){let t=e.length-1,n=new Float32Array(6*t);for(let r=0;r<t;r++)n[6*r]=e[r].x,n[6*r+1]=e[r].y,n[6*r+2]=e[r].z||0,n[6*r+3]=e[r+1].x,n[6*r+4]=e[r+1].y,n[6*r+5]=e[r+1].z||0;return super.setPositions(n),this}fromLine(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}},Sy=class extends kf{constructor(e=new xy,t=new uf({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},Cy={x:15026253,y:3187820,z:4088797},wy=999,Ty=class{group=null;constructor(e){this.ctx=e}show(e){this.clear();let{from:t,to:n,axis:r}=e;if(Ey(t,n)<1e-12)return;let i=new oi;if(i.name=`measureOverlay`,i.userData.isMetaShape=!0,i.add(this.makeLine(t,n,Wd.highlightColor.getHex(),{width:2.5})),r){let e={x:r===`x`?n.x:t.x,y:r===`y`?n.y:t.y,z:r===`z`?n.z:t.z};Ey(t,e)>1e-12&&i.add(this.makeLine(t,e,Cy[r],{width:3.5})),Ey(e,n)>1e-12&&i.add(this.makeLine(e,n,Wd.metaEdgeColor.getHex(),{width:1.5,dashed:!0})),i.add(this.makePoints([t,n,e]))}else i.add(this.makePoints([t,n]));i.traverse(e=>{e.userData.isMetaShape=!0,e.renderOrder=wy}),this.group=i,this.ctx.scene.add(i),this.ctx.requestRender()}clear(){this.group&&(this.group.traverse(e=>{e.geometry?.dispose(),e.material?.dispose()}),this.group.parent?.remove(this.group),this.group=null,this.ctx.requestRender())}makeLine(e,t,n,r){let i=new xy;i.setPositions([e.x,e.y,e.z,t.x,t.y,t.z]);let a=Math.sqrt(Ey(e,t)),o=new uf({color:n,linewidth:r.width,transparent:!0,depthTest:!1,depthWrite:!1,dashed:!!r.dashed,dashSize:a/16,gapSize:a/24});Kd.register(o);let s=new Sy(i,o);return r.dashed&&s.computeLineDistances(),s}makePoints(e){let t=new H,n=e.flatMap(e=>[e.x,e.y,e.z]);return t.setAttribute(`position`,new br(n,3)),new ta(t,new Xi({color:Wd.highlightColor.getHex(),size:7,sizeAttenuation:!1,transparent:!0,depthTest:!1,depthWrite:!1}))}};function Ey(e,t){let n=e.x-t.x,r=e.y-t.y,i=e.z-t.z;return n*n+r*r+i*i}var Dy=[{value:`mm`,label:`Millimeter`},{value:`cm`,label:`Centimeter`},{value:`m`,label:`Meter`},{value:`in`,label:`Inch`}],Oy=[{value:`deg`,label:`Degree`},{value:`rad`,label:`Radian`}],ky={mm:1,cm:.1,m:.001,in:1/25.4},Ay={mm:2,cm:3,m:5,in:3};function jy(e,t){return e*ky[t]}function My(e,t){return`${jy(e,t).toFixed(Ay[t])} ${t}`}function Ny(e,t){let n=ky[t];return`${(e*n*n).toFixed(Ay[t])} ${t}²`}function Py(e,t){return t===`rad`?`${(Math.PI/180*e).toFixed(4)} rad`:`${e.toFixed(2)} deg`}var Fy={plane:`Plane face`,cylinder:`Cylindrical face`,cone:`Conical face`,sphere:`Spherical face`,torus:`Toroidal face`,surface:`Face`,line:`Line edge`,circle:`Circle edge`,arc:`Arc edge`,ellipse:`Ellipse edge`,curve:`Edge`},Iy=[{key:`parallelDist`,label:`Parallel dist`},{key:`centerDist`,label:`Center dist`},{key:`axisDist`,label:`Axis dist`},{key:`minDist`,label:`Min dist`},{key:`maxDist`,label:`Max dist`}],Ly=[{axis:`x`,cls:`text-error`},{axis:`y`,cls:`text-success`},{axis:`z`,cls:`text-info`}];function Ry(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}var zy=class{el;data={entities:[],result:null,lengthUnit:`mm`,angleUnit:`deg`};constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`absolute bottom-[64px] right-[76px] z-[150] w-[290px] panel-bg border border-base-content/10 rounded-lg p-3 shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-xs text-base-content select-none max-h-[70vh] overflow-y-auto hidden`,e.appendChild(this.el)}get isVisible(){return!this.el.classList.contains(`hidden`)}setVisible(e){this.el.classList.toggle(`hidden`,!e)}update(e){this.data=e,this.render()}render(){let{entities:e,result:t}=this.data,n=e.length?e.map((e,t)=>`<div class="flex items-center justify-between gap-1 px-2 py-1 border-b border-base-content/10 last:border-0">
5440
- <span class="truncate">${Ry(e.label)}</span>
5441
- <button data-remove="${t}" title="Remove" class="btn btn-ghost btn-xs btn-square shrink-0 opacity-60 hover:opacity-100 [&>svg]:w-3 [&>svg]:h-3">${sg}</button>
5442
- </div>`).join(``):`<div class="px-2 py-2 text-base-content/50">Click faces or edges in the viewport to measure</div>`,r=Dy.map(e=>`<option value="${e.value}" ${e.value===this.data.lengthUnit?`selected`:``}>${e.label}</option>`).join(``),i=Oy.map(e=>`<option value="${e.value}" ${e.value===this.data.angleUnit?`selected`:``}>${e.label}</option>`).join(``);this.el.innerHTML=`
5439
+ `,e.appendChild(this.el),this.wrapperEl=this.el.querySelector(`.expression-wrapper`),this.input=this.el.querySelector(`.expression-input`),this.label=this.el.querySelector(`.expression-label`),this.dropdown=this.el.querySelector(`.expression-dropdown`),this.errorEl=this.el.querySelector(`.expression-error`),this.input.addEventListener(`keydown`,e=>{if(e.key!==`Escape`&&e.stopPropagation(),e.key===`ArrowDown`){e.preventDefault(),this.moveSelection(1);return}if(e.key===`ArrowUp`){e.preventDefault(),this.moveSelection(-1);return}if(e.key===`Tab`){e.preventDefault(),this.fillSelected();return}if(e.key===`Enter`){e.preventDefault(),this.selectedIndex>=0&&this.selectedIndex<this.filteredVars.length&&(this.input.value=this.filteredVars[this.selectedIndex].name),this.commit();return}if(e.key===` `&&this.onSpaceOverride){e.preventDefault(),this.onSpaceOverride();return}if(e.key===`Escape`){e.preventDefault(),this.userIsTyping=!1,this.input.blur(),this.hide();return}}),this.input.addEventListener(`input`,()=>{this.userIsTyping=!0,this.errorVisible&&this.clearInlineError(),this.filterAndRender()}),this.input.addEventListener(`focus`,()=>{this.filterAndRender()}),this.input.addEventListener(`mousedown`,e=>e.stopPropagation()),this.input.addEventListener(`mouseup`,e=>e.stopPropagation()),this.input.addEventListener(`click`,e=>e.stopPropagation()),this.dropdown.addEventListener(`mousedown`,e=>e.stopPropagation())}show(e){this.label.textContent=e.label,this.onCommit=e.onCommit,this.variables=e.variables,this.numericOnly=e.numericOnly??!1,this.visible=!0,this.userIsTyping=!1,this.selectedIndex=-1,this.seedValue=e.value,this.el.classList.remove(`hidden`),this.updatePosition(e.clientX,e.clientY),this.input.value=e.value,this.input.focus(),this.input.select(),this.clearInlineError(),this.filterAndRender()}hide(){this.visible&&(this.visible=!1,this.userIsTyping=!1,this.el.classList.add(`hidden`),this.dropdown.classList.add(`hidden`),this.clearInlineError(),this.onCommit=null,this.input.blur())}get isVisible(){return this.visible}containsElement(e){return e instanceof Node&&this.el.contains(e)}updateValue(e){if(!this.visible||this.userIsTyping)return;let t=typeof e==`string`?e:String(Math.round(e*100)/100);this.input.value=t,this.seedValue=t,this.input.select()}updatePosition(e,t){if(!this.visible)return;let n=this.el.parentElement.getBoundingClientRect();this.el.style.left=`${e-n.left+H_}px`,this.el.style.top=`${t-n.top+U_}px`}commitCurrentValue(){let e=this.input.value.trim();return e?this.runCommit(e):!1}commit(){let e=this.input.value.trim();e?this.runCommit(e):this.hide()}runCommit(e){if(!this.onCommit)return!1;let t=this.classifyCommit(e);return t.kind===`error`?(this.showInlineError(t.message),!1):(t.kind===`declare`?this.onCommit({expression:t.name,newVariable:{name:t.name,initializer:t.initializer}}):this.onCommit({expression:t.expression}),this.hide(),!0)}classifyCommit(e){if(this.numericOnly)return isNaN(parseFloat(e))?{kind:`error`,message:`Enter a numeric value`}:{kind:`expression`,expression:e};let t=e.match(G_);if(t){let e=t[1],n=t[2].trim();return q_(e)?this.variables.some(t=>t.name===e)?{kind:`error`,message:`'${e}' is already defined`}:n?{kind:`declare`,name:e,initializer:n}:{kind:`error`,message:`Missing value`}:{kind:`error`,message:`'${e}' is not a valid name`}}if(W_.test(e)){if(this.variables.some(t=>t.name===e)||!q_(e))return{kind:`expression`,expression:e};let t=this.seedValue.trim();return t?{kind:`declare`,name:e,initializer:t}:{kind:`error`,message:`No value to assign`}}return{kind:`expression`,expression:e}}showInlineError(e){this.errorVisible=!0,this.errorEl.textContent=e,this.errorEl.classList.remove(`hidden`),this.wrapperEl.classList.add(`border-red-500/70`),this.wrapperEl.classList.remove(`border-base-content/10`)}clearInlineError(){if(!this.errorVisible){this.errorEl.classList.add(`hidden`);return}this.errorVisible=!1,this.errorEl.classList.add(`hidden`),this.errorEl.textContent=``,this.wrapperEl.classList.remove(`border-red-500/70`),this.wrapperEl.classList.add(`border-base-content/10`)}moveSelection(e){this.filteredVars.length!==0&&(this.selectedIndex+=e,this.selectedIndex<0?this.selectedIndex=this.filteredVars.length-1:this.selectedIndex>=this.filteredVars.length&&(this.selectedIndex=0),this.renderDropdown())}fillSelected(){this.selectedIndex>=0&&this.selectedIndex<this.filteredVars.length&&(this.input.value=this.filteredVars[this.selectedIndex].name,this.userIsTyping=!0,this.filterAndRender())}filterAndRender(){if(this.numericOnly){this.filteredVars=[],this.selectedIndex=-1,this.renderDropdown();return}if(!this.userIsTyping)this.filteredVars=[...this.variables];else{let e=this.input.value.trim().toLowerCase();e?this.filteredVars=this.variables.filter(t=>t.name.toLowerCase().includes(e)):this.filteredVars=[...this.variables]}this.selectedIndex=-1,this.renderDropdown()}renderDropdown(){if(this.filteredVars.length===0){this.dropdown.classList.add(`hidden`);return}if(this.dropdown.classList.remove(`hidden`),this.dropdown.innerHTML=this.filteredVars.map((e,t)=>{let n=t===this.selectedIndex?`bg-primary/10`:``,r=e.initializer?`<span class="text-base-content/40 ml-2">= ${this.escapeHtml(this.truncate(e.initializer,20))}</span>`:``;return`<div class="px-2 py-1 text-sm font-mono cursor-pointer hover:bg-primary/10 ${n}" data-idx="${t}">${this.escapeHtml(e.name)}${r}</div>`}).join(``),this.dropdown.querySelectorAll(`[data-idx]`).forEach(e=>{e.addEventListener(`mousedown`,t=>{t.preventDefault(),t.stopPropagation();let n=parseInt(e.dataset.idx,10);this.input.value=this.filteredVars[n].name,this.commit()})}),this.selectedIndex>=0){let e=this.dropdown.children[this.selectedIndex];e&&e.scrollIntoView({block:`nearest`})}}escapeHtml(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}truncate(e,t){return e.length>t?e.slice(0,t)+`...`:e}},X=2280550,Y_=11579568,Z=16762232,X_=8947848,Z_=2.5,Q_=7.5;function $_(e){return e===`vertex`?Z:X_}function Q(e,t,n,r,i,a,o=1,s=4,c=Z_,l=Q_){let u=new U(new oa(c,16),new mr({color:n,side:2,depthTest:!1,transparent:o<1,opacity:o}));u.renderOrder=s;let d=new oi;d.renderOrder=s;let f=Ep(t,a);d.position.copy(f),d.lookAt(f.clone().add(i)),tf(u,d,f,l,c),d.add(u),e.add(d)}function ev(e,t,n,r,i=3){let a=Ep(t,r),o=Ep(n,r),s=new Float32Array(6);s[0]=a.x,s[1]=a.y,s[2]=a.z,s[3]=o.x,s[4]=o.y,s[5]=o.z;let c=new H;c.setAttribute(`position`,new V(s,3));let l=new Gi(c,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));l.computeLineDistances(),l.renderOrder=i,e.add(l)}function tv(e,t,n,r,i=3){let a=new Float32Array(195);for(let e=0;e<=64;e++){let i=e/64*Math.PI*2,o=Ep([t[0]+Math.cos(i)*n,t[1]+Math.sin(i)*n],r);a[e*3]=o.x,a[e*3+1]=o.y,a[e*3+2]=o.z}let o=new H;o.setAttribute(`position`,new V(a,3));let s=new Gi(o,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));s.computeLineDistances(),s.renderOrder=i,e.add(s)}function nv(e,t,n,r,i=3){let a=t[0],o=t[1],s=n[0],c=n[1],l=[[a,o],[s,o],[s,c],[a,c],[a,o]],u=new Float32Array(l.length*3);for(let e=0;e<l.length;e++){let t=Ep(l[e],r);u[e*3]=t.x,u[e*3+1]=t.y,u[e*3+2]=t.z}let d=new H;d.setAttribute(`position`,new V(u,3));let f=new Gi(d,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));f.computeLineDistances(),f.renderOrder=i,e.add(f)}var rv=8;function iv(e,t,n,r,i,a=3){let o=Math.min(t[0],n[0]),s=Math.max(t[0],n[0]),c=Math.min(t[1],n[1]),l=Math.max(t[1],n[1]),u=s-o,d=l-c,f=Math.min(r,u/2,d/2);if(f<=0){nv(e,t,n,i,a);return}let p=[];p.push([o+f,c]),p.push([s-f,c]);for(let e=0;e<=rv;e++){let t=-Math.PI/2+e/rv*(Math.PI/2);p.push([s-f+f*Math.cos(t),c+f+f*Math.sin(t)])}p.push([s,c+f]),p.push([s,l-f]);for(let e=0;e<=rv;e++){let t=0+e/rv*(Math.PI/2);p.push([s-f+f*Math.cos(t),l-f+f*Math.sin(t)])}p.push([s-f,l]),p.push([o+f,l]);for(let e=0;e<=rv;e++){let t=Math.PI/2+e/rv*(Math.PI/2);p.push([o+f+f*Math.cos(t),l-f+f*Math.sin(t)])}p.push([o,l-f]),p.push([o,c+f]);for(let e=0;e<=rv;e++){let t=Math.PI+e/rv*(Math.PI/2);p.push([o+f+f*Math.cos(t),c+f+f*Math.sin(t)])}p.push([o+f,c]);let m=new Float32Array(p.length*3);for(let e=0;e<p.length;e++){let t=Ep(p[e],i);m[e*3]=t.x,m[e*3+1]=t.y,m[e*3+2]=t.z}let h=new H;h.setAttribute(`position`,new V(m,3));let g=new Gi(h,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));g.computeLineDistances(),g.renderOrder=a,e.add(g)}function av(e,t,n,r,i,a=3){let o=new Float32Array((r+1)*3);for(let e=0;e<=r;e++){let a=e/r*Math.PI*2,s=Ep([t[0]+Math.cos(a)*n,t[1]+Math.sin(a)*n],i);o[e*3]=s.x,o[e*3+1]=s.y,o[e*3+2]=s.z}let s=new H;s.setAttribute(`position`,new V(o,3));let c=new Gi(s,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));c.computeLineDistances(),c.renderOrder=a,e.add(c)}function ov(e,t,n,r,i,a,o,s=3){let c=i-r;a?c<=0&&(c+=Math.PI*2):c>=0&&(c-=Math.PI*2);let l=Math.max(Math.round(Math.abs(c)/(Math.PI*2)*64),2),u=new Float32Array((l+1)*3);for(let e=0;e<=l;e++){let i=e/l,a=r+c*i,s=Ep([t[0]+Math.cos(a)*n,t[1]+Math.sin(a)*n],o);u[e*3]=s.x,u[e*3+1]=s.y,u[e*3+2]=s.z}let d=new H;d.setAttribute(`position`,new V(u,3));let f=new Gi(d,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));f.computeLineDistances(),f.renderOrder=s,e.add(f)}function sv(e,t){let n=e.slice();for(;n.length>1;){let e=[];for(let r=0;r<n.length-1;r++)e.push([(1-t)*n[r][0]+t*n[r+1][0],(1-t)*n[r][1]+t*n[r+1][1]]);n=e}return n[0]}function cv(e,t,n,r=3){if(t.length<2)return;let i=new Float32Array(195);for(let e=0;e<=64;e++){let r=Ep(sv(t,e/64),n);i[e*3]=r.x,i[e*3+1]=r.y,i[e*3+2]=r.z}let a=new H;a.setAttribute(`position`,new V(i,3));let o=new Gi(a,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));o.computeLineDistances(),o.renderOrder=r,e.add(o)}var lv=16;function uv(e,t,n,r,i,a=3){let o=n[0]-t[0],s=n[1]-t[1],c=Math.sqrt(o*o+s*s),l,u;c>1e-10?(l=o/c,u=s/c):(l=1,u=0);let d=-u,f=l,p=[],m=Math.atan2(f,d);for(let e=0;e<=lv;e++){let n=m+e/lv*Math.PI;p.push([t[0]+r*Math.cos(n),t[1]+r*Math.sin(n)])}p.push([n[0]-r*d,n[1]-r*f]);let h=Math.atan2(-f,-d);for(let e=0;e<=lv;e++){let t=h+e/lv*Math.PI;p.push([n[0]+r*Math.cos(t),n[1]+r*Math.sin(t)])}p.push([t[0]+r*d,t[1]+r*f]);let g=new Float32Array(p.length*3);for(let e=0;e<p.length;e++){let t=Ep(p[e],i);g[e*3]=t.x,g[e*3+1]=t.y,g[e*3+2]=t.z}let _=new H;_.setAttribute(`position`,new V(g,3));let v=new Gi(_,new xa({color:Y_,dashSize:3,gapSize:2,depthTest:!1}));v.computeLineDistances(),v.renderOrder=a,e.add(v)}function dv(e,t){return Math.atan2(t[1]-e[1],t[0]-e[0])}function fv(e,t,n){return[e[0]+t*Math.cos(n),e[1]+t*Math.sin(n)]}function pv(e,t,n){let r=2*(e[0]*(t[1]-n[1])+t[0]*(n[1]-e[1])+n[0]*(e[1]-t[1]));if(Math.abs(r)<1e-10)return null;let i=e[0]*e[0]+e[1]*e[1],a=t[0]*t[0]+t[1]*t[1],o=n[0]*n[0]+n[1]*n[1];return[(i*(t[1]-n[1])+a*(n[1]-e[1])+o*(e[1]-t[1]))/r,(i*(n[0]-t[0])+a*(e[0]-n[0])+o*(t[0]-e[0]))/r]}function mv(e,t,n){let r=dv(e,t),i=dv(e,n)-r;return i<0&&(i+=Math.PI*2),i<Math.PI}function hv(e,t,n,r){let i=(e[0]+t[0])/2,a=(e[1]+t[1])/2,o=t[0]-e[0],s=t[1]-e[1],c=Math.sqrt(o*o+s*s)/2;if(Math.abs(n)<c-1e-10)return null;let l=Math.sqrt(Math.max(n*n-c*c,0)),u=-s,d=o,f=Math.sqrt(u*u+d*d);if(f<1e-10)return null;let p=r?1:-1;return[i+p*l*u/f,a+p*l*d/f]}var gv=new Set([`line-two-points`,`hline`,`vline`,`arc`,`tarc-to-point`,`tarc-to-point-tangent`,`tarc-with-tangent`,`tline`]);function _v(e,t){let n=t.origin.x,r=t.origin.y,i=t.origin.z,a=t.xDirection.x,o=t.xDirection.y,s=t.xDirection.z,c=t.yDirection.x,l=t.yDirection.y,u=t.yDirection.z,d=[];for(let t=0;t<e.length;t+=3){let f=e[t]-n,p=e[t+1]-r,m=e[t+2]-i;d.push([f*a+p*o+m*s,f*c+p*l+m*u])}return d}function vv(e,t){let n,r;if(t===`end`){let t=e[e.length-2],i=e[e.length-1];n=i[0]-t[0],r=i[1]-t[1]}else{let t=e[0],i=e[1];n=t[0]-i[0],r=t[1]-i[1]}let i=Math.sqrt(n*n+r*r);return i<1e-10?null:[n/i,r/i]}var yv=class extends V_{id=`line`;label=`Line`;icon=Jh;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;ctrlHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;sceneObjects=[];sketchId=``;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.startPoint=null,this.mousePoint=null,this.shiftHeld=!1,this.ctrlHeld=!1,this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){this.sceneObjects=e,this.sketchId=t;let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY,this.syncModifiers(e)}handleMouseUp(e){this.syncModifiers(e);let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.rebuildPreview();return}this.isTLineMode()&&this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.isTLineMode()?this.commitTLineDirect():this.shiftHeld&&this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitLine(this.startPoint,i),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}syncModifiers(e){let t=this.isTLineMode();this.shiftHeld=e.shiftKey,this.ctrlHeld=e.ctrlKey||e.metaKey,this.isTLineMode()!==t&&this.expressionInput.hide()}handleKeyDown(e){this.syncModifiers(e),(e.key===`Shift`||e.key===`Control`||e.key===`Meta`)&&(this.rebuildPreview(),this.updateDimensionInput()),e.key===`Escape`&&this.startPoint&&(this.startPoint=null,this.expressionInput.hide(),this.rebuildPreview())}handleKeyUp(e){this.syncModifiers(e),(e.key===`Shift`||e.key===`Control`||e.key===`Meta`)&&(this.shiftHeld||this.expressionInput.hide(),this.rebuildPreview(),this.updateDimensionInput())}isTLineMode(){return this.shiftHeld&&this.ctrlHeld}findTangentAtStart(){if(!this.startPoint||!this.isAtCurrentPosition(Y(this.startPoint)))return null;let e=null;for(let t of this.sceneObjects)t.parentId!==this.sketchId||!t.sourceLocation||gv.has(t.uniqueType??``)&&(e=t);if(!e)return null;for(let t of e.sceneShapes)if(!t.isMetaShape)for(let e of t.meshes){let t=_v(e.vertices,this.plane);if(!(t.length<2))return vv(t,`end`)}return null}getEffectiveEndPoint(){if(!this.startPoint||!this.mousePoint)return null;if(this.isTLineMode()){let e=this.findTangentAtStart();if(e){let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=t*e[0]+n*e[1];return[this.startPoint[0]+e[0]*r,this.startPoint[1]+e[1]*r]}return this.mousePoint}if(this.shiftHeld){let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1];return Math.abs(e)>=Math.abs(t)?[this.mousePoint[0],this.startPoint[1]]:[this.startPoint[0],this.mousePoint[1]]}return this.mousePoint}updateDimensionInput(){if(!this.startPoint||!this.mousePoint||!this.shiftHeld){this.expressionInput.hide();return}if(this.isTLineMode()){this.updateTLineDimensionInput();return}let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1],n=Math.abs(e)>=Math.abs(t),r=Math.abs(n?e:t);this.expressionInput.isVisible?(this.expressionInput.updateValue(r),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:n?`H:`:`V:`,value:String(Math.round(r*100)/100),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.commitWithDimension(e)})}updateTLineDimensionInput(){let e=this.findTangentAtStart();if(!e){this.expressionInput.hide();return}let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=t*e[0]+n*e[1];this.expressionInput.isVisible?(this.expressionInput.updateValue(Math.abs(r)),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`T:`,value:String(Math.round(Math.abs(r)*100)/100),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.commitTLine(e,r)})}commitWithDimension(e){if(!this.startPoint||!this.mousePoint)return;let{expression:t,newVariable:n}=e,r=Y(this.startPoint),i=this.isAtCurrentPosition(r),a=this.mousePoint[0]-this.startPoint[0],o=this.mousePoint[1]-this.startPoint[1],s=Math.abs(a)>=Math.abs(o),c=Math.sign(s?a:o),l=parseFloat(t),u=!isNaN(l)&&String(l)===t?String(Math.round(c*l*100)/100):t,d=s?`hLine`:`vLine`,f=i?`${d}(${u})`:`${d}(${this.formatPoint(r)}, ${u})`;this.insertGeometry(f,n),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitTLine(e,t){if(!this.startPoint)return;let{expression:n,newVariable:r}=e,i=Math.sign(t),a=parseFloat(n),o=!isNaN(a)&&String(a)===n?String(Math.round(i*a*100)/100):n;this.insertGeometry(`tLine(${o})`,r),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitTLineDirect(){if(!this.startPoint||!this.mousePoint)return;let e=this.findTangentAtStart();if(!e)return;let t=this.mousePoint[0]-this.startPoint[0],n=this.mousePoint[1]-this.startPoint[1],r=Math.round((t*e[0]+n*e[1])*100)/100;this.insertGeometry(`tLine(${r})`),this.expressionInput.hide(),this.startPoint=null,this.rebuildPreview()}commitLine(e,t){let n=Y(e),r=Y(t),i=this.isAtCurrentPosition(n);if(this.shiftHeld){let e=r[0]-n[0],t=r[1]-n[1],a=Math.abs(e)>=Math.abs(t),o=a?Y([e,0])[0]:Y([0,t])[1];a?i?this.insertGeometry(`hLine(${o})`):this.insertGeometry(`hLine(${this.formatPoint(n)}, ${o})`):i?this.insertGeometry(`vLine(${o})`):this.insertGeometry(`vLine(${this.formatPoint(n)}, ${o})`);return}i?this.insertGeometry(`line(${this.formatPoint(r)})`):this.insertGeometry(`line(${this.formatPoint(n)}, ${this.formatPoint(r)})`)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){Q(this.previewGroup,this.startPoint,X,e,t,this.plane);let n=this.getEffectiveEndPoint();if(n&&(ev(this.previewGroup,this.startPoint,n,this.plane),this.lastSnapType!==`none`)){let r=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,n,r,e,t,this.plane,.6)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},bv=class extends V_{id=`circle`;label=`Circle`;icon=Yh;centerPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.centerPoint=null,this.mousePoint=null,this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.centerPoint){this.centerPoint=i,this.rebuildPreview();return}if(this.expressionInput.isVisible)this.expressionInput.commitCurrentValue();else{let e=Math.round(Ap(this.centerPoint,i)*2*100)/100;if(e<=0)return;this.commitCircle(this.centerPoint,{expression:String(e)})}this.expressionInput.hide(),this.centerPoint=null,this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&this.centerPoint&&(this.centerPoint=null,this.expressionInput.hide(),this.rebuildPreview())}updateDimensionInput(){if(!this.centerPoint||!this.mousePoint)return;let e=Math.round(Ap(this.centerPoint,this.mousePoint)*2*100)/100;e<=0||(this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`⌀`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>{this.centerPoint&&(this.commitCircle(this.centerPoint,e),this.expressionInput.hide(),this.centerPoint=null,this.rebuildPreview())}}))}commitCircle(e,t){let{expression:n,newVariable:r}=t,i=this.isAtCurrentPosition(e)?`circle(${n})`:`circle(${this.formatPoint(e)}, ${n})`;this.insertGeometry(i,r)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.centerPoint){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint){let e=Ap(this.centerPoint,this.mousePoint);e>0&&tv(this.previewGroup,this.centerPoint,e,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},xv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.CENTER_PLACED=1]=`CENTER_PLACED`,e[e.START_PLACED=2]=`START_PLACED`,e}(xv||{}),Sv=class extends V_{id=`arc2`;label=`Center Arc`;icon=Xh;state=xv.IDLE;centerPoint=null;startPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;lastCCW=!0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.resetState(),this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.state=xv.IDLE,this.centerPoint=null,this.startPoint=null,this.mousePoint=null}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(this.state===xv.IDLE){this.centerPoint=i,this.state=xv.CENTER_PLACED,this.rebuildPreview();return}if(this.state===xv.CENTER_PLACED){if(Ap(this.centerPoint,i)<=0)return;this.startPoint=i,this.state=xv.START_PLACED,this.rebuildPreview();return}this.state===xv.START_PLACED&&(this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromMouse())}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.state===xv.START_PLACED&&this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&(this.state===xv.START_PLACED?(this.startPoint=null,this.state=xv.CENTER_PLACED,this.expressionInput.hide()):this.state===xv.CENTER_PLACED&&(this.centerPoint=null,this.state=xv.IDLE),this.rebuildPreview())}getSweepDeg(){if(!this.centerPoint||!this.startPoint||!this.mousePoint)return null;let e=dv(this.centerPoint,this.startPoint),t=dv(this.centerPoint,this.mousePoint);this.lastCCW=mv(this.centerPoint,this.startPoint,this.mousePoint);let n;return this.lastCCW?(n=t-e,n<=0&&(n+=Math.PI*2)):(n=e-t,n<=0&&(n+=Math.PI*2)),n===0?null:Math.round(180/Math.PI*n*100)/100}updateDimensionInput(){let e=this.getSweepDeg();e===null||e<=0||(this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`∠`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,numericOnly:!0,onCommit:e=>this.commitFromExpression(e)}))}commitFromMouse(){if(!this.centerPoint||!this.startPoint||!this.mousePoint)return;let e=mv(this.centerPoint,this.startPoint,this.mousePoint),t=Ap(this.centerPoint,this.startPoint),n=dv(this.centerPoint,this.mousePoint),r=fv(this.centerPoint,t,n);this.emitArc(this.startPoint,r,this.centerPoint,e)}commitFromExpression(e){if(!this.centerPoint||!this.startPoint)return;let{expression:t,newVariable:n}=e,r=parseFloat(t);if(isNaN(r)||r<=0)return;let i=Math.PI/180*r,a=Ap(this.centerPoint,this.startPoint),o=dv(this.centerPoint,this.startPoint)+(this.lastCCW?1:-1)*i,s=fv(this.centerPoint,a,o);this.emitArc(this.startPoint,s,this.centerPoint,this.lastCCW,n)}emitArc(e,t,n,r,i){let a=Y(e),o=Y(t),s=Y(n),c=r?``:`.cw()`,l=this.isAtCurrentPosition(a)?`arc(${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`:`arc(${this.formatPoint(a)}, ${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`;this.insertGeometry(l,i),this.expressionInput.hide(),this.resetState(),this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.state===xv.IDLE){if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===xv.CENTER_PLACED){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===xv.START_PLACED&&this.centerPoint&&this.startPoint&&(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),Q(this.previewGroup,this.startPoint,X,e,t,this.plane),ev(this.previewGroup,this.centerPoint,this.startPoint,this.plane),this.mousePoint)){let n=Ap(this.centerPoint,this.startPoint),r=dv(this.centerPoint,this.startPoint),i=dv(this.centerPoint,this.mousePoint),a=fv(this.centerPoint,n,i);ev(this.previewGroup,this.centerPoint,a,this.plane);let o=mv(this.centerPoint,this.startPoint,this.mousePoint);if(ov(this.previewGroup,this.centerPoint,n,r,i,o,this.plane),this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}this.requestRender()}},Cv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.START_PLACED=1]=`START_PLACED`,e[e.END_PLACED=2]=`END_PLACED`,e}(Cv||{}),wv=class extends V_{id=`arc3`;label=`3-Point Arc`;icon=Zh;state=Cv.IDLE;startPoint=null;endPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;lastCCW=!0;lastCenterOnLeft=!0;shiftHeld=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.expressionInput.hide(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.state=Cv.IDLE,this.startPoint=null,this.endPoint=null,this.mousePoint=null}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){this.shiftHeld=e.shiftKey;let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(this.state===Cv.IDLE){this.startPoint=i,this.state=Cv.START_PLACED,this.rebuildPreview();return}if(this.state===Cv.START_PLACED){if(Ap(this.startPoint,i)<=0)return;this.endPoint=i,this.state=Cv.END_PLACED,this.rebuildPreview();return}this.state===Cv.END_PLACED&&(this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromMouse())}handleMouseMove(e){this.shiftHeld=e.shiftKey,this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.state===Cv.END_PLACED&&this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&(this.state===Cv.END_PLACED?(this.endPoint=null,this.state=Cv.START_PLACED,this.expressionInput.hide()):this.state===Cv.START_PLACED&&(this.startPoint=null,this.state=Cv.IDLE),this.rebuildPreview()),e.key===`Shift`&&!this.shiftHeld&&(this.shiftHeld=!0,this.rebuildPreview(),this.state===Cv.END_PLACED&&this.updateDimensionInput())}handleKeyUp(e){e.key===`Shift`&&this.shiftHeld&&(this.shiftHeld=!1,this.rebuildPreview(),this.state===Cv.END_PLACED&&this.updateDimensionInput())}snapCenterToCollinear(e){if(!this.startPoint||!this.endPoint)return null;let t=this.endPoint[0]-this.startPoint[0],n=this.endPoint[1]-this.startPoint[1],r=t*t+n*n;if(r<1e-10)return null;let i=e[0]-this.startPoint[0],a=e[1]-this.startPoint[1],o=Math.abs(i*n-a*t)/Math.sqrt(r),s=Ep([(this.startPoint[0]+this.endPoint[0])/2,(this.startPoint[1]+this.endPoint[1])/2],this.plane);return o>=Xd(this.ctx.renderer,this.ctx.camera,s,10)?null:[(this.startPoint[0]+this.endPoint[0])/2,(this.startPoint[1]+this.endPoint[1])/2]}computeCenter(){if(!this.startPoint||!this.endPoint||!this.mousePoint)return null;let e=pv(this.startPoint,this.endPoint,this.mousePoint);return e?this.shiftHeld?e:this.snapCenterToCollinear(e)??e:null}isMouseCCW(){if(!this.startPoint||!this.endPoint||!this.mousePoint)return!0;let e=this.computeCenter();if(!e)return!0;let t=dv(e,this.startPoint),n=dv(e,this.endPoint),r=dv(e,this.mousePoint)-t;r<0&&(r+=Math.PI*2);let i=n-t;return i<0&&(i+=Math.PI*2),r<i}updateDimensionInput(){let e=this.computeCenter();if(!e||!this.startPoint)return;let t=Math.round(Ap(e,this.startPoint)*100)/100;if(t<=0)return;this.lastCCW=this.isMouseCCW();let n=this.endPoint[0]-this.startPoint[0],r=this.endPoint[1]-this.startPoint[1],i=e[0]-this.startPoint[0];this.lastCenterOnLeft=n*(e[1]-this.startPoint[1])-r*i>0,this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`R`,value:String(t),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,numericOnly:!0,onCommit:e=>this.commitFromExpression(e)})}commitFromMouse(){if(!this.startPoint||!this.endPoint)return;let e=this.computeCenter();e&&this.emitArc(this.startPoint,this.endPoint,e,this.isMouseCCW())}commitFromExpression(e){if(!this.startPoint||!this.endPoint)return;let{expression:t,newVariable:n}=e,r=parseFloat(t);if(isNaN(r)||r<=0)return;let i=hv(this.startPoint,this.endPoint,r,this.lastCenterOnLeft);i&&this.emitArc(this.startPoint,this.endPoint,i,this.lastCCW,n)}emitArc(e,t,n,r,i){let a=Y(e),o=Y(t),s=Y(n),c=r?``:`.cw()`,l=this.isAtCurrentPosition(a)?`arc(${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`:`arc(${this.formatPoint(a)}, ${this.formatPoint(o)}).center(${this.formatPoint(s)})${c}`;this.insertGeometry(l,i),this.expressionInput.hide(),this.resetState(),this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.state===Cv.IDLE){if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===Cv.START_PLACED){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}else if(this.state===Cv.END_PLACED&&this.startPoint&&this.endPoint&&(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),Q(this.previewGroup,this.endPoint,X,e,t,this.plane),ev(this.previewGroup,this.startPoint,this.endPoint,this.plane),this.mousePoint)){let n=this.computeCenter();if(n){let r=Ap(n,this.startPoint),i=dv(n,this.startPoint),a=dv(n,this.endPoint),o=this.isMouseCCW();ov(this.previewGroup,n,r,i,a,o,this.plane),Q(this.previewGroup,n,Y_,e,t,this.plane,.7),ev(this.previewGroup,n,this.startPoint,this.plane),ev(this.previewGroup,n,this.endPoint,this.plane)}if(this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}}this.requestRender()}},Tv=class extends V_{id=`rect`;label=`Rectangle`;icon=Qh;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`width`;widthExpression=null;lockedWidth=null;widthIsNumeric=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.startPoint=null,this.mousePoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.shiftHeld=!1,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.rebuildPreview();return}this.expressionInput.isVisible?this.expressionInput.commitCurrentValue():this.commitFromGeometry(i)}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.startPoint&&(this.resetState(),this.rebuildPreview());return}e.key===`Shift`&&(this.shiftHeld=!0,this.rebuildPreview())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.rebuildPreview())}syncModifiers(e){this.shiftHeld=e.shiftKey}computeDimensions(e){let t=this.startPoint;if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{width:Math.round(n*2*100)/100,height:Math.round(r*2*100)/100}}return{width:Math.round((e[0]-t[0])*100)/100,height:Math.round((e[1]-t[1])*100)/100}}computePreviewCorners(e){let t=this.startPoint;if(this.lockedWidth!==null){if(this.shiftHeld){let n=this.lockedWidth/2,r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}let n=e[0]>=t[0]?1:-1;return{c1:t,c2:[t[0]+n*this.lockedWidth,e[1]]}}if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}return{c1:t,c2:e}}dimensionInputAnchor(){if(!this.startPoint||!this.mousePoint)return{clientX:this.lastClientX,clientY:this.lastClientY};let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint),n=this.expressionPhase===`width`?[(e[0]+t[0])/2,e[1]]:[t[0],(e[1]+t[1])/2];return Dp(this.ctx,this.plane,n)}updateDimensionInput(){if(!this.startPoint||!this.mousePoint)return;let{width:e,height:t}=this.computeDimensions(this.mousePoint),n=this.dimensionInputAnchor();if(this.expressionPhase===`width`){let t=Math.round(Math.abs(e)*100)/100;if(t<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(n.clientX,n.clientY)):this.expressionInput.show({label:`W`,value:String(t),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onWidthCommit(e)})}else if(this.expressionPhase===`height`){let e=Math.round(Math.abs(t)*100)/100;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(n.clientX,n.clientY)):this.expressionInput.show({label:`H`,value:String(e),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e)})}}onWidthCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.widthIsNumeric=n,n?(this.widthExpression=e,this.lockedWidth=t):(this.widthExpression=e,this.lockedWidth=null),this.expressionPhase=`height`,queueMicrotask(()=>{if(this.mousePoint&&this.startPoint){let{height:e}=this.computeDimensions(this.mousePoint),t=Math.round(Math.abs(e)*100)/100,n=this.dimensionInputAnchor();this.expressionInput.show({label:`H`,value:String(t),clientX:n.clientX,clientY:n.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e)})}this.rebuildPreview()})}onHeightCommit(e){if(!this.startPoint||!this.widthExpression)return;let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression,r=this.resolveSignedDim(this.widthExpression,this.widthIsNumeric,this.lockedWidth,0),i;if(n&&this.mousePoint&&!this.shiftHeld){let n=this.mousePoint[1]>=this.startPoint[1]?1:-1;i={expression:String(Math.round(n*t*100)/100),newVariable:e.newVariable}}else i=e;this.commitRect(this.startPoint,r,i),this.expressionInput.hide(),this.startPoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.rebuildPreview()}commitFromGeometry(e){if(!this.startPoint)return;let{width:t,height:n}=this.computeDimensions(e);t===0||n===0||(this.commitRect(this.startPoint,{expression:String(t)},{expression:String(n)}),this.expressionInput.hide(),this.startPoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.lockedWidth=null,this.widthIsNumeric=!1,this.rebuildPreview())}resolveSignedDim(e,t,n,r){if(!t||n===null||!this.mousePoint||!this.startPoint||this.shiftHeld)return e;let i=r===0?this.mousePoint[0]>=this.startPoint[0]?1:-1:this.mousePoint[1]>=this.startPoint[1]?1:-1;return{expression:String(Math.round(i*n*100)/100),newVariable:e.newVariable}}commitRect(e,t,n){let r=this.isAtCurrentPosition(e),i;i=r?`rect(${t.expression}, ${n.expression})`:`rect(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,this.shiftHeld&&(i+=`.centered()`);let a=t.newVariable??n.newVariable;this.insertGeometry(i,a)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.mousePoint){let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint);nv(this.previewGroup,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},Ev=class extends V_{id=`rounded-rect`;label=`Rounded Rectangle`;icon=$h;startPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`width`;widthExpression=null;heightExpression=null;lockedWidth=null;lockedHeight=null;widthIsNumeric=!1;heightIsNumeric=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.startPoint=null,this.mousePoint=null,this.expressionPhase=`width`,this.widthExpression=null,this.heightExpression=null,this.lockedWidth=null,this.lockedHeight=null,this.widthIsNumeric=!1,this.heightIsNumeric=!1,this.shiftHeld=!1,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.rebuildPreview();return}if(this.expressionInput.isVisible)this.expressionInput.commitCurrentValue();else if(this.expressionPhase===`width`||this.expressionPhase===`height`)this.commitDimensionsFromGeometry(i);else if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(i);this.commitRoundedRect(this.startPoint,this.widthExpression,this.heightExpression,{expression:String(e)}),this.resetState(),this.rebuildPreview()}}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.startPoint&&(this.resetState(),this.rebuildPreview());return}e.key===`Shift`&&(this.shiftHeld=!0,this.rebuildPreview())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.rebuildPreview())}syncModifiers(e){this.shiftHeld=e.shiftKey}computeDimensions(e){let t=this.startPoint;if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{width:Math.round(n*2*100)/100,height:Math.round(r*2*100)/100}}return{width:Math.round((e[0]-t[0])*100)/100,height:Math.round((e[1]-t[1])*100)/100}}computePreviewCorners(e){let t=this.startPoint,n=this.lockedWidth!==null,r=this.lockedHeight!==null;if(n&&r)return this.getLockedPreviewCorners();if(n){if(this.shiftHeld){let n=this.lockedWidth/2,r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}let n=e[0]>=t[0]?1:-1;return{c1:t,c2:[t[0]+n*this.lockedWidth,e[1]]}}if(this.shiftHeld){let n=e[0]-t[0],r=e[1]-t[1];return{c1:[t[0]-n,t[1]-r],c2:[t[0]+n,t[1]+r]}}return{c1:t,c2:e}}getLockedPreviewCorners(){if(!this.startPoint||this.lockedWidth===null||this.lockedHeight===null)return null;if(this.shiftHeld){let e=this.lockedWidth/2,t=this.lockedHeight/2;return{c1:[this.startPoint[0]-e,this.startPoint[1]-t],c2:[this.startPoint[0]+e,this.startPoint[1]+t]}}let e=this.mousePoint?this.mousePoint[0]>=this.startPoint[0]?1:-1:1,t=this.mousePoint?this.mousePoint[1]>=this.startPoint[1]?1:-1:1;return{c1:this.startPoint,c2:[this.startPoint[0]+e*this.lockedWidth,this.startPoint[1]+t*this.lockedHeight]}}computeRadiusFromMouse(e){let t=this.getLockedPreviewCorners();if(!t)return 0;let{c1:n,c2:r}=t,i=[[n[0],n[1]],[r[0],n[1]],[r[0],r[1]],[n[0],r[1]]],a=1/0;for(let t of i){let n=Ap(e,t);n<a&&(a=n)}let o=Math.min(Math.abs(r[0]-n[0])/2,Math.abs(r[1]-n[1])/2);return Math.round(Math.min(a,o)*100)/100}dimensionInputAnchor(){let e={clientX:this.lastClientX,clientY:this.lastClientY};if(!this.startPoint||!this.mousePoint)return e;if(this.expressionPhase===`radius`){let t=this.getLockedPreviewCorners();if(!t)return e;let{c1:n,c2:r}=t;return Dp(this.ctx,this.plane,[(n[0]+r[0])/2,(n[1]+r[1])/2])}let{c1:t,c2:n}=this.computePreviewCorners(this.mousePoint),r=this.expressionPhase===`width`?[(t[0]+n[0])/2,t[1]]:[n[0],(t[1]+n[1])/2];return Dp(this.ctx,this.plane,r)}updateDimensionInput(){if(!this.startPoint||!this.mousePoint)return;let e=this.dimensionInputAnchor();if(this.expressionPhase===`width`){let{width:t}=this.computeDimensions(this.mousePoint),n=Math.round(Math.abs(t)*100)/100;if(n<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(n),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`W`,value:String(n),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onWidthCommit(e)})}else if(this.expressionPhase===`height`){let{height:t}=this.computeDimensions(this.mousePoint),n=Math.round(Math.abs(t)*100)/100,r=t>=0?1:-1;this.expressionInput.isVisible?(this.expressionInput.updateValue(n),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`H`,value:String(n),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e,r)})}else if(this.expressionPhase===`radius`){let t=this.computeRadiusFromMouse(this.mousePoint);this.expressionInput.isVisible?(this.expressionInput.updateValue(t),this.expressionInput.updatePosition(e.clientX,e.clientY)):this.expressionInput.show({label:`R`,value:String(t),clientX:e.clientX,clientY:e.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}}onWidthCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.widthIsNumeric=n,n?(this.widthExpression=e,this.lockedWidth=t):(this.widthExpression=e,this.lockedWidth=null),this.expressionPhase=`height`,queueMicrotask(()=>{if(this.mousePoint&&this.startPoint){let{height:e}=this.computeDimensions(this.mousePoint),t=Math.round(Math.abs(e)*100)/100,n=e>=0?1:-1,r=this.dimensionInputAnchor();this.expressionInput.show({label:`H`,value:String(t),clientX:r.clientX,clientY:r.clientY,variables:this.cachedVariables,onCommit:e=>this.onHeightCommit(e,n)})}this.rebuildPreview()})}onHeightCommit(e,t){if(!this.startPoint||!this.widthExpression)return;let n=parseFloat(e.expression),r=!isNaN(n)&&String(n)===e.expression;this.heightIsNumeric=r,r?(this.heightExpression=e,this.lockedHeight=n):(this.heightExpression=e,this.lockedHeight=null),this.expressionPhase=`radius`,queueMicrotask(()=>{if(this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint),t=this.dimensionInputAnchor();this.expressionInput.show({label:`R`,value:String(e),clientX:t.clientX,clientY:t.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()})}onRadiusCommit(e){if(!this.startPoint||!this.widthExpression||!this.heightExpression)return;let t=this.resolveSignedExpression(this.widthExpression,this.widthIsNumeric,this.lockedWidth,0),n=this.resolveSignedExpression(this.heightExpression,this.heightIsNumeric,this.lockedHeight,1);this.commitRoundedRect(this.startPoint,t,n,e),this.resetState(),this.rebuildPreview()}resolveSignedExpression(e,t,n,r){if(!t||n===null||!this.mousePoint||!this.startPoint||this.shiftHeld)return e;let i=r===0?this.mousePoint[0]>=this.startPoint[0]?1:-1:this.mousePoint[1]>=this.startPoint[1]?1:-1,a=Math.round(i*n*100)/100;return{expression:String(a),newVariable:e.newVariable}}commitDimensionsFromGeometry(e){if(!this.startPoint)return;let{width:t,height:n}=this.computeDimensions(e);if(!(t===0||n===0)){if(this.widthExpression={expression:String(t)},this.lockedWidth=Math.abs(t),this.widthIsNumeric=!0,this.heightExpression={expression:String(n)},this.lockedHeight=Math.abs(n),this.heightIsNumeric=!0,this.expressionPhase=`radius`,this.expressionInput.hide(),this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint),t=this.dimensionInputAnchor();this.expressionInput.show({label:`R`,value:String(e),clientX:t.clientX,clientY:t.clientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()}}commitRoundedRect(e,t,n,r){let i=this.isAtCurrentPosition(e),a;a=i?`rect(${t.expression}, ${n.expression})`:`rect(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,a+=`.radius(${r.expression})`,this.shiftHeld&&(a+=`.centered()`);let o=t.newVariable??n.newVariable??r.newVariable;this.insertGeometry(a,o)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){if(Q(this.previewGroup,this.startPoint,X,e,t,this.plane),this.expressionPhase===`radius`){let e=this.getLockedPreviewCorners();if(e){let t=this.mousePoint?this.computeRadiusFromMouse(this.mousePoint):0;t>0?iv(this.previewGroup,e.c1,e.c2,t,this.plane):nv(this.previewGroup,e.c1,e.c2,this.plane)}}else if(this.mousePoint){let{c1:e,c2:t}=this.computePreviewCorners(this.mousePoint);nv(this.previewGroup,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},Dv=class extends V_{id=`slot`;label=`Slot`;icon=eg;startPoint=null;endPoint=null;mousePoint=null;lastSnapType=`none`;shiftHeld=!1;horizontalMode=!1;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`endpoint`;distanceExpression=null;lockedDistance=null;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),window.addEventListener(`keyup`,this.boundKeyUp),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),window.removeEventListener(`keyup`,this.boundKeyUp),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}handleEscape(){return this.startPoint?this.expressionPhase===`radius`?(this.expressionPhase=this.horizontalMode?`distance`:`endpoint`,this.endPoint=null,this.distanceExpression=null,this.lockedDistance=null,this.expressionInput.hide(),this.rebuildPreview(),!0):this.expressionPhase===`distance`?(this.expressionPhase=`endpoint`,this.horizontalMode=!1,this.expressionInput.hide(),this.rebuildPreview(),!0):(this.resetState(),this.rebuildPreview(),!0):!1}resetState(){this.startPoint=null,this.endPoint=null,this.mousePoint=null,this.expressionPhase=`endpoint`,this.horizontalMode=!1,this.distanceExpression=null,this.lockedDistance=null,this.expressionInput.hide()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.startPoint){this.startPoint=i,this.syncModifiers(e),this.shiftHeld&&(this.horizontalMode=!0,this.expressionPhase=`distance`),this.rebuildPreview();return}if(this.expressionInput.isVisible){this.expressionInput.commitCurrentValue();return}if(this.expressionPhase===`endpoint`){if(Ap(this.startPoint,i)<=0)return;this.endPoint=i,this.expressionPhase=`radius`,this.expressionInput.hide(),this.rebuildPreview(),this.updateDimensionInput();return}if(this.expressionPhase===`distance`){let e=Math.round((i[0]-this.startPoint[0])*100)/100;if(e===0)return;this.onDistanceCommit({expression:String(e)});return}if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(i);if(e<=0)return;this.onRadiusCommit({expression:String(e)})}}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY,this.syncModifiers(e);let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){if(e.key===`Escape`){this.handleEscape()&&e.stopPropagation();return}e.key===`Shift`&&(this.shiftHeld=!0,this.startPoint&&this.expressionPhase===`endpoint`&&!this.horizontalMode&&(this.horizontalMode=!0,this.expressionPhase=`distance`,this.expressionInput.hide()),this.rebuildPreview(),this.updateDimensionInput())}handleKeyUp(e){e.key===`Shift`&&(this.shiftHeld=!1,this.expressionPhase===`distance`&&!this.distanceExpression&&(this.horizontalMode=!1,this.expressionPhase=`endpoint`,this.expressionInput.hide()),this.rebuildPreview(),this.updateDimensionInput())}syncModifiers(e){this.shiftHeld=e.shiftKey}getSlotAxis(){if(!this.startPoint)return null;if(this.horizontalMode){let e=this.lockedDistance??(this.mousePoint?this.mousePoint[0]-this.startPoint[0]:0);return{dir:e>=0?[1,0]:[-1,0],leftCenter:this.startPoint,rightCenter:[this.startPoint[0]+e,this.startPoint[1]]}}if(this.endPoint){let e=this.endPoint[0]-this.startPoint[0],t=this.endPoint[1]-this.startPoint[1],n=Math.sqrt(e*e+t*t);return n<1e-10?null:{dir:[e/n,t/n],leftCenter:this.startPoint,rightCenter:this.endPoint}}if(this.mousePoint){let e=this.mousePoint[0]-this.startPoint[0],t=this.mousePoint[1]-this.startPoint[1],n=Math.sqrt(e*e+t*t);return n<1e-10?null:{dir:[e/n,t/n],leftCenter:this.startPoint,rightCenter:this.mousePoint}}return null}computeRadiusFromMouse(e){let t=this.getSlotAxis();if(!t)return 0;let n=e[0]-t.leftCenter[0],r=e[1]-t.leftCenter[1],i=Math.abs(-t.dir[1]*n+t.dir[0]*r);return Math.round(i*100)/100}updateDimensionInput(){if(!(!this.startPoint||!this.mousePoint)){if(this.expressionPhase===`distance`){let e=Math.round((this.mousePoint[0]-this.startPoint[0])*100)/100;if(e===0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`D`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onDistanceCommit(e)});return}if(this.expressionPhase===`radius`){let e=this.computeRadiusFromMouse(this.mousePoint);if(e<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`R`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}}}onDistanceCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.distanceExpression=e,this.lockedDistance=n?t:null,this.expressionPhase=`radius`,queueMicrotask(()=>{if(this.mousePoint){let e=this.computeRadiusFromMouse(this.mousePoint);this.expressionInput.show({label:`R`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onRadiusCommit(e)})}this.rebuildPreview()})}onRadiusCommit(e){this.startPoint&&(this.horizontalMode&&this.distanceExpression?this.commitHorizontalSlot(this.startPoint,this.distanceExpression,e):this.endPoint&&this.commitTwoPointSlot(this.startPoint,this.endPoint,e),this.resetState(),this.rebuildPreview())}commitTwoPointSlot(e,t,n){let r=`slot(${this.formatPoint(e)}, ${this.formatPoint(t)}, ${n.expression})`;this.insertGeometry(r,n.newVariable)}commitHorizontalSlot(e,t,n){let r=this.isAtCurrentPosition(e)?`slot(${t.expression}, ${n.expression})`:`slot(${this.formatPoint(e)}, ${t.expression}, ${n.expression})`,i=t.newVariable??n.newVariable;this.insertGeometry(r,i)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.startPoint){Q(this.previewGroup,this.startPoint,X,e,t,this.plane);let n=this.getSlotAxis();if(n){let r=Ap(n.leftCenter,n.rightCenter);if(r>0)if(this.expressionPhase===`radius`&&this.mousePoint){let r=this.computeRadiusFromMouse(this.mousePoint);r>0?uv(this.previewGroup,n.leftCenter,n.rightCenter,r,this.plane):ev(this.previewGroup,n.leftCenter,n.rightCenter,this.plane),Q(this.previewGroup,n.rightCenter,X,e,t,this.plane)}else uv(this.previewGroup,n.leftCenter,n.rightCenter,r/6,this.plane),Q(this.previewGroup,n.rightCenter,Z,e,t,this.plane)}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}},Ov={line:`Line`,hLine:`H-Line`,vLine:`V-Line`,arc:`Arc`,tArc:`T-Arc`,tLine:`T-Line`},kv=class{el;labelSpan;constructor(e){this.el=document.createElement(`div`),this.el.className=`absolute z-[999] pointer-events-none hidden`;let t=document.createElement(`div`);t.className=`panel-bg border border-base-content/10 rounded-md px-2 py-0.5 shadow-sm flex items-center gap-1.5`,this.labelSpan=document.createElement(`span`),this.labelSpan.className=`text-xs font-mono text-base-content/70`;let n=document.createElement(`span`);n.className=`text-[10px] text-base-content/30`,n.textContent=`Space`,t.appendChild(this.labelSpan),t.appendChild(n),this.el.appendChild(t),e.appendChild(this.el)}show(e){this.labelSpan.textContent=Ov[e],this.el.classList.remove(`hidden`)}hide(){this.el.classList.add(`hidden`)}update(e){this.labelSpan.textContent=Ov[e]}updatePosition(e,t){this.el.style.left=`${e+16}px`,this.el.style.top=`${t+16}px`}dispose(){this.el.remove()}},Av=class{id=`line`;label=`Line`;requiresTangent=!1;mousePoint=null;lastSnapType=`none`;enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null}handleClick(e,t,n){let r=Y(n.startPoint),i=Y(e),a=n.isAtCurrentPosition(r)?`line(${n.formatPoint(i)})`:`line(${n.formatPoint(r)}, ${n.formatPoint(i)})`;n.insertGeometry(a);let o=i[0]-r[0],s=i[1]-r[1],c=Math.sqrt(o*o+s*s);return{kind:`committed`,result:{endpoint:i,exitTangent:c>1e-10?{direction:[o/c,s/c],point:i}:null}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return!1}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint&&(ev(e.previewGroup,e.startPoint,this.mousePoint,e.plane),this.lastSnapType!==`none`)){let t=this.lastSnapType===`vertex`?Z:X_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}},jv=class{id;label;requiresTangent=!1;axis;mousePoint=null;lastSnapType=`none`;constructor(e){this.axis=e,this.id=e===`h`?`hLine`:`vLine`,this.label=e===`h`?`H-Line`:`V-Line`}enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null,e.hideExpressionInput()}getEffectiveEnd(e,t){return this.axis===`h`?[t[0],e[1]]:[e[0],t[1]]}getDistance(e,t){return this.axis===`h`?t[0]-e[0]:t[1]-e[1]}handleClick(e,t,n){if(n.isExpressionVisible())return n.commitExpressionValue(),{kind:`ignored`};let r=Y(n.startPoint),i=this.getDistance(r,e),a=Math.round(i*100)/100;if(a===0)return{kind:`ignored`};let o=n.isAtCurrentPosition(r),s=this.axis===`h`?`hLine`:`vLine`,c=o?`${s}(${a})`:`${s}(${n.formatPoint(r)}, ${a})`;n.insertGeometry(c),n.hideExpressionInput();let l=Y(this.axis===`h`?[r[0]+a,r[1]]:[r[0],r[1]+a]);return{kind:`committed`,result:{endpoint:l,exitTangent:{direction:this.axis===`h`?[Math.sign(a)||1,0]:[0,Math.sign(a)||1],point:l}}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType;let a=Math.abs(this.getDistance(i.startPoint,e)),o=this.axis===`h`?`H:`:`V:`;i.isExpressionVisible()?(i.updateExpressionValue(a),i.updateExpressionPosition(n,r)):i.showExpressionInput({label:o,value:String(Math.round(a*100)/100),clientX:n,clientY:r,onCommit:e=>this.commitWithDimension(e,i)})}handleEscape(e){return e.isExpressionVisible()?(e.hideExpressionInput(),!0):!1}commitWithDimension(e,t){let n=Y(t.startPoint);if(!this.mousePoint)return;let{expression:r,newVariable:i}=e,a=this.getDistance(n,this.mousePoint),o=Math.sign(a),s=parseFloat(r),c=!isNaN(s)&&String(s)===r?String(Math.round(o*s*100)/100):r,l=t.isAtCurrentPosition(n),u=this.axis===`h`?`hLine`:`vLine`,d=l?`${u}(${c})`:`${u}(${t.formatPoint(n)}, ${c})`;t.insertGeometry(d,i),t.hideExpressionInput();let f=parseFloat(c),p=isNaN(f)?Math.round(o*Math.abs(this.getDistance(n,this.mousePoint))*100)/100:f,m=this.axis===`h`?[n[0]+p,n[1]]:[n[0],n[1]+p],h=this.axis===`h`?[Math.sign(p)||1,0]:[0,Math.sign(p)||1];t.onSegmentCommitted({endpoint:Y(m),exitTangent:{direction:h,point:Y(m)}})}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint){let t=this.getEffectiveEnd(e.startPoint,this.mousePoint);if(ev(e.previewGroup,e.startPoint,t,e.plane),this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(e.previewGroup,t,n,e.camera,e.planeNormal,e.plane,.6)}}}},Mv=function(e){return e[e.AWAITING_END=0]=`AWAITING_END`,e[e.AWAITING_THROUGH=1]=`AWAITING_THROUGH`,e}(Mv||{}),Nv=class{id=`arc`;label=`Arc`;requiresTangent=!1;subState=Mv.AWAITING_END;endPoint=null;mousePoint=null;lastSnapType=`none`;enter(e){this.subState=Mv.AWAITING_END,this.endPoint=null,this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.subState=Mv.AWAITING_END,this.endPoint=null,this.mousePoint=null}handleClick(e,t,n){if(this.subState===Mv.AWAITING_END)return Ap(n.startPoint,e)<1e-6?{kind:`ignored`}:(this.endPoint=e,this.subState=Mv.AWAITING_THROUGH,{kind:`consumed`});if(!this.endPoint)return{kind:`ignored`};let r=pv(n.startPoint,this.endPoint,e);if(!r)return{kind:`ignored`};let i=this.isMouseCCW(n.startPoint,this.endPoint,e,r),a=Y(n.startPoint),o=Y(this.endPoint),s=Y(r),c=i?``:`.cw()`,l=n.isAtCurrentPosition(a)?`arc(${n.formatPoint(o)}).center(${n.formatPoint(s)})${c}`:`arc(${n.formatPoint(a)}, ${n.formatPoint(o)}).center(${n.formatPoint(s)})${c}`;return n.insertGeometry(l),{kind:`committed`,result:{endpoint:o,exitTangent:this.computeExitTangent(o,s,i)}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return this.subState===Mv.AWAITING_THROUGH?(this.endPoint=null,this.subState=Mv.AWAITING_END,!0):!1}isMouseCCW(e,t,n,r){let i=dv(r,e),a=dv(r,t),o=dv(r,n)-i;o<0&&(o+=Math.PI*2);let s=a-i;return s<0&&(s+=Math.PI*2),o<s}semicirclePreview(e,t){let n=t[0]-e[0],r=t[1]-e[1],i=Math.sqrt(n*n+r*r);if(i<1e-6)return null;let a=[(e[0]+t[0])/2,(e[1]+t[1])/2];return{center:a,radius:i/2,startAngle:dv(a,e),endAngle:dv(a,t)}}computeExitTangent(e,t,n){let r=e[0]-t[0],i=e[1]-t[1],a=Math.sqrt(r*r+i*i);return a<1e-10?null:{direction:[n?-i/a:i/a,n?r/a:-r/a],point:e}}rebuildPreview(e){if(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.subState===Mv.AWAITING_END){if(this.mousePoint){let t=this.semicirclePreview(e.startPoint,this.mousePoint);if(t&&ov(e.previewGroup,t.center,t.radius,t.startAngle,t.endAngle,!0,e.plane),this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:X_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}else if(this.endPoint&&(Q(e.previewGroup,this.endPoint,X,e.camera,e.planeNormal,e.plane),ev(e.previewGroup,e.startPoint,this.endPoint,e.plane),this.mousePoint)){let t=pv(e.startPoint,this.endPoint,this.mousePoint);if(t){let n=Ap(t,e.startPoint),r=dv(t,e.startPoint),i=dv(t,this.endPoint),a=this.isMouseCCW(e.startPoint,this.endPoint,this.mousePoint,t);ov(e.previewGroup,t,n,r,i,a,e.plane)}if(this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:X_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}},Pv=class{id=`tArc`;label=`T-Arc`;requiresTangent=!0;mousePoint=null;lastSnapType=`none`;enter(e){this.mousePoint=null,this.lastSnapType=`none`}exit(e){this.mousePoint=null}handleClick(e,t,n){if(!n.tangent)return{kind:`ignored`};let r=Y(e);n.insertGeometry(`tArc(${n.formatPoint(r)})`);let i=this.computeArcPreview(n.startPoint,e,n.tangent.direction),a=null;if(i){let e=r[0]-i.center[0],t=r[1]-i.center[1],n=Math.sqrt(e*e+t*t);n>1e-10&&(a={direction:[i.ccw?-t/n:t/n,i.ccw?e/n:-e/n],point:r})}return{kind:`committed`,result:{endpoint:r,exitTangent:a}}}handleMouseMove(e,t,n,r,i){this.mousePoint=e,this.lastSnapType=t.snapType}handleEscape(e){return!1}computeArcPreview(e,t,n){let r=-n[1],i=n[0],a=e[0]-t[0],o=e[1]-t[1],s=a*a+o*o,c=a*r+o*i;if(Math.abs(c)<1e-10)return null;let l=-s/(2*c),u=Math.abs(l),d=[e[0]+r*l,e[1]+i*l];return{center:d,radius:u,startAngle:dv(d,e),endAngle:dv(d,t),ccw:l>=0}}rebuildPreview(e){if(e.tangent&&(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint)){let t=this.computeArcPreview(e.startPoint,this.mousePoint,e.tangent.direction);if(t&&ov(e.previewGroup,t.center,t.radius,t.startAngle,t.endAngle,t.ccw,e.plane),this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:X_;Q(e.previewGroup,this.mousePoint,t,e.camera,e.planeNormal,e.plane,.6)}}}},Fv=class{id=`tLine`;label=`T-Line`;requiresTangent=!0;mousePoint=null;enter(e){this.mousePoint=null}exit(e){this.mousePoint=null,e.hideExpressionInput()}projectOnTangent(e,t,n){let r=t[0]-e[0],i=t[1]-e[1],a=r*n[0]+i*n[1];return{projected:[e[0]+n[0]*a,e[1]+n[1]*a],distance:a}}handleClick(e,t,n){if(!n.tangent)return{kind:`ignored`};if(n.isExpressionVisible())return n.commitExpressionValue(),{kind:`ignored`};if(!this.mousePoint)return{kind:`ignored`};let{distance:r}=this.projectOnTangent(n.startPoint,this.mousePoint,n.tangent.direction),i=Math.round(r*100)/100;if(i===0)return{kind:`ignored`};n.insertGeometry(`tLine(${i})`),n.hideExpressionInput();let a=Y([n.startPoint[0]+n.tangent.direction[0]*r,n.startPoint[1]+n.tangent.direction[1]*r]);return{kind:`committed`,result:{endpoint:a,exitTangent:{direction:n.tangent.direction,point:a}}}}handleMouseMove(e,t,n,r,i){if(this.mousePoint=e,!i.tangent)return;let{distance:a}=this.projectOnTangent(i.startPoint,e,i.tangent.direction),o=Math.abs(a);i.isExpressionVisible()?(i.updateExpressionValue(o),i.updateExpressionPosition(n,r)):i.showExpressionInput({label:`T:`,value:String(Math.round(o*100)/100),clientX:n,clientY:r,onCommit:e=>this.commitWithDimension(e,i)})}handleEscape(e){return e.isExpressionVisible()?(e.hideExpressionInput(),!0):!1}commitWithDimension(e,t){if(!t.tangent||!this.mousePoint)return;let{expression:n,newVariable:r}=e,{distance:i}=this.projectOnTangent(t.startPoint,this.mousePoint,t.tangent.direction),a=Math.sign(i),o=parseFloat(n),s=!isNaN(o)&&String(o)===n?String(Math.round(a*o*100)/100):n;t.insertGeometry(`tLine(${s})`,r),t.hideExpressionInput();let c=Y([t.startPoint[0]+t.tangent.direction[0]*i,t.startPoint[1]+t.tangent.direction[1]*i]);t.onSegmentCommitted({endpoint:c,exitTangent:{direction:t.tangent.direction,point:c}})}rebuildPreview(e){if(e.tangent&&(Q(e.previewGroup,e.startPoint,X,e.camera,e.planeNormal,e.plane),this.mousePoint)){let{projected:t}=this.projectOnTangent(e.startPoint,this.mousePoint,e.tangent.direction);ev(e.previewGroup,e.startPoint,t,e.plane)}}},Iv=function(e){return e[e.IDLE=0]=`IDLE`,e[e.DRAWING=1]=`DRAWING`,e}({}),Lv=[`line`,`hLine`,`vLine`,`arc`,`tArc`,`tLine`],Rv=class extends V_{id=`polyline`;label=`Polyline`;icon=ng;phase=Iv.IDLE;startPoint=null;currentModeIndex=0;tangent=null;modes;expressionInput;fetchVariables;cachedVariables=[];modeIndicator;sceneObjects=[];sketchId=``;mousePoint=null;lastSnapType=`none`;lastSnapResult=null;lastClientX=0;lastClientY=0;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.modeIndicator=new kv(i),this.modes=[new Av,new jv(`h`),new jv(`v`),new Nv,new Pv,new Fv],this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.expressionInput.onSpaceOverride=()=>{this.cycleMode(1)}}get currentMode(){return this.modes[this.currentModeIndex]}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e}),this.modeIndicator.show(this.currentMode.id)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.expressionInput.hide(),this.modeIndicator.dispose(),this.phase=Iv.IDLE,this.startPoint=null,this.tangent=null,this.removePreviewFromScene()}onSceneUpdate(e,t){this.sceneObjects=e,this.sketchId=t;let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e}),this.phase===Iv.DRAWING&&this.startPoint&&this.updateTangentFromScene()}handleEscape(){return!1}buildModeContext(){if(!this.startPoint)return null;let e=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);return{plane:this.plane,previewGroup:this.previewGroup,camera:this.ctx.camera,planeNormal:e,tangent:this.tangent,sceneObjects:this.sceneObjects,sketchId:this.sketchId,startPoint:this.startPoint,isAtCurrentPosition:e=>this.isAtCurrentPosition(e),formatPoint:e=>this.formatPoint(e),insertGeometry:(e,t)=>this.insertGeometry(e,t),requestRender:()=>this.requestRender(),showExpressionInput:e=>{this.expressionInput.isVisible||this.expressionInput.show({...e,variables:this.cachedVariables})},updateExpressionValue:e=>this.expressionInput.updateValue(e),updateExpressionPosition:(e,t)=>this.expressionInput.updatePosition(e,t),hideExpressionInput:()=>this.expressionInput.hide(),isExpressionVisible:()=>this.expressionInput.isVisible,commitExpressionValue:()=>this.expressionInput.commitCurrentValue(),onSegmentCommitted:e=>this.handleModeCommit(e)}}handleModeCommit(e){let{endpoint:t,exitTangent:n}=e;this.startPoint=t,this.tangent=n,this.currentMode.requiresTangent&&!this.tangent&&(this.advanceToNextValidMode(),this.modeIndicator.update(this.currentMode.id));let r=this.buildModeContext();this.currentMode.enter(r),this.rebuildPreview()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=this.snapController.snap(r),a=Y(i.point2d);if(this.phase===Iv.IDLE){this.startPoint=a,this.phase=Iv.DRAWING,this.tangent=this.findTangentAtPoint(a),this.currentMode.requiresTangent&&!this.tangent&&this.advanceToNextValidMode();let e=this.buildModeContext();this.currentMode.enter(e),this.modeIndicator.update(this.currentMode.id),this.rebuildPreview();return}let o=this.buildModeContext();if(!o)return;let s=this.currentMode.handleClick(a,i,o);s.kind===`committed`?this.handleModeCommit(s.result):this.rebuildPreview()}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);if(this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.lastSnapResult=n,this.modeIndicator.updatePosition(e.clientX,e.clientY),this.phase===Iv.DRAWING){let t=this.buildModeContext();t&&this.currentMode.handleMouseMove(n.point2d,n,e.clientX,e.clientY,t)}this.rebuildPreview()}handleKeyDown(e){if(e.key===` `){e.preventDefault(),this.cycleMode(e.shiftKey?-1:1);return}}cycleMode(e){let t=this.buildModeContext();t&&(this.expressionInput.hide(),this.currentMode.exit(t));let n=this.currentModeIndex;for(let t=0;t<Lv.length&&(this.currentModeIndex=(this.currentModeIndex+e+Lv.length)%Lv.length,!(!this.modes[this.currentModeIndex].requiresTangent||this.tangent||this.currentModeIndex===n));t++);if(this.modeIndicator.update(this.currentMode.id),this.phase===Iv.DRAWING){let e=this.buildModeContext();e&&(this.currentMode.enter(e),this.mousePoint&&this.lastSnapResult&&this.currentMode.handleMouseMove(this.mousePoint,this.lastSnapResult,this.lastClientX,this.lastClientY,e))}this.rebuildPreview()}advanceToNextValidMode(){let e=this.currentModeIndex;for(let t=0;t<Lv.length;t++)if(this.currentModeIndex=(this.currentModeIndex+1)%Lv.length,!this.modes[this.currentModeIndex].requiresTangent||this.tangent||this.currentModeIndex===e)return}findTangentAtPoint(e){if(!this.isAtCurrentPosition(Y(e)))return null;let t=null;for(let e of this.sceneObjects)e.parentId!==this.sketchId||!e.sourceLocation||gv.has(e.uniqueType??``)&&(t=e);if(!t)return null;for(let n of t.sceneShapes)if(!n.isMetaShape)for(let t of n.meshes){let n=_v(t.vertices,this.plane);if(n.length<2)continue;let r=vv(n,`end`);if(r)return{direction:r,point:e}}return null}updateTangentFromScene(){if(!this.startPoint||this.tangent)return;let e=this.findTangentAtPoint(this.startPoint);e&&(this.tangent=e)}rebuildPreview(){this.disposePreview();let e=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.phase===Iv.DRAWING){let e=this.buildModeContext();e&&this.currentMode.rebuildPreview(e)}else if(this.mousePoint&&this.lastSnapType!==`none`){let t=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,t,this.ctx.camera,e,this.plane,.6)}this.requestRender()}},zv=class extends V_{id=`bezier`;label=`Bezier`;icon=rg;activeSourceLocation=null;existingPoles=[];mousePoint=null;lastSnapType=`none`;pendingFirstClick=!1;pendingStart=null;boundMouseDown;boundMouseUp;boundMouseMove;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove)}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.activeSourceLocation=null,this.existingPoles=[],this.mousePoint=null,this.lastSnapType=`none`,this.pendingFirstClick=!1,this.pendingStart=null,this.removePreviewFromScene()}handleEscape(){return!1}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);if(this.updateSnapManager(n),!this.activeSourceLocation&&!this.pendingFirstClick){this.rebuildPreview();return}let r=null;for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.parentId===t&&i.type===`bezier`){r=i;break}}if(r&&r.sourceLocation){let e=r.object?.startPoint,t=r.object?.resolvedPoints;this.activeSourceLocation=r.sourceLocation,this.existingPoles=e?[e,...t??[]]:[],this.pendingFirstClick=!1,this.pendingStart=null}this.rebuildPreview()}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64||this.pendingFirstClick)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.activeSourceLocation){this.insertGeometry(`bezier(${this.formatPoint(i)})`),this.pendingFirstClick=!0,this.pendingStart=i,this.rebuildPreview();return}Nm(i,this.activeSourceLocation)}handleMouseMove(e){let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview()}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),n=[...this.existingPoles];if(n.length===0&&this.pendingStart&&n.push(this.pendingStart),this.mousePoint&&(this.activeSourceLocation||this.pendingStart)&&n.push(this.mousePoint),n.length>=2){for(let e=1;e<n.length;e++)ev(this.previewGroup,n[e-1],n[e],this.plane);cv(this.previewGroup,n,this.plane)}for(let r=0;r<n.length;r++){let i=r===0?X:Y_,a=r===0?1:.85;Q(this.previewGroup,n[r],i,e,t,this.plane,a)}this.mousePoint&&this.lastSnapType!==`none`&&Q(this.previewGroup,this.mousePoint,$_(this.lastSnapType),e,t,this.plane,.6),this.requestRender()}},Bv=3,Vv=24,Hv=6,Uv=25,Wv=class extends V_{id=`polygon`;label=`Polygon`;icon=tg;centerPoint=null;mousePoint=null;lastSnapType=`none`;expressionInput;fetchVariables;cachedVariables=[];lastClientX=0;lastClientY=0;expressionPhase=`diameter`;diameterExpression=null;lockedDiameter=null;currentSides=Hv;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;downX=0;downY=0;constructor(e,t,n,r,i,a){super(e,t,n,r),this.expressionInput=new J_(i),this.fetchVariables=a,this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this)}activate(){this.addPreviewToScene(),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp),this.canvas.addEventListener(`mousemove`,this.boundMouseMove),window.addEventListener(`keydown`,this.boundKeyDown),this.fetchVariables().then(e=>{this.cachedVariables=e})}deactivate(){this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),window.removeEventListener(`keydown`,this.boundKeyDown),this.resetState(),this.removePreviewFromScene()}onSceneUpdate(e,t){let n=v_.fromSceneObjects(e,t,this.plane,this.ctx);this.updateSnapManager(n),this.fetchVariables().then(e=>{this.cachedVariables=e})}resetState(){this.centerPoint=null,this.mousePoint=null,this.expressionPhase=`diameter`,this.diameterExpression=null,this.lockedDiameter=null,this.currentSides=Hv,this.expressionInput.hide()}sidesFromDistance(e){if(this.lockedDiameter!==null&&this.lockedDiameter>0){let t=e/(this.lockedDiameter/2);return Math.max(Bv,Math.min(Vv,Math.round(t*Hv)))}let t=kp(this.ctx,Uv);return t<=0?Hv:Math.max(Bv,Math.min(Vv,Math.round(e/t)))}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseUp(e){let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!r)return;let i=Y(this.snapController.snap(r).point2d);if(!this.centerPoint){this.centerPoint=i,this.rebuildPreview();return}if(this.expressionInput.isVisible){this.expressionInput.commitCurrentValue();return}if(this.expressionPhase===`diameter`){let e=Math.round(Ap(this.centerPoint,i)*2*100)/100;if(e<=0)return;this.onDiameterCommit({expression:String(e)})}else this.onSidesCommit({expression:String(this.currentSides)})}handleMouseMove(e){this.lastClientX=e.clientX,this.lastClientY=e.clientY;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview();return}let n=this.snapController.snap(t);if(this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.centerPoint&&this.expressionPhase===`sides`){let e=Ap(this.centerPoint,this.mousePoint);this.currentSides=this.sidesFromDistance(e)}this.rebuildPreview(),this.updateDimensionInput()}handleKeyDown(e){e.key===`Escape`&&this.centerPoint&&(this.resetState(),this.rebuildPreview())}updateDimensionInput(){if(!(!this.centerPoint||!this.mousePoint))if(this.expressionPhase===`diameter`){let e=Math.round(Ap(this.centerPoint,this.mousePoint)*2*100)/100;if(e<=0)return;this.expressionInput.isVisible?(this.expressionInput.updateValue(e),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`⌀`,value:String(e),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onDiameterCommit(e)})}else this.expressionInput.isVisible?(this.expressionInput.updateValue(this.currentSides),this.expressionInput.updatePosition(this.lastClientX,this.lastClientY)):this.expressionInput.show({label:`N`,value:String(this.currentSides),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onSidesCommit(e)})}onDiameterCommit(e){let t=parseFloat(e.expression),n=!isNaN(t)&&String(t)===e.expression;this.diameterExpression=e,this.lockedDiameter=n?t:null,this.expressionPhase=`sides`,queueMicrotask(()=>{if(this.mousePoint&&this.centerPoint){let e=Ap(this.centerPoint,this.mousePoint);this.currentSides=this.sidesFromDistance(e)}this.expressionInput.show({label:`N`,value:String(this.currentSides),clientX:this.lastClientX,clientY:this.lastClientY,variables:this.cachedVariables,onCommit:e=>this.onSidesCommit(e)}),this.rebuildPreview()})}onSidesCommit(e){!this.centerPoint||!this.diameterExpression||(this.commitPolygon(this.centerPoint,this.diameterExpression,e),this.resetState(),this.rebuildPreview())}commitPolygon(e,t,n){let r=this.isAtCurrentPosition(e)?`polygon(${n.expression}, ${t.expression})`:`polygon(${this.formatPoint(e)}, ${n.expression}, ${t.expression})`,i=n.newVariable??t.newVariable;this.insertGeometry(r,i)}rebuildPreview(){this.disposePreview();let e=this.ctx.camera,t=new R(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(this.centerPoint){if(Q(this.previewGroup,this.centerPoint,X,e,t,this.plane),this.mousePoint)if(this.expressionPhase===`diameter`){let e=Ap(this.centerPoint,this.mousePoint);e>0&&tv(this.previewGroup,this.centerPoint,e,this.plane)}else{let e=this.lockedDiameter===null?Ap(this.centerPoint,this.mousePoint):this.lockedDiameter/2;if(e>0&&this.currentSides>=Bv){let t=e/Math.cos(Math.PI/this.currentSides);av(this.previewGroup,this.centerPoint,t,this.currentSides,this.plane)}}}else if(this.mousePoint&&this.lastSnapType!==`none`){let n=this.lastSnapType===`vertex`?Z:X_;Q(this.previewGroup,this.mousePoint,n,e,t,this.plane,.6)}this.requestRender()}};function Gv(e,t,n,r,i){let a=t.filter(e=>e.parentId===n),o=kp(i,12),s=o*o,c=null,l=1/0;for(let t of a){if(!t.sourceLocation||!yp(t.uniqueType))continue;let n=t.uniqueType,i=t.sourceLocation;if(n&&n.startsWith(`bezier-`)){let r=Zv(e,t,i,n,s,l);r&&(c=r.hit,l=r.distSq);continue}if(n===`polygon`){let n=[];for(let e of t.sceneShapes)if(!e.isMetaShape)for(let t of e.meshes){let e=_v(t.vertices,r);for(let t of e)n.push(t)}if(n.length>0){let r=$v(e,n,i,t,s,l);r&&(c=r.hit,l=r.distSq)}continue}if(n===`slot`){let n=[];for(let e of t.sceneShapes)if(e.isMetaShape){for(let t of e.meshes)if(t.vertices.length===3&&t.indices.length===0){let e=_v(t.vertices,r);e.length===1&&n.push(e[0])}}if(n.length===2){let a=ey(e,n,i,t,r,s,l);a&&(c=a.hit,l=a.distSq)}continue}if(n===`rect`){let n=[];for(let e of t.sceneShapes)if(!e.isMetaShape)for(let t of e.meshes){let e=_v(t.vertices,r);for(let t of e)n.push(t)}if(n.length>0){let r=Qv(e,n,i,t,s,l);r&&(c=r.hit,l=r.distSq)}continue}for(let a of t.sceneShapes)if(!a.isMetaShape)for(let o of a.meshes){let a=_v(o.vertices,r);if(a.length!==0)if(n===`circle`){let t=Kv(e,a,i,s,l);t&&(c=t.hit,l=t.distSq)}else if(n===`line-two-points`||n===`hline`||n===`vline`||n===`tline`){let r=qv(e,a,i,n,t,s,l);r&&(c=r.hit,l=r.distSq)}else if(n===`arc`&&a.length>=3){let n=Yv(e,a,i,t,r,s,l);n&&(c=n.hit,l=n.distSq)}else if((n===`tarc-to-point`||n===`tarc-to-point-tangent`)&&a.length>=2){let o=Xv(e,a,i,n,t,r,s,l);o&&(c=o.hit,l=o.distSq)}else for(let t of a){let r=t[0]-e[0],a=t[1]-e[1],o=r*r+a*a;o<s&&o<l&&(c={sourceLocation:i,uniqueType:n||``,hitZone:`body`},l=o)}}}return c}function Kv(e,t,n,r,i){let a=[];for(let e of t){let t=!1;for(let n of a){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||a.push(e)}let o=0,s=0;for(let e of a)o+=e[0],s+=e[1];o/=a.length,s/=a.length;let c=a[0],l=c[0]-o,u=c[1]-s,d=Math.sqrt(l*l+u*u),f=Math.round(2*d*100)/100,p=null;for(let a of t){let t=a[0]-e[0],c=a[1]-e[1],l=t*t+c*c;l<r&&l<i&&(p={hit:{sourceLocation:n,uniqueType:`circle`,hitZone:`body`,anchorPoint:[o,s],initialValue:f},distSq:l},i=l)}return p}function qv(e,t,n,r,i,a,o){let s=t[0],c=t[t.length-1],l=s[0]-e[0],u=s[1]-e[1],d=l*l+u*u,f=c[0]-e[0],p=c[1]-e[1],m=f*f+p*p,h=r===`hline`||r===`vline`||r===`tline`,g,_;if(r===`tline`){let e=c[0]-s[0],n=c[1]-s[1],r=Math.sqrt(e*e+n*n);if(r>1e-10){if(_=[e/r,n/r],g=r,t.length>=2){let e=t[t.length-2],n=t[t.length-1],r=n[0]-e[0],i=n[1]-e[1],a=Math.sqrt(r*r+i*i);a>1e-10&&(_=[r/a,i/a])}let i=c[0]-s[0],a=c[1]-s[1];g=i*_[0]+a*_[1]}}else (r===`hline`||r===`vline`)&&(g=r===`hline`?c[0]-s[0]:c[1]-s[1]);let v=h?Math.round((g??0)*100)/100:void 0,y=d<a||m<a,b=null;if(m<a&&m<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`end`,anchorPoint:s,fixedVertex:s,initialValue:v,draggedVertices:[c],tangentDir:_},distSq:m},o=m),r!==`tline`&&i.object?.hasExplicitStart===!0&&!(h&&i.object?.centered===!0)&&d<a&&d<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`start`,anchorPoint:s,fixedVertex:c,originalDistance:g,draggedVertices:[s]},distSq:d},o=d),!y&&r===`line-two-points`){let t=Cp(e[0],e[1],s[0],s[1],c[0],c[1]),i=t*t;i<a&&i<o&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`body`,anchorPoint:s,fixedVertex:c,originalDistance:g,initialValue:v,draggedVertices:[s,c]},distSq:i})}return b}function Jv(e,t){for(let n of e.sceneShapes)if(n.isMetaShape){for(let e of n.meshes)if(e.vertices.length===3&&e.indices.length===0){let n=_v(e.vertices,t);if(n.length===1)return n[0]}}return null}function Yv(e,t,n,r,i,a,o){let s=t[0],c=t[t.length-1],l=r.object?.startPoint!==void 0,u=l?3:2,d=Jv(r,i);if(!d){let e=t[Math.floor(t.length/2)];d=pv(s,e,c)}if(!d)return null;let f=t[Math.floor(t.length/2)],p=mv(d,s,f),m=s[0]-e[0],h=s[1]-e[1],g=m*m+h*h,_=c[0]-e[0],v=c[1]-e[1],y=_*_+v*v,b=d[0]-e[0],x=d[1]-e[1],S=b*b+x*x,C=Math.min(g,y,S),w=null;return l&&g<a&&g<o&&g===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`start`,anchorPoint:d,fixedVertex:c,draggedVertices:[s],arcCCW:p,arcArgCount:u},distSq:g},o=g),y<a&&y<o&&y===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`end`,anchorPoint:d,fixedVertex:s,draggedVertices:[c],arcCCW:p,arcArgCount:u},distSq:y},o=y),S<a&&S<o&&S===C&&(w={hit:{sourceLocation:n,uniqueType:`arc`,hitZone:`center`,anchorPoint:d,fixedVertex:s,fixedVertex2:c,draggedVertices:[d],arcCCW:p,arcArgCount:u},distSq:S}),w}function Xv(e,t,n,r,i,a,o,s){let c=t[0],l=t[t.length-1],u=t[1][0]-c[0],d=t[1][1]-c[1],f=Math.sqrt(u*u+d*d),p=f>1e-10?[u/f,d/f]:[1,0],m=Jv(i,a);if(!m){let e=t[Math.floor(t.length/2)];m=pv(c,e,l)}let h=t[Math.floor(t.length/2)],g=m?mv(m,c,h):!0,_=l[0]-e[0],v=l[1]-e[1],y=_*_+v*v,b=null;if(y<o&&y<s&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`end`,anchorPoint:c,fixedVertex:c,draggedVertices:[l],tangentDir:p,arcCCW:g},distSq:y},s=y),m){let t=m[0]-e[0],i=m[1]-e[1],a=t*t+i*i;a<o&&a<s&&(b={hit:{sourceLocation:n,uniqueType:r||``,hitZone:`center`,anchorPoint:c,fixedVertex:c,fixedVertex2:l,draggedVertices:[m],tangentDir:p,arcCCW:g},distSq:a})}return b}function Zv(e,t,n,r,i,a){let o=t.object?.startPoint,s=t.object?.resolvedPoints??[],c=o?[o,...s]:s;if(c.length===0)return null;let l=null;for(let t=0;t<c.length;t++){let o=c[t],s=o[0]-e[0],u=o[1]-e[1],d=s*s+u*u;d<i&&d<a&&(l={hit:{sourceLocation:n,uniqueType:r,hitZone:`end`,anchorPoint:o,draggedVertices:[o],bezierPoleIndex:t,bezierPoles:c},distSq:d},a=d)}return l}function Qv(e,t,n,r,i,a){if(r.object?.radius)return null;let o=[];for(let e of t){let t=!1;for(let n of o){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||o.push(e)}if(o.length<4)return null;let s=r.object?.centered===!0,c;if(s){let e=0,t=0;for(let n of o)e+=n[0],t+=n[1];c=[e/o.length,t/o.length]}let l=null;for(let t of o){let r=t[0]-e[0],u=t[1]-e[1],d=r*r+u*u;if(d<i&&d<a){let e;if(s&&c)e=c;else{let n=-1;e=o[0];for(let r of o){let i=r[0]-t[0],a=r[1]-t[1],o=i*i+a*a;o>n&&(n=o,e=r)}}l={hit:{sourceLocation:n,uniqueType:`rect`,hitZone:`end`,anchorPoint:e,fixedVertex:e,draggedVertices:[t],rectCentered:s},distSq:d},a=d}}return l}function $v(e,t,n,r,i,a){let o=[];for(let e of t){let t=!1;for(let n of o){let r=n[0]-e[0],i=n[1]-e[1];if(r*r+i*i<1e-6){t=!0;break}}t||o.push(e)}let s=0,c=0;for(let e of o)s+=e[0],c+=e[1];s/=o.length,c/=o.length;let l=o[0],u=l[0]-s,d=l[1]-c,f=Math.sqrt(u*u+d*d),p=r.object?.numberOfSides??o.length,m=r.object?.diameter??Math.round(2*f*100)/100,h=null;for(let r of t){let t=r[0]-e[0],o=r[1]-e[1],l=t*t+o*o;l<i&&l<a&&(h={hit:{sourceLocation:n,uniqueType:`polygon`,hitZone:`body`,anchorPoint:[s,c],initialValue:m,originalDistance:f,polygonSides:p},distSq:l},a=l)}return h}function ey(e,t,n,r,i,a,o){let s=t[0],c=t[1],l=r.object?.hasTwoPoints??!1,u=r.object?.radius??0,d=c[0]-s[0],f=c[1]-s[1],p=Math.sqrt(d*d+f*f),m;if(l)m=p>1e-10?[d/p,f/p]:[1,0];else{let e=(r.object?.angle??0)*Math.PI/180;m=[Math.cos(e),Math.sin(e)]}let h={sourceLocation:n,uniqueType:`slot`,initialValue:u,slotHasTwoPoints:l,slotAxisDir:m,slotRadius:u};function g(){return{...h,hitZone:`start`,anchorPoint:s,fixedVertex:c,slotOtherCenter:c,slotPointIndex:0,draggedVertices:[s]}}function _(){return{...h,hitZone:`end`,anchorPoint:c,fixedVertex:s,slotOtherCenter:s,slotPointIndex:1,draggedVertices:[c]}}let v=null,y=s[0]-e[0],b=s[1]-e[1],x=y*y+b*b,S=c[0]-e[0],C=c[1]-e[1],w=S*S+C*C;x<a&&x<o&&x<=w&&(v={hit:g(),distSq:x},o=x),w<a&&w<o&&(v={hit:_(),distSq:w},o=w);for(let t of r.sceneShapes)if(!t.isMetaShape)for(let n of t.meshes){let t=_v(n.vertices,i);for(let n of t){let t=n[0]-e[0],r=n[1]-e[1],i=t*t+r*r;i<a&&i<o&&(v={hit:{...h,hitZone:`body`,anchorPoint:s,fixedVertex:c,slotOtherCenter:c,slotRadius:u},distSq:i},o=i)}}return v}function ty(e,t,n){let r=(t[0]+n[0])/2,i=(t[1]+n[1])/2,a=n[0]-t[0],o=-(n[1]-t[1]),s=a,c=o*o+s*s;if(c<1e-10)return e;let l=((e[0]-r)*o+(e[1]-i)*s)/c;return[r+l*o,i+l*s]}function ny(e,t,n){let r=-n[1],i=n[0],a=(e[0]-t[0])*r+(e[1]-t[1])*i;return[t[0]+a*r,t[1]+a*i]}function ry(e,t,n){let r=-n[1],i=n[0],a=e[0]-t[0],o=e[1]-t[1],s=a*a+o*o,c=a*r+o*i;if(Math.abs(c)<1e-10)return null;let l=-s/(2*c),u=Math.abs(l),d=[e[0]+r*l,e[1]+i*l];return{center:d,radius:u,startAngle:dv(d,e),endAngle:dv(d,t),ccw:l>=0}}function iy(e,t,n){let r=(t[0]+n[0])/2,i=(t[1]+n[1])/2,a=n[0]-t[0],o=-(n[1]-t[1]),s=a,c=o*o+s*s;if(c<1e-10)return e;let l=e[0]-r,u=e[1]-i,d=(l*o+u*s)/c;return[r+d*o,i+d*s]}var $=5;function ay(e,t,n,r,i,a){let o=new R(a.normal.x,a.normal.y,a.normal.z),{uniqueType:s,hitZone:c,anchorPoint:l,fixedVertex:u}=r;if(s===`polygon`&&l&&r.polygonSides){let n=l,s=t[0]-n[0],c=t[1]-n[1],u=Math.sqrt(s*s+c*c);Q(e,n,X,i,o,a,1,$),av(e,n,u,r.polygonSides,a,$),Q(e,t,Z,i,o,a,1,$)}else if(s===`circle`&&l){let n=l,r=t[0]-n[0],s=t[1]-n[1],c=Math.sqrt(r*r+s*s);Q(e,n,X,i,o,a,1,$),tv(e,n,c,a,$)}else if(s===`tline`&&l&&r.tangentDir){let n=l,s=r.tangentDir,c=t[0]-n[0],u=t[1]-n[1],d=c*s[0]+u*s[1],f=[n[0]+s[0]*d,n[1]+s[1]*d];Q(e,n,X,i,o,a,1,$),ev(e,n,f,a,$),Q(e,f,Z,i,o,a,1,$)}else if(s===`hline`||s===`vline`)if(c===`end`){let n=l,r=s===`hline`?[t[0],n[1]]:[n[0],t[1]];Q(e,n,X,i,o,a,1,$),ev(e,n,r,a,$),Q(e,r,Z,i,o,a,1,$)}else{let n=r.originalDistance??0,c=s===`hline`?[t[0]+n,t[1]]:[t[0],t[1]+n];Q(e,t,X,i,o,a,1,$),ev(e,t,c,a,$),Q(e,c,Z,i,o,a,1,$)}else if(s===`line-two-points`&&u&&l)if(c===`body`){let n=u[0]-l[0],r=u[1]-l[1],s=[t[0]+n,t[1]+r];Q(e,t,X,i,o,a,1,$),ev(e,t,s,a,$),Q(e,s,Z,i,o,a,1,$)}else c===`start`?(Q(e,t,Z,i,o,a,1,$),ev(e,t,u,a,$),Q(e,u,X,i,o,a,1,$)):(Q(e,u,X,i,o,a,1,$),ev(e,u,t,a,$),Q(e,t,Z,i,o,a,1,$));else if(s===`arc`&&l&&u)oy(e,t,r,i,o,a);else if(s===`rect`&&l)if(r.rectCentered){let n=[2*l[0]-t[0],2*l[1]-t[1]];Q(e,l,X,i,o,a,1,$),nv(e,n,t,a,$),Q(e,t,Z,i,o,a,1,$)}else Q(e,l,X,i,o,a,1,$),nv(e,l,t,a,$),Q(e,t,Z,i,o,a,1,$);else if(s===`slot`&&r.slotRadius!==void 0)if(c===`body`){let n=l,s=u,c=r.slotAxisDir?.[0]??1,d=r.slotAxisDir?.[1]??0,f=t[0]-n[0],p=t[1]-n[1],m=Math.abs(-d*f+c*p);Q(e,n,X,i,o,a,1,$),Q(e,s,X,i,o,a,1,$),m>0?uv(e,n,s,m,a,$):ev(e,n,s,a,$),Q(e,t,Z,i,o,a,1,$)}else{let n=r.slotOtherCenter,s=r.slotRadius,l=c===`start`?t:n,u=c===`start`?n:t;Q(e,n,X,i,o,a,1,$),s>0?uv(e,l,u,s,a,$):ev(e,l,u,a,$),Q(e,t,Z,i,o,a,1,$)}else if((s===`tarc-to-point`||s===`tarc-to-point-tangent`)&&u&&r.tangentDir)sy(e,t,r,i,o,a);else if(s.startsWith(`bezier-`)&&r.bezierPoles&&r.bezierPoleIndex!==void 0){let n=r.bezierPoles.slice();n[r.bezierPoleIndex]=t;for(let t=1;t<n.length;t++)ev(e,n[t-1],n[t],a,$);cv(e,n,a,$);for(let t=0;t<n.length;t++)t!==r.bezierPoleIndex&&Q(e,n[t],Y_,i,o,a,.85,$);Q(e,t,Z,i,o,a,1,$)}else Q(e,t,Z,i,o,a,1,$),n&&ev(e,n,t,a,$)}function oy(e,t,n,r,i,a){let{hitZone:o,anchorPoint:s,fixedVertex:c}=n,l=n.arcCCW!==!1;if(o===`center`){let o=c,s=n.fixedVertex2,u=t,d=Math.sqrt((o[0]-u[0])**2+(o[1]-u[1])**2),f=dv(u,o),p=dv(u,s),m=[u[0]+d*Math.cos(p),u[1]+d*Math.sin(p)];Q(e,o,X,r,i,a,1,$),ov(e,u,d,f,p,l,a,$),Q(e,m,X,r,i,a,1,$),Q(e,u,Z,r,i,a,1,$)}else{let n=iy(s,c,t),u=Math.sqrt((t[0]-n[0])**2+(t[1]-n[1])**2);if(o===`start`){let o=dv(n,t),s=dv(n,c);Q(e,t,Z,r,i,a,1,$),ov(e,n,u,o,s,l,a,$),Q(e,c,X,r,i,a,1,$)}else{let o=dv(n,c),s=dv(n,t);Q(e,c,X,r,i,a,1,$),ov(e,n,u,o,s,l,a,$),Q(e,t,Z,r,i,a,1,$)}}}function sy(e,t,n,r,i,a){let{hitZone:o,fixedVertex:s,tangentDir:c}=n,l=s,u=c;if(o===`center`){let o=t,s=n.fixedVertex2,c=Math.sqrt((l[0]-o[0])**2+(l[1]-o[1])**2),u=dv(o,l),d=dv(o,s),f=n.arcCCW!==!1,p=[o[0]+c*Math.cos(d),o[1]+c*Math.sin(d)];Q(e,l,X,r,i,a,1,$),ov(e,o,c,u,d,f,a,$),Q(e,p,X,r,i,a,1,$),Q(e,o,Z,r,i,a,1,$)}else{let n=ry(l,t,u);n?(Q(e,l,X,r,i,a,1,$),ov(e,n.center,n.radius,n.startAngle,n.endAngle,n.ccw,a,$),Q(e,t,Z,r,i,a,1,$)):(Q(e,l,X,r,i,a,1,$),ev(e,l,t,a,$),Q(e,t,Z,r,i,a,1,$))}}function cy(e){for(;e.children.length>0;){let t=e.children[0];e.remove(t);let n=t;n.geometry&&n.geometry.dispose(),n.material&&n.material.dispose()}}function ly(e,t,n){let r=Y(e),{sourceLocation:i,uniqueType:a,hitZone:o,anchorPoint:s,fixedVertex:c}=t;if(a===`line-two-points`&&o===`body`&&s&&c){let e=c[0]-s[0],t=c[1]-s[1];Rm(r,Y([r[0]+e,r[1]+t]),i);return}if(a===`line-two-points`)zm(r,i,o===`start`?0:-1);else if(a===`arc`&&s&&c){let e=t.arcArgCount===2,n=+!e,a=e?1:2;if(o===`center`){let e=c,o=t.fixedVertex2,s=Math.sqrt((e[0]-r[0])**2+(e[1]-r[1])**2),l=Math.atan2(o[1]-r[1],o[0]-r[0]);Bm([{pointIndex:n,position:Y([r[0]+s*Math.cos(l),r[1]+s*Math.sin(l)])},{pointIndex:a,position:r}],i)}else{let e=Y(iy(s,c,r));Bm([{pointIndex:o===`start`?0:n,position:r},{pointIndex:a,position:e}],i)}}else if((a===`hline`||a===`vline`)&&(o===`start`||o===`body`))zm(r,i,0);else if(a===`tline`&&o===`end`&&s&&t.tangentDir){let e=t.tangentDir,a=r[0]-s[0],o=r[1]-s[1],c=Math.round((a*e[0]+o*e[1])*100)/100,l=n();Hm(String(c),i,l)}else if(a===`polygon`&&s&&t.originalDistance&&t.initialValue){let e=r[0]-s[0],a=r[1]-s[1],o=Math.sqrt(e*e+a*a),c=Math.round(t.initialValue*o/t.originalDistance*100)/100,l=n();Hm(String(c),i,l)}else if(a===`rect`&&s)if(t.rectCentered)Vm(Math.round(Math.abs(r[0]-s[0])*2*100)/100,Math.round(Math.abs(r[1]-s[1])*2*100)/100,i);else{let e=Math.min(s[0],r[0]),t=Math.min(s[1],r[1]);Vm(Math.round(Math.abs(r[0]-s[0])*100)/100,Math.round(Math.abs(r[1]-s[1])*100)/100,i,Y([e,t]))}else if(a===`tarc-to-point`||a===`tarc-to-point-tangent`){let e=a===`tarc-to-point`?0:1;if(o===`center`&&c&&t.fixedVertex2){let n=c,a=t.fixedVertex2,o=Math.sqrt((n[0]-r[0])**2+(n[1]-r[1])**2),s=Math.atan2(a[1]-r[1],a[0]-r[0]);zm(Y([r[0]+o*Math.cos(s),r[1]+o*Math.sin(s)]),i,e)}else zm(r,i,e)}else if(a===`slot`){if(o===`body`){let e=t.anchorPoint,a=t.slotAxisDir?.[0]??1,o=t.slotAxisDir?.[1]??0,s=r[0]-e[0],c=r[1]-e[1],l=Math.round(Math.abs(-o*s+a*c)*100)/100,u=n();Hm(String(l),i,u)}else if(t.slotHasTwoPoints)zm(r,i,t.slotPointIndex??0);else if(o===`start`)zm(r,i,0);else if(t.slotOtherCenter&&t.slotAxisDir){let e=t.slotOtherCenter,a=t.slotAxisDir,o=r[0]-e[0],s=r[1]-e[1],c=Math.round((o*a[0]+s*a[1])*100)/100,l=n();Hm(String(c),i,l,void 0,1)}}else a.startsWith(`bezier-`)&&t.bezierPoleIndex!==void 0?zm(r,i,t.bezierPoleIndex):zm(r,i)}var uy=class{expressionInput;fetchVariables;getSketchSourceLine;cachedVariables=[];standaloneInputActive=!1;onRequestEndResize=null;onRequestCloseStandalone=null;constructor(e,t,n){this.expressionInput=new J_(e),this.fetchVariables=t,this.getSketchSourceLine=n}get isVisible(){return this.expressionInput.isVisible}containsElement(e){return this.expressionInput.containsElement(e)}refreshVariables(){return this.fetchVariables().then(e=>{this.cachedVariables=e})}showForDrag(e,t,n,r){let{uniqueType:i,hitZone:a}=e,o=null,s=0;if(i===`polygon`){o=`⌀`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1],a=Math.sqrt(r*r+i*i);s=e.originalDistance&&e.initialValue?Math.round(e.initialValue*a/e.originalDistance*100)/100:Math.round(2*a*100)/100}else if(i===`circle`){o=`⌀`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1];s=Math.round(2*Math.sqrt(r*r+i*i)*100)/100}else if((i===`hline`||i===`vline`)&&a===`end`){o=i===`hline`?`H:`:`V:`;let n=e.anchorPoint;s=i===`hline`?Math.round(Math.abs(t[0]-n[0])*100)/100:Math.round(Math.abs(t[1]-n[1])*100)/100}else if(i===`tline`&&a===`end`&&e.tangentDir){o=`T:`;let n=e.anchorPoint,r=e.tangentDir,i=t[0]-n[0],a=t[1]-n[1];s=Math.round(Math.abs(i*r[0]+a*r[1])*100)/100}else if(i===`slot`&&!e.slotHasTwoPoints&&e.slotOtherCenter&&e.slotAxisDir&&a===`end`){o=`D`;let n=e.slotOtherCenter,r=e.slotAxisDir,i=t[0]-n[0],a=t[1]-n[1];s=Math.round((i*r[0]+a*r[1])*100)/100}else if(i===`slot`&&a===`body`){o=`R`;let n=e.anchorPoint,r=t[0]-n[0],i=t[1]-n[1];s=Math.round(Math.sqrt(r*r+i*i)*100)/100}o!==null&&this.openInput(o,s,e,n,r,!0)}showForDoubleClick(e,t,n){let r,i;if(e.uniqueType===`polygon`||e.uniqueType===`circle`)r=`⌀`,i=e.initialValue??0;else if(e.uniqueType===`hline`||e.uniqueType===`vline`)r=e.uniqueType===`hline`?`H:`:`V:`,i=Math.abs(e.initialValue??0);else if(e.uniqueType===`tline`)r=`T:`,i=Math.abs(e.initialValue??0);else if(e.uniqueType===`slot`)if(e.hitZone===`start`||e.hitZone===`end`){if(e.slotHasTwoPoints)return!1;r=`D`;let t=e.anchorPoint,n=e.fixedVertex,a=e.slotAxisDir??[1,0];i=Math.round(((n[0]-t[0])*a[0]+(n[1]-t[1])*a[1])*100)/100}else r=`R`,i=e.slotRadius??0;else return!1;return this.standaloneInputActive=!0,this.openInput(r,i,e,t,n,!1),!0}updateValue(e,t){if(!this.expressionInput.isVisible)return;let{uniqueType:n,anchorPoint:r}=e,i;if(n===`polygon`){let n=r,a=t[0]-n[0],o=t[1]-n[1],s=Math.sqrt(a*a+o*o);i=e.originalDistance&&e.initialValue?Math.round(e.initialValue*s/e.originalDistance*100)/100:Math.round(2*s*100)/100}else if(n===`circle`){let e=r,n=t[0]-e[0],a=t[1]-e[1];i=Math.round(2*Math.sqrt(n*n+a*a)*100)/100}else if(n===`tline`&&e.tangentDir){let n=r,a=e.tangentDir,o=t[0]-n[0],s=t[1]-n[1];i=Math.round(Math.abs(o*a[0]+s*a[1])*100)/100}else if(n===`slot`&&e.hitZone===`body`){let n=r,a=e.slotAxisDir?.[0]??1,o=e.slotAxisDir?.[1]??0,s=t[0]-n[0],c=t[1]-n[1];i=Math.round(Math.abs(-o*s+a*c)*100)/100}else if(n===`slot`&&e.slotOtherCenter&&e.slotAxisDir){let n=e.slotOtherCenter,r=e.slotAxisDir,a=t[0]-n[0],o=t[1]-n[1];i=Math.round((a*r[0]+o*r[1])*100)/100}else{let e=r,a=n===`hline`?t[0]-e[0]:t[1]-e[1];i=Math.round(Math.abs(a)*100)/100}this.expressionInput.updateValue(i)}updatePosition(e,t){this.expressionInput.updatePosition(e,t)}updateValueIfUnmoved(e){this.expressionInput.updateValue(e)}commitIfVisible(e){this.expressionInput.isVisible&&e&&this.expressionInput.commitCurrentValue()}hide(){this.expressionInput.hide()}closeStandalone(){this.standaloneInputActive&&(this.standaloneInputActive=!1,this.expressionInput.hide())}openInput(e,t,n,r,i,a){let{sourceLocation:o}=n,s=String(t);this.expressionInput.show({label:e,value:s,clientX:r,clientY:i,variables:this.cachedVariables,onCommit:t=>{let{expression:r,newVariable:i}=t,s=parseFloat(r),c=!isNaN(s)&&String(s)===r,l=r;if(c&&n.uniqueType!==`circle`&&n.uniqueType!==`polygon`&&n.uniqueType!==`slot`){let e=this.computeDistanceSign(n,null);l=String(Math.round(e*s*100)/100)}else c&&(l=String(Math.round(s*100)/100));let u=this.getSketchSourceLine();Hm(l,o,u,i,+(e===`D`)),a?this.onRequestEndResize?.():this.closeStandalone()}}),e!==`D`&&Um(o.line).then(({expression:e})=>{e&&(a||this.standaloneInputActive)&&this.updateValueIfUnmoved(e)})}computeDistanceSign(e,t){if(t){let n=e.anchorPoint;if(e.uniqueType===`tline`&&e.tangentDir){let r=e.tangentDir,i=t[0]-n[0],a=t[1]-n[1];return i*r[0]+a*r[1]>=0?1:-1}return e.uniqueType===`hline`?t[0]>=n[0]?1:-1:t[1]>=n[1]?1:-1}return(e.initialValue??e.originalDistance??0)>=0?1:-1}},dy=class{ctx;plane;snapController;sceneObjects=[];sketchId=``;canvas;previewGroup;_isResizing=!1;hasMoved=!1;hitResult=null;startPoint=null;currentPoint=null;grabOffset=null;pendingHit=null;dimensionInput;getSketchSourceLine;boundCanvasPointerDown;boundPointerMove;boundPointerUp;boundKeyDown;boundCanvasDoubleClick;constructor(e,t,n,r,i,a){this.ctx=e,this.plane=t,this.snapController=n,this.canvas=e.renderer.domElement,this.getSketchSourceLine=a,this.previewGroup=new oi,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=5,this.dimensionInput=new uy(r,i,a),this.dimensionInput.onRequestEndResize=()=>this.endResize(),this.dimensionInput.onRequestCloseStandalone=()=>{this.dimensionInput.closeStandalone(),this.hitResult=null},this.boundCanvasPointerDown=this.handleCanvasPointerDown.bind(this),this.boundPointerMove=this.handlePointerMove.bind(this),this.boundPointerUp=this.handlePointerUp.bind(this),this.boundKeyDown=this.handleKeyDown.bind(this),this.boundCanvasDoubleClick=this.handleCanvasDoubleClick.bind(this)}get isResizing(){return this._isResizing}activate(){this.ctx.scene.add(this.previewGroup),this.canvas.addEventListener(`pointerdown`,this.boundCanvasPointerDown,{capture:!0}),this.canvas.addEventListener(`dblclick`,this.boundCanvasDoubleClick),window.addEventListener(`pointermove`,this.boundPointerMove),window.addEventListener(`pointerup`,this.boundPointerUp,{capture:!0}),window.addEventListener(`keydown`,this.boundKeyDown)}deactivate(){this.canvas.removeEventListener(`pointerdown`,this.boundCanvasPointerDown,{capture:!0}),this.canvas.removeEventListener(`dblclick`,this.boundCanvasDoubleClick),window.removeEventListener(`pointermove`,this.boundPointerMove),window.removeEventListener(`pointerup`,this.boundPointerUp,{capture:!0}),window.removeEventListener(`keydown`,this.boundKeyDown),this.endResize(),this.dimensionInput.closeStandalone(),this.pendingHit=null,this.ctx.scene.remove(this.previewGroup),cy(this.previewGroup)}updatePlane(e){this.plane=e}updateSnapController(e){this.snapController=e,this._isResizing&&this.hitResult?.draggedVertices&&this.snapController.setExcludedVertices(this.hitResult.draggedVertices)}updateSceneData(e,t){this.sceneObjects=e,this.sketchId=t,this.dimensionInput.refreshVariables()}handleCanvasPointerDown(e){if(e.button!==0||this._isResizing||this.dimensionInput.standaloneInputActive&&this.dimensionInput.containsElement(e.target))return;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t)return;let n=Gv(t,this.sceneObjects,this.sketchId,this.plane,this.ctx);n&&(this.pendingHit={hit:n,point2d:t,clientX:e.clientX,clientY:e.clientY},this.ctx.cameraControls.enabled=!1,e.stopPropagation())}handlePointerUp(e){if(e.button===0){if(this._isResizing){this.commitResize(),e.stopPropagation(),e.preventDefault();return}this.pendingHit&&(this.pendingHit=null,this.ctx.cameraControls.enabled=!0)}}startResize(e){this._isResizing=!0,this.hasMoved=!1,this.hitResult=e.hit,this.startPoint=e.point2d,this.currentPoint=e.point2d;let t=e.hit;t.hitZone===`body`&&t.anchorPoint&&(t.uniqueType===`hline`||t.uniqueType===`vline`||t.uniqueType===`line-two-points`)?this.grabOffset=[e.point2d[0]-t.anchorPoint[0],e.point2d[1]-t.anchorPoint[1]]:this.grabOffset=null,this.ctx.cameraControls.enabled=!1,this.canvas.style.cursor=`crosshair`,this.snapController.setExcludedVertices(t.draggedVertices??[]),this.dimensionInput.showForDrag(t,e.point2d,e.clientX,e.clientY)}commitResize(){this.dimensionInput.isVisible&&this.hasMoved?this.dimensionInput.commitIfVisible(this.hasMoved):this.currentPoint&&this.hitResult&&ly(this.currentPoint,this.hitResult,this.getSketchSourceLine),this.endResize()}handleKeyDown(e){e.key===`Escape`&&(this._isResizing?this.endResize():this.dimensionInput.standaloneInputActive&&(this.dimensionInput.closeStandalone(),this.hitResult=null))}handlePointerMove(e){if(this.pendingHit&&!this._isResizing){let t=e.clientX-this.pendingHit.clientX,n=e.clientY-this.pendingHit.clientY;if(t*t+n*n>=16){let e=this.pendingHit;this.pendingHit=null,this.startResize(e)}else return}if(!this._isResizing)return;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(t){if(this.hasMoved=!0,this.grabOffset&&this.hitResult?.hitZone===`body`){let e=[t[0]-this.grabOffset[0],t[1]-this.grabOffset[1]];this.currentPoint=this.snapController.snap(e).point2d}else this.currentPoint=this.snapController.snap(t).point2d;if(this.hitResult?.hitZone===`start`&&this.hitResult.anchorPoint&&(this.hitResult.uniqueType===`hline`||this.hitResult.uniqueType===`vline`)&&(this.hitResult.uniqueType===`hline`?this.currentPoint=[this.currentPoint[0],this.hitResult.anchorPoint[1]]:this.currentPoint=[this.hitResult.anchorPoint[0],this.currentPoint[1]]),this.hitResult?.uniqueType===`tline`&&this.hitResult.hitZone===`end`&&this.hitResult.anchorPoint&&this.hitResult.tangentDir){let e=this.hitResult.anchorPoint,t=this.hitResult.tangentDir,n=this.currentPoint[0]-e[0],r=this.currentPoint[1]-e[1],i=n*t[0]+r*t[1];this.currentPoint=[e[0]+t[0]*i,e[1]+t[1]*i]}if(this.hitResult?.hitZone===`center`&&this.hitResult.uniqueType===`arc`&&this.hitResult.fixedVertex&&this.hitResult.fixedVertex2&&e.shiftKey&&(this.currentPoint=ty(this.currentPoint,this.hitResult.fixedVertex,this.hitResult.fixedVertex2)),this.hitResult?.hitZone===`center`&&this.hitResult.tangentDir&&this.hitResult.fixedVertex&&(this.currentPoint=ny(this.currentPoint,this.hitResult.fixedVertex,this.hitResult.tangentDir)),this.hitResult?.uniqueType===`slot`&&!this.hitResult.slotHasTwoPoints&&(this.hitResult.hitZone===`start`||this.hitResult.hitZone===`end`)&&this.hitResult.slotAxisDir&&this.hitResult.slotOtherCenter){let e=this.hitResult.slotAxisDir,t=this.hitResult.slotOtherCenter,n=this.currentPoint[0]-t[0],r=this.currentPoint[1]-t[1],i=n*e[0]+r*e[1];this.currentPoint=[t[0]+e[0]*i,t[1]+e[1]*i]}cy(this.previewGroup),this.currentPoint&&this.hitResult&&ay(this.previewGroup,this.currentPoint,this.startPoint,this.hitResult,this.ctx.camera,this.plane),this.ctx.requestRender(),this.currentPoint&&this.hitResult&&this.dimensionInput.updateValue(this.hitResult,this.currentPoint),this.dimensionInput.updatePosition(e.clientX,e.clientY)}}handleCanvasDoubleClick(e){if(this._isResizing)return;let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t)return;let n=Gv(t,this.sceneObjects,this.sketchId,this.plane,this.ctx);n&&n.uniqueType!==`line-two-points`&&(this.hitResult=n,this.startPoint=null,this.currentPoint=null,this.dimensionInput.showForDoubleClick(n,e.clientX,e.clientY)||(this.hitResult=null))}endResize(){this._isResizing=!1,this.hasMoved=!1,this.hitResult=null,this.startPoint=null,this.currentPoint=null,this.grabOffset=null,this.pendingHit=null,this.ctx.cameraControls.enabled=!0,this.canvas.style.cursor=``,this.snapController.setExcludedVertices([]),this.dimensionInput.hide(),cy(this.previewGroup),this.ctx.requestRender()}},fy=12,py=2,my=6,hy=class{ctx;plane;canvas;edges=[];centers=[];hoveredShapeId=null;hoveredCenterOverlay=null;hoveredCenterPoint=null;selectedShapeIds=new Set;isExternalResizing;boundMouseMove;boundMouseDown;boundMouseUp;downX=0;downY=0;constructor(e,t,n){this.ctx=e,this.plane=t,this.canvas=e.renderer.domElement,this.isExternalResizing=n,this.boundMouseMove=this.handleMouseMove.bind(this),this.boundMouseDown=this.handleMouseDown.bind(this),this.boundMouseUp=this.handleMouseUp.bind(this)}activate(){this.canvas.addEventListener(`mousemove`,this.boundMouseMove),this.canvas.addEventListener(`mousedown`,this.boundMouseDown),this.canvas.addEventListener(`mouseup`,this.boundMouseUp)}deactivate(){this.canvas.removeEventListener(`mousemove`,this.boundMouseMove),this.canvas.removeEventListener(`mousedown`,this.boundMouseDown),this.canvas.removeEventListener(`mouseup`,this.boundMouseUp),this.clearHover(),this.clearSelection(),this.removeCenterOverlay()}updatePlane(e){this.plane=e}updateSceneData(e,t){this.edges=bp(e,t,this.plane),this.centers=Sp(e,t,this.plane);let n=new Set(this.edges.map(e=>e.shapeId));for(let e of this.centers)n.add(e.shapeId);this.hoveredShapeId&&!n.has(this.hoveredShapeId)&&this.clearHover();for(let e of this.selectedShapeIds)n.has(e)||(this.removeSelectionHighlight(e),this.selectedShapeIds.delete(e))}get selectedIds(){return this.selectedShapeIds}handleMouseDown(e){this.downX=e.clientX,this.downY=e.clientY}handleMouseMove(e){if(this.isExternalResizing()){this.hoveredShapeId&&this.clearHover();return}let t=Tp(this.ctx,this.plane,e.clientX,e.clientY);if(!t){this.hoveredShapeId&&this.clearHover();return}let n=kp(this.ctx,fy),r=this.findNearestEdge(t,n),i=r?.shapeId??null;i!==this.hoveredShapeId&&(this.hoveredShapeId&&this.removeHoverHighlight(this.hoveredShapeId),this.removeCenterOverlay(),i?(this.applyHoverHighlight(i),this.canvas.style.cursor=`pointer`):this.canvas.style.cursor=``,this.hoveredShapeId=i,this.ctx.requestRender()),r?.isCenter&&r.centerPoint?this.hoveredCenterPoint&&this.hoveredCenterPoint[0]===r.centerPoint[0]&&this.hoveredCenterPoint[1]===r.centerPoint[1]||(this.removeCenterOverlay(),this.addCenterOverlay(r.centerPoint),this.hoveredCenterPoint=r.centerPoint,this.ctx.requestRender()):this.hoveredCenterOverlay&&(this.removeCenterOverlay(),this.ctx.requestRender())}handleMouseUp(e){if(this.isExternalResizing())return;let t=e.clientX-this.downX,n=e.clientY-this.downY;if(t*t+n*n>64)return;let r=e.ctrlKey||e.metaKey;if(!this.hoveredShapeId){r||(this.clearSelection(),this.ctx.requestRender());return}r?this.selectedShapeIds.has(this.hoveredShapeId)?(this.removeSelectionHighlight(this.hoveredShapeId),this.selectedShapeIds.delete(this.hoveredShapeId),this.applyHoverHighlight(this.hoveredShapeId)):(this.selectedShapeIds.add(this.hoveredShapeId),this.applySelectionHighlight(this.hoveredShapeId)):(this.clearSelection(),this.selectedShapeIds.add(this.hoveredShapeId),this.applySelectionHighlight(this.hoveredShapeId)),this.ctx.requestRender()}findNearestEdge(e,t){let n=1/0,r=null,i=!1,a=null;for(let t of this.edges)for(let o of t.segments){let s=Cp(e[0],e[1],o.ax,o.ay,o.bx,o.by);s<n&&(n=s,r=t.shapeId,i=!1,a=null)}for(let t of this.centers){let o=t.point2d[0]-e[0],s=t.point2d[1]-e[1],c=Math.sqrt(o*o+s*s);c<n&&(n=c,r=t.shapeId,i=!0,a=t.point2d)}return n>t||!r?null:a?{shapeId:r,isCenter:i,centerPoint:a}:{shapeId:r,isCenter:i}}applyHoverHighlight(e){this.selectedShapeIds.has(e)||this.traverseShapeEdges(e,e=>{e.userData.selectOriginalColor===void 0&&(e.userData.hoverOriginalColor=e.material.color.getHex(),e.material.color.set(Wd.highlightColor))})}removeHoverHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.hoverOriginalColor!==void 0&&(e.material.color.setHex(e.userData.hoverOriginalColor),delete e.userData.hoverOriginalColor)})}applySelectionHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.hoverOriginalColor===void 0?e.userData.selectOriginalColor=e.material.color.getHex():(e.userData.selectOriginalColor=e.userData.hoverOriginalColor,delete e.userData.hoverOriginalColor),e.material.color.set(Wd.highlightColor)})}removeSelectionHighlight(e){this.traverseShapeEdges(e,e=>{e.userData.selectOriginalColor!==void 0&&(e.material.color.setHex(e.userData.selectOriginalColor),delete e.userData.selectOriginalColor)})}clearHover(){this.hoveredShapeId&&(this.removeHoverHighlight(this.hoveredShapeId),this.hoveredShapeId=null,this.canvas.style.cursor=``,this.removeCenterOverlay(),this.ctx.requestRender())}clearSelection(){for(let e of this.selectedShapeIds)this.removeSelectionHighlight(e);this.selectedShapeIds.clear()}traverseShapeEdges(e,t){this.ctx.scene.traverse(n=>{n.userData.isMetaShape||(n.isLine||n.userData.isEdgeLine)&&this.findShapeId(n)===e&&t(n)})}findShapeId(e){let t=e;for(;t;){if(t.userData.shapeId&&!t.userData.isMetaShape)return t.userData.shapeId;t=t.parent}return null}addCenterOverlay(e){this.removeCenterOverlay();let t=Ep(e,this.plane),n=this.plane.normal,r=new R(n.x,n.y,n.z),i=new U(new oa(py,16),new mr({color:Wd.highlightColor,side:2,depthTest:!1,transparent:!0,opacity:.9}));i.renderOrder=6;let a=new oi;a.renderOrder=6,a.userData.isCenterOverlay=!0,a.add(i),a.position.copy(t),a.lookAt(t.clone().add(r)),tf(i,a,t,my,py),this.ctx.scene.add(a),this.hoveredCenterOverlay=a}removeCenterOverlay(){if(this.hoveredCenterOverlay){this.ctx.scene.remove(this.hoveredCenterOverlay);let e=this.hoveredCenterOverlay.children[0];e.geometry.dispose(),e.material.dispose(),this.hoveredCenterOverlay=null,this.hoveredCenterPoint=null}}},gy=`#8899aa`,_y=1.5,vy=4.5,yy=.5,by=2,xy=class{ctx;group;active=!1;constructor(e){this.ctx=e,this.group=new oi,this.group.userData.isMetaShape=!0,this.group.renderOrder=3}activate(){this.active||=(this.ctx.scene.add(this.group),!0)}deactivate(){this.active&&(this.ctx.scene.remove(this.group),this.disposeGroup(),this.active=!1,this.ctx.requestRender())}update(e,t,n){if(!this.active)return;this.disposeGroup();let r=this.ctx.camera,i=new R(n.normal.x,n.normal.y,n.normal.z);for(let a of e){if(a.parentId!==t||a.type!==`bezier`)continue;let e=a.object?.startPoint,o=a.object?.resolvedPoints,s=[];e&&s.push(e),o&&s.push(...o);for(let e=1;e<s.length;e++)ev(this.group,s[e-1],s[e],n,by);for(let e of s)Q(this.group,e,gy,r,i,n,yy,by,_y,vy)}this.ctx.requestRender()}disposeGroup(){for(;this.group.children.length>0;){let e=this.group.children[0];this.group.remove(e);let t=e;t.geometry&&t.geometry.dispose(),t.material&&t.material.dispose();let n=e.children?.[0];n?.geometry&&n.geometry.dispose(),n?.material&&n.material.dispose()}}},Sy=class{snapManager;plane;excludedVertices=[];snapToVertices=!0;snapToGrid=!0;constructor(e,t){this.snapManager=e,this.plane=t}updateSnapManager(e){this.snapManager=e,this.snapManager.setExcludedVertices(this.excludedVertices)}setExcludedVertices(e){this.excludedVertices=e,this.snapManager.setExcludedVertices(e)}snap(e){if(!this.snapToVertices&&!this.snapToGrid)return this.noSnapResult(e);let t=this.snapManager.snap(e,this.plane);return t.snapType===`vertex`&&!this.snapToVertices||t.snapType===`grid`&&!this.snapToGrid?this.noSnapResult(e):t}noSnapResult(e){let t=this.plane.origin,n=this.plane.xDirection,r=this.plane.yDirection;return{point2d:e,worldPoint:new R(t.x+n.x*e[0]+r.x*e[1],t.y+n.y*e[0]+r.y*e[1],t.z+n.z*e[0]+r.z*e[1]),snapType:`none`}}},Cy=class{viewer;container;trimService;timelinePanel;toolbar;activeSketchInfo=null;activeDrawingTool=null;activeDragHandler=null;activeHoverSelectHandler=null;bezierHandles;shortcuts;constructor(e,t,n,r){this.viewer=t,this.container=e,this.trimService=n,this.timelinePanel=r,this.toolbar=new B_(r.toolbarHost,e=>{this.handleToolSelect(e)}),this.shortcuts=new P_,this.shortcuts.register(`n`,()=>this.lookAlongSketchNormal()),this.bezierHandles=new xy(t.sceneContext),this.toolbar.onSnapVerticesChange=e=>{this.activeDrawingTool&&(this.activeDrawingTool.snapController.snapToVertices=e),this.activeDragHandler&&(this.activeDragHandler.snapController.snapToVertices=e)},this.toolbar.onSnapGridChange=e=>{this.activeDrawingTool&&(this.activeDrawingTool.snapController.snapToGrid=e),this.activeDragHandler&&(this.activeDragHandler.snapController.snapToGrid=e)}}get hasActiveDrawingTool(){return this.activeDrawingTool!==null}update(e){let t=null;for(let n=e.length-1;n>=0;n--)if(y_(e[n],e)){t=e[n];break}if(t?.type===`sketch`&&t.id&&t.object?.plane&&t.sourceLocation){let n=t.object.plane,r=this.activeSketchInfo?.sketchObj.id;if(this.activeSketchInfo={sketchObj:t,plane:n,sourceLocation:t.sourceLocation},this.toolbar.isVisible||(this.toolbar.show(),this.shortcuts.enable(),this.timelinePanel.slideOut()),this.bezierHandles.activate(),this.bezierHandles.update(e,t.id,n),this.activeDrawingTool)r===t.id?(this.activeDrawingTool.updatePlane(n),this.activeDrawingTool.onSceneUpdate(e,t.id),t.object?.currentPosition&&this.activeDrawingTool.updateCurrentPosition(t.object.currentPosition)):this.handleToolSelect(this.toolbar.activeTool);else if(this.activeDragHandler){this.activeDragHandler.updatePlane(n);let r=new Sy(v_.fromSceneObjects(e,t.id,n,this.viewer.sceneContext),n);r.snapToVertices=this.toolbar.snapVerticesChecked,r.snapToGrid=this.toolbar.snapGridChecked,this.activeDragHandler.updateSnapController(r),this.activeDragHandler.updateSceneData(e,t.id),this.activeHoverSelectHandler&&(this.activeHoverSelectHandler.updatePlane(n),this.activeHoverSelectHandler.updateSceneData(e,t.id))}else this.toolbar.activeTool||this.activateDragHandler()}else this.activeDrawingTool&&=(this.activeDrawingTool.deactivate(),null),this.deactivateDragHandler(),this.bezierHandles.deactivate(),this.activeSketchInfo=null,this.toolbar.hide(),this.shortcuts.disable(),this.timelinePanel.slideIn()}async fetchScopeVariables(){return this.activeSketchInfo?Wm(this.activeSketchInfo.sourceLocation.line):[]}createTool(e,t,n,r){let i=new Sy(v_.fromSceneObjects(n,r,t,this.viewer.sceneContext),t);i.snapToVertices=this.toolbar.snapVerticesChecked,i.snapToGrid=this.toolbar.snapGridChecked;let a=(e,t)=>{this.activeSketchInfo&&Lm(e,this.activeSketchInfo.sourceLocation,t)},o=()=>this.fetchScopeVariables();switch(e){case`line`:{let e=new yv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`circle`:return new bv(this.viewer.sceneContext,t,i,a,this.container,o);case`polygon`:return new Wv(this.viewer.sceneContext,t,i,a,this.container,o);case`arc2`:return new Sv(this.viewer.sceneContext,t,i,a,this.container,o);case`arc3`:{let e=new wv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`polyline`:{let e=new Rv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`bezier`:{let e=new zv(this.viewer.sceneContext,t,i,a,this.container,o);return e.onSceneUpdate(n,r),e}case`rect`:return new Tv(this.viewer.sceneContext,t,i,a,this.container,o);case`rounded-rect`:return new Ev(this.viewer.sceneContext,t,i,a,this.container,o);case`slot`:return new Dv(this.viewer.sceneContext,t,i,a,this.container,o);default:return null}}activateDragHandler(){if(this.activeDragHandler||!this.activeSketchInfo)return;let e=new Sy(v_.fromSceneObjects(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id,this.activeSketchInfo.plane,this.viewer.sceneContext),this.activeSketchInfo.plane);e.snapToVertices=this.toolbar.snapVerticesChecked,e.snapToGrid=this.toolbar.snapGridChecked,this.activeDragHandler=new dy(this.viewer.sceneContext,this.activeSketchInfo.plane,e,this.container,()=>this.fetchScopeVariables(),()=>this.activeSketchInfo?.sourceLocation.line??null),this.activeDragHandler.updateSceneData(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id),this.activeDragHandler.activate(),this.activeHoverSelectHandler=new hy(this.viewer.sceneContext,this.activeSketchInfo.plane,()=>this.activeDragHandler?.isResizing??!1),this.activeHoverSelectHandler.updateSceneData(this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id),this.activeHoverSelectHandler.activate()}deactivateDragHandler(){this.activeHoverSelectHandler&&=(this.activeHoverSelectHandler.deactivate(),null),this.activeDragHandler&&=(this.activeDragHandler.deactivate(),null)}handleToolSelect(e){if(!e&&this.activeDrawingTool?.handleEscape?.())return;if(this.activeDrawingTool&&=(this.activeDrawingTool.deactivate(),null),this.toolbar.activeTool===`trim`&&e!==`trim`&&this.exitTrimFromToolbar(),this.toolbar.setActiveTool(e),!e||!this.activeSketchInfo){!e&&this.activeSketchInfo&&this.activateDragHandler();return}if(this.deactivateDragHandler(),e===`trim`){this.enterTrimFromToolbar();return}let t=this.createTool(e,this.activeSketchInfo.plane,this.viewer.currentSceneObjects,this.activeSketchInfo.sketchObj.id);t&&(this.activeSketchInfo.sketchObj.object?.currentPosition&&t.updateCurrentPosition(this.activeSketchInfo.sketchObj.object.currentPosition),t.activate(),this.activeDrawingTool=t)}enterTrimFromToolbar(){if(this.activeSketchInfo){if(this.trimService.lastPickInfo){this.trimService.enter(),this.trimService.hideBars();return}this.trimService.pendingActivation=!0,Lm(`trim()`,this.activeSketchInfo.sourceLocation)}}exitTrimFromToolbar(){if(this.trimService.pendingActivation=!1,this.trimService.state===`picking-active`&&this.trimService.exit(),this.trimService.lastPickInfo){let e=this.trimService.lastPickInfo.trimObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&Im(e.sourceLocation)}this.trimService.reset()}lookAlongSketchNormal(){this.activeSketchInfo&&this.viewer.lookAlongSketchNormal(this.activeSketchInfo.plane)}},wy=class extends vf{constructor(){super(),this.isLineGeometry=!0,this.type=`LineGeometry`}setPositions(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setPositions(n),this}setColors(e){let t=e.length-3,n=new Float32Array(2*t);for(let r=0;r<t;r+=3)n[2*r]=e[r],n[2*r+1]=e[r+1],n[2*r+2]=e[r+2],n[2*r+3]=e[r+3],n[2*r+4]=e[r+4],n[2*r+5]=e[r+5];return super.setColors(n),this}setFromPoints(e){let t=e.length-1,n=new Float32Array(6*t);for(let r=0;r<t;r++)n[6*r]=e[r].x,n[6*r+1]=e[r].y,n[6*r+2]=e[r].z||0,n[6*r+3]=e[r+1].x,n[6*r+4]=e[r+1].y,n[6*r+5]=e[r+1].z||0;return super.setPositions(n),this}fromLine(e){let t=e.geometry;return this.setPositions(t.attributes.position.array),this}},Ty=class extends Rf{constructor(e=new wy,t=new yf({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},Ey={x:15026253,y:3187820,z:4088797},Dy=999,Oy=class{group=null;constructor(e){this.ctx=e}show(e){this.clear();let{from:t,to:n,axis:r}=e;if(ky(t,n)<1e-12)return;let i=new oi;if(i.name=`measureOverlay`,i.userData.isMetaShape=!0,i.add(this.makeLine(t,n,Wd.highlightColor.getHex(),{width:2.5})),r){let e={x:r===`x`?n.x:t.x,y:r===`y`?n.y:t.y,z:r===`z`?n.z:t.z};ky(t,e)>1e-12&&i.add(this.makeLine(t,e,Ey[r],{width:3.5})),ky(e,n)>1e-12&&i.add(this.makeLine(e,n,Wd.metaEdgeColor.getHex(),{width:1.5,dashed:!0})),i.add(this.makePoints([t,n,e]))}else i.add(this.makePoints([t,n]));i.traverse(e=>{e.userData.isMetaShape=!0,e.renderOrder=Dy}),this.group=i,this.ctx.scene.add(i),this.ctx.requestRender()}clear(){this.group&&(this.group.traverse(e=>{e.geometry?.dispose(),e.material?.dispose()}),this.group.parent?.remove(this.group),this.group=null,this.ctx.requestRender())}makeLine(e,t,n,r){let i=new wy;i.setPositions([e.x,e.y,e.z,t.x,t.y,t.z]);let a=Math.sqrt(ky(e,t)),o=new yf({color:n,linewidth:r.width,transparent:!0,depthTest:!1,depthWrite:!1,dashed:!!r.dashed,dashSize:a/16,gapSize:a/24});Kd.register(o);let s=new Ty(i,o);return r.dashed&&s.computeLineDistances(),s}makePoints(e){let t=new H,n=e.flatMap(e=>[e.x,e.y,e.z]);return t.setAttribute(`position`,new br(n,3)),new ta(t,new Xi({color:Wd.highlightColor.getHex(),size:7,sizeAttenuation:!1,transparent:!0,depthTest:!1,depthWrite:!1}))}};function ky(e,t){let n=e.x-t.x,r=e.y-t.y,i=e.z-t.z;return n*n+r*r+i*i}var Ay=[{value:`mm`,label:`Millimeter`},{value:`cm`,label:`Centimeter`},{value:`m`,label:`Meter`},{value:`in`,label:`Inch`}],jy=[{value:`deg`,label:`Degree`},{value:`rad`,label:`Radian`}],My={mm:1,cm:.1,m:.001,in:1/25.4},Ny={mm:2,cm:3,m:5,in:3};function Py(e,t){return e*My[t]}function Fy(e,t){return`${Py(e,t).toFixed(Ny[t])} ${t}`}function Iy(e,t){let n=My[t];return`${(e*n*n).toFixed(Ny[t])} ${t}²`}function Ly(e,t){return t===`rad`?`${(Math.PI/180*e).toFixed(4)} rad`:`${e.toFixed(2)} deg`}var Ry={plane:`Plane face`,cylinder:`Cylindrical face`,cone:`Conical face`,sphere:`Spherical face`,torus:`Toroidal face`,surface:`Face`,line:`Line edge`,circle:`Circle edge`,arc:`Arc edge`,ellipse:`Ellipse edge`,curve:`Edge`},zy=[{key:`parallelDist`,label:`Parallel dist`},{key:`centerDist`,label:`Center dist`},{key:`axisDist`,label:`Axis dist`},{key:`minDist`,label:`Min dist`},{key:`maxDist`,label:`Max dist`}],By=[{axis:`x`,cls:`text-error`},{axis:`y`,cls:`text-success`},{axis:`z`,cls:`text-info`}];function Vy(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}var Hy=class{el;data={entities:[],result:null,lengthUnit:`mm`,angleUnit:`deg`};constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`absolute bottom-[64px] right-[76px] z-[150] w-[290px] panel-bg border border-base-content/10 rounded-lg p-3 shadow-[0_4px_24px_rgba(0,0,0,0.5)] text-xs text-base-content select-none max-h-[70vh] overflow-y-auto hidden`,e.appendChild(this.el)}get isVisible(){return!this.el.classList.contains(`hidden`)}setVisible(e){this.el.classList.toggle(`hidden`,!e)}update(e){this.data=e,this.render()}render(){let{entities:e,result:t}=this.data,n=e.length?e.map((e,t)=>`<div class="flex items-center justify-between gap-1 px-2 py-1 border-b border-base-content/10 last:border-0">
5440
+ <span class="truncate">${Vy(e.label)}</span>
5441
+ <button data-remove="${t}" title="Remove" class="btn btn-ghost btn-xs btn-square shrink-0 opacity-60 hover:opacity-100 [&>svg]:w-3 [&>svg]:h-3">${ug}</button>
5442
+ </div>`).join(``):`<div class="px-2 py-2 text-base-content/50">Click faces or edges in the viewport to measure</div>`,r=Ay.map(e=>`<option value="${e.value}" ${e.value===this.data.lengthUnit?`selected`:``}>${e.label}</option>`).join(``),i=jy.map(e=>`<option value="${e.value}" ${e.value===this.data.angleUnit?`selected`:``}>${e.label}</option>`).join(``);this.el.innerHTML=`
5443
5443
  <div class="flex items-center justify-between mb-2">
5444
5444
  <span class="text-sm font-semibold">Measure</span>
5445
- <button data-close title="Close" class="btn btn-ghost btn-xs btn-square opacity-60 hover:opacity-100 [&>svg]:w-4 [&>svg]:h-4">${sg}</button>
5445
+ <button data-close title="Close" class="btn btn-ghost btn-xs btn-square opacity-60 hover:opacity-100 [&>svg]:w-4 [&>svg]:h-4">${ug}</button>
5446
5446
  </div>
5447
5447
  <div class="border border-base-content/15 rounded-md mb-2 max-h-28 overflow-y-auto">${n}</div>
5448
5448
  <div class="grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-1 mb-2">
@@ -5452,13 +5452,13 @@ void main() {
5452
5452
  <select data-angle-unit class="select select-xs w-full bg-base-200 border-base-content/15">${i}</select>
5453
5453
  </div>
5454
5454
  ${t?`<div class="border-t border-base-content/10 pt-2">${this.renderRows(t)}</div>`:``}
5455
- `,this.bindEvents()}renderRows(e){let t=[];this.data.entities.length===1&&e.entities.length===1&&t.push(this.renderEntityDetails(e.entities[0]));let n=e.entities.length===2;if(n)if(e.primary===`angle`&&e.angleDeg!==void 0)t.push(this.row(Ry(e.angleLabel??`Angle`),Py(e.angleDeg,this.data.angleUnit)));else{let n=Iy.find(t=>t.key===e.primary);n&&e[n.key]&&t.push(this.distanceRows(n.key,n.label,e[n.key])),e.angleDeg!==void 0&&t.push(this.row(Ry(e.angleLabel??`Angle`),Py(e.angleDeg,this.data.angleUnit)))}let r=e.entities.filter(e=>e.ref.kind===`face`).length,i=e.entities.filter(e=>e.ref.kind===`edge`).length;if(e.totalArea!==void 0&&t.push(this.row(r>1?`Total area`:`Area`,Ny(e.totalArea,this.data.lengthUnit))),e.totalLength!==void 0&&t.push(this.row(i>1?`Total length`:`Length`,My(e.totalLength,this.data.lengthUnit))),n)for(let{key:n,label:r}of Iy){if(n===e.primary)continue;let i=e[n];i&&t.push(this.distanceRows(n,r,i))}return t.join(``)}renderEntityDetails(e){let t=[this.row(`Type`,Fy[e.geomType]??e.geomType)];return e.area!==void 0&&t.push(this.row(`Area`,Ny(e.area,this.data.lengthUnit))),e.radius!==void 0&&(t.push(this.row(`Radius`,My(e.radius,this.data.lengthUnit))),t.push(this.row(`Diameter`,My(e.radius*2,this.data.lengthUnit)))),t.join(``)}row(e,t){return`<div class="flex justify-between items-baseline gap-2 px-1 py-0.5 rounded">
5455
+ `,this.bindEvents()}renderRows(e){let t=[];this.data.entities.length===1&&e.entities.length===1&&t.push(this.renderEntityDetails(e.entities[0]));let n=e.entities.length===2;if(n)if(e.primary===`angle`&&e.angleDeg!==void 0)t.push(this.row(Vy(e.angleLabel??`Angle`),Ly(e.angleDeg,this.data.angleUnit)));else{let n=zy.find(t=>t.key===e.primary);n&&e[n.key]&&t.push(this.distanceRows(n.key,n.label,e[n.key])),e.angleDeg!==void 0&&t.push(this.row(Vy(e.angleLabel??`Angle`),Ly(e.angleDeg,this.data.angleUnit)))}let r=e.entities.filter(e=>e.ref.kind===`face`).length,i=e.entities.filter(e=>e.ref.kind===`edge`).length;if(e.totalArea!==void 0&&t.push(this.row(r>1?`Total area`:`Area`,Iy(e.totalArea,this.data.lengthUnit))),e.totalLength!==void 0&&t.push(this.row(i>1?`Total length`:`Length`,Fy(e.totalLength,this.data.lengthUnit))),n)for(let{key:n,label:r}of zy){if(n===e.primary)continue;let i=e[n];i&&t.push(this.distanceRows(n,r,i))}return t.join(``)}renderEntityDetails(e){let t=[this.row(`Type`,Ry[e.geomType]??e.geomType)];return e.area!==void 0&&t.push(this.row(`Area`,Iy(e.area,this.data.lengthUnit))),e.radius!==void 0&&(t.push(this.row(`Radius`,Fy(e.radius,this.data.lengthUnit))),t.push(this.row(`Diameter`,Fy(e.radius*2,this.data.lengthUnit)))),t.join(``)}row(e,t){return`<div class="flex justify-between items-baseline gap-2 px-1 py-0.5 rounded">
5456
5456
  <span class="text-base-content/60">${e}</span>
5457
5457
  <span class="font-medium tabular-nums">${t}</span>
5458
5458
  </div>`}distanceRows(e,t,n){return`<div data-viz="${e}" class="flex justify-between items-baseline gap-2 px-1 py-0.5 rounded hover:bg-base-content/10 cursor-default">
5459
5459
  <span class="text-base-content/60">${t}</span>
5460
- <span class="font-medium tabular-nums">${My(n.value,this.data.lengthUnit)}</span>
5461
- </div>`+Ly.map(({axis:t,cls:r})=>{let i=n.to[t]-n.from[t];return`<div data-viz="${e}:${t}" class="flex justify-between items-baseline gap-2 pl-5 pr-1 py-0.5 rounded hover:bg-base-content/10 cursor-default">
5460
+ <span class="font-medium tabular-nums">${Fy(n.value,this.data.lengthUnit)}</span>
5461
+ </div>`+By.map(({axis:t,cls:r})=>{let i=n.to[t]-n.from[t];return`<div data-viz="${e}:${t}" class="flex justify-between items-baseline gap-2 pl-5 pr-1 py-0.5 rounded hover:bg-base-content/10 cursor-default">
5462
5462
  <span class="${r} font-semibold">${t.toUpperCase()}</span>
5463
- <span class="tabular-nums text-base-content/90">${My(i,this.data.lengthUnit)}</span>
5464
- </div>`}).join(``)}bindEvents(){this.el.querySelector(`[data-close]`)?.addEventListener(`click`,()=>this.callbacks.onClose()),this.el.querySelectorAll(`[data-remove]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=parseInt(e.dataset.remove,10),n=this.data.entities[t];n&&this.callbacks.onRemoveEntity(n.ref)})}),this.el.querySelector(`[data-length-unit]`)?.addEventListener(`change`,e=>{this.callbacks.onLengthUnitChange(e.target.value)}),this.el.querySelector(`[data-angle-unit]`)?.addEventListener(`change`,e=>{this.callbacks.onAngleUnitChange(e.target.value)}),this.el.querySelectorAll(`[data-viz]`).forEach(e=>{e.addEventListener(`mouseenter`,()=>{let t=this.resolveViz(e.dataset.viz);t&&this.callbacks.onHoverViz(t)}),e.addEventListener(`mouseleave`,()=>this.callbacks.onHoverViz(null))})}resolveViz(e){let[t,n]=e.split(`:`),r=this.data.result?.[t];return r?{from:r.from,to:r.to,axis:n}:null}},By=class{el;labelEl;valueEl;chevronEl;constructor(e,t){this.el=document.createElement(`div`),this.el.className=`absolute bottom-6 right-[76px] z-[150] panel-bg border border-base-content/10 rounded-lg h-8 px-3 text-xs text-base-content flex items-center gap-2 cursor-pointer select-none hover:border-base-content/30 hidden`,this.el.title=`Show all measurements`;let n=document.createElement(`span`);n.className=`opacity-60 [&>svg]:w-4 [&>svg]:h-4`,n.innerHTML=Wh,this.labelEl=document.createElement(`span`),this.labelEl.className=`text-base-content/60 whitespace-nowrap`,this.valueEl=document.createElement(`span`),this.valueEl.className=`font-medium tabular-nums whitespace-nowrap`,this.chevronEl=document.createElement(`span`),this.chevronEl.className=`opacity-60 transition-transform rotate-180`,this.chevronEl.innerHTML=ng,this.el.append(n,this.labelEl,this.valueEl,this.chevronEl),this.el.addEventListener(`click`,t),e.appendChild(this.el)}show(e,t){this.labelEl.textContent=`${e}:`,this.valueEl.textContent=t,this.el.classList.remove(`hidden`)}hide(){this.el.classList.add(`hidden`)}setExpanded(e){this.chevronEl.classList.toggle(`rotate-180`,!e)}},Vy=8,Hy=[`parallelDist`,`centerDist`,`axisDist`,`minDist`,`maxDist`];function Uy(e,t){return e.shapeId===t.shapeId&&e.sub.type===t.sub.type&&e.sub.index===t.sub.index}function Wy(e){return{shapeId:e.shapeId,kind:e.sub.type,index:e.sub.index}}var Gy=class{entities=[];result=null;panelOpen=!1;lengthUnit=`mm`;angleUnit=`deg`;abortController=null;statusBar;panel;overlay;constructor(e,t){this.viewer=t,this.statusBar=new By(e,()=>this.togglePanel()),this.panel=new zy(e,{onClose:()=>this.togglePanel(!1),onRemoveEntity:e=>this.removeEntity(e),onLengthUnitChange:e=>{this.lengthUnit=e,th(`measureLengthUnit`,e),this.updateUI()},onAngleUnitChange:e=>{this.angleUnit=e,th(`measureAngleUnit`,e),this.updateUI()},onHoverViz:e=>{e?this.overlay.show(e):this.applyDefaultViz()}}),this.overlay=new Ty(t.sceneContext)}applyPreferences(e){e.measureLengthUnit&&(this.lengthUnit=e.measureLengthUnit),e.measureAngleUnit&&(this.angleUnit=e.measureAngleUnit),this.updateUI()}get selection(){return this.entities}handleClick(e,t,n){if(!e||!t)return n&&this.entities.length>0||this.setSelection([]),this.entities;let r={shapeId:e,sub:t},i=this.entities.findIndex(e=>Uy(e,r)),a;return n||this.panelOpen?(a=i>=0?this.entities.filter((e,t)=>t!==i):[...this.entities,r],a.length>Vy&&(a=a.slice(a.length-Vy))):a=[r],this.setSelection(a),this.entities}clearSelection(){this.setSelection([])}onSceneRendered(){this.abortController?.abort(),this.abortController=null,this.entities=[],this.result=null,this.updateUI()}setSelection(e){this.entities=e,e.length>0?this.viewer.highlightEntities(e):this.viewer.clearHighlight(),this.fetchMeasurement()}fetchMeasurement(){if(this.abortController?.abort(),this.abortController=null,this.entities.length===0){this.result=null,this.updateUI();return}let e=new AbortController;this.abortController=e;let t=this.entities.map(Wy);this.result=null,this.updateUI(),Gm(t,e.signal).then(t=>{e.signal.aborted||this.abortController!==e||(this.result=t,this.updateUI())})}removeEntity(e){let t=this.entities.filter(t=>!(t.shapeId===e.shapeId&&t.sub.type===e.kind&&t.sub.index===e.index));this.setSelection(t)}togglePanel(e=!this.panelOpen){this.panelOpen=e,this.panel.setVisible(e),this.statusBar.setExpanded(e)}updateUI(){this.entities.length>=2&&this.result?(this.statusBar.show(this.result.primaryLabel,this.primaryValueText(this.result)),this.statusBar.setExpanded(this.panelOpen)):this.entities.length>=2?this.statusBar.show(`Measuring`,`…`):this.statusBar.hide(),this.panel.update({entities:this.entities.map((e,t)=>({ref:Wy(e),label:`Selection ${t+1} [${e.sub.type===`face`?`Face`:`Edge`}]`})),result:this.result,lengthUnit:this.lengthUnit,angleUnit:this.angleUnit}),this.applyDefaultViz()}primaryValueText(e){if(e.primary===`angle`)return e.angleDeg===void 0?`—`:Py(e.angleDeg,this.angleUnit);if(e.primary===`totalArea`)return e.totalArea===void 0?`—`:Ny(e.totalArea,this.lengthUnit);if(e.primary===`totalLength`)return e.totalLength===void 0?`—`:My(e.totalLength,this.lengthUnit);let t=e[e.primary];return t?My(t.value,this.lengthUnit):`—`}applyDefaultViz(){let e=this.result;if(!e||this.entities.length!==2||!Hy.includes(e.primary)){this.overlay.clear();return}let t=e[e.primary];t?this.overlay.show({from:t.from,to:t.to}):this.overlay.clear()}};k_();var Ky=document.getElementById(`fluidcad-viewer`)||document.body,qy=new n_(Ky),Jy=new vg(`fluidcad-viewer`);Gd(()=>Jy.rebuildSceneMesh()),eh().then(e=>{e&&(document.documentElement.setAttribute(`data-theme`,e.theme),ef(e),eb.setShowBuildTimings(!!e.showBuildTimings),Zy.applyPreferences(e))});var Yy=new Tg(Ky),Xy=new Og(Ky),Zy=new Gy(Ky,Jy),Qy=new $g(Ky,Jy.sceneContext),$y=new r_(Ky,{showLoading:e=>qy.show(e),hideLoading:()=>qy.hide()}),eb=new Ig(Ky,e=>Jy.highlightShape(e),e=>Qy.show(e),(e,t)=>Jy.setShapeVisibility(e,t),e=>Jy.isShapeHidden(e),(e,t)=>Jy.setShapeTransparency(e,t),e=>Jy.getShapeTransparency(e),()=>Jy.resetAllTransparency(),()=>$y.openPicker()),tb=new Lg(Jy.settingsPanelHost);Jy.setParamsToggleHandler(()=>{tb.toggle(),Jy.setParamsButtonActive(tb.isVisible)});var nb=new y_(Ky,Jy),rb=new w_(Ky,Jy),ib=new by(Ky,Jy,nb,eb),ab=new e_(Ky,()=>{rb.state===`picking-active`&&rb.exit(),nb.state===`picking-active`&&nb.exit()}),ob=new t_(Ky,e=>{Zm(e)});Yy.setOpenHandler(()=>{Zy.clearSelection(),Jy.clearHighlight(),Xy.hide()}),Yy.setCentroidHandler(e=>{e?Jy.showCentroid(e):Jy.clearCentroid()}),Jy.setSelectionHandler((e,t,n)=>{if(Yy.isOpen){Zy.clearSelection(),e?Jy.highlightShape(e):Jy.clearHighlight(),Yy.setSelectedShape(e),Xy.hide();return}let r=Zy.handleClick(e,t,n.additive);if(r.length===1){let e=r[0];Yy.setSelectedShape(e.shapeId),e.sub.type===`face`?Xy.showForFace(e.shapeId,e.sub.index):Xy.showForEdge(e.shapeId,e.sub.index)}else Yy.setSelectedShape(r.length>0?r[0].shapeId:null),Xy.hide()});async function sb(e,t,n){try{let r={...n||{}},i=!!r.multi;delete r.multi;let a=await(i?await Kg(Jy.sceneContext,r):await Gg(Jy.sceneContext,r)).arrayBuffer(),o=new Uint8Array(a),s=``;for(let e=0;e<o.length;e++)s+=String.fromCharCode(o[e]);e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!0,data:btoa(s)}))}catch(n){e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!1,error:n.message||String(n)}))}}var cb=200,lb=0,ub=!1,db=null;function fb(){if(!db||db.readyState!==WebSocket.OPEN)return;let e=Jy.sceneContext,t=e.camera,n={x:0,y:0,z:0};e.cameraControls.getTarget(n),db.send(JSON.stringify({type:`camera-state`,position:[t.position.x,t.position.y,t.position.z],target:[n.x,n.y,n.z],up:[t.up.x,t.up.y,t.up.z],projection:t.isOrthographicCamera?`orthographic`:`perspective`}))}function pb(){let e=Date.now();if(e-lb>=cb){lb=e,fb();return}if(ub)return;ub=!0;let t=cb-(e-lb);setTimeout(()=>{ub=!1,lb=Date.now(),fb()},Math.max(0,t))}Jy.sceneContext.cameraControls.addEventListener(`update`,pb);function mb(){let e=`ws://${window.location.host}`,t=new WebSocket(e);t.addEventListener(`open`,()=>{db=t,fb()}),t.addEventListener(`message`,e=>{let n=JSON.parse(e.data);switch(n.type){case`init-complete`:qy.show(`Loading model...`);break;case`processing-file`:qy.show(`Loading model...`);break;case`scene-rendered`:{qy.hide();let e=n.rollbackStop!=null&&n.rollbackStop<n.result.length-1;Jy.isTrimming=!e&&nb.state===`picking-active`,Jy.isDrawing=!e&&ib.hasActiveDrawingTool,Jy.updateView(n.result,e,n.rollbackStop),Zy.onSceneRendered(),n.absPath&&Jy.setFileName(n.absPath),e?(nb.reset(),rb.reset(),ib.update([])):(nb.update(n.result),rb.update(n.result),ib.update(n.result)),eb.update(n.result,n.rollbackStop??n.result.length-1,n.absPath),n.params!==void 0&&(tb.update(n.params),Jy.setParamsButtonVisible(tb.hasAnyParams)),ob.update(n.result,n.compileError??null),n.breakpointHit!==void 0&&ab.setActive(n.breakpointHit);break}case`highlight-shape`:Zy.clearSelection(),Jy.highlightShape(n.shapeId),Yy.setSelectedShape(n.shapeId);break;case`clear-highlight`:Zy.clearSelection(),Jy.clearHighlight(),Yy.setSelectedShape(null),Xy.hide();break;case`show-shape-properties`:Zy.clearSelection(),Jy.clearHighlight(),Xy.hide(),Yy.show(n.shapeId);break;case`take-screenshot`:sb(t,n.requestId,n.options);break}}),t.addEventListener(`close`,()=>{db===t&&(db=null),ob.update([],null),setTimeout(mb,1e3)})}mb();
5463
+ <span class="tabular-nums text-base-content/90">${Fy(i,this.data.lengthUnit)}</span>
5464
+ </div>`}).join(``)}bindEvents(){this.el.querySelector(`[data-close]`)?.addEventListener(`click`,()=>this.callbacks.onClose()),this.el.querySelectorAll(`[data-remove]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=parseInt(e.dataset.remove,10),n=this.data.entities[t];n&&this.callbacks.onRemoveEntity(n.ref)})}),this.el.querySelector(`[data-length-unit]`)?.addEventListener(`change`,e=>{this.callbacks.onLengthUnitChange(e.target.value)}),this.el.querySelector(`[data-angle-unit]`)?.addEventListener(`change`,e=>{this.callbacks.onAngleUnitChange(e.target.value)}),this.el.querySelectorAll(`[data-viz]`).forEach(e=>{e.addEventListener(`mouseenter`,()=>{let t=this.resolveViz(e.dataset.viz);t&&this.callbacks.onHoverViz(t)}),e.addEventListener(`mouseleave`,()=>this.callbacks.onHoverViz(null))})}resolveViz(e){let[t,n]=e.split(`:`),r=this.data.result?.[t];return r?{from:r.from,to:r.to,axis:n}:null}},Uy=class{el;labelEl;valueEl;chevronEl;constructor(e,t){this.el=document.createElement(`div`),this.el.className=`absolute bottom-6 right-[76px] z-[150] panel-bg border border-base-content/10 rounded-lg h-8 px-3 text-xs text-base-content flex items-center gap-2 cursor-pointer select-none hover:border-base-content/30 hidden`,this.el.title=`Show all measurements`;let n=document.createElement(`span`);n.className=`opacity-60 [&>svg]:w-4 [&>svg]:h-4`,n.innerHTML=qh,this.labelEl=document.createElement(`span`),this.labelEl.className=`text-base-content/60 whitespace-nowrap`,this.valueEl=document.createElement(`span`),this.valueEl.className=`font-medium tabular-nums whitespace-nowrap`,this.chevronEl=document.createElement(`span`),this.chevronEl.className=`opacity-60 transition-transform rotate-180`,this.chevronEl.innerHTML=ag,this.el.append(n,this.labelEl,this.valueEl,this.chevronEl),this.el.addEventListener(`click`,t),e.appendChild(this.el)}show(e,t){this.labelEl.textContent=`${e}:`,this.valueEl.textContent=t,this.el.classList.remove(`hidden`)}hide(){this.el.classList.add(`hidden`)}setExpanded(e){this.chevronEl.classList.toggle(`rotate-180`,!e)}},Wy=8,Gy=[`parallelDist`,`centerDist`,`axisDist`,`minDist`,`maxDist`];function Ky(e,t){return e.shapeId===t.shapeId&&e.sub.type===t.sub.type&&e.sub.index===t.sub.index}function qy(e){return{shapeId:e.shapeId,kind:e.sub.type,index:e.sub.index}}var Jy=class{entities=[];result=null;panelOpen=!1;lengthUnit=`mm`;angleUnit=`deg`;abortController=null;statusBar;panel;overlay;constructor(e,t){this.viewer=t,this.statusBar=new Uy(e,()=>this.togglePanel()),this.panel=new Hy(e,{onClose:()=>this.togglePanel(!1),onRemoveEntity:e=>this.removeEntity(e),onLengthUnitChange:e=>{this.lengthUnit=e,ih(`measureLengthUnit`,e),this.updateUI()},onAngleUnitChange:e=>{this.angleUnit=e,ih(`measureAngleUnit`,e),this.updateUI()},onHoverViz:e=>{e?this.overlay.show(e):this.applyDefaultViz()}}),this.overlay=new Oy(t.sceneContext)}applyPreferences(e){e.measureLengthUnit&&(this.lengthUnit=e.measureLengthUnit),e.measureAngleUnit&&(this.angleUnit=e.measureAngleUnit),this.updateUI()}get selection(){return this.entities}handleClick(e,t,n){if(!e||!t)return n&&this.entities.length>0||this.setSelection([]),this.entities;let r={shapeId:e,sub:t},i=this.entities.findIndex(e=>Ky(e,r)),a;return n||this.panelOpen?(a=i>=0?this.entities.filter((e,t)=>t!==i):[...this.entities,r],a.length>Wy&&(a=a.slice(a.length-Wy))):a=[r],this.setSelection(a),this.entities}clearSelection(){this.setSelection([])}onSceneRendered(){this.abortController?.abort(),this.abortController=null,this.entities=[],this.result=null,this.updateUI()}setSelection(e){this.entities=e,e.length>0?this.viewer.highlightEntities(e):this.viewer.clearHighlight(),this.fetchMeasurement()}fetchMeasurement(){if(this.abortController?.abort(),this.abortController=null,this.entities.length===0){this.result=null,this.updateUI();return}let e=new AbortController;this.abortController=e;let t=this.entities.map(qy);this.result=null,this.updateUI(),Jm(t,e.signal).then(t=>{e.signal.aborted||this.abortController!==e||(this.result=t,this.updateUI())})}removeEntity(e){let t=this.entities.filter(t=>!(t.shapeId===e.shapeId&&t.sub.type===e.kind&&t.sub.index===e.index));this.setSelection(t)}togglePanel(e=!this.panelOpen){this.panelOpen=e,this.panel.setVisible(e),this.statusBar.setExpanded(e)}updateUI(){this.entities.length>=2&&this.result?(this.statusBar.show(this.result.primaryLabel,this.primaryValueText(this.result)),this.statusBar.setExpanded(this.panelOpen)):this.entities.length>=2?this.statusBar.show(`Measuring`,`…`):this.statusBar.hide(),this.panel.update({entities:this.entities.map((e,t)=>({ref:qy(e),label:`Selection ${t+1} [${e.sub.type===`face`?`Face`:`Edge`}]`})),result:this.result,lengthUnit:this.lengthUnit,angleUnit:this.angleUnit}),this.applyDefaultViz()}primaryValueText(e){if(e.primary===`angle`)return e.angleDeg===void 0?`—`:Ly(e.angleDeg,this.angleUnit);if(e.primary===`totalArea`)return e.totalArea===void 0?`—`:Iy(e.totalArea,this.lengthUnit);if(e.primary===`totalLength`)return e.totalLength===void 0?`—`:Fy(e.totalLength,this.lengthUnit);let t=e[e.primary];return t?Fy(t.value,this.lengthUnit):`—`}applyDefaultViz(){let e=this.result;if(!e||this.entities.length!==2||!Gy.includes(e.primary)){this.overlay.clear();return}let t=e[e.primary];t?this.overlay.show({from:t.from,to:t.to}):this.overlay.clear()}};M_();var Yy=document.getElementById(`fluidcad-viewer`)||document.body,Xy=new a_(Yy),Zy=new xg(`fluidcad-viewer`);Gd(()=>Zy.rebuildSceneMesh()),rh().then(e=>{e&&(document.documentElement.setAttribute(`data-theme`,e.theme),uf(e),rb.setShowBuildTimings(!!e.showBuildTimings),eb.applyPreferences(e))});var Qy=new Og(Yy),$y=new jg(Yy),eb=new Jy(Yy,Zy),tb=new n_(Yy,Zy.sceneContext),nb=new o_(Yy,{showLoading:e=>Xy.show(e),hideLoading:()=>Xy.hide()}),rb=new zg(Yy,e=>Zy.highlightShape(e),e=>tb.show(e),(e,t)=>Zy.setShapeVisibility(e,t),e=>Zy.isShapeHidden(e),(e,t)=>Zy.setShapeTransparency(e,t),e=>Zy.getShapeTransparency(e),()=>Zy.resetAllTransparency(),()=>nb.openPicker()),ib=new Bg(Zy.settingsPanelHost);Zy.setParamsToggleHandler(()=>{ib.toggle(),Zy.setParamsButtonActive(ib.isVisible)});var ab=new S_(Yy,Zy),ob=new D_(Yy,Zy),sb=new Cy(Yy,Zy,ab,rb),cb=new r_(Yy,()=>{ob.state===`picking-active`&&ob.exit(),ab.state===`picking-active`&&ab.exit()}),lb=new i_(Yy,e=>{eh(e)});Qy.setOpenHandler(()=>{eb.clearSelection(),Zy.clearHighlight(),$y.hide()}),Qy.setCentroidHandler(e=>{e?Zy.showCentroid(e):Zy.clearCentroid()}),Zy.setSelectionHandler((e,t,n)=>{if(Qy.isOpen){eb.clearSelection(),e?Zy.highlightShape(e):Zy.clearHighlight(),Qy.setSelectedShape(e),$y.hide();return}let r=eb.handleClick(e,t,n.additive);if(r.length===1){let e=r[0];Qy.setSelectedShape(e.shapeId),e.sub.type===`face`?$y.showForFace(e.shapeId,e.sub.index):$y.showForEdge(e.shapeId,e.sub.index)}else Qy.setSelectedShape(r.length>0?r[0].shapeId:null),$y.hide()});async function ub(e,t,n){try{let r={...n||{}},i=!!r.multi;delete r.multi;let a=await(i?await Yg(Zy.sceneContext,r):await Jg(Zy.sceneContext,r)).arrayBuffer(),o=new Uint8Array(a),s=``;for(let e=0;e<o.length;e++)s+=String.fromCharCode(o[e]);e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!0,data:btoa(s)}))}catch(n){e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!1,error:n.message||String(n)}))}}var db=200,fb=0,pb=!1,mb=null;function hb(){if(!mb||mb.readyState!==WebSocket.OPEN)return;let e=Zy.sceneContext,t=e.camera,n={x:0,y:0,z:0};e.cameraControls.getTarget(n),mb.send(JSON.stringify({type:`camera-state`,position:[t.position.x,t.position.y,t.position.z],target:[n.x,n.y,n.z],up:[t.up.x,t.up.y,t.up.z],projection:t.isOrthographicCamera?`orthographic`:`perspective`}))}function gb(){let e=Date.now();if(e-fb>=db){fb=e,hb();return}if(pb)return;pb=!0;let t=db-(e-fb);setTimeout(()=>{pb=!1,fb=Date.now(),hb()},Math.max(0,t))}Zy.sceneContext.cameraControls.addEventListener(`update`,gb);function _b(){let e=`ws://${window.location.host}`,t=new WebSocket(e);t.addEventListener(`open`,()=>{mb=t,hb()}),t.addEventListener(`message`,e=>{let n=JSON.parse(e.data);switch(n.type){case`init-complete`:Xy.show(`Loading model...`);break;case`processing-file`:Xy.show(`Loading model...`);break;case`scene-rendered`:{Xy.hide();let e=n.rollbackStop!=null&&n.rollbackStop<n.result.length-1;Zy.isTrimming=!e&&ab.state===`picking-active`,Zy.isDrawing=!e&&sb.hasActiveDrawingTool,Zy.updateView(n.result,e,n.rollbackStop),eb.onSceneRendered(),n.absPath&&Zy.setFileName(n.absPath),e?(ab.reset(),ob.reset(),sb.update([])):(ab.update(n.result),ob.update(n.result),sb.update(n.result)),rb.update(n.result,n.rollbackStop??n.result.length-1,n.absPath),n.params!==void 0&&(ib.update(n.params),Zy.setParamsButtonVisible(ib.hasAnyParams)),lb.update(n.result,n.compileError??null),n.breakpointHit!==void 0&&cb.setActive(n.breakpointHit);break}case`highlight-shape`:eb.clearSelection(),Zy.highlightShape(n.shapeId),Qy.setSelectedShape(n.shapeId);break;case`clear-highlight`:eb.clearSelection(),Zy.clearHighlight(),Qy.setSelectedShape(null),$y.hide();break;case`show-shape-properties`:eb.clearSelection(),Zy.clearHighlight(),$y.hide(),Qy.show(n.shapeId);break;case`take-screenshot`:ub(t,n.requestId,n.options);break}}),t.addEventListener(`close`,()=>{mb===t&&(mb=null),lb.update([],null),setTimeout(_b,1e3)})}_b();