fluidcad 0.0.26 → 0.0.27

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.
Files changed (58) hide show
  1. package/lib/dist/common/shape-factory.d.ts +1 -1
  2. package/lib/dist/common/shapes.d.ts +0 -1
  3. package/lib/dist/common/shapes.js +0 -1
  4. package/lib/dist/core/extrude.d.ts +12 -13
  5. package/lib/dist/core/extrude.js +19 -1
  6. package/lib/dist/core/part.d.ts +2 -1
  7. package/lib/dist/core/part.js +4 -1
  8. package/lib/dist/core/sketch.d.ts +4 -3
  9. package/lib/dist/core/sketch.js +4 -1
  10. package/lib/dist/features/extrude-base.d.ts +7 -1
  11. package/lib/dist/features/extrude-base.js +36 -3
  12. package/lib/dist/features/extrude-to-face.d.ts +1 -1
  13. package/lib/dist/features/extrude-to-face.js +29 -17
  14. package/lib/dist/features/extrude-two-distances.d.ts +1 -1
  15. package/lib/dist/features/extrude-two-distances.js +23 -12
  16. package/lib/dist/features/extrude.d.ts +1 -1
  17. package/lib/dist/features/extrude.js +47 -15
  18. package/lib/dist/features/mirror-shape.d.ts +1 -3
  19. package/lib/dist/features/mirror-shape.js +2 -1
  20. package/lib/dist/features/revolve.js +4 -2
  21. package/lib/dist/features/rotate.js +1 -0
  22. package/lib/dist/features/simple-extruder.js +5 -0
  23. package/lib/dist/features/translate.js +3 -1
  24. package/lib/dist/filters/face/face-filter.d.ts +12 -0
  25. package/lib/dist/filters/face/face-filter.js +21 -0
  26. package/lib/dist/filters/face/torus-filter.d.ts +19 -0
  27. package/lib/dist/filters/face/torus-filter.js +38 -0
  28. package/lib/dist/helpers/scene-helpers.d.ts +3 -1
  29. package/lib/dist/helpers/scene-helpers.js +6 -3
  30. package/lib/dist/index.d.ts +1 -0
  31. package/lib/dist/oc/boolean-ops.d.ts +5 -3
  32. package/lib/dist/oc/boolean-ops.js +15 -2
  33. package/lib/dist/oc/face-ops.d.ts +0 -1
  34. package/lib/dist/oc/face-ops.js +0 -13
  35. package/lib/dist/oc/face-query.d.ts +2 -0
  36. package/lib/dist/oc/face-query.js +30 -0
  37. package/lib/dist/oc/fillet-ops.js +84 -66
  38. package/lib/dist/oc/mesh.d.ts +25 -2
  39. package/lib/dist/oc/mesh.js +112 -35
  40. package/lib/dist/oc/shape-ops.d.ts +1 -21
  41. package/lib/dist/oc/shape-ops.js +0 -103
  42. package/lib/dist/rendering/mesh-transform.js +17 -1
  43. package/lib/dist/rendering/render-solid.js +19 -6
  44. package/lib/dist/rendering/render-wire.js +2 -0
  45. package/lib/dist/rendering/render.d.ts +12 -2
  46. package/lib/dist/rendering/render.js +195 -220
  47. package/lib/dist/scene-manager.d.ts +2 -0
  48. package/lib/dist/scene-manager.js +4 -3
  49. package/lib/dist/tests/features/extrude.test.js +71 -0
  50. package/lib/dist/tests/features/fillet2d.test.js +16 -1
  51. package/lib/dist/tests/features/select.test.js +50 -0
  52. package/lib/dist/tests/setup.js +3 -2
  53. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +3 -3
  55. package/ui/dist/assets/{index-BeLxRMCv.js → index-55iqIwnj.js} +37 -37
  56. package/ui/dist/index.html +1 -1
  57. package/lib/dist/common/solid-face.d.ts +0 -9
  58. package/lib/dist/common/solid-face.js +0 -22
@@ -4199,7 +4199,7 @@ void main() {
4199
4199
  #include <premultiplied_alpha_fragment>
4200
4200
 
4201
4201
  }
4202
- `};var Qu=class extends qr{constructor(e){super({type:`LineMaterial`,uniforms:Wr.clone(yo.line.uniforms),vertexShader:yo.line.vertexShader,fragmentShader:yo.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)}},$u=new Lt,ed=new B,td=new B,nd=new Lt,rd=new Lt,id=new Lt,ad=new B,od=new gn,sd=new po,cd=new B,ld=new Ht,ud=new sn,dd=new Lt,fd,pd;function md(e,t,n){return dd.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),dd.multiplyScalar(1/dd.w),dd.x=pd/n.width,dd.y=pd/n.height,dd.applyMatrix4(e.projectionMatrixInverse),dd.multiplyScalar(1/dd.w),Math.abs(Math.max(dd.x,dd.y))}function hd(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++){sd.start.fromBufferAttribute(i,r),sd.end.fromBufferAttribute(a,r),sd.applyMatrix4(n);let o=new B,s=new B;fd.distanceSqToSegment(sd.start,sd.end,s,o),s.distanceTo(o)<pd*.5&&t.push({point:s,pointOnLine:o,distance:fd.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function gd(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;fd.at(1,id),id.w=1,id.applyMatrix4(t.matrixWorldInverse),id.applyMatrix4(r),id.multiplyScalar(1/id.w),id.x*=i.x/2,id.y*=i.y/2,id.z=0,ad.copy(id),od.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(nd.fromBufferAttribute(s,t),rd.fromBufferAttribute(c,t),nd.w=1,rd.w=1,nd.applyMatrix4(od),rd.applyMatrix4(od),nd.z>u&&rd.z>u)continue;if(nd.z>u){let e=nd.z-rd.z,t=(nd.z-u)/e;nd.lerp(rd,t)}else if(rd.z>u){let e=rd.z-nd.z,t=(rd.z-u)/e;rd.lerp(nd,t)}nd.applyMatrix4(r),rd.applyMatrix4(r),nd.multiplyScalar(1/nd.w),rd.multiplyScalar(1/rd.w),nd.x*=i.x/2,nd.y*=i.y/2,rd.x*=i.x/2,rd.y*=i.y/2,sd.start.copy(nd),sd.start.z=0,sd.end.copy(rd),sd.end.z=0;let o=sd.closestPointToPointParameter(ad,!0);sd.at(o,cd);let l=pt.lerp(nd.z,rd.z,o),d=l>=-1&&l<=1,f=ad.distanceTo(cd)<pd*.5;if(d&&f){sd.start.fromBufferAttribute(s,t),sd.end.fromBufferAttribute(c,t),sd.start.applyMatrix4(a),sd.end.applyMatrix4(a);let r=new B,i=new B;fd.distanceSqToSegment(sd.start,sd.end,i,r),n.push({point:i,pointOnLine:r,distance:fd.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var _d=class extends G{constructor(e=new Zu,t=new Qu({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)ed.fromBufferAttribute(t,e),td.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+ed.distanceTo(td);let i=new $a(r,2,1);return e.setAttribute(`instanceDistanceStart`,new ui(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new ui(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;fd=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;pd=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),ud.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?pd*.5:md(r,Math.max(r.near,ud.distanceToPoint(fd.origin)),s.resolution),ud.radius+=c,fd.intersectsSphere(ud)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),ld.copy(o.boundingBox).applyMatrix4(a);let l;l=n?pd*.5:md(r,Math.max(r.near,ld.distanceToPoint(fd.origin)),s.resolution),ld.expandByScalar(l),fd.intersectsBox(ld)!==!1&&(n?hd(this,t):gd(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport($u),this.material.uniforms.resolution.value.set($u.z,$u.w))}},vd=class extends Zu{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}},yd=class extends _d{constructor(e=new vd,t=new Qu({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},bd=e=>{let t=new U,n=[],r=[],{isSphere:i}=e;return wu.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?Pu-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 yd(new vd().setPositions(n).setColors(r),new Qu({linewidth:e.lineWidth,vertexColors:!0,resolution:new z(window.innerWidth,window.innerHeight)})).computeLineDistances():null},xd=e=>{let{corners:t,edges:n}=e,r=[],i=zu(e),a=Uu(e,i);return r.push(...a),t.enabled&&r.push(...Wu(e,i)),n.enabled&&r.push(...Gu(e,i,t.enabled?7:6)),[r,Ju(a,e),bd(e)]},Sd=(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?Bu(n.map,t):n.color.set(a)},Cd=new gn,wd=new io,Td=new z,Ed=new B,Dd=new Lt,Od=class extends Un{constructor(e,t,n={}){super(),lu(this,`enabled`,!0),lu(this,`camera`),lu(this,`renderer`),lu(this,`options`),lu(this,`target`,new B),lu(this,`animated`,!0),lu(this,`speed`,1),lu(this,`animating`,!1),lu(this,`_options`),lu(this,`_intersections`),lu(this,`_background`,null),lu(this,`_viewport`,[0,0,0,0]),lu(this,`_originalViewport`,[0,0,0,0]),lu(this,`_originalScissor`,[0,0,0,0]),lu(this,`_scene`),lu(this,`_camera`),lu(this,`_container`),lu(this,`_domElement`),lu(this,`_domRect`),lu(this,`_dragging`,!1),lu(this,`_distance`,0),lu(this,`_clock`,new Ba),lu(this,`_targetQuaternion`,new mt),lu(this,`_quaternionStart`,new mt),lu(this,`_quaternionEnd`,new mt),lu(this,`_pointerStart`,new z),lu(this,`_focus`,null),lu(this,`_placement`),lu(this,`_controls`),lu(this,`_controlsListeners`),this.camera=e,this.renderer=t,this._scene=new si().add(this),this.set(n)}get placement(){return this._placement}set placement(e){this._placement=uu(this._domElement,e),this.domUpdate()}set(e={}){this.dispose(),this.options=e,this._options=Lu(e),this._camera=this._options.isSphere?new Pa(-1.8,1.8,1.8,-1.8,5,10):new Qr(26,1,5,10),this._camera.position.set(0,0,7);let[t,n,r]=xd(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?fu(i):document.body,this._domElement=du(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(Dd).toArray(this._originalViewport),e.getScissorTest()&&e.getScissor(Dd).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 B().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()),gu(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()*Su*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)<xu&&(this._controls&&(this._controls.enabled=!0),this.animating=!1,this.dispatchEvent({type:`end`}))}_setOrientation(e){let t=this.camera,n=this.target;Ed.copy(e).multiplyScalar(this._distance),Cd.setPosition(Ed).lookAt(Ed,this.position,this.up),this._targetQuaternion.setFromRotationMatrix(Cd),Ed.add(n),Cd.lookAt(Ed,n,this.up),this._quaternionEnd.setFromRotationMatrix(Cd),Cd.setPosition(t.position).lookAt(t.position,n,this.up),this._quaternionStart.setFromRotationMatrix(Cd),this.animating=!0,this._clock.start(),this.dispatchEvent({type:`start`})}_onPointerDown(e){if(!this.enabled)return;let t=e=>{if(!this._dragging){if(_u(e,this._pointerStart))return;this._dragging=!0}let t=Td.set(e.clientX,e.clientY).sub(this._pointerStart).multiplyScalar(1/this._domRect.width*Math.PI),n=this.coordinateConversion(Ed.subVectors(this.camera.position,this.target)),r=wd.setFromVector3(n);r.theta=a-t.x,r.phi=pu(o-t.y,xu,Math.PI-xu),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&&=(Sd(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(Ed.subVectors(this.camera.position,this.target)),i=wd.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=Un.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&&Fu(this._background,!0),this._handleHover(e))}_onPointerLeave(){!this.enabled||this._dragging||(this._background&&Fu(this._background,!1),this._focus&&Sd(this._focus,!1),this._domElement.style.cursor=``)}_handleClick(e){let t=bu(e,this._domRect,this._camera,this._intersections);this._focus&&=(Sd(this._focus,!1),null),t&&(this._setOrientation(t.object.position),this.dispatchEvent({type:`change`}))}_handleHover(e){let t=bu(e,this._domRect,this._camera,this._intersections)?.object||null;this._focus!==t&&(this._domElement.style.cursor=t?`pointer`:``,this._focus&&Sd(this._focus,!1),(this._focus=t)?Sd(t,!0):gu(this._options,this._intersections,this.camera))}},kd=class extends He{target=new B;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)}},Ad=new Set;function jd(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Md(){Nd.faceColor.set(jd(`--scene-face-color`,`#969696`)),Nd.edgeColor.set(jd(`--scene-edge-color`,`#000000`)),Nd.gridColor.set(jd(`--scene-grid-color`,`#6f6f6f`)),Nd.metaEdgeColor.set(jd(`--scene-meta-edge-color`,`#b0b0b0`)),Nd.backgroundColor.set(jd(`--color-base-100`,`#1e1e1e`))}var Nd={faceColor:new U(`#969696`),edgeColor:new U(`#000000`),gridColor:new U(`#6f6f6f`),metaEdgeColor:new U(`#b0b0b0`),backgroundColor:new U(`#1e1e1e`)};Md(),new MutationObserver(()=>{Md();for(let e of Ad)e()}).observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]});function Pd(e){return Ad.add(e),()=>Ad.delete(e)}ou.install({THREE:{Vector2:z,Vector3:B,Vector4:Lt,Quaternion:mt,Matrix4:gn,Spherical:io,Box3:Ht,Sphere:sn,Raycaster:to,MathUtils:{DEG2RAD:pt.DEG2RAD,clamp:pt.clamp}}});var Fd=new B(0,0,1),Id=120,Ld=1.1,Rd=class{scene;renderer;gizmo;orthoCamera;perspCamera;activeCamera=`orthographic`;_cc;_adapter;dirLight;renderRequested=!1;resizeObserver;clock=new Ba;animFrameId=0;gizmoWasActive=!1;constructor(e){this.container=e,Un.DEFAULT_UP=Fd.clone();let t=e.clientWidth||window.innerWidth,n=e.clientHeight||window.innerHeight;this.renderer=new vl({antialias:!0,alpha:!0}),this.renderer.setSize(t,n),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.toneMapping=4,this.renderer.outputColorSpace=Fe,this.renderer.localClippingEnabled=!0,e.appendChild(this.renderer.domElement),this.scene=new si,this.scene.background=Nd.backgroundColor.clone();let r=t/n;this.orthoCamera=new Pa(-r*Id/2,r*Id/2,Id/2,-Id/2,-1e4,1e4),this.orthoCamera.position.set(50,-50,40),this.orthoCamera.up.copy(Fd),this.orthoCamera.lookAt(0,0,0),this.perspCamera=new Qr(50,r,.5,1e4),this.perspCamera.position.set(50,-50,40),this.perspCamera.up.copy(Fd),this.perspCamera.lookAt(0,0,0),this.dirLight=new Ia(16777215,1),this.scene.add(this.dirLight),this.scene.add(new La(14544639,2.5)),this._cc=new ou(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 kd(this._cc),this.gizmo=new Od(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),Pd(()=>{this.scene.background=Nd.backgroundColor.clone(),this.requestRender()}),this.tick()}get camera(){return this.activeCamera===`orthographic`?this.orthoCamera:this.perspCamera}get cameraControls(){return this._cc}get controls(){return this._adapter}requestRender(){this.renderRequested=!0}fitToBox(e,t){let n=e.getCenter(new B),r=e.getSize(new B).length()/2;if(r===0)return;let i=new sn(n,r*Ld);this._cc.fitToSphere(i,t)}switchCamera(e){if(e===this.activeCamera)return;let t=new B,n=new B;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=pt.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 ou(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 kd(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=ou.ACTION.TOUCH_ROTATE,this._cc.touches.two=ou.ACTION.TOUCH_ZOOM_TRUCK):(this._cc.touches.one=ou.ACTION.TOUCH_ROTATE,this._cc.touches.two=ou.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),this.orthoCamera.left=-n*Id/2,this.orthoCamera.right=n*Id/2,this.orthoCamera.top=Id/2,this.orthoCamera.bottom=-Id/2,this.orthoCamera.updateProjectionMatrix(),this.perspCamera.aspect=n,this.perspCamera.updateProjectionMatrix(),this.gizmo.update(),this.requestRender()}updateLightPositions(){let e=new B;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 G{constructor(e=10,t=100,n=new U(`white`),r=8e3,i=new B(0,1,0)){let a=new aa(2,2,1,1),o=new qr({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 Qu=class extends qr{constructor(e){super({type:`LineMaterial`,uniforms:Wr.clone(yo.line.uniforms),vertexShader:yo.line.vertexShader,fragmentShader:yo.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)}},$u=new Lt,ed=new B,td=new B,nd=new Lt,rd=new Lt,id=new Lt,ad=new B,od=new gn,sd=new po,cd=new B,ld=new Ht,ud=new sn,dd=new Lt,fd,pd;function md(e,t,n){return dd.set(0,0,-t,1).applyMatrix4(e.projectionMatrix),dd.multiplyScalar(1/dd.w),dd.x=pd/n.width,dd.y=pd/n.height,dd.applyMatrix4(e.projectionMatrixInverse),dd.multiplyScalar(1/dd.w),Math.abs(Math.max(dd.x,dd.y))}function hd(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++){sd.start.fromBufferAttribute(i,r),sd.end.fromBufferAttribute(a,r),sd.applyMatrix4(n);let o=new B,s=new B;fd.distanceSqToSegment(sd.start,sd.end,s,o),s.distanceTo(o)<pd*.5&&t.push({point:s,pointOnLine:o,distance:fd.origin.distanceTo(s),object:e,face:null,faceIndex:r,uv:null,uv1:null})}}function gd(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;fd.at(1,id),id.w=1,id.applyMatrix4(t.matrixWorldInverse),id.applyMatrix4(r),id.multiplyScalar(1/id.w),id.x*=i.x/2,id.y*=i.y/2,id.z=0,ad.copy(id),od.multiplyMatrices(t.matrixWorldInverse,a);for(let t=0,o=l;t<o;t++){if(nd.fromBufferAttribute(s,t),rd.fromBufferAttribute(c,t),nd.w=1,rd.w=1,nd.applyMatrix4(od),rd.applyMatrix4(od),nd.z>u&&rd.z>u)continue;if(nd.z>u){let e=nd.z-rd.z,t=(nd.z-u)/e;nd.lerp(rd,t)}else if(rd.z>u){let e=rd.z-nd.z,t=(rd.z-u)/e;rd.lerp(nd,t)}nd.applyMatrix4(r),rd.applyMatrix4(r),nd.multiplyScalar(1/nd.w),rd.multiplyScalar(1/rd.w),nd.x*=i.x/2,nd.y*=i.y/2,rd.x*=i.x/2,rd.y*=i.y/2,sd.start.copy(nd),sd.start.z=0,sd.end.copy(rd),sd.end.z=0;let o=sd.closestPointToPointParameter(ad,!0);sd.at(o,cd);let l=pt.lerp(nd.z,rd.z,o),d=l>=-1&&l<=1,f=ad.distanceTo(cd)<pd*.5;if(d&&f){sd.start.fromBufferAttribute(s,t),sd.end.fromBufferAttribute(c,t),sd.start.applyMatrix4(a),sd.end.applyMatrix4(a);let r=new B,i=new B;fd.distanceSqToSegment(sd.start,sd.end,i,r),n.push({point:i,pointOnLine:r,distance:fd.origin.distanceTo(i),object:e,face:null,faceIndex:t,uv:null,uv1:null})}}}var _d=class extends G{constructor(e=new Zu,t=new Qu({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)ed.fromBufferAttribute(t,e),td.fromBufferAttribute(n,e),r[i]=i===0?0:r[i-1],r[i+1]=r[i]+ed.distanceTo(td);let i=new $a(r,2,1);return e.setAttribute(`instanceDistanceStart`,new ui(i,1,0)),e.setAttribute(`instanceDistanceEnd`,new ui(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;fd=e.ray;let a=this.matrixWorld,o=this.geometry,s=this.material;pd=s.linewidth+i,o.boundingSphere===null&&o.computeBoundingSphere(),ud.copy(o.boundingSphere).applyMatrix4(a);let c;if(c=n?pd*.5:md(r,Math.max(r.near,ud.distanceToPoint(fd.origin)),s.resolution),ud.radius+=c,fd.intersectsSphere(ud)===!1)return;o.boundingBox===null&&o.computeBoundingBox(),ld.copy(o.boundingBox).applyMatrix4(a);let l;l=n?pd*.5:md(r,Math.max(r.near,ld.distanceToPoint(fd.origin)),s.resolution),ld.expandByScalar(l),fd.intersectsBox(ld)!==!1&&(n?hd(this,t):gd(this,r,t))}onBeforeRender(e){let t=this.material.uniforms;t&&t.resolution&&(e.getViewport($u),this.material.uniforms.resolution.value.set($u.z,$u.w))}},vd=class extends Zu{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}},yd=class extends _d{constructor(e=new vd,t=new Qu({color:Math.random()*16777215})){super(e,t),this.isLine2=!0,this.type=`Line2`}},bd=e=>{let t=new U,n=[],r=[],{isSphere:i}=e;return wu.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?Pu-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 yd(new vd().setPositions(n).setColors(r),new Qu({linewidth:e.lineWidth,vertexColors:!0,resolution:new z(window.innerWidth,window.innerHeight)})).computeLineDistances():null},xd=e=>{let{corners:t,edges:n}=e,r=[],i=zu(e),a=Uu(e,i);return r.push(...a),t.enabled&&r.push(...Wu(e,i)),n.enabled&&r.push(...Gu(e,i,t.enabled?7:6)),[r,Ju(a,e),bd(e)]},Sd=(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?Bu(n.map,t):n.color.set(a)},Cd=new gn,wd=new io,Td=new z,Ed=new B,Dd=new Lt,Od=class extends Un{constructor(e,t,n={}){super(),lu(this,`enabled`,!0),lu(this,`camera`),lu(this,`renderer`),lu(this,`options`),lu(this,`target`,new B),lu(this,`animated`,!0),lu(this,`speed`,1),lu(this,`animating`,!1),lu(this,`_options`),lu(this,`_intersections`),lu(this,`_background`,null),lu(this,`_viewport`,[0,0,0,0]),lu(this,`_originalViewport`,[0,0,0,0]),lu(this,`_originalScissor`,[0,0,0,0]),lu(this,`_scene`),lu(this,`_camera`),lu(this,`_container`),lu(this,`_domElement`),lu(this,`_domRect`),lu(this,`_dragging`,!1),lu(this,`_distance`,0),lu(this,`_clock`,new Ba),lu(this,`_targetQuaternion`,new mt),lu(this,`_quaternionStart`,new mt),lu(this,`_quaternionEnd`,new mt),lu(this,`_pointerStart`,new z),lu(this,`_focus`,null),lu(this,`_placement`),lu(this,`_controls`),lu(this,`_controlsListeners`),this.camera=e,this.renderer=t,this._scene=new si().add(this),this.set(n)}get placement(){return this._placement}set placement(e){this._placement=uu(this._domElement,e),this.domUpdate()}set(e={}){this.dispose(),this.options=e,this._options=Lu(e),this._camera=this._options.isSphere?new Pa(-1.8,1.8,1.8,-1.8,5,10):new Qr(26,1,5,10),this._camera.position.set(0,0,7);let[t,n,r]=xd(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?fu(i):document.body,this._domElement=du(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(Dd).toArray(this._originalViewport),e.getScissorTest()&&e.getScissor(Dd).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 B().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()),gu(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()*Su*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)<xu&&(this._controls&&(this._controls.enabled=!0),this.animating=!1,this.dispatchEvent({type:`end`}))}_setOrientation(e){let t=this.camera,n=this.target;Ed.copy(e).multiplyScalar(this._distance),Cd.setPosition(Ed).lookAt(Ed,this.position,this.up),this._targetQuaternion.setFromRotationMatrix(Cd),Ed.add(n),Cd.lookAt(Ed,n,this.up),this._quaternionEnd.setFromRotationMatrix(Cd),Cd.setPosition(t.position).lookAt(t.position,n,this.up),this._quaternionStart.setFromRotationMatrix(Cd),this.animating=!0,this._clock.start(),this.dispatchEvent({type:`start`})}_onPointerDown(e){if(!this.enabled)return;let t=e=>{if(!this._dragging){if(_u(e,this._pointerStart))return;this._dragging=!0}let t=Td.set(e.clientX,e.clientY).sub(this._pointerStart).multiplyScalar(1/this._domRect.width*Math.PI),n=this.coordinateConversion(Ed.subVectors(this.camera.position,this.target)),r=wd.setFromVector3(n);r.theta=a-t.x,r.phi=pu(o-t.y,xu,Math.PI-xu),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&&=(Sd(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(Ed.subVectors(this.camera.position,this.target)),i=wd.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=Un.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&&Fu(this._background,!0),this._handleHover(e))}_onPointerLeave(){!this.enabled||this._dragging||(this._background&&Fu(this._background,!1),this._focus&&Sd(this._focus,!1),this._domElement.style.cursor=``)}_handleClick(e){let t=bu(e,this._domRect,this._camera,this._intersections);this._focus&&=(Sd(this._focus,!1),null),t&&(this._setOrientation(t.object.position),this.dispatchEvent({type:`change`}))}_handleHover(e){let t=bu(e,this._domRect,this._camera,this._intersections)?.object||null;this._focus!==t&&(this._domElement.style.cursor=t?`pointer`:``,this._focus&&Sd(this._focus,!1),(this._focus=t)?Sd(t,!0):gu(this._options,this._intersections,this.camera))}},kd=class extends He{target=new B;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)}},Ad=new Set;function jd(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Md(){Nd.faceColor.set(jd(`--scene-face-color`,`#969696`)),Nd.edgeColor.set(jd(`--scene-edge-color`,`#000000`)),Nd.gridColor.set(jd(`--scene-grid-color`,`#6f6f6f`)),Nd.metaEdgeColor.set(jd(`--scene-meta-edge-color`,`#b0b0b0`)),Nd.backgroundColor.set(jd(`--color-base-100`,`#1e1e1e`))}var Nd={faceColor:new U(`#969696`),edgeColor:new U(`#000000`),gridColor:new U(`#6f6f6f`),metaEdgeColor:new U(`#b0b0b0`),backgroundColor:new U(`#1e1e1e`)};Md(),new MutationObserver(()=>{Md();for(let e of Ad)e()}).observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]});function Pd(e){return Ad.add(e),()=>Ad.delete(e)}ou.install({THREE:{Vector2:z,Vector3:B,Vector4:Lt,Quaternion:mt,Matrix4:gn,Spherical:io,Box3:Ht,Sphere:sn,Raycaster:to,MathUtils:{DEG2RAD:pt.DEG2RAD,clamp:pt.clamp}}});var Fd=new B(0,0,1),Id=120,Ld=1.1,Rd=class{scene;renderer;gizmo;orthoCamera;perspCamera;activeCamera=`orthographic`;_cc;_adapter;dirLight;renderRequested=!1;resizeObserver;clock=new Ba;animFrameId=0;gizmoWasActive=!1;constructor(e){this.container=e,Un.DEFAULT_UP=Fd.clone();let t=e.clientWidth||window.innerWidth,n=e.clientHeight||window.innerHeight;this.renderer=new vl({antialias:!0,alpha:!0}),this.renderer.setSize(t,n),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.toneMapping=4,this.renderer.outputColorSpace=Fe,this.renderer.localClippingEnabled=!0,e.appendChild(this.renderer.domElement),this.scene=new si,this.scene.background=Nd.backgroundColor.clone();let r=t/n;this.orthoCamera=new Pa(-r*Id/2,r*Id/2,Id/2,-Id/2,-1e4,1e4),this.orthoCamera.position.set(50,-50,40),this.orthoCamera.up.copy(Fd),this.orthoCamera.lookAt(0,0,0),this.perspCamera=new Qr(50,r,.5,1e4),this.perspCamera.position.set(50,-50,40),this.perspCamera.up.copy(Fd),this.perspCamera.lookAt(0,0,0),this.dirLight=new Ia(16777215,1),this.scene.add(this.dirLight),this.scene.add(new La(14544639,2.5)),this._cc=new ou(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 kd(this._cc),this.gizmo=new Od(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),Pd(()=>{this.scene.background=Nd.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 to;if(r.setFromCamera(new z(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 B),r=e.getSize(new B).length()/2;if(r===0)return;let i=new sn(n,r*Ld);this._cc.fitToSphere(i,t)}switchCamera(e){if(e===this.activeCamera)return;let t=new B,n=new B;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=pt.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 ou(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 kd(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=ou.ACTION.TOUCH_ROTATE,this._cc.touches.two=ou.ACTION.TOUCH_ZOOM_TRUCK):(this._cc.touches.one=ou.ACTION.TOUCH_ROTATE,this._cc.touches.two=ou.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),this.orthoCamera.left=-n*Id/2,this.orthoCamera.right=n*Id/2,this.orthoCamera.top=Id/2,this.orthoCamera.bottom=-Id/2,this.orthoCamera.updateProjectionMatrix(),this.perspCamera.aspect=n,this.perspCamera.updateProjectionMatrix(),this.gizmo.update(),this.requestRender()}updateLightPositions(){let e=new B;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 G{constructor(e=10,t=100,n=new U(`white`),r=8e3,i=new B(0,1,0)){let a=new aa(2,2,1,1),o=new qr({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
 
@@ -4305,7 +4305,7 @@ void main() {
4305
4305
 
4306
4306
  gl_FragColor = vec4(color, 1.0);
4307
4307
  }
4308
- `,of=class extends ii{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 Tr;i.setAttribute(`position`,new W(new Float32Array(r),3));let a=new Ui(i,new qr({uniforms:{color:{value:Nd.metaEdgeColor},dashLength:{value:$d},gapLength:{value:ef},dotLength:{value:tf},patternLength:{value:nf}},vertexShader:rf,fragmentShader:af,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},sf=`#2297ff`,cf=2,lf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let r=new qi(e,new Fi({color:sf,linewidth:cf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0}));this.add(r)}}},uf=`#2297ff`,df=`#2297ff`,ff=.15,pf=.4,mf=class extends ii{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?df:uf,r=t?pf:ff;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(t.indices),1)),e.computeBoundingBox();let a=new G(e,new dr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},hf=`#2297ff`,gf=2,_f=2,vf=16,yf=.003,bf=1.5,xf=1e-8;function Sf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var Cf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;let t=new Zi(_f,vf),n=new dr({color:hf,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let i=new Fi({color:hf,linewidth:gf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});this.add(new qi(e,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 B(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<xf)||r.push(t)}}for(let e of r){let r=new G(t,n);r.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),r.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Sf(r,e,yf),bf)),i.updateMatrixWorld(!0)},this.add(i)}}},wf={color:`#2297ff`,lineWidth:2},Tf={trim:e=>new lf(e),"pick-edge":e=>new Cf(e)};function Ef(e){let t=e.metaType?Tf[e.metaType]:void 0;return t?t(e):new of(e)}var Df={"pick-region":e=>new mf(e,!1),"pick-region-selected":e=>new mf(e,!0)};function Of(e){let t=e.metaType?Df[e.metaType]:void 0;return t?t(e):new Zd(e)}var kf=class extends ii{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=Ef(a);break;case`face`:e=Of(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new Yd(a,n?.edge??(r?wf:void 0));break;case`face`:e=new Zd(a,n?.face);break;case`solid`:e=new Qd(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}};function Af(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var jf=`#2297ff`,Mf=2,Nf=16,Pf=.003,Ff=1.5,If=15954511,Lf=64,Rf=3,zf=15954511,Bf=.35,Vf=.6,Hf=18,Uf=5,Wf=2.5,Gf=class extends ii{constructor(e,t,n,r){super(),this.buildEdges(e,t),this.buildVertices(e,t,r),n&&e.id===n&&(this.buildCursor(e,r),this.buildTangentArrow(e,r))}buildEdges(e,t){for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length))for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=Ef(e);e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let t=new Yd(e,{color:jf,lineWidth:2});e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}}buildVertices(e,t,n){let r=e.object?.plane?.normal,i=[];for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length)){for(let e of n.sceneShapes)if(!(e.isMetaShape||e.isGuide))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[n,r]of e)r===1&&i.push(new B(t.vertices[n*3],t.vertices[n*3+1],t.vertices[n*3+2]))}}let a=[];for(let e of i)a.some(t=>t.distanceToSquared(e)<1e-12)||a.push(e);let o=new Zi(Mf,Nf),s=new dr({color:jf,side:2,depthTest:!1});for(let e of a){let t=new G(o,s);t.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(t),i.position.copy(e),r&&i.lookAt(new B(e.x+r.x,e.y+r.y,e.z+r.z)),i.scale.setScalar(Math.min(Af(n,e,Pf),Ff)),t.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Af(r,e,Pf),Ff)),i.updateMatrixWorld(!0)},this.add(i)}}buildCursor(e,t){let n=e.object?.currentPosition;if(!n)return;let r=new Zi(Rf,Lf),i=new dr({color:If,side:2,depthTest:!1});i.transparent=!0,i.opacity=.8;let a=new G(r,i);a.renderOrder=1;let o=new ii;o.renderOrder=1,o.add(a),o.position.set(n.x,n.y,n.z);let s=e.object?.plane?.normal;if(s){let e=new B(n.x+s.x,n.y+s.y,n.z+s.z);o.lookAt(e)}o.scale.setScalar(Af(t,o.position,.003)),a.onBeforeRender=(e,t,n)=>{o.scale.setScalar(Af(n,o.position,.003)),o.updateMatrixWorld(!0)},this.add(o)}buildTangentArrow(e,t){let n=e.object?.currentPosition,r=e.object?.currentTangent,i=e.object?.plane?.origin;if(!n||!r||!i)return;let a=new B(r.x-i.x,r.y-i.y,r.z-i.z).normalize(),o=new dr({color:zf,transparent:!0,opacity:Bf,side:2,depthTest:!1,depthWrite:!1}),s=new Qi(Vf,Vf,Hf,16);s.translate(0,Hf/2,0);let c=new G(s,o),l=new $i(Wf,Uf,16);l.translate(0,Hf+Uf/2,0);let u=new G(l,o),d=new ii;d.renderOrder=1,d.add(c),d.add(u);let f=new B(0,1,0),p=new mt().setFromUnitVectors(f,a);d.quaternion.copy(p),d.position.set(n.x,n.y,n.z),d.scale.setScalar(Af(t,d.position,.003)),c.onBeforeRender=(e,t,n)=>{d.scale.setScalar(Af(n,d.position,.003)),d.updateMatrixWorld(!0)},this.add(d)}};function Kf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var qf=`#ffc26c`,Jf=`#c88f40`,Yf=`#c88f40`,Xf=.1,Zf=20,Qf=3,$f=1.5,ep=.4,tp=class extends ii{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 Tr;a.setAttribute(`position`,new W(new Float32Array(n.vertices),3)),a.setAttribute(`normal`,new W(new Float32Array(n.normals),3)),a.setIndex(new W(new Uint16Array(n.indices),1)),a.computeBoundingBox();let o=new G(a,new dr({color:qf,transparent:!0,opacity:Xf,side:2,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}));this.add(o);let s=new qi(new ia(a,18),new Fi({color:Jf,linewidth:1}));this.add(s);let c=new B(r.x,r.y,r.z).normalize(),l=new B(i.x,i.y,i.z),u=new dr({color:Yf}),d=Zf-Qf,f=new Qi(ep,ep,d,8);f.translate(0,d/2,0);let p=new G(f,u),m=new $i($f,Qf,8);m.translate(0,d+Qf/2,0);let h=new G(m,u),g=new ii;g.add(p),g.add(h);let _=new B(0,1,0),v=new mt().setFromUnitVectors(_,c);g.quaternion.copy(v),g.position.copy(l),g.scale.setScalar(Kf(t,g.position,.006)),p.onBeforeRender=(e,t,n)=>{g.scale.setScalar(Kf(n,g.position,.006)),g.updateMatrixWorld(!0)},this.add(g),this.position.z=.01}},np=`#c88f40`,rp=class extends ii{constructor(e){super();let t=e.sceneShapes[0]?.meshes[0];if(!t)return;let n=new Tr;n.setAttribute(`position`,new W(new Float32Array(t.vertices),3));let r=new qi(n,new fa({color:np,dashSize:5,gapSize:5}));r.computeLineDistances(),this.add(r)}},ip={edge:{color:`#11a4ed`,lineWidth:3,depthWrite:!1},face:{color:`#5c9fcc`,opacity:1}},ap={edge:{opacity:.3},face:{opacity:.3}};function op(e,t,n,r){if(r)return r;if(e===`select`)return ip;if(t&&n!==`sketch`)return ap}function sp(e,t,n,r,i,a){switch(e.type){case`sketch`:return new Gf(e,t,n,r);case`plane`:return new tp(e,r);case`axis`:return new rp(e)}let o=e.uniqueType===`select`,s=op(e.uniqueType,n,e.type,a),c=t.filter(t=>t.parentId===e.id),l;if(c.length>0){let e=new ii;for(let a of c)e.add(sp(a,t,n,r,i,s));l=e}else l=new kf(e,i,s);return o&&l.traverse(e=>{e.renderOrder=999}),l}function cp(e,t,n,r=!1){let i=new ii;i.name=`compiledMesh`;for(let a of e)a.parentId||!a.visible&&!(t&&a.type===`sketch`)||i.add(sp(a,e,t,n,r));let a=new Map,o=0;for(let t of e)if(t.sceneShapes)for(let e of t.sceneShapes)e.isMetaShape||(e.shapeId&&a.set(e.shapeId,o),o++);return i.traverse(e=>{let t=e.userData.shapeId;t&&a.has(t)&&(e.userData.shapeIndex=a.get(t))}),i}var lp=`/api/preferences`;async function up(){try{let e=await fetch(lp);return e.ok?await e.json():null}catch{return null}}function dp(e,t){fetch(lp,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({[e]:t})}).catch(()=>{})}var fp=`<svg
4308
+ `,of=class extends ii{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 Tr;i.setAttribute(`position`,new W(new Float32Array(r),3));let a=new Ui(i,new qr({uniforms:{color:{value:Nd.metaEdgeColor},dashLength:{value:$d},gapLength:{value:ef},dotLength:{value:tf},patternLength:{value:nf}},vertexShader:rf,fragmentShader:af,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},sf=`#2297ff`,cf=2,lf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let r=new qi(e,new Fi({color:sf,linewidth:cf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0}));this.add(r)}}},uf=`#2297ff`,df=`#2297ff`,ff=.15,pf=.4,mf=class extends ii{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?df:uf,r=t?pf:ff;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(t.indices),1)),e.computeBoundingBox();let a=new G(e,new dr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},hf=`#2297ff`,gf=2,_f=2,vf=16,yf=.003,bf=1.5,xf=1e-8;function Sf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var Cf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;let t=new Zi(_f,vf),n=new dr({color:hf,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let i=new Fi({color:hf,linewidth:gf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});this.add(new qi(e,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 B(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<xf)||r.push(t)}}for(let e of r){let r=new G(t,n);r.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),r.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Sf(r,e,yf),bf)),i.updateMatrixWorld(!0)},this.add(i)}}},wf={color:`#2297ff`,lineWidth:2},Tf={trim:e=>new lf(e),"pick-edge":e=>new Cf(e)};function Ef(e){let t=e.metaType?Tf[e.metaType]:void 0;return t?t(e):new of(e)}var Df={"pick-region":e=>new mf(e,!1),"pick-region-selected":e=>new mf(e,!0)};function Of(e){let t=e.metaType?Df[e.metaType]:void 0;return t?t(e):new Zd(e)}var kf=class extends ii{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=Ef(a);break;case`face`:e=Of(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new Yd(a,n?.edge??(r?wf:void 0));break;case`face`:e=new Zd(a,n?.face);break;case`solid`:e=new Qd(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}};function Af(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var jf=`#2297ff`,Mf=2,Nf=16,Pf=.003,Ff=1.5,If=15954511,Lf=64,Rf=3,zf=15954511,Bf=.35,Vf=.6,Hf=18,Uf=5,Wf=2.5,Gf=class extends ii{constructor(e,t,n,r){super(),this.userData.isSketchRoot=!0,this.buildEdges(e,t),this.buildVertices(e,t,r),n&&e.id===n&&(this.buildCursor(e,r),this.buildTangentArrow(e,r))}buildEdges(e,t){for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length))for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=Ef(e);e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let t=new Yd(e,{color:jf,lineWidth:2});e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}}buildVertices(e,t,n){let r=e.object?.plane?.normal,i=[];for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length)){for(let e of n.sceneShapes)if(!(e.isMetaShape||e.isGuide))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[n,r]of e)r===1&&i.push(new B(t.vertices[n*3],t.vertices[n*3+1],t.vertices[n*3+2]))}}let a=[];for(let e of i)a.some(t=>t.distanceToSquared(e)<1e-12)||a.push(e);let o=new Zi(Mf,Nf),s=new dr({color:jf,side:2,depthTest:!1});for(let e of a){let t=new G(o,s);t.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(t),i.position.copy(e),r&&i.lookAt(new B(e.x+r.x,e.y+r.y,e.z+r.z)),i.scale.setScalar(Math.min(Af(n,e,Pf),Ff)),t.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Af(r,e,Pf),Ff)),i.updateMatrixWorld(!0)},this.add(i)}}buildCursor(e,t){let n=e.object?.currentPosition;if(!n)return;let r=new Zi(Rf,Lf),i=new dr({color:If,side:2,depthTest:!1});i.transparent=!0,i.opacity=.8;let a=new G(r,i);a.renderOrder=1;let o=new ii;o.renderOrder=1,o.add(a),o.position.set(n.x,n.y,n.z);let s=e.object?.plane?.normal;if(s){let e=new B(n.x+s.x,n.y+s.y,n.z+s.z);o.lookAt(e)}o.scale.setScalar(Af(t,o.position,.003)),a.onBeforeRender=(e,t,n)=>{o.scale.setScalar(Af(n,o.position,.003)),o.updateMatrixWorld(!0)},this.add(o)}buildTangentArrow(e,t){let n=e.object?.currentPosition,r=e.object?.currentTangent,i=e.object?.plane?.origin;if(!n||!r||!i)return;let a=new B(r.x-i.x,r.y-i.y,r.z-i.z).normalize(),o=new dr({color:zf,transparent:!0,opacity:Bf,side:2,depthTest:!1,depthWrite:!1}),s=new Qi(Vf,Vf,Hf,16);s.translate(0,Hf/2,0);let c=new G(s,o),l=new $i(Wf,Uf,16);l.translate(0,Hf+Uf/2,0);let u=new G(l,o),d=new ii;d.renderOrder=1,d.add(c),d.add(u);let f=new B(0,1,0),p=new mt().setFromUnitVectors(f,a);d.quaternion.copy(p),d.position.set(n.x,n.y,n.z),d.scale.setScalar(Af(t,d.position,.003)),c.onBeforeRender=(e,t,n)=>{d.scale.setScalar(Af(n,d.position,.003)),d.updateMatrixWorld(!0)},this.add(d)}};function Kf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var qf=`#ffc26c`,Jf=`#c88f40`,Yf=`#c88f40`,Xf=.1,Zf=20,Qf=3,$f=1.5,ep=.4,tp=class extends ii{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 Tr;a.setAttribute(`position`,new W(new Float32Array(n.vertices),3)),a.setAttribute(`normal`,new W(new Float32Array(n.normals),3)),a.setIndex(new W(new Uint16Array(n.indices),1)),a.computeBoundingBox();let o=new G(a,new dr({color:qf,transparent:!0,opacity:Xf,side:2,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}));this.add(o);let s=new qi(new ia(a,18),new Fi({color:Jf,linewidth:1}));this.add(s);let c=new B(r.x,r.y,r.z).normalize(),l=new B(i.x,i.y,i.z),u=new dr({color:Yf}),d=Zf-Qf,f=new Qi(ep,ep,d,8);f.translate(0,d/2,0);let p=new G(f,u),m=new $i($f,Qf,8);m.translate(0,d+Qf/2,0);let h=new G(m,u),g=new ii;g.add(p),g.add(h);let _=new B(0,1,0),v=new mt().setFromUnitVectors(_,c);g.quaternion.copy(v),g.position.copy(l),g.scale.setScalar(Kf(t,g.position,.006)),p.onBeforeRender=(e,t,n)=>{g.scale.setScalar(Kf(n,g.position,.006)),g.updateMatrixWorld(!0)},this.add(g),this.position.z=.01}},np=`#c88f40`,rp=class extends ii{constructor(e){super();let t=e.sceneShapes[0]?.meshes[0];if(!t)return;let n=new Tr;n.setAttribute(`position`,new W(new Float32Array(t.vertices),3));let r=new qi(n,new fa({color:np,dashSize:5,gapSize:5}));r.computeLineDistances(),this.add(r)}},ip={edge:{color:`#11a4ed`,lineWidth:3,depthWrite:!1},face:{color:`#5c9fcc`,opacity:1}};function ap(e,t){if(t)return t;if(e===`select`)return ip}function op(e,t,n,r,i,a){switch(e.type){case`sketch`:return new Gf(e,t,n,r);case`plane`:return new tp(e,r);case`axis`:return new rp(e)}let o=e.uniqueType===`select`,s=ap(e.uniqueType,a),c=t.filter(t=>t.parentId===e.id),l;if(c.length>0){let e=new ii;for(let a of c)e.add(op(a,t,n,r,i,s));l=e}else l=new kf(e,i,s);return o&&l.traverse(e=>{e.renderOrder=999}),l}function sp(e,t,n,r=!1){let i=new ii;i.name=`compiledMesh`;for(let a of e)a.parentId||!a.visible&&!(t&&a.type===`sketch`)||i.add(op(a,e,t,n,r));let a=new Map,o=0;for(let t of e)if(t.sceneShapes)for(let e of t.sceneShapes)e.isMetaShape||(e.shapeId&&a.set(e.shapeId,o),o++);return i.traverse(e=>{let t=e.userData.shapeId;t&&a.has(t)&&(e.userData.shapeIndex=a.get(t))}),i}var cp=`/api/preferences`;async function lp(){try{let e=await fetch(cp);return e.ok?await e.json():null}catch{return null}}function up(e,t){fetch(cp,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({[e]:t})}).catch(()=>{})}var dp=`<svg
4309
4309
  xmlns="http://www.w3.org/2000/svg"
4310
4310
  width="24"
4311
4311
  height="24"
@@ -4323,7 +4323,7 @@ void main() {
4323
4323
  <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" />
4324
4324
  <path d="M10 7h-7" />
4325
4325
  <path d="M21 7h-7" />
4326
- </svg>`,pp=`<svg
4326
+ </svg>`,fp=`<svg
4327
4327
  xmlns="http://www.w3.org/2000/svg"
4328
4328
  width="24"
4329
4329
  height="24"
@@ -4338,7 +4338,7 @@ void main() {
4338
4338
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4339
4339
  <path d="M8.511 4.502l9.63 1.375a1 1 0 0 1 .859 .99v8.133m-.859 3.123l-12 1.714a1 1 0 0 1 -1.141 -.99v-13.694a1 1 0 0 1 .01 -.137" />
4340
4340
  <path d="M3 3l18 18" />
4341
- </svg>`,mp=`<svg
4341
+ </svg>`,pp=`<svg
4342
4342
  xmlns="http://www.w3.org/2000/svg"
4343
4343
  width="24"
4344
4344
  height="24"
@@ -4352,7 +4352,7 @@ void main() {
4352
4352
  >
4353
4353
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4354
4354
  <path d="M6.141 4.163l12 1.714a1 1 0 0 1 .859 .99v10.266a1 1 0 0 1 -.859 .99l-12 1.714a1 1 0 0 1 -1.141 -.99v-13.694a1 1 0 0 1 1.141 -.99" />
4355
- </svg>`,hp=`<svg
4355
+ </svg>`,mp=`<svg
4356
4356
  xmlns="http://www.w3.org/2000/svg"
4357
4357
  width="24"
4358
4358
  height="24"
@@ -4371,7 +4371,7 @@ void main() {
4371
4371
  <path d="M6 3v18" />
4372
4372
  <path d="M12 3v18" />
4373
4373
  <path d="M18 3v18" />
4374
- </svg>`,gp=`<svg
4374
+ </svg>`,hp=`<svg
4375
4375
  xmlns="http://www.w3.org/2000/svg"
4376
4376
  width="24"
4377
4377
  height="24"
@@ -4389,7 +4389,7 @@ void main() {
4389
4389
  <path d="M12 3l0 17" />
4390
4390
  <path d="M9 12l-3 -6l-3 6a3 3 0 0 0 6 0" />
4391
4391
  <path d="M21 12l-3 -6l-3 6a3 3 0 0 0 6 0" />
4392
- </svg>`,_p=`<svg
4392
+ </svg>`,gp=`<svg
4393
4393
  xmlns="http://www.w3.org/2000/svg"
4394
4394
  width="24"
4395
4395
  height="24"
@@ -4406,7 +4406,7 @@ void main() {
4406
4406
  <path d="M3 17a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
4407
4407
  <path d="M8.6 8.6l10.4 10.4" />
4408
4408
  <path d="M8.6 15.4l10.4 -10.4" />
4409
- </svg>`,vp=`<svg
4409
+ </svg>`,_p=`<svg
4410
4410
  xmlns="http://www.w3.org/2000/svg"
4411
4411
  width="24"
4412
4412
  height="24"
@@ -4421,7 +4421,7 @@ void main() {
4421
4421
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4422
4422
  <path d="M14 3v4a1 1 0 0 0 1 1h4" />
4423
4423
  <path d="M5 13v-8a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2h-5.5m-9.5 -2h7m-3 -3l3 3l-3 3" />
4424
- </svg>`,yp=`<svg
4424
+ </svg>`,vp=`<svg
4425
4425
  xmlns="http://www.w3.org/2000/svg"
4426
4426
  width="24"
4427
4427
  height="24"
@@ -4436,7 +4436,7 @@ void main() {
4436
4436
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4437
4437
  <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" />
4438
4438
  <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" />
4439
- </svg>`,bp=`<svg
4439
+ </svg>`,yp=`<svg
4440
4440
  xmlns="http://www.w3.org/2000/svg"
4441
4441
  width="24"
4442
4442
  height="24"
@@ -4451,7 +4451,7 @@ void main() {
4451
4451
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4452
4452
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
4453
4453
  <path d="M9 12l2 2l4 -4" />
4454
- </svg>`,xp=`<svg
4454
+ </svg>`,bp=`<svg
4455
4455
  xmlns="http://www.w3.org/2000/svg"
4456
4456
  width="24"
4457
4457
  height="24"
@@ -4466,7 +4466,7 @@ void main() {
4466
4466
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4467
4467
  <path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
4468
4468
  <path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
4469
- </svg>`,Sp=`<svg
4469
+ </svg>`,xp=`<svg
4470
4470
  xmlns="http://www.w3.org/2000/svg"
4471
4471
  width="24"
4472
4472
  height="24"
@@ -4483,7 +4483,7 @@ void main() {
4483
4483
  <path d="M15 6l3 3" />
4484
4484
  <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" />
4485
4485
  <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" />
4486
- </svg>`,Cp=`<svg
4486
+ </svg>`,Sp=`<svg
4487
4487
  xmlns="http://www.w3.org/2000/svg"
4488
4488
  width="24"
4489
4489
  height="24"
@@ -4498,7 +4498,7 @@ void main() {
4498
4498
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4499
4499
  <path d="M8 12a4 4 0 1 0 8 0a4 4 0 1 0 -8 0" />
4500
4500
  <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" />
4501
- </svg>`,wp=`<svg
4501
+ </svg>`,Cp=`<svg
4502
4502
  xmlns="http://www.w3.org/2000/svg"
4503
4503
  width="24"
4504
4504
  height="24"
@@ -4512,7 +4512,7 @@ void main() {
4512
4512
  >
4513
4513
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4514
4514
  <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" />
4515
- </svg>`,Tp=`<svg
4515
+ </svg>`,wp=`<svg
4516
4516
  xmlns="http://www.w3.org/2000/svg"
4517
4517
  width="24"
4518
4518
  height="24"
@@ -4527,7 +4527,7 @@ void main() {
4527
4527
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4528
4528
  <path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
4529
4529
  <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" />
4530
- </svg>`,Ep=`<svg
4530
+ </svg>`,Tp=`<svg
4531
4531
  xmlns="http://www.w3.org/2000/svg"
4532
4532
  width="24"
4533
4533
  height="24"
@@ -4543,7 +4543,7 @@ void main() {
4543
4543
  <path d="M10.585 10.587a2 2 0 0 0 2.829 2.828" />
4544
4544
  <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" />
4545
4545
  <path d="M3 3l18 18" />
4546
- </svg>`,Dp=`<svg
4546
+ </svg>`,Ep=`<svg
4547
4547
  xmlns="http://www.w3.org/2000/svg"
4548
4548
  width="24"
4549
4549
  height="24"
@@ -4561,7 +4561,7 @@ void main() {
4561
4561
  <path d="M12 14l7 -7" />
4562
4562
  <path d="M12 19l8.5 -8.5" />
4563
4563
  <path d="M12 9l4.5 -4.5" />
4564
- </svg>`,Op=`<svg
4564
+ </svg>`,Dp=`<svg
4565
4565
  xmlns="http://www.w3.org/2000/svg"
4566
4566
  width="24"
4567
4567
  height="24"
@@ -4576,16 +4576,16 @@ void main() {
4576
4576
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
4577
4577
  <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" />
4578
4578
  <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" />
4579
- </svg>`,kp=fp,Ap=pp,jp=mp,Mp=hp,Np=gp,Pp=_p,Fp=vp,Ip=yp,Lp=bp,Rp=xp,zp=Sp,Bp=Cp,Vp=wp,Hp=Tp,Up=Ep,Wp=Dp,Gp=Op,Kp=`btn btn-ghost btn-square btn-sm text-base-content/60`,qp=`btn btn-soft btn-primary btn-square btn-sm`;function Jp(){return document.documentElement.getAttribute(`data-theme`)||`fluidcad-dark`}function Yp(){return Jp()!==`fluidcad-light`}var Xp=class{el;sectionViewEl;onFitView=null;onSectionViewToggle=null;constructor(e,t){this.onCameraSwitch=t;let n=document.createElement(`div`);n.className=`absolute right-6 top-1/2 -translate-y-1/2 z-[100] flex flex-col items-end gap-2 select-none`,e.appendChild(n),this.sectionViewEl=document.createElement(`div`),this.sectionViewEl.className=`panel-bg border border-base-content/10 rounded-md p-1`,this.sectionViewEl.style.display=`none`,this.sectionViewEl.innerHTML=`<button class="${qp}" data-action="section-view" title="Toggle section view">${Wp}</button>`,n.appendChild(this.sectionViewEl),this.el=document.createElement(`div`),this.el.className=`flex flex-col gap-0.5 panel-bg border border-base-content/10 rounded-md p-1`,this.el.innerHTML=this.buildHTML(),n.appendChild(this.el),this.bindEvents(),Vd.subscribe(()=>this.sync())}buildHTML(){let e=Vd.current,t=Yp()?Bp:Vp,n=Yp()?`Switch to light theme`:`Switch to dark theme`;return`
4580
- <button class="${Kp}" data-action="fit" title="Fit to view">${kp}</button>
4579
+ </svg>`,Op=dp,kp=fp,Ap=pp,jp=mp,Mp=hp,Np=gp,Pp=_p,Fp=vp,Ip=yp,Lp=bp,Rp=xp,zp=Sp,Bp=Cp,Vp=wp,Hp=Tp,Up=Ep,Wp=Dp,Gp=`btn btn-ghost btn-square btn-sm text-base-content/60`,Kp=`btn btn-soft btn-primary btn-square btn-sm`;function qp(){return document.documentElement.getAttribute(`data-theme`)||`fluidcad-dark`}function Jp(){return qp()!==`fluidcad-light`}var Yp=class{el;sectionViewEl;onFitView=null;onSectionViewToggle=null;constructor(e,t){this.onCameraSwitch=t;let n=document.createElement(`div`);n.className=`absolute right-6 top-1/2 -translate-y-1/2 z-[100] flex flex-col items-end gap-2 select-none`,e.appendChild(n),this.sectionViewEl=document.createElement(`div`),this.sectionViewEl.className=`panel-bg border border-base-content/10 rounded-md p-1`,this.sectionViewEl.style.display=`none`,this.sectionViewEl.innerHTML=`<button class="${Kp}" data-action="section-view" title="Toggle section view">${Up}</button>`,n.appendChild(this.sectionViewEl),this.el=document.createElement(`div`),this.el.className=`flex flex-col gap-0.5 panel-bg border border-base-content/10 rounded-md p-1`,this.el.innerHTML=this.buildHTML(),n.appendChild(this.el),this.bindEvents(),Vd.subscribe(()=>this.sync())}buildHTML(){let e=Vd.current,t=Jp()?zp:Bp,n=Jp()?`Switch to light theme`:`Switch to dark theme`;return`
4580
+ <button class="${Gp}" data-action="fit" title="Fit to view">${Op}</button>
4581
4581
  <div class="h-px bg-base-content/[0.08] my-0.5"></div>
4582
- <button class="${Kp} ${e.cameraMode===`orthographic`?qp:``}" data-mode="orthographic" title="Orthographic projection">${Ap}</button>
4583
- <button class="${Kp} ${e.cameraMode===`perspective`?qp:``}" data-mode="perspective" title="Perspective projection">${jp}</button>
4582
+ <button class="${Gp} ${e.cameraMode===`orthographic`?Kp:``}" data-mode="orthographic" title="Orthographic projection">${kp}</button>
4583
+ <button class="${Gp} ${e.cameraMode===`perspective`?Kp:``}" data-mode="perspective" title="Perspective projection">${Ap}</button>
4584
4584
  <div class="h-px bg-base-content/[0.08] my-0.5"></div>
4585
- <button class="${Kp} ${e.showGrid?qp:``}" data-action="grid" title="Toggle grid">${Mp}</button>
4585
+ <button class="${Gp} ${e.showGrid?Kp:``}" data-action="grid" title="Toggle grid">${jp}</button>
4586
4586
  <div class="h-px bg-base-content/[0.08] my-0.5"></div>
4587
- <button class="${Kp}" data-action="theme" title="${n}">${t}</button>
4588
- `}bindEvents(){this.el.querySelector(`[data-action="fit"]`)?.addEventListener(`click`,()=>{this.onFitView?.()}),this.el.querySelectorAll(`[data-mode]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.mode;Vd.update({cameraMode:t}),dp(`cameraMode`,t),this.onCameraSwitch(t)})}),this.el.querySelector(`[data-action="grid"]`)?.addEventListener(`click`,()=>{let e=!Vd.current.showGrid;Vd.update({showGrid:e}),dp(`showGrid`,e)}),this.sectionViewEl.querySelector(`[data-action="section-view"]`)?.addEventListener(`click`,()=>{let e=!Vd.current.sectionView;Vd.update({sectionView:e}),this.onSectionViewToggle?.(e)}),this.el.querySelector(`[data-action="theme"]`)?.addEventListener(`click`,()=>{let e=Yp()?`fluidcad-light`:`fluidcad-dark`;document.documentElement.setAttribute(`data-theme`,e),this.syncThemeButton(),dp(`theme`,e)})}setFitHandler(e){this.onFitView=e}setFitButtonVisible(e){let t=this.el.querySelector(`[data-action="fit"]`);t&&(t.style.display=e?``:`none`);let n=this.el.querySelector(`.h-px`);n&&(n.style.display=e?``:`none`)}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?qp:Kp)}setProjectionLocked(e){this.el.querySelectorAll(`[data-mode]`).forEach(t=>{t.disabled=e})}syncThemeButton(){let e=this.el.querySelector(`[data-action="theme"]`);e&&(e.innerHTML=Yp()?Bp:Vp,e.title=Yp()?`Switch to light theme`:`Switch to dark theme`)}sync(){let e=Vd.current;this.el.querySelectorAll(`[data-mode]`).forEach(t=>{t.className=t.dataset.mode===e.cameraMode?qp:Kp});let t=this.el.querySelector(`[data-action="grid"]`);if(t&&(t.className=e.showGrid?qp:Kp),this.sectionViewEl.style.display!==`none`){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e.sectionView?qp:Kp)}}},Zp=class{mesh=null;show(e,t,n){this.clear(e);let r=new G(new oa(n,16,16),new dr({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 Qp(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)Qp(e,n)}var $p=`#ffc578`,em=`#ffc578`,tm=`#64B5F6`,nm=`#64B5F6`,rm=.3,im=class{ctx;modeManager;settingsPanel;sceneObjects=[];highlightedShapeId=null;faceHighlightMeshes=[];hasRendered=!1;lastFitBox=null;isTrimming=!1;isRegionPicking=!1;isBezierDrawing=!1;selectionHandler=null;centroidIndicator=new Zp;hoverState=null;hoverFaceOverlayMeshes=[];hoverRafId=null;isMouseDown=!1;highlightedSub=null;activeSketchId=null;hiddenShapeIndices=new Set;shapeOpacities=new Map;constructor(e){let t=document.getElementById(e);this.ctx=new Rd(t),this.modeManager=new qd(this.ctx),this.settingsPanel=new Xp(t,e=>this.ctx.switchCamera(e)),this.settingsPanel.setFitHandler(()=>this.fitViewToScene()),Vd.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}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.isBezierDrawing||this.modeManager.isSketchMode)return;let r=e.clientX-t,i=e.clientY-n;if(r*r+i*i>64)return;this.clearHover();let a=this.pickAt(e.clientX,e.clientY);a?this.selectionHandler(a.shapeId,a.sub):this.selectionHandler(null,null)})}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=new to;o.setFromCamera(new z(i,a),n),o.params.Line={threshold:this.computeEdgePickThreshold()};let s=[],c=[];this.ctx.scene.traverse(e=>{e.userData.isMetaShape||(e.isMesh&&e.userData.faceMapping?s.push(e):e.isLine&&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 B;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 B,_=new B;for(let e of u){let t=e.object.geometry,n=t.getAttribute(`position`),r=t.getIndex();if(r!==null&&e.faceIndex!=null){let t=r.getX(e.faceIndex*2),i=r.getX(e.faceIndex*2+1),a=new B().fromBufferAttribute(n,t).applyMatrix4(e.object.matrixWorld),s=new B().fromBufferAttribute(n,i).applyMatrix4(e.object.matrixWorld);o.ray.distanceSqToSegment(a,s,void 0,g)}else g.copy(e.point);if(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){if(this.sceneObjects=e,this.highlightedShapeId=null,this.highlightedSub=null,this.hoverState=null,this.hoverFaceOverlayMeshes=[],this.ctx.renderer.domElement.style.cursor=``,this.removeCompiledMesh(),!t){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 n=cp(e,this.activeSketchId,this.ctx.camera,this.isRegionPicking);if(this.ctx.scene.add(n),this.applyHiddenShapes(),this.applyShapeOpacities(),this.settingsPanel.setSectionViewVisible(this.modeManager.isSketchMode),this.modeManager.isSketchMode&&(this.settingsPanel.setSectionViewActive(Vd.current.sectionView),Vd.current.sectionView&&this.applySectionView()),!this.hasRendered||this.modeManager.isSketchMode&&!t&&!this.isTrimming&&!this.isRegionPicking&&!this.isBezierDrawing){let e=new Ht;Qp(e,n),!e.isEmpty()&&!this.isBoxContained(e)&&(this.ctx.fitToBox(e,!0),this.lastFitBox=e.clone(),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=>{e.material&&(r&&e instanceof G?(e.userData.originalColor=e.material.color.getHex(),e.material.color.set($p)):!r&&e instanceof qi&&(e.userData.originalColor=e.material.color.getHex(),e.material.color.set(em),e.material.opacity<1&&(e.userData.originalOpacity=e.material.opacity,e.material.opacity=1)))}),this.highlightedShapeId=e,this.highlightedSub=null,this.ctx.render()}clearHighlight(){if(!(!this.highlightedShapeId&&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)});for(let e of this.faceHighlightMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.faceHighlightMeshes=[],this.highlightedShapeId=null,this.highlightedSub=null,this.ctx.render()}}highlightFace(e,t){this.clearHighlight(),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 Tr;f.setAttribute(`position`,new W(new Float32Array(d),3));let p=new G(f,new la({color:$p,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.faceHighlightMeshes.push(p)}),this.highlightedShapeId=e,this.highlightedSub={type:`face`,index:t},this.ctx.render()}highlightEdge(e,t){this.clearHighlight(),this.ctx.scene.traverse(n=>{if(!n.isLine||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=n.material.color.getHex(),n.material.color.set(em))}),this.highlightedShapeId=e,this.highlightedSub={type:`edge`,index:t},this.ctx.render()}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.isBezierDrawing||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.highlightedShapeId===n.shapeId&&this.highlightedSub?.type===n.sub?.type&&this.highlightedSub?.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)}),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 Tr;f.setAttribute(`position`,new W(new Float32Array(d),3));let p=new G(f,new la({color:tm,transparent:!0,opacity:rm,depthWrite:!1,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.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(nm))}),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 B;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 Ht;if(Qp(t,e),!t.isEmpty())return t.getSize(new B).length()*.015}return 2}fitViewToScene(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=new Ht;Qp(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&&(n.visible||n.type===`sketch`)||n.parentId&&(n.visible||n.type===`sketch`)&&e.find(e=>e.id===n.parentId)?.type===`part`)return n}}isBoxContained(e){if(!this.lastFitBox)return!1;let t=this.lastFitBox.getCenter(new B),n=this.lastFitBox.getSize(new B).length()/2*Ld;if(n===0)return!1;let r=e.getCenter(new B),i=e.getSize(new B).length()/2;return t.distanceTo(r)+i<=n}rebuildSceneMesh(){if(!this.sceneObjects)return;this.removeCompiledMesh();let e=cp(this.sceneObjects,this.activeSketchId,this.ctx.camera,this.isRegionPicking);this.ctx.scene.add(e),this.applyHiddenShapes(),this.applyShapeOpacities(),this.modeManager.isSketchMode&&Vd.current.sectionView&&this.applySectionView(),this.ctx.requestRender()}setShapeVisibility(e,t){let n=this.findShapeIndexForId(e);n!==void 0&&(t?this.hiddenShapeIndices.delete(n):this.hiddenShapeIndices.add(n),this.applyVisibilityForIndex(n,t),this.ctx.requestRender())}isShapeHidden(e){let t=this.findShapeIndexForId(e);return t===void 0?!1:this.hiddenShapeIndices.has(t)}applyVisibilityForIndex(e,t){this.ctx.scene.traverse(n=>{n.userData.shapeIndex===e&&(n.visible=t)})}setShapeTransparency(e,t){let n=this.findShapeIndexForId(e);n!==void 0&&(t>=1?this.shapeOpacities.delete(n):this.shapeOpacities.set(n,t),this.applyOpacityForIndex(n,t),this.ctx.requestRender())}getShapeTransparency(e){let t=this.findShapeIndexForId(e);return t===void 0?1:this.shapeOpacities.get(t)??1}findShapeIndexForId(e){let t;return this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&typeof n.userData.shapeIndex==`number`&&(t=n.userData.shapeIndex)}),t}applyOpacityForIndex(e,t){let n=[];this.ctx.scene.traverse(t=>{t.userData.shapeIndex===e&&n.push(t)});for(let e of n)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})}applyShapeOpacities(){for(let[e,t]of this.shapeOpacities)this.applyOpacityForIndex(e,t)}applyHiddenShapes(){for(let e of this.hiddenShapeIndices)this.applyVisibilityForIndex(e,!1)}applySectionView(){let e=this.modeManager.sectionPlane;if(!e)return;let t=this.ctx.scene.getObjectByName(`compiledMesh`);t&&(t.traverse(t=>{let n=t.material;if(!n)return;let r=Array.isArray(n)?n:[n];for(let t of r)t.clippingPlanes=[e]}),this.ctx.requestRender())}clearSectionView(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(e.traverse(e=>{let t=e.material;if(!t)return;let n=Array.isArray(t)?t:[t];for(let e of n)e.clippingPlanes=[]}),this.ctx.requestRender())}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 am(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 om(e){switch(e){case`inch`:return`in`;case`foot`:return`ft`;case`yard`:return`yd`;case`meter`:return`m`;default:return`mm`}}function sm(e,t,n){let r=t===`kg`?1e3:t===`lbs`?453.592:1;return e*am(n)/r}function cm(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 lm(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 um(e){return e===0?`0`:parseFloat(e.toPrecision(6)).toString()}var dm=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=Np,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`
4587
+ <button class="${Gp}" data-action="theme" title="${n}">${t}</button>
4588
+ `}bindEvents(){this.el.querySelector(`[data-action="fit"]`)?.addEventListener(`click`,()=>{this.onFitView?.()}),this.el.querySelectorAll(`[data-mode]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.mode;Vd.update({cameraMode:t}),up(`cameraMode`,t),this.onCameraSwitch(t)})}),this.el.querySelector(`[data-action="grid"]`)?.addEventListener(`click`,()=>{let e=!Vd.current.showGrid;Vd.update({showGrid:e}),up(`showGrid`,e)}),this.sectionViewEl.querySelector(`[data-action="section-view"]`)?.addEventListener(`click`,()=>{let e=!Vd.current.sectionView;Vd.update({sectionView:e}),this.onSectionViewToggle?.(e)}),this.el.querySelector(`[data-action="theme"]`)?.addEventListener(`click`,()=>{let e=Jp()?`fluidcad-light`:`fluidcad-dark`;document.documentElement.setAttribute(`data-theme`,e),this.syncThemeButton(),up(`theme`,e)})}setFitHandler(e){this.onFitView=e}setFitButtonVisible(e){let t=this.el.querySelector(`[data-action="fit"]`);t&&(t.style.display=e?``:`none`);let n=this.el.querySelector(`.h-px`);n&&(n.style.display=e?``:`none`)}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?Kp:Gp)}setProjectionLocked(e){this.el.querySelectorAll(`[data-mode]`).forEach(t=>{t.disabled=e})}syncThemeButton(){let e=this.el.querySelector(`[data-action="theme"]`);e&&(e.innerHTML=Jp()?zp:Bp,e.title=Jp()?`Switch to light theme`:`Switch to dark theme`)}sync(){let e=Vd.current;this.el.querySelectorAll(`[data-mode]`).forEach(t=>{t.className=t.dataset.mode===e.cameraMode?Kp:Gp});let t=this.el.querySelector(`[data-action="grid"]`);if(t&&(t.className=e.showGrid?Kp:Gp),this.sectionViewEl.style.display!==`none`){let t=this.sectionViewEl.querySelector(`[data-action="section-view"]`);t&&(t.className=e.sectionView?Kp:Gp)}}},Xp=class{mesh=null;show(e,t,n){this.clear(e);let r=new G(new oa(n,16,16),new dr({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 Zp(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)Zp(e,n)}var Qp=`#ffc578`,$p=`#ffc578`,em=`#64B5F6`,tm=`#64B5F6`,nm=.3,rm=.75,im=class{ctx;modeManager;settingsPanel;sceneObjects=[];highlightedShapeId=null;faceHighlightMeshes=[];hasRendered=!1;lastFitBox=null;isTrimming=!1;isRegionPicking=!1;isBezierDrawing=!1;selectionHandler=null;centroidIndicator=new Xp;hoverState=null;hoverFaceOverlayMeshes=[];hoverRafId=null;isMouseDown=!1;highlightedSub=null;activeSketchId=null;hiddenShapeIndices=new Set;shapeOpacities=new Map;constructor(e){let t=document.getElementById(e);this.ctx=new Rd(t),this.modeManager=new qd(this.ctx),this.settingsPanel=new Yp(t,e=>this.ctx.switchCamera(e)),this.settingsPanel.setFitHandler(()=>this.fitViewToScene()),Vd.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}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.isBezierDrawing||this.modeManager.isSketchMode)return;let r=e.clientX-t,i=e.clientY-n;if(r*r+i*i>64)return;this.clearHover();let a=this.pickAt(e.clientX,e.clientY);a?this.selectionHandler(a.shapeId,a.sub):this.selectionHandler(null,null)})}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()};let s=[],c=[];this.ctx.scene.traverse(e=>{e.userData.isMetaShape||(e.isMesh&&e.userData.faceMapping?s.push(e):e.isLine&&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 B;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 B,_=new B;for(let e of u){let t=e.object.geometry,n=t.getAttribute(`position`),r=t.getIndex();if(r!==null&&e.faceIndex!=null){let t=r.getX(e.faceIndex*2),i=r.getX(e.faceIndex*2+1),a=new B().fromBufferAttribute(n,t).applyMatrix4(e.object.matrixWorld),s=new B().fromBufferAttribute(n,i).applyMatrix4(e.object.matrixWorld);o.ray.distanceSqToSegment(a,s,void 0,g)}else g.copy(e.point);if(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){if(this.sceneObjects=e,this.highlightedShapeId=null,this.highlightedSub=null,this.hoverState=null,this.hoverFaceOverlayMeshes=[],this.ctx.renderer.domElement.style.cursor=``,this.removeCompiledMesh(),!t){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 n=sp(e,this.activeSketchId,this.ctx.camera,this.isRegionPicking);if(this.ctx.scene.add(n),this.applyHiddenShapes(),this.applyShapeOpacities(),this.activeSketchId&&this.applySketchModeGhosting(),this.settingsPanel.setSectionViewVisible(this.modeManager.isSketchMode),this.modeManager.isSketchMode&&(this.settingsPanel.setSectionViewActive(Vd.current.sectionView),Vd.current.sectionView&&this.applySectionView()),!this.hasRendered||this.modeManager.isSketchMode&&!t&&!this.isTrimming&&!this.isRegionPicking&&!this.isBezierDrawing){let e=new Ht;Zp(e,n),!e.isEmpty()&&!this.isBoxContained(e)&&(this.ctx.fitToBox(e,!0),this.lastFitBox=e.clone(),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=>{e.material&&(r&&e instanceof G?(e.userData.originalColor=e.material.color.getHex(),e.material.color.set(Qp)):!r&&e instanceof qi&&(e.userData.originalColor=e.material.color.getHex(),e.material.color.set($p),e.material.opacity<1&&(e.userData.originalOpacity=e.material.opacity,e.material.opacity=1)))}),this.highlightedShapeId=e,this.highlightedSub=null,this.ctx.render()}clearHighlight(){if(!(!this.highlightedShapeId&&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)});for(let e of this.faceHighlightMeshes)e.parent?.remove(e),e.geometry.dispose(),e.material.dispose();this.faceHighlightMeshes=[],this.highlightedShapeId=null,this.highlightedSub=null,this.ctx.render()}}highlightFace(e,t){this.clearHighlight(),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 Tr;f.setAttribute(`position`,new W(new Float32Array(d),3));let p=new G(f,new la({color:Qp,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-1}));(o.parent??this.ctx.scene).add(p),this.faceHighlightMeshes.push(p)}),this.highlightedShapeId=e,this.highlightedSub={type:`face`,index:t},this.ctx.render()}highlightEdge(e,t){this.clearHighlight(),this.ctx.scene.traverse(n=>{if(!n.isLine||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=n.material.color.getHex(),n.material.color.set($p))}),this.highlightedShapeId=e,this.highlightedSub={type:`edge`,index:t},this.ctx.render()}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.isBezierDrawing||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.highlightedShapeId===n.shapeId&&this.highlightedSub?.type===n.sub?.type&&this.highlightedSub?.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)}),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 Tr;f.setAttribute(`position`,new W(new Float32Array(d),3));let p=new G(f,new la({color:em,transparent:!0,opacity:nm,depthWrite:!1,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.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(tm))}),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 B;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 Ht;if(Zp(t,e),!t.isEmpty())return t.getSize(new B).length()*.015}return 2}fitViewToScene(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=new Ht;Zp(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&&(n.visible||n.type===`sketch`)||n.parentId&&(n.visible||n.type===`sketch`)&&e.find(e=>e.id===n.parentId)?.type===`part`)return n}}isBoxContained(e){if(!this.lastFitBox)return!1;let t=this.lastFitBox.getCenter(new B),n=this.lastFitBox.getSize(new B).length()/2*Ld;if(n===0)return!1;let r=e.getCenter(new B),i=e.getSize(new B).length()/2;return t.distanceTo(r)+i<=n}rebuildSceneMesh(){if(!this.sceneObjects)return;this.removeCompiledMesh();let e=sp(this.sceneObjects,this.activeSketchId,this.ctx.camera,this.isRegionPicking);this.ctx.scene.add(e),this.applyHiddenShapes(),this.applyShapeOpacities(),this.modeManager.isSketchMode&&Vd.current.sectionView&&this.applySectionView(),this.ctx.requestRender()}setShapeVisibility(e,t){let n=this.findShapeIndexForId(e);n!==void 0&&(t?this.hiddenShapeIndices.delete(n):this.hiddenShapeIndices.add(n),this.applyVisibilityForIndex(n,t),this.ctx.requestRender())}isShapeHidden(e){let t=this.findShapeIndexForId(e);return t===void 0?!1:this.hiddenShapeIndices.has(t)}applyVisibilityForIndex(e,t){this.ctx.scene.traverse(n=>{n.userData.shapeIndex===e&&(n.visible=t)})}setShapeTransparency(e,t){let n=this.findShapeIndexForId(e);n!==void 0&&(t>=1?this.shapeOpacities.delete(n):this.shapeOpacities.set(n,t),this.applyOpacityForIndex(n,t),this.ctx.requestRender())}getShapeTransparency(e){let t=this.findShapeIndexForId(e);return t===void 0?1:this.shapeOpacities.get(t)??1}findShapeIndexForId(e){let t;return this.ctx.scene.traverse(n=>{n.userData.shapeId===e&&typeof n.userData.shapeIndex==`number`&&(t=n.userData.shapeIndex)}),t}applyOpacityForIndex(e,t){let n=[];this.ctx.scene.traverse(t=>{t.userData.shapeIndex===e&&n.push(t)});for(let e of n)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})}applyShapeOpacities(){for(let[e,t]of this.shapeOpacities)this.applyOpacityForIndex(e,t)}applyHiddenShapes(){for(let e of this.hiddenShapeIndices)this.applyVisibilityForIndex(e,!1)}applySketchModeGhosting(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);if(!e)return;let t=Nd.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 U)||(n.userData.ghostOriginalColor||(n.userData.ghostOriginalColor=n.color.clone()),n.color.copy(n.userData.ghostOriginalColor).lerp(t,rm))}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&&(t.traverse(t=>{let n=t.material;if(!n)return;let r=Array.isArray(n)?n:[n];for(let t of r)t.clippingPlanes=[e]}),this.ctx.requestRender())}clearSectionView(){let e=this.ctx.scene.getObjectByName(`compiledMesh`);e&&(e.traverse(e=>{let t=e.material;if(!t)return;let n=Array.isArray(t)?t:[t];for(let e of n)e.clippingPlanes=[]}),this.ctx.requestRender())}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 am(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 om(e){switch(e){case`inch`:return`in`;case`foot`:return`ft`;case`yard`:return`yd`;case`meter`:return`m`;default:return`mm`}}function sm(e,t,n){let r=t===`kg`?1e3:t===`lbs`?453.592:1;return e*am(n)/r}function cm(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 lm(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 um(e){return e===0?`0`:parseFloat(e.toPrecision(6)).toString()}var dm=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=Mp,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`
4589
4589
  <div class="flex items-center justify-between mb-3">
4590
4590
  <span class="text-xs font-semibold text-base-content/70 uppercase tracking-wider">Shape Properties</span>
4591
4591
  <button class="btn btn-ghost btn-xs btn-square" data-action="panel-close">×</button>
@@ -4662,7 +4662,7 @@ void main() {
4662
4662
  <span class="text-sm font-medium text-base-content/70">Shapes</span>
4663
4663
  `,this.panel.appendChild(d),this.shapesBody=document.createElement(`div`),this.shapesBody.className=`py-1 overflow-y-auto min-h-[33vh] flex-1`,this.panel.appendChild(this.shapesBody),l.addEventListener(`click`,()=>{this.timelineExpanded=!this.timelineExpanded,this.timelineBody.classList.toggle(`hidden`,!this.timelineExpanded),l.querySelector(`[data-ref="chevron"]`).classList.toggle(`rotate-90`,this.timelineExpanded)}),d.addEventListener(`click`,()=>{this.shapesExpanded=!this.shapesExpanded,this.shapesBody.classList.toggle(`hidden`,!this.shapesExpanded),d.querySelector(`span`).classList.toggle(`rotate-90`,this.shapesExpanded)})}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.renderShapes(),this.updateHistoryTotal()}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=`· ${Sm(e)}`,this.historyTotalLabel.classList.remove(`hidden`)}renderTimeline(e=!1){let t=this.sceneObjects,n=this.rollbackStop,r=new Set;for(let e of t)e.uniqueType!==`lazy-select`&&e.parentId&&r.add(e.parentId);let i=``;for(let e=0;e<t.length;e++){let a=t[e];if(a.parentId||a.uniqueType===`lazy-select`)continue;let o=a.id!=null&&r.has(a.id),s=a.id!=null&&this.collapsedIds.has(a.id);if(i+=this.renderTimelineItem(a,e,n,!1,o,s),o&&!s)for(let e=0;e<t.length;e++)t[e].uniqueType!==`lazy-select`&&t[e].parentId===a.id&&(i+=this.renderTimelineItem(t[e],e,n,!0,!1,!1))}if(this.timelineBody.innerHTML=i,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()})}),e){let e=this.timelineBody.querySelector(`[data-current="true"]`);e&&e.scrollIntoView({block:`nearest`})}}renderTimelineItem(e,t,n,r,i,a){let o=t===n,s=t>n,c=e.visible===!1,l=e.hasError===!0,u=e.name?e.name.charAt(0).toUpperCase()+e.name.slice(1):e.type||`Unknown`,d=e.type===`part`?`/icons/box.png`:`/icons/${gm(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`),o?f+=` border-l-2 border-primary bg-primary/10 text-primary`:l?f+=` text-error`:s||c?f+=` text-base-content/60`:f+=` text-base-content/80`;let p=c?`w-4 h-4 object-contain grayscale opacity-60`:`w-4 h-4 object-contain`,m=``;if(i){let t=a?``:`rotate-90`;m=`<span data-toggle="${e.id}" class="flex items-center justify-center w-5 h-5 opacity-50 hover:opacity-100 transition-transform ${t}">
4664
4664
  ${vm}
4665
- </span>`}else m=`<span class="w-4"></span>`;let h=this.showBuildTimings&&!e.fromCache&&e.buildDurationMs!=null,g=h?`<span class="ml-auto shrink-0 text-xs text-base-content/40 tabular-nums">${Sm(e.buildDurationMs)}</span>`:``,_=h?`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`,v=e.fromCache?`<span class="${_}">${Lp}</span>`:`<span class="${_}">${Rp}</span>`;return`
4665
+ </span>`}else m=`<span class="w-4"></span>`;let h=this.showBuildTimings&&!e.fromCache&&e.buildDurationMs!=null,g=h?`<span class="ml-auto shrink-0 text-xs text-base-content/40 tabular-nums">${Sm(e.buildDurationMs)}</span>`:``,_=h?`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`,v=e.fromCache?`<span class="${_}">${Ip}</span>`:`<span class="${_}">${Lp}</span>`;return`
4666
4666
  <div class="${f}" data-index="${t}" data-container="${e.isContainer??!1}" data-current="${o}">
4667
4667
  ${m}
4668
4668
  <img src="${d}" class="${p}" alt="" />
@@ -4678,7 +4678,7 @@ void main() {
4678
4678
  <span>${e}</span>
4679
4679
  <span class="text-base-content/40 ml-1">${r.length}</span>
4680
4680
  </div>
4681
- `,!i)for(let n=0;n<r.length;n++){let i=r[n],a=this.selectedShapeIds.has(i.shapeId)?` bg-primary/10`:``,o=this.isShapeHidden(i.shapeId),s=o?Up:Hp,c=`<button class="ml-auto btn btn-ghost btn-square btn-xs ${o?`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="${i.shapeId}">${s}</button>`,l=`<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="${i.shapeId}">${bm}</button>`;t+=`
4681
+ `,!i)for(let n=0;n<r.length;n++){let i=r[n],a=this.selectedShapeIds.has(i.shapeId)?` bg-primary/10`:``,o=this.isShapeHidden(i.shapeId),s=o?Hp:Vp,c=`<button class="ml-auto btn btn-ghost btn-square btn-xs ${o?`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="${i.shapeId}">${s}</button>`,l=`<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="${i.shapeId}">${bm}</button>`;t+=`
4682
4682
  <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${a}" data-shape-id="${i.shapeId}" data-shape-type="${i.shapeType}">
4683
4683
  <img src="/icons/${i.shapeType}.png" class="w-4 h-4 object-contain" alt="" />
4684
4684
  <span class="truncate">${e} ${n+1}</span>
@@ -4688,7 +4688,7 @@ void main() {
4688
4688
  `}}this.shapesBody.innerHTML=t,this.shapesBody.querySelectorAll(`[data-shape-group]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.shapeGroup;this.collapsedShapeGroups.has(t)?this.collapsedShapeGroups.delete(t):this.collapsedShapeGroups.add(t),this.renderShapes()})}),this.shapesBody.querySelectorAll(`[data-shape-id]`).forEach(e=>{e.addEventListener(`click`,t=>{if(t.target.closest(`[data-dots]`)||t.target.closest(`[data-eye]`))return;let n=e.dataset.shapeId;t.ctrlKey||t.metaKey?this.selectedShapeIds.has(n)?this.selectedShapeIds.delete(n):this.selectedShapeIds.add(n):(this.selectedShapeIds.clear(),this.selectedShapeIds.add(n)),this.renderShapes(),n&&this.onHighlightShape(n)})}),this.shapesBody.querySelectorAll(`[data-dots]`).forEach(e=>{e.addEventListener(`click`,t=>{t.stopPropagation();let n=e.dataset.dots;this.showShapeDropdown(e,n)})}),this.shapesBody.querySelectorAll(`[data-eye]`).forEach(e=>{e.addEventListener(`click`,t=>{t.stopPropagation();let n=e.dataset.eye,r=this.isShapeHidden(n);this.onToggleShapeVisibility(n,r),this.renderShapes()})})}setShowBuildTimings(e){this.showBuildTimings!==e&&(this.showBuildTimings=e,this.applyPanelWidth(),this.updateHistoryTotal(),this.loaded&&this.renderTimeline())}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=`
4689
4689
  <ul class="menu menu-xs p-1 min-w-[180px]">
4690
4690
  <li><button data-action="recompute" class="flex items-center gap-2">
4691
- <span class="flex items-center justify-center w-4 h-4 shrink-0 [&>svg]:size-3.5">${Rp}</span>
4691
+ <span class="flex items-center justify-center w-4 h-4 shrink-0 [&>svg]:size-3.5">${Lp}</span>
4692
4692
  <span>Recompute scene</span>
4693
4693
  </button></li>
4694
4694
  <li><button data-action="toggle-timings" class="flex items-center gap-2">
@@ -4696,7 +4696,7 @@ void main() {
4696
4696
  <span>Show execution time</span>
4697
4697
  </button></li>
4698
4698
  </ul>
4699
- `,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(),dp(`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)}showShapeDropdown(e,t){this.closeDropdown();let n=document.createElement(`div`);n.className=`absolute z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)]`;let r=e.getBoundingClientRect(),i=this.panel.getBoundingClientRect();n.style.top=`${r.bottom-i.top+2}px`,n.style.left=`${r.left-i.left}px`,n.innerHTML=`
4699
+ `,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(),up(`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)}showShapeDropdown(e,t){this.closeDropdown();let n=document.createElement(`div`);n.className=`absolute z-[200] panel-bg border border-base-content/10 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.4)]`;let r=e.getBoundingClientRect(),i=this.panel.getBoundingClientRect();n.style.top=`${r.bottom-i.top+2}px`,n.style.left=`${r.left-i.left}px`,n.innerHTML=`
4700
4700
  <ul class="menu menu-xs p-1 min-w-[140px]">
4701
4701
  <li><button data-action="export">Export</button></li>
4702
4702
  <li><button data-action="set-transparency">Set Transparency</button></li>
@@ -4803,14 +4803,14 @@ void main() {
4803
4803
  </div>
4804
4804
  `}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 fetch(`/api/export`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json();throw Error(e.error||`Export failed`)}let r=await n.blob(),i=e===`step`?`.step`:`.stl`,a=URL.createObjectURL(r),o=document.createElement(`a`);o.href=a,o.download=`export${i}`,o.click(),URL.revokeObjectURL(a),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 Tm(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}}},Am=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=`
4805
4805
  <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">
4806
- <span class="text-warning [&>svg]:size-5">${Gp}</span>
4806
+ <span class="text-warning [&>svg]:size-5">${Wp}</span>
4807
4807
  <span class="text-base-content/80">Breakpoint Active</span>
4808
4808
  <div class="h-4 w-px bg-base-content/10"></div>
4809
4809
  <button class="text-base-content/60 hover:text-base-content transition-colors cursor-pointer fluidcad-breakpoint-continue">
4810
4810
  Continue
4811
4811
  </button>
4812
4812
  </div>
4813
- `,e.appendChild(this.element),this.element.querySelector(`.fluidcad-breakpoint-continue`).addEventListener(`click`,async()=>{t?.();try{await fetch(`/api/clear-breakpoints`,{method:`POST`})}catch(e){console.error(`Clear breakpoints failed:`,e)}})}setActive(e){this.element.classList.toggle(`hidden`,!e)}},jm=12,Mm=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=Nm(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=Nm(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,a=[Math.round(i[0]*100)/100,Math.round(i[1]*100)/100];this.onPick(a)}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(){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 B;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*jm}findNearestEdge(e,t){let n=1/0,r=null;for(let t of this.edges)for(let i of t.segments){let a=Pm(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=Fm(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){let n=this.ctx.renderer,r=this.ctx.camera,i=n.domElement.getBoundingClientRect(),a=(e-i.left)/i.width*2-1,o=-((t-i.top)/i.height)*2+1,s=new to;s.setFromCamera(new z(a,o),r);let c=s.ray.origin,l=s.ray.direction,u=new B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),d=new B(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),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=new B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),g=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[m.dot(h),m.dot(g)]}};function Nm(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)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}function Pm(e,t,n,r,i,a){return Fm(e,t,n,r,i,a).dist}function Fm(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)}}var Im=`#64B5F6`,Lm=.35,Rm=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(Im),e.opacity=Lm,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,r=this.ctx.camera,i=n.domElement.getBoundingClientRect(),a=(e-i.left)/i.width*2-1,o=-((t-i.top)/i.height)*2+1,s=new to;s.setFromCamera(new z(a,o),r);let c=[];if(this.ctx.scene.traverse(e=>{if(e.userData.isPickRegion&&e.children)for(let t of e.children)t.isMesh&&c.push(t)}),c.length===0)return null;let l=s.intersectObjects(c,!1);return l.length===0?null:{mesh:l[0].object,point:l[0].point}}projectToSketch(e,t){let n=this.ctx.renderer,r=this.ctx.camera,i=n.domElement.getBoundingClientRect(),a=(e-i.left)/i.width*2-1,o=-((t-i.top)/i.height)*2+1,s=new to;s.setFromCamera(new z(a,o),r);let c=s.ray.origin,l=s.ray.direction,u=new B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),d=new B(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),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=new B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),g=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[m.dot(h),m.dot(g)]}},zm=64,Bm={r:.69,g:.69,b:.69},Vm=11579568,Hm=.35,Um=11579568,Wm=15954511,Gm=16737792,Km=2280550,qm=4,Jm=1.5,Ym=.6,Xm=qm+Jm+Ym+Jm,Zm=`
4813
+ `,e.appendChild(this.element),this.element.querySelector(`.fluidcad-breakpoint-continue`).addEventListener(`click`,async()=>{t?.();try{await fetch(`/api/clear-breakpoints`,{method:`POST`})}catch(e){console.error(`Clear breakpoints failed:`,e)}})}setActive(e){this.element.classList.toggle(`hidden`,!e)}},jm=12,Mm=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=Nm(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=Nm(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,a=[Math.round(i[0]*100)/100,Math.round(i[1]*100)/100];this.onPick(a)}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(){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 B;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*jm}findNearestEdge(e,t){let n=1/0,r=null;for(let t of this.edges)for(let i of t.segments){let a=Pm(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=Fm(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){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 B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),l=new B(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 B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),m=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[f.dot(p),f.dot(m)]}};function Nm(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)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}function Pm(e,t,n,r,i,a){return Fm(e,t,n,r,i,a).dist}function Fm(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)}}var Im=`#64B5F6`,Lm=.35,Rm=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(Im),e.opacity=Lm,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 B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),l=new B(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 B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),m=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[f.dot(p),f.dot(m)]}},zm=64,Bm={r:.69,g:.69,b:.69},Vm=11579568,Hm=.35,Um=11579568,Wm=15954511,Gm=16737792,Km=2280550,qm=4,Jm=1.5,Ym=.6,Xm=qm+Jm+Ym+Jm,Zm=`
4814
4814
  attribute float lineDistance;
4815
4815
  varying float vLineDistance;
4816
4816
  void main() {
@@ -4837,26 +4837,26 @@ void main() {
4837
4837
  }
4838
4838
  gl_FragColor = vec4(color, 1.0);
4839
4839
  }
4840
- `,$m=16762232,eh=8947848,th=2.5,nh=16,rh=.003,ih=1.5,ah=12;function oh(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}function sh(e){let t=e.camera,n=e.renderer.domElement.getBoundingClientRect().height||1,r,i=t;if(i.isOrthographicCamera)r=(i.top-i.bottom)/(i.zoom||1);else{let n=new B;e.cameraControls.getTarget(n);let a=t.position.distanceTo(n),o=i.fov*Math.PI/180;r=2*a*Math.tan(o/2)}return r/n*ah}function ch(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 lh(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 uh(e,t){let n=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(n*n+r*r)}var dh=class{canvas;ctx;plane;snapController;onPick;onSetPoints;existingPoles=[];mousePoint=null;lastSnapType=`none`;downX=0;downY=0;dragIndex=-1;dragPoles=null;previewGroup;curveLineObj=null;polygonLineObj=null;cpDots=[];snapIndicator=null;ctrlHeld=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;constructor(e,t,n,r,i,a=null){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.snapController=n,this.existingPoles=r,this.onPick=i,this.onSetPoints=a,this.previewGroup=new ii,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=3,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.ctx.scene.add(this.previewGroup),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.rebuildPreview()}deactivate(){this.endDrag(),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.ctx.scene.remove(this.previewGroup),this.disposePreview(),this.ctx.requestRender()}updateExistingPoles(e){this.existingPoles=e,this.dragIndex<0&&this.rebuildPreview()}hitTestControlPoint(e){let t=sh(this.ctx),n=-1,r=1/0;for(let i=1;i<this.existingPoles.length;i++){let a=uh(e,this.existingPoles[i]);a<t&&a<r&&(r=a,n=i)}return n}startDrag(e){this.dragIndex=e,this.dragPoles=this.existingPoles.map(e=>[e[0],e[1]]),this.ctx.cameraControls.enabled=!1,this.canvas.style.cursor=`grabbing`}endDrag(){this.dragIndex<0||(this.dragIndex=-1,this.dragPoles=null,this.ctx.cameraControls.enabled=!0,this.canvas.style.cursor=``)}get isDragging(){return this.dragIndex>=0}handleMouseDown(e){if(this.downX=e.clientX,this.downY=e.clientY,(e.ctrlKey||e.metaKey)&&this.onSetPoints){let t=this.projectToSketch(e.clientX,e.clientY);if(t){let n=this.hitTestControlPoint(t);if(n>=0){e.preventDefault(),e.stopPropagation(),this.startDrag(n);return}}}}handleMouseUp(e){if(this.isDragging){if(this.dragPoles&&this.onSetPoints){let e=this.dragPoles.slice(1).map(e=>[Math.round(e[0]*100)/100,Math.round(e[1]*100)/100]);this.onSetPoints(e)}this.endDrag();return}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.snapController.snap(r),a=[Math.round(i.point2d[0]*100)/100,Math.round(i.point2d[1]*100)/100];this.onPick(a)}handleMouseMove(e){let t=this.projectToSketch(e.clientX,e.clientY);if(this.isDragging){if(!t||!this.dragPoles)return;let e=this.snapController.snap(t);this.dragPoles[this.dragIndex]=e.point2d,this.lastSnapType=e.snapType,this.mousePoint=null,this.rebuildPreview();return}if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.canvas.style.cursor=``,this.rebuildPreview();return}if(this.ctrlHeld){this.hitTestControlPoint(t)>=0?this.canvas.style.cursor=`grab`:this.canvas.style.cursor=``,this.mousePoint!==null&&(this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview());return}this.canvas.style.cursor=``;let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview()}handleKeyDown(e){if((e.key===`Control`||e.key===`Meta`)&&!this.ctrlHeld&&(this.ctrlHeld=!0,this.isDragging||(this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview())),e.key===`Escape`){if(this.isDragging){this.endDrag(),this.rebuildPreview();return}if(this.existingPoles.length>1&&this.onSetPoints){e.preventDefault();let t=this.existingPoles.slice(1,-1);this.onSetPoints(t)}}}handleKeyUp(e){(e.key===`Control`||e.key===`Meta`)&&(this.ctrlHeld=!1,this.canvas.style.cursor=``)}disposePreview(){for(let e of[...this.previewGroup.children])this.previewGroup.remove(e),e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose();this.curveLineObj=null,this.polygonLineObj=null,this.cpDots=[],this.snapIndicator=null}rebuildPreview(){this.disposePreview();let e;if(this.isDragging&&this.dragPoles?e=[...this.dragPoles]:(e=[...this.existingPoles],this.mousePoint&&e.push(this.mousePoint)),e.length<1){this.ctx.requestRender();return}let t=this.ctx.camera,n=new B(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(e.length>=2){let t=new Float32Array(e.length*3),n=[];for(let r=0;r<e.length;r++){let i=lh(e[r],this.plane);t[r*3]=i.x,t[r*3+1]=i.y,t[r*3+2]=i.z,r>0&&n.push(r-1,r)}let r=new Tr;r.setAttribute(`position`,new W(t,3)),r.setIndex(n),this.polygonLineObj=new qi(r,new Fi({color:Vm,transparent:!0,opacity:Hm,depthTest:!1})),this.polygonLineObj.renderOrder=3,this.previewGroup.add(this.polygonLineObj)}if(e.length>=2){let t=zm,n=new Float32Array((t+1)*3);for(let r=0;r<=t;r++){let i=r/t,a=lh(ch(e,i),this.plane);n[r*3]=a.x,n[r*3+1]=a.y,n[r*3+2]=a.z}let r=new Tr;r.setAttribute(`position`,new W(n,3)),this.curveLineObj=new Ui(r,new qr({uniforms:{color:{value:{...Bm}},dashLength:{value:qm},gapLength:{value:Jm},dotLength:{value:Ym},patternLength:{value:Xm}},vertexShader:Zm,fragmentShader:Qm,side:2,transparent:!0,depthTest:!1})),this.curveLineObj.computeLineDistances(),this.curveLineObj.renderOrder=3,this.previewGroup.add(this.curveLineObj)}let r=new Zi(th,nh);for(let i=0;i<e.length;i++){let a=i===0,o=!this.isDragging&&this.mousePoint&&i===e.length-1,s=this.isDragging&&i===this.dragIndex,c=Um;a&&(c=Km),o&&(c=Wm),s&&(c=Gm);let l=new G(r,new dr({color:c,side:2,depthTest:!1}));l.renderOrder=4;let u=new ii;u.renderOrder=4;let d=lh(e[i],this.plane);u.position.copy(d),u.lookAt(d.clone().add(n)),u.scale.setScalar(Math.min(oh(t,d,rh),ih)),l.onBeforeRender=(e,t,n)=>{u.scale.setScalar(Math.min(oh(n,d,rh),ih)),u.updateMatrixWorld(!0)},u.add(l),this.previewGroup.add(u),this.cpDots.push(u)}let i=this.isDragging?this.dragPoles?this.dragPoles[this.dragIndex]:null:this.mousePoint;if(i&&this.lastSnapType!==`none`){let e=this.lastSnapType===`vertex`?$m:eh,r=new G(new Zi(th*1.6,nh),new dr({color:e,side:2,depthTest:!1,transparent:!0,opacity:.6}));r.renderOrder=5,this.snapIndicator=new ii,this.snapIndicator.renderOrder=5;let a=lh(i,this.plane);this.snapIndicator.position.copy(a),this.snapIndicator.lookAt(a.clone().add(n)),this.snapIndicator.scale.setScalar(Math.min(oh(t,a,rh),ih)),r.onBeforeRender=(e,t,n)=>{this.snapIndicator.scale.setScalar(Math.min(oh(n,a,rh),ih)),this.snapIndicator.updateMatrixWorld(!0)},this.snapIndicator.add(r),this.previewGroup.add(this.snapIndicator)}this.ctx.requestRender()}projectToSketch(e,t){let n=this.ctx.renderer,r=this.ctx.camera,i=n.domElement.getBoundingClientRect(),a=(e-i.left)/i.width*2-1,o=-((t-i.top)/i.height)*2+1,s=new to;s.setFromCamera(new z(a,o),r);let c=s.ray.origin,l=s.ray.direction,u=new B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),d=new B(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z),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=new B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),g=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[m.dot(h),m.dot(g)]}},fh=class{vertices2d=[];plane;constructor(e,t){this.vertices2d=e,this.plane=t}snap(e,t){let n=1/0,r=null;for(let i of this.vertices2d){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:ph(r,this.plane),snapType:`vertex`}:null}};function ph(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 mh=class{spacing;plane;constructor(e,t=10){this.plane=e,this.spacing=t}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)>t)return null;let o=[n,r];return{point2d:o,worldPoint:hh(o,this.plane),snapType:`grid`}}};function hh(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 gh=15,_h=class e{snappers=[];threshold;constructor(e,t=gh){this.snappers=e,this.threshold=t}snap(e,t){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 B(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`}}static fromSceneObjects(t,n,r){let i=[];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,a]of t)if(a===1){let t=e.vertices[n*3],a=e.vertices[n*3+1],o=e.vertices[n*3+2],s=t-r.origin.x,c=a-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;i.some(e=>(e[0]-u)*(e[0]-u)+(e[1]-d)*(e[1]-d)<1e-6)||i.push([u,d])}}}return new e([new fh(i,r),new mh(r)])}},vh=class{snapManager;plane;snapToVertices=!0;snapToGrid=!0;constructor(e,t){this.snapManager=e,this.plane=t}updateSnapManager(e){this.snapManager=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 B(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`}}},yh=document.getElementById(`fluidcad-viewer`)||document.body;up().then(e=>{e&&(document.documentElement.setAttribute(`data-theme`,e.theme),Hd(e),kh.setShowBuildTimings(!!e.showBuildTimings))});function bh(e,t){return e.parentId?t.find(t=>t.id===e.parentId)?.type===`part`:!0}var xh=document.createElement(`div`);xh.id=`fluidcad-loading`,xh.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1000] pointer-events-none`,xh.innerHTML=`
4840
+ `,$m=16762232,eh=8947848,th=2.5,nh=16,rh=.003,ih=1.5,ah=12;function oh(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}function sh(e){let t=e.camera,n=e.renderer.domElement.getBoundingClientRect().height||1,r,i=t;if(i.isOrthographicCamera)r=(i.top-i.bottom)/(i.zoom||1);else{let n=new B;e.cameraControls.getTarget(n);let a=t.position.distanceTo(n),o=i.fov*Math.PI/180;r=2*a*Math.tan(o/2)}return r/n*ah}function ch(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 lh(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 uh(e,t){let n=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(n*n+r*r)}var dh=class{canvas;ctx;plane;snapController;onPick;onSetPoints;existingPoles=[];mousePoint=null;lastSnapType=`none`;downX=0;downY=0;dragIndex=-1;dragPoles=null;previewGroup;curveLineObj=null;polygonLineObj=null;cpDots=[];snapIndicator=null;ctrlHeld=!1;boundMouseDown;boundMouseUp;boundMouseMove;boundKeyDown;boundKeyUp;constructor(e,t,n,r,i,a=null){this.canvas=e.renderer.domElement,this.ctx=e,this.plane=t,this.snapController=n,this.existingPoles=r,this.onPick=i,this.onSetPoints=a,this.previewGroup=new ii,this.previewGroup.userData.isMetaShape=!0,this.previewGroup.renderOrder=3,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.ctx.scene.add(this.previewGroup),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.rebuildPreview()}deactivate(){this.endDrag(),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.ctx.scene.remove(this.previewGroup),this.disposePreview(),this.ctx.requestRender()}updateExistingPoles(e){this.existingPoles=e,this.dragIndex<0&&this.rebuildPreview()}hitTestControlPoint(e){let t=sh(this.ctx),n=-1,r=1/0;for(let i=1;i<this.existingPoles.length;i++){let a=uh(e,this.existingPoles[i]);a<t&&a<r&&(r=a,n=i)}return n}startDrag(e){this.dragIndex=e,this.dragPoles=this.existingPoles.map(e=>[e[0],e[1]]),this.ctx.cameraControls.enabled=!1,this.canvas.style.cursor=`grabbing`}endDrag(){this.dragIndex<0||(this.dragIndex=-1,this.dragPoles=null,this.ctx.cameraControls.enabled=!0,this.canvas.style.cursor=``)}get isDragging(){return this.dragIndex>=0}handleMouseDown(e){if(this.downX=e.clientX,this.downY=e.clientY,(e.ctrlKey||e.metaKey)&&this.onSetPoints){let t=this.projectToSketch(e.clientX,e.clientY);if(t){let n=this.hitTestControlPoint(t);if(n>=0){e.preventDefault(),e.stopPropagation(),this.startDrag(n);return}}}}handleMouseUp(e){if(this.isDragging){if(this.dragPoles&&this.onSetPoints){let e=this.dragPoles.slice(1).map(e=>[Math.round(e[0]*100)/100,Math.round(e[1]*100)/100]);this.onSetPoints(e)}this.endDrag();return}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.snapController.snap(r),a=[Math.round(i.point2d[0]*100)/100,Math.round(i.point2d[1]*100)/100];this.onPick(a)}handleMouseMove(e){let t=this.projectToSketch(e.clientX,e.clientY);if(this.isDragging){if(!t||!this.dragPoles)return;let e=this.snapController.snap(t);this.dragPoles[this.dragIndex]=e.point2d,this.lastSnapType=e.snapType,this.mousePoint=null,this.rebuildPreview();return}if(!t){this.mousePoint=null,this.lastSnapType=`none`,this.canvas.style.cursor=``,this.rebuildPreview();return}if(this.ctrlHeld){this.hitTestControlPoint(t)>=0?this.canvas.style.cursor=`grab`:this.canvas.style.cursor=``,this.mousePoint!==null&&(this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview());return}this.canvas.style.cursor=``;let n=this.snapController.snap(t);this.mousePoint=n.point2d,this.lastSnapType=n.snapType,this.rebuildPreview()}handleKeyDown(e){if((e.key===`Control`||e.key===`Meta`)&&!this.ctrlHeld&&(this.ctrlHeld=!0,this.isDragging||(this.mousePoint=null,this.lastSnapType=`none`,this.rebuildPreview())),e.key===`Escape`){if(this.isDragging){this.endDrag(),this.rebuildPreview();return}if(this.existingPoles.length>1&&this.onSetPoints){e.preventDefault();let t=this.existingPoles.slice(1,-1);this.onSetPoints(t)}}}handleKeyUp(e){(e.key===`Control`||e.key===`Meta`)&&(this.ctrlHeld=!1,this.canvas.style.cursor=``)}disposePreview(){for(let e of[...this.previewGroup.children])this.previewGroup.remove(e),e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose();this.curveLineObj=null,this.polygonLineObj=null,this.cpDots=[],this.snapIndicator=null}rebuildPreview(){this.disposePreview();let e;if(this.isDragging&&this.dragPoles?e=[...this.dragPoles]:(e=[...this.existingPoles],this.mousePoint&&e.push(this.mousePoint)),e.length<1){this.ctx.requestRender();return}let t=this.ctx.camera,n=new B(this.plane.normal.x,this.plane.normal.y,this.plane.normal.z);if(e.length>=2){let t=new Float32Array(e.length*3),n=[];for(let r=0;r<e.length;r++){let i=lh(e[r],this.plane);t[r*3]=i.x,t[r*3+1]=i.y,t[r*3+2]=i.z,r>0&&n.push(r-1,r)}let r=new Tr;r.setAttribute(`position`,new W(t,3)),r.setIndex(n),this.polygonLineObj=new qi(r,new Fi({color:Vm,transparent:!0,opacity:Hm,depthTest:!1})),this.polygonLineObj.renderOrder=3,this.previewGroup.add(this.polygonLineObj)}if(e.length>=2){let t=zm,n=new Float32Array((t+1)*3);for(let r=0;r<=t;r++){let i=r/t,a=lh(ch(e,i),this.plane);n[r*3]=a.x,n[r*3+1]=a.y,n[r*3+2]=a.z}let r=new Tr;r.setAttribute(`position`,new W(n,3)),this.curveLineObj=new Ui(r,new qr({uniforms:{color:{value:{...Bm}},dashLength:{value:qm},gapLength:{value:Jm},dotLength:{value:Ym},patternLength:{value:Xm}},vertexShader:Zm,fragmentShader:Qm,side:2,transparent:!0,depthTest:!1})),this.curveLineObj.computeLineDistances(),this.curveLineObj.renderOrder=3,this.previewGroup.add(this.curveLineObj)}let r=new Zi(th,nh);for(let i=0;i<e.length;i++){let a=i===0,o=!this.isDragging&&this.mousePoint&&i===e.length-1,s=this.isDragging&&i===this.dragIndex,c=Um;a&&(c=Km),o&&(c=Wm),s&&(c=Gm);let l=new G(r,new dr({color:c,side:2,depthTest:!1}));l.renderOrder=4;let u=new ii;u.renderOrder=4;let d=lh(e[i],this.plane);u.position.copy(d),u.lookAt(d.clone().add(n)),u.scale.setScalar(Math.min(oh(t,d,rh),ih)),l.onBeforeRender=(e,t,n)=>{u.scale.setScalar(Math.min(oh(n,d,rh),ih)),u.updateMatrixWorld(!0)},u.add(l),this.previewGroup.add(u),this.cpDots.push(u)}let i=this.isDragging?this.dragPoles?this.dragPoles[this.dragIndex]:null:this.mousePoint;if(i&&this.lastSnapType!==`none`){let e=this.lastSnapType===`vertex`?$m:eh,r=new G(new Zi(th*1.6,nh),new dr({color:e,side:2,depthTest:!1,transparent:!0,opacity:.6}));r.renderOrder=5,this.snapIndicator=new ii,this.snapIndicator.renderOrder=5;let a=lh(i,this.plane);this.snapIndicator.position.copy(a),this.snapIndicator.lookAt(a.clone().add(n)),this.snapIndicator.scale.setScalar(Math.min(oh(t,a,rh),ih)),r.onBeforeRender=(e,t,n)=>{this.snapIndicator.scale.setScalar(Math.min(oh(n,a,rh),ih)),this.snapIndicator.updateMatrixWorld(!0)},this.snapIndicator.add(r),this.previewGroup.add(this.snapIndicator)}this.ctx.requestRender()}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 B(this.plane.origin.x,this.plane.origin.y,this.plane.origin.z),l=new B(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 B(this.plane.xDirection.x,this.plane.xDirection.y,this.plane.xDirection.z),m=new B(this.plane.yDirection.x,this.plane.yDirection.y,this.plane.yDirection.z);return[f.dot(p),f.dot(m)]}},fh=class{vertices2d=[];plane;constructor(e,t){this.vertices2d=e,this.plane=t}snap(e,t){let n=1/0,r=null;for(let i of this.vertices2d){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:ph(r,this.plane),snapType:`vertex`}:null}};function ph(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 mh=class{spacing;plane;constructor(e,t=10){this.plane=e,this.spacing=t}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)>t)return null;let o=[n,r];return{point2d:o,worldPoint:hh(o,this.plane),snapType:`grid`}}};function hh(e,t){let n=t.origin,r=t.xDirection,i=t.yDirection;return new B(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 gh=15,_h=class e{snappers=[];threshold;constructor(e,t=gh){this.snappers=e,this.threshold=t}snap(e,t){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 B(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`}}static fromSceneObjects(t,n,r){let i=[];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,a]of t)if(a===1){let t=e.vertices[n*3],a=e.vertices[n*3+1],o=e.vertices[n*3+2],s=t-r.origin.x,c=a-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;i.some(e=>(e[0]-u)*(e[0]-u)+(e[1]-d)*(e[1]-d)<1e-6)||i.push([u,d])}}}return new e([new fh(i,r),new mh(r)])}},vh=class{snapManager;plane;snapToVertices=!0;snapToGrid=!0;constructor(e,t){this.snapManager=e,this.plane=t}updateSnapManager(e){this.snapManager=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 B(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`}}},yh=document.getElementById(`fluidcad-viewer`)||document.body;lp().then(e=>{e&&(document.documentElement.setAttribute(`data-theme`,e.theme),Hd(e),kh.setShowBuildTimings(!!e.showBuildTimings))});function bh(e,t){return e.parentId?t.find(t=>t.id===e.parentId)?.type===`part`:!0}var xh=document.createElement(`div`);xh.id=`fluidcad-loading`,xh.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[1000] pointer-events-none`,xh.innerHTML=`
4841
4841
  <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">
4842
4842
  <span class="loading loading-spinner loading-sm"></span>
4843
4843
  <span class="loading-text">Loading FluidCAD...</span>
4844
4844
  </div>
4845
4845
  `,yh.appendChild(xh);var Sh=xh.querySelector(`.loading-text`);function Ch(e){Sh.textContent=e,xh.classList.remove(`hidden`)}function wh(){xh.classList.add(`hidden`)}var $=new im(`fluidcad-viewer`);Pd(()=>$.rebuildSceneMesh());var Th=new dm(yh),Eh=new mm(yh),Dh=new km(yh,$.sceneContext),Oh=new Am(yh,()=>{Zh===`picking-active`&&ag(),Mh===`picking-active`&&Bh()}),kh=new Cm(yh,e=>$.highlightShape(e),e=>Dh.show(e),(e,t)=>$.setShapeVisibility(e,t),e=>$.isShapeHidden(e),(e,t)=>$.setShapeTransparency(e,t),e=>$.getShapeTransparency(e));Th.setOpenHandler(()=>{$.clearHighlight(),Eh.hide()}),Th.setCentroidHandler(e=>{e?$.showCentroid(e):$.clearCentroid()}),$.setSelectionHandler((e,t)=>{e?Th.isOpen?$.highlightShape(e):t?.type===`face`?$.highlightFace(e,t.index):t?.type===`edge`?$.highlightEdge(e,t.index):$.clearHighlight():$.clearHighlight(),Th.setSelectedShape(e),e!==null&&t!==null?t.type===`face`?Eh.showForFace(e,t.index):Eh.showForEdge(e,t.index):Eh.hide()});var Ah=document.createElement(`div`);Ah.id=`fluidcad-trim-pick-trigger`,Ah.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,Ah.innerHTML=`
4846
4846
  <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">
4847
- <span class="[&>svg]:size-5">${Pp}</span>
4847
+ <span class="[&>svg]:size-5">${Np}</span>
4848
4848
  <span>Interactive Trimming</span>
4849
4849
  </button>
4850
4850
  `,yh.appendChild(Ah);var jh=document.createElement(`div`);jh.id=`fluidcad-trim-pick-active`,jh.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,jh.innerHTML=`
4851
4851
  <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">
4852
- <span class="[&>svg]:size-5">${Pp}</span>
4852
+ <span class="[&>svg]:size-5">${Np}</span>
4853
4853
  <span>Trimming Mode</span>
4854
4854
  <div class="h-4 w-px bg-base-content/10"></div>
4855
4855
  <button class="text-base-content/60 hover:text-base-content transition-colors cursor-pointer" id="exit-trim-pick">Exit</button>
4856
4856
  </div>
4857
4857
  `,yh.appendChild(jh);var Mh=`idle`,Nh=null,Ph=null,Fh=null,Ih=null;function Lh(e){let t=null;for(let n=e.length-1;n>=0;n--)if(bh(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}}function Rh(e,t){Vh();let n=e.sketchObj.object.plane,r=e.trimObj.sourceLocation,i=e.sketchObj.id,a=_h.fromSceneObjects(t,i,n);Fh=new Mm($.sceneContext,n,a,t,i,e=>{fetch(`/api/insert-point`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({point:e,sourceLocation:r})})},e=>{$.clearHighlight(),Jh(),e&&($.highlightShape(e.shapeId),qh(e.endpoints))}),Ih=r.line,Fh.activate()}function zh(){if(Nh){if(!Nh.trimObj.object?.picking){fetch(`/api/add-pick`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sourceLocation:Nh.trimObj.sourceLocation})}),Mh=`picking-active`,Ah.classList.add(`hidden`),jh.classList.remove(`hidden`),$.isTrimming=!0;return}Ph&&Rh(Nh,Ph),Mh=`picking-active`,Ah.classList.add(`hidden`),jh.classList.remove(`hidden`),$.isTrimming=!0}}function Bh(){Vh(),$.isTrimming=!1;let e=Nh?.trimObj,t=e?.object?.picking,n=e?.object?.pickPoints;t&&(!n||n.length===0)&&e?.sourceLocation&&fetch(`/api/remove-pick`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sourceLocation:e.sourceLocation})}),Nh?(Mh=`icon-visible`,jh.classList.add(`hidden`),Ah.classList.remove(`hidden`)):(Mh=`idle`,jh.classList.add(`hidden`),Ah.classList.add(`hidden`))}function Vh(){Fh&&(Fh.deactivate(),Fh=null,Ih=null),Jh()}function Hh(){Vh(),Mh=`idle`,Ah.classList.add(`hidden`),jh.classList.add(`hidden`),Nh=null,Ph=null,$.isTrimming=!1}function Uh(e){let t=Lh(e);if(!t.hasTrigger){Hh();return}Nh={trimObj:t.trimObj,sketchObj:t.sketchObj},Ph=e;let n=t.trimObj.object?.picking;if(Mh===`picking-active`){if(n){let n=Nh.trimObj.sourceLocation.line;if(Fh&&Ih===n){Fh.updateEdges(e,t.sketchObj.id);return}Rh(Nh,e)}return}Mh=`icon-visible`,Ah.classList.remove(`hidden`),jh.classList.add(`hidden`)}Ah.querySelector(`button`).addEventListener(`click`,()=>{zh()}),jh.querySelector(`#exit-trim-pick`).addEventListener(`click`,()=>{Bh()});var Wh=16762232,Gh=1e-4,Kh=[];function qh(e){Jh(),e.length!==0&&($.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<Gh){let e=n.material,t=e.clone();t.color.setHex(Wh),n.material=t,Kh.push({mesh:n,originalMaterial:e});break}}}),$.sceneContext.requestRender())}function Jh(){for(let{mesh:e,originalMaterial:t}of Kh)e.material.dispose(),e.material=t;Kh.length>0&&(Kh.length=0,$.sceneContext.requestRender())}var Yh=document.createElement(`div`);Yh.id=`fluidcad-region-pick-trigger`,Yh.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,Yh.innerHTML=`
4858
4858
  <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">
4859
- <span class="[&>svg]:size-5">${zp}</span>
4859
+ <span class="[&>svg]:size-5">${Rp}</span>
4860
4860
  <span>Pick Regions</span>
4861
4861
  </button>
4862
4862
  `,yh.appendChild(Yh);var Xh=document.createElement(`div`);Xh.id=`fluidcad-region-pick-active`,Xh.className=`absolute top-4 left-1/2 -translate-x-1/2 z-[999] pointer-events-auto hidden`,Xh.innerHTML=`
@@ -4880,13 +4880,13 @@ void main() {
4880
4880
  </div>
4881
4881
  `,yh.appendChild(lg),lg.querySelector(`[data-snap="vertex"]`).addEventListener(`change`,e=>{ug&&(ug.snapController.snapToVertices=e.target.checked)}),lg.querySelector(`[data-snap="grid"]`).addEventListener(`change`,e=>{ug&&(ug.snapController.snapToGrid=e.target.checked)});var ug=null,dg=null;function fg(e){let t=null;for(let n=e.length-1;n>=0;n--)if(bh(e[n],e)){t=e[n];break}if(!t||t.type!==`sketch`||!t.id)return!1;for(let n=e.length-1;n>=0;n--)if(e[n].parentId===t.id)return e[n].type===`bezier`;return!1}function pg(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.parentId===t&&r.type===`bezier`){let e=r.object?.startPoint,t=r.object?.resolvedPoints;return e?[e,...t||[]]:[]}}return[]}function mg(e){let t=null;for(let n=e.length-1;n>=0;n--)if(bh(e[n],e)){t=e[n];break}let n=t?.type===`sketch`?t:null;if(!n||!n.id||!n.object?.plane){hg();return}let r=null;for(let t=e.length-1;t>=0;t--)if(e[t].parentId===n.id){r=e[t];break}if(!r||r.type!==`bezier`||!r.sourceLocation){hg();return}let i=r.sourceLocation.line,a=n.object.plane,o=pg(e,n.id),s=_h.fromSceneObjects(e,n.id,a);if(ug&&dg===i){ug.updateExistingPoles(o),ug.snapController.updateSnapManager(s);return}hg();let c=r.sourceLocation,l=new vh(s,a),u=lg.querySelector(`[data-snap="vertex"]`),d=lg.querySelector(`[data-snap="grid"]`);u&&(l.snapToVertices=u.checked),d&&(l.snapToGrid=d.checked),ug=new dh($.sceneContext,a,l,o,e=>{fetch(`/api/insert-point`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({point:e,sourceLocation:c})})},e=>{fetch(`/api/set-pick-points`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({points:e,sourceLocation:c})})}),dg=i,ug.activate(),lg.classList.remove(`hidden`)}function hg(){ug&&(ug.deactivate(),ug=null,dg=null),lg.classList.add(`hidden`)}var gg=document.createElement(`div`);gg.className=`absolute bottom-6 left-6 z-[100]`,gg.innerHTML=`
4882
4882
  <button class="btn btn-ghost btn-square btn-sm text-base-content/60" title="Import File">
4883
- <span class="[&>svg]:size-5">${Fp}</span>
4883
+ <span class="[&>svg]:size-5">${Pp}</span>
4884
4884
  </button>
4885
4885
  `,yh.appendChild(gg);var _g=document.createElement(`div`);_g.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`,yh.appendChild(_g);var vg=null;function yg(e,t){t?(_g.innerHTML=`
4886
4886
  <div class="flex items-center gap-2">
4887
4887
  <span>${e} <code class="bg-base-content/10 px-1.5 py-0.5 rounded text-base-content/90">${t}</code></span>
4888
4888
  <button class="btn btn-ghost btn-square btn-xs text-base-content/60 import-toast-copy" title="Copy">
4889
- <span class="[&>svg]:size-3.5">${Ip}</span>
4889
+ <span class="[&>svg]:size-3.5">${Fp}</span>
4890
4890
  </button>
4891
4891
  </div>
4892
4892
  `,_g.querySelector(`.import-toast-copy`).addEventListener(`click`,()=>{navigator.clipboard.writeText(t);let e=_g.querySelector(`.import-toast-copy`);e.setAttribute(`title`,`Copied!`),setTimeout(()=>e.setAttribute(`title`,`Copy`),1500)})):_g.textContent=e,_g.classList.remove(`hidden`),vg&&clearTimeout(vg),vg=setTimeout(()=>{_g.classList.add(`hidden`),vg=null},6e3)}var bg=document.createElement(`input`);bg.type=`file`,bg.accept=`.step,.stp`,bg.style.display=`none`,yh.appendChild(bg),gg.querySelector(`button`).addEventListener(`click`,()=>{bg.click()}),bg.addEventListener(`change`,async()=>{let e=bg.files?.[0];if(e){bg.value=``,Ch(`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 fetch(`/api/import-file`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({fileName:e.name,data:i})}),o=await a.json();!a.ok||!o.success?yg(`Import failed: ${o.error||`Unknown error`}`):yg(`Imported! Use:`,`load('${o.fileName}')`)}catch{yg(`Import failed: network error`)}finally{wh()}}});async function xg(e,t,n){try{let r=await(await Tm($.sceneContext,n)).arrayBuffer(),i=new Uint8Array(r),a=``;for(let e=0;e<i.length;e++)a+=String.fromCharCode(i[e]);e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!0,data:btoa(a)}))}catch(n){e.send(JSON.stringify({type:`screenshot-result`,requestId:t,success:!1,error:n.message||String(n)}))}}function Sg(){let e=`ws://${window.location.host}`,t=new WebSocket(e);t.addEventListener(`message`,e=>{let n=JSON.parse(e.data);switch(n.type){case`init-complete`:Ch(`Loading model...`);break;case`processing-file`:Ch(`Loading model...`);break;case`scene-rendered`:{wh();let e=n.rollbackStop!=null&&n.rollbackStop<n.result.length-1;$.isTrimming=!e&&Mh===`picking-active`,$.isBezierDrawing=!e&&fg(n.result),$.updateView(n.result,e),n.absPath&&$.setFileName(n.absPath),e?(Hh(),sg(),hg()):(Uh(n.result),cg(n.result),mg(n.result)),kh.update(n.result,n.rollbackStop??n.result.length-1,n.absPath),n.breakpointHit!==void 0&&Oh.setActive(n.breakpointHit);break}case`highlight-shape`:$.highlightShape(n.shapeId),Th.setSelectedShape(n.shapeId);break;case`clear-highlight`:$.clearHighlight(),Th.setSelectedShape(null),Eh.hide();break;case`show-shape-properties`:$.clearHighlight(),Eh.hide(),Th.show(n.shapeId);break;case`take-screenshot`:xg(t,n.requestId,n.options);break}}),t.addEventListener(`close`,()=>{setTimeout(Sg,1e3)})}Sg();