string-tune-3d 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var Q=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ie=Object.prototype.hasOwnProperty;var ne=(b,t)=>{for(var e in t)Q(b,e,{get:t[e],enumerable:!0})},ae=(b,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of re(t))!ie.call(b,i)&&i!==e&&Q(b,i,{get:()=>t[i],enumerable:!(r=te(t,i))||r.enumerable});return b};var se=b=>ae(Q({},"__esModule",{value:!0}),b);var le={};ne(le,{String3D:()=>$,String3DCamera:()=>W,String3DCustomFilterRegistry:()=>k,String3DObject:()=>E,String3DRenderer:()=>H,String3DScene:()=>A,String3DSynchronizer:()=>V,ThreeJSEngine:()=>U,ThreeJSProvider:()=>q});module.exports=se(le);var ee=require("@fiddle-digital/string-tune");var W=class{constructor(t,e="orthographic",r=50,i=.1,n=1e4){this.scaleCache=new Map;this._width=1;this._height=1;this.engine=t,this.mode=e,this.perspectiveFov=r,e==="orthographic"?this._camera=t.createOrthographicCamera(-1,1,1,-1,i,n):this._camera=t.createPerspectiveCamera(r,1,i,n),this._position=t.createVector3(0,0,1e3),this.update()}get camera(){return this._camera}resize(t,e){if(this._width=t,this._height=e,this.mode==="orthographic"){let r=this._camera;r.left=-t/2,r.right=t/2,r.top=e/2,r.bottom=-e/2}else this._camera.aspect=t/e;this.update()}setPosition(t,e,r){this._position.set(t,e,r),this._camera.position.copy(this._position),this.update()}lookAt(t,e,r){this._camera.lookAt(t,e,r),this.update()}update(){this._camera.updateProjectionMatrix(),this._camera.updateMatrixWorld?.()}screenToWorld(t,e,r=0){if(this.mode==="orthographic"){let i=t-this._width/2,n=-(e-this._height/2);return this.engine.createVector3(i,n,r)}else{let{width:i,height:n}=this.getFrustumSizeAt(r),a=t/this._width,o=e/this._height,l=(a-.5)*i,s=-(o-.5)*n;return this.engine.createVector3(l,s,r)}}getFrustumSizeAt(t){if(this.mode==="orthographic")return{width:this._width,height:this._height};let e=this.engine.degToRad(this.perspectiveFov),r=Math.abs(t-this._camera.position.z),i=2*Math.tan(e/2)*r;return{width:i*this._camera.aspect,height:i}}getScaleAtZ(t,e){if(this.mode==="orthographic")return 1;let r=Math.round(t*1e3)/1e3;if(this.scaleCache.has(r))return this.scaleCache.get(r);let{height:i}=this.getFrustumSizeAt(t),n=i/e;return this.scaleCache.set(r,n),n}clearScaleCache(){this.scaleCache.clear()}getMode(){return this.mode}getPerspectiveFov(){return this.perspectiveFov}getPositionZ(){return this._position.z}};var k=class{static register(t){let e=t.name.trim().toLowerCase();if(!e)throw new Error("[String3D] Custom filter name is required.");this.filters.set(e,{...t,name:e})}static get(t){return this.filters.get(t.trim().toLowerCase())}static has(t){return this.filters.has(t.trim().toLowerCase())}static list(){return Array.from(this.filters.values())}};k.filters=new Map;var J=class{constructor(t){this.pool=[];this.create=t}acquire(t,e){let r=this.pool.pop()||this.create(t,e);return(r.width!==t||r.height!==e)&&r.setSize(t,e),r}release(t){this.pool.push(t)}dispose(){this.pool.forEach(t=>t.dispose()),this.pool=[]}},X=class{constructor(t,e,r,i){this.scale=1;this.customMaterials=new Map;this.engine=t,this.renderer=e,this.width=r,this.height=i,this.scene=t.createScene(),this.camera=t.createOrthographicCamera(-1,1,1,-1,0,1);let n=t.createPlaneGeometry(2,2);this.copyMaterial=this.createCopyMaterial(),this.blurMaterial=this.createBlurMaterial(),this.pixelMaterial=this.createPixelMaterial(),this.bloomExtractMaterial=this.createBloomExtractMaterial(),this.bloomAddMaterial=this.createBloomAddMaterial(),this.colorMaterial=this.createColorMaterial(),this.quad=t.createMesh(n,this.copyMaterial),this.scene.add(this.quad);let a=(o,l)=>{if(!this.engine.createRenderTarget)throw new Error("[String3DFilterPipeline] Render target support missing.");return this.engine.createRenderTarget(o,l)};this.pool=new J(a)}isSupported(){return!!this.engine.createRenderTarget&&!!this.engine.createShaderMaterial&&!!this.renderer.setRenderTarget}resize(t,e){this.width=t,this.height=e}setScale(t){let e=Math.max(.75,Math.min(1,t));this.scale=e}applyFilters(t,e,r=1){let i=t,n=[],a=l=>{let s=n.indexOf(l);s>=0&&(n.splice(s,1),this.pool.release(l))},o=()=>{let{width:l,height:s}=this.getScaledSize(),c=this.pool.acquire(l,s);return n.push(c),c};return e.forEach(l=>{if(l.type==="blur"){let s=l.amount*r;if(s<=1e-4)return;let c=o();this.renderPass(this.blurMaterial,i,c,{uDirection:[1,0],uRadius:s});let m=o();this.renderPass(this.blurMaterial,c,m,{uDirection:[0,1],uRadius:s}),a(c),i!==t&&a(i),i=m}else if(l.type==="pixel"){if(l.size<=.5)return;let s=o();this.renderPass(this.pixelMaterial,i,s,{uPixelSize:l.size}),i!==t&&a(i),i=s}else if(l.type==="bloom"){let s=l.intensity;if(s<=1e-4||l.threshold>=.99)return;let c=Math.max(1,4*r),m=o();this.renderPass(this.bloomExtractMaterial,i,m,{uThreshold:l.threshold});let h=o();this.renderPass(this.blurMaterial,m,h,{uDirection:[1,0],uRadius:c});let u=o();this.renderPass(this.blurMaterial,h,u,{uDirection:[0,1],uRadius:c}),a(m),a(h);let p=o();this.renderAddPass(i,u,p,s),a(u),i!==t&&a(i),i=p}else if(l.type==="brightness"||l.type==="contrast"||l.type==="saturate"||l.type==="grayscale"||l.type==="sepia"||l.type==="invert"||l.type==="hue-rotate"){let s=o(),c=this.getColorMode(l.type),m=l.type==="hue-rotate"?l.angle:l.amount;this.renderPass(this.colorMaterial,i,s,{uMode:c,uAmount:m}),i!==t&&a(i),i=s}else if(l.type==="custom"){let s=o(),c=this.getCustomMaterial(l.name);c?(this.renderPass(c,i,s,l.uniforms),i!==t&&a(i),i=s):a(s)}}),n.forEach(l=>{l!==i&&this.pool.release(l)}),i}acquireTarget(){let{width:t,height:e}=this.getScaledSize();return this.pool.acquire(t,e)}releaseTarget(t){this.pool.release(t)}renderToScreen(t){this.renderPass(this.copyMaterial,t,null,{},!1)}dispose(){this.pool.dispose(),this.customMaterials.forEach(t=>t.dispose()),this.customMaterials.clear()}renderPass(t,e,r,i={},n=!0){let a=this.renderer;a.setRenderTarget&&a.setRenderTarget(r),this.setMaterial(this.quad,t),this.setUniform(t,"tDiffuse",e.texture);let{width:o,height:l}=this.getScaledSize();this.setUniform(t,"uResolution",[o,l]),this.setUniform(t,"uTexel",[1/o,1/l]),Object.entries(i).forEach(([s,c])=>this.setUniform(t,s,c)),n&&a.clear&&a.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera)}renderAddPass(t,e,r,i){let n=this.renderer;n.setRenderTarget&&n.setRenderTarget(r),this.setMaterial(this.quad,this.bloomAddMaterial),this.setUniform(this.bloomAddMaterial,"tBase",t.texture),this.setUniform(this.bloomAddMaterial,"tBloom",e.texture),this.setUniform(this.bloomAddMaterial,"uIntensity",i);let{width:a,height:o}=this.getScaledSize();this.setUniform(this.bloomAddMaterial,"uResolution",[a,o]),n.clear&&n.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera)}setMaterial(t,e){let r=t;r.material!==e&&(r.material=e)}setUniform(t,e,r){let i=t.uniforms;i&&(i[e]?i[e].value=r:i[e]={value:r})}createCopyMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null}},vertexShader:this.getVertexShader(),fragmentShader:`
1
+ "use strict";var Ue=Object.defineProperty;var nt=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var ot=(g,e)=>{for(var t in e)Ue(g,t,{get:e[t],enumerable:!0})},lt=(g,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of at(e))!st.call(g,i)&&i!==t&&Ue(g,i,{get:()=>e[i],enumerable:!(r=nt(e,i))||r.enumerable});return g};var ct=g=>lt(Ue({},"__esModule",{value:!0}),g);var gt={};ot(gt,{FontConverter:()=>ee,String3D:()=>Ne,String3DCamera:()=>fe,String3DCustomFilterRegistry:()=>ae,String3DCustomMaterialRegistry:()=>K,String3DFontRegistry:()=>X,String3DObject:()=>$,String3DRenderer:()=>ge,String3DScene:()=>be,String3DSynchronizer:()=>Me,ThreeJSEngine:()=>Fe,ThreeJSMaterialFactory:()=>xe,ThreeJSProvider:()=>_e});module.exports=ct(gt);var tt=require("@fiddle-digital/string-tune");var fe=class{constructor(e,t="perspective",r=50,i=.1,n=1e4){this.scaleCache=new Map;this._width=1;this._height=1;this.engine=e,this.mode=t,this.perspectiveFov=r,t==="orthographic"?this._camera=e.createOrthographicCamera(-1,1,1,-1,i,n):this._camera=e.createPerspectiveCamera(r,1,i,n),this._position=e.createVector3(0,0,1e3),this.update()}get camera(){return this._camera}resize(e,t){if(this._width=e,this._height=t,this.mode==="orthographic"){let r=this._camera;r.left=-e/2,r.right=e/2,r.top=t/2,r.bottom=-t/2}else this._camera.aspect=e/t;this.update()}setPosition(e,t,r){this._position.set(e,t,r),this._camera.position.copy(this._position),this.update()}lookAt(e,t,r){this._camera.lookAt(e,t,r),this.update()}update(){this._camera.updateProjectionMatrix(),this._camera.updateMatrixWorld?.()}screenToWorld(e,t,r=0){if(this.mode==="orthographic"){let i=e-this._width/2,n=-(t-this._height/2);return this.engine.createVector3(i,n,r)}else{let{width:i,height:n}=this.getFrustumSizeAt(r),a=e/this._width,o=t/this._height,s=(a-.5)*i,l=-(o-.5)*n;return this.engine.createVector3(s,l,r)}}getFrustumSizeAt(e){if(this.mode==="orthographic")return{width:this._width,height:this._height};let t=this.engine.degToRad(this.perspectiveFov),r=Math.abs(e-this._camera.position.z),i=2*Math.tan(t/2)*r;return{width:i*this._camera.aspect,height:i}}getScaleAtZ(e,t){if(this.mode==="orthographic")return 1;let r=Math.round(e*1e3)/1e3;if(this.scaleCache.has(r))return this.scaleCache.get(r);let{height:i}=this.getFrustumSizeAt(e),n=i/t;return this.scaleCache.set(r,n),n}clearScaleCache(){this.scaleCache.clear()}getMode(){return this.mode}getPerspectiveFov(){return this.perspectiveFov}getPositionZ(){return this._position.z}};var ae=class{static register(e){let t=e.name.trim().toLowerCase();if(!t)throw new Error("[String3D] Custom filter name is required.");this.filters.set(t,{...e,name:t})}static get(e){return this.filters.get(e.trim().toLowerCase())}static has(e){return this.filters.has(e.trim().toLowerCase())}static list(){return Array.from(this.filters.values())}};ae.filters=new Map;var We=class{constructor(e){this.pool=[];this.create=e}acquire(e,t){let r=this.pool.pop()||this.create(e,t);return(r.width!==e||r.height!==t)&&r.setSize(e,t),r}release(e){this.pool.push(e)}dispose(){this.pool.forEach(e=>e.dispose()),this.pool=[]}},Te=class{constructor(e,t,r,i){this.scale=1;this.customMaterials=new Map;this.engine=e,this.renderer=t,this.width=r,this.height=i,this.scene=e.createScene(),this.camera=e.createOrthographicCamera(-1,1,1,-1,0,1);let n=e.createPlaneGeometry(2,2);this.copyMaterial=this.createCopyMaterial(),this.blurMaterial=this.createBlurMaterial(),this.pixelMaterial=this.createPixelMaterial(),this.bloomExtractMaterial=this.createBloomExtractMaterial(),this.bloomAddMaterial=this.createBloomAddMaterial(),this.colorMaterial=this.createColorMaterial(),this.quad=e.createMesh(n,this.copyMaterial),this.scene.add(this.quad);let a=(o,s)=>{if(!this.engine.createRenderTarget)throw new Error("[String3DFilterPipeline] Render target support missing.");return this.engine.createRenderTarget(o,s)};this.pool=new We(a)}isSupported(){return!!this.engine.createRenderTarget&&!!this.engine.createShaderMaterial&&!!this.renderer.setRenderTarget}resize(e,t){this.width=e,this.height=t}setScale(e){let t=Math.max(.75,Math.min(1,e));this.scale=t}applyFilters(e,t,r=1){let i=e,n=[],a=s=>{let l=n.indexOf(s);l>=0&&(n.splice(l,1),this.pool.release(s))},o=()=>{let{width:s,height:l}=this.getScaledSize(),c=this.pool.acquire(s,l);return n.push(c),c};return t.forEach(s=>{if(s.type==="blur"){let l=s.amount*r;if(l<=1e-4)return;let c=o();this.renderPass(this.blurMaterial,i,c,{uDirection:[1,0],uRadius:l});let h=o();this.renderPass(this.blurMaterial,c,h,{uDirection:[0,1],uRadius:l}),a(c),i!==e&&a(i),i=h}else if(s.type==="pixel"){if(s.size<=.5)return;let l=o();this.renderPass(this.pixelMaterial,i,l,{uPixelSize:s.size}),i!==e&&a(i),i=l}else if(s.type==="bloom"){let l=s.intensity;if(l<=1e-4||s.threshold>=.99)return;let c=Math.max(1,4*r),h=o();this.renderPass(this.bloomExtractMaterial,i,h,{uThreshold:s.threshold});let u=o();this.renderPass(this.blurMaterial,h,u,{uDirection:[1,0],uRadius:c});let m=o();this.renderPass(this.blurMaterial,u,m,{uDirection:[0,1],uRadius:c}),a(h),a(u);let d=o();this.renderAddPass(i,m,d,l),a(m),i!==e&&a(i),i=d}else if(s.type==="brightness"||s.type==="contrast"||s.type==="saturate"||s.type==="grayscale"||s.type==="sepia"||s.type==="invert"||s.type==="hue-rotate"){let l=o(),c=this.getColorMode(s.type),h=s.type==="hue-rotate"?s.angle:s.amount;this.renderPass(this.colorMaterial,i,l,{uMode:c,uAmount:h}),i!==e&&a(i),i=l}else if(s.type==="custom"){let l=o(),c=this.getCustomMaterial(s.name);c?(this.renderPass(c,i,l,s.uniforms),i!==e&&a(i),i=l):a(l)}}),n.forEach(s=>{s!==i&&this.pool.release(s)}),i}acquireTarget(){let{width:e,height:t}=this.getScaledSize();return this.pool.acquire(e,t)}releaseTarget(e){this.pool.release(e)}renderToScreen(e){this.renderPass(this.copyMaterial,e,null,{},!1)}dispose(){this.pool.dispose(),this.customMaterials.forEach(e=>e.dispose()),this.customMaterials.clear()}renderPass(e,t,r,i={},n=!0){let a=this.renderer;a.setRenderTarget&&a.setRenderTarget(r),this.setMaterial(this.quad,e),this.setUniform(e,"tDiffuse",t.texture);let{width:o,height:s}=this.getScaledSize();this.setUniform(e,"uResolution",[o,s]),this.setUniform(e,"uTexel",[1/o,1/s]),Object.entries(i).forEach(([l,c])=>this.setUniform(e,l,c)),n&&a.clear&&a.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera)}renderAddPass(e,t,r,i){let n=this.renderer;n.setRenderTarget&&n.setRenderTarget(r),this.setMaterial(this.quad,this.bloomAddMaterial),this.setUniform(this.bloomAddMaterial,"tBase",e.texture),this.setUniform(this.bloomAddMaterial,"tBloom",t.texture),this.setUniform(this.bloomAddMaterial,"uIntensity",i);let{width:a,height:o}=this.getScaledSize();this.setUniform(this.bloomAddMaterial,"uResolution",[a,o]),n.clear&&n.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera)}setMaterial(e,t){let r=e;r.material!==t&&(r.material=t)}setUniform(e,t,r){let i=e.uniforms;i&&(i[t]?i[t].value=r:i[t]={value:r})}createCopyMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null}},vertexShader:this.getVertexShader(),fragmentShader:`
2
2
  varying vec2 vUv;
3
3
  uniform sampler2D tDiffuse;
4
4
  void main() {
@@ -105,146 +105,15 @@
105
105
 
106
106
  gl_FragColor = color;
107
107
  }
108
- `,transparent:!0,depthTest:!1,depthWrite:!1})}getColorMode(t){switch(t){case"brightness":return 1;case"contrast":return 2;case"saturate":return 3;case"grayscale":return 4;case"sepia":return 5;case"invert":return 6;case"hue-rotate":return 7;default:return 0}}createShaderMaterial(t){if(!this.engine.createShaderMaterial)throw new Error("[String3DFilterPipeline] Shader material support missing.");return this.engine.createShaderMaterial(t)}getCustomMaterial(t){let e=t.trim().toLowerCase();if(!e)return null;if(this.customMaterials.has(e))return this.customMaterials.get(e);let r=k.get(e);if(!r)return null;let i={tDiffuse:{value:null}},{width:n,height:a}=this.getScaledSize();i.uResolution={value:[n,a]},i.uTexel={value:[1/n,1/a]},Object.entries(r.uniforms||{}).forEach(([l,s])=>{i[l]={value:s}});let o=this.createShaderMaterial({uniforms:i,vertexShader:this.getVertexShader(),fragmentShader:r.fragmentShader,transparent:!0,depthTest:!1,depthWrite:!1});return this.customMaterials.set(e,o),o}getScaledSize(){let t=Math.max(1,Math.round(this.width*this.scale)),e=Math.max(1,Math.round(this.height*this.scale));return{width:t,height:e}}getVertexShader(){return`
108
+ `,transparent:!0,depthTest:!1,depthWrite:!1})}getColorMode(e){switch(e){case"brightness":return 1;case"contrast":return 2;case"saturate":return 3;case"grayscale":return 4;case"sepia":return 5;case"invert":return 6;case"hue-rotate":return 7;default:return 0}}createShaderMaterial(e){if(!this.engine.createShaderMaterial)throw new Error("[String3DFilterPipeline] Shader material support missing.");return this.engine.createShaderMaterial(e)}getCustomMaterial(e){let t=e.trim().toLowerCase();if(!t)return null;if(this.customMaterials.has(t))return this.customMaterials.get(t);let r=ae.get(t);if(!r)return null;let i={tDiffuse:{value:null}},{width:n,height:a}=this.getScaledSize();i.uResolution={value:[n,a]},i.uTexel={value:[1/n,1/a]},Object.entries(r.uniforms||{}).forEach(([s,l])=>{i[s]={value:l}});let o=this.createShaderMaterial({uniforms:i,vertexShader:this.getVertexShader(),fragmentShader:r.fragmentShader,transparent:!0,depthTest:!1,depthWrite:!1});return this.customMaterials.set(t,o),o}getScaledSize(){let e=Math.max(1,Math.round(this.width*this.scale)),t=Math.max(1,Math.round(this.height*this.scale));return{width:e,height:t}}getVertexShader(){return`
109
109
  varying vec2 vUv;
110
110
  void main() {
111
111
  vUv = uv;
112
112
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
113
113
  }
114
- `}};var H=class{constructor(t,e){this.filterPipeline=null;this.filterCache=new Map;this.frameId=0;this.lastFrameTime=performance.now();this.avgFrameMs=16.7;this.qualityScale=1;this.lastQualityChange=0;this.filterLayer=1;this.engine=e,this._container=t;let{width:r,height:i}=t.getBoundingClientRect();this._width=r,this._height=i,this._renderer=e.createRenderer({antialias:!0,alpha:!0,logarithmicDepthBuffer:!0}),this._renderer.setPixelRatio(window.devicePixelRatio),this._renderer.setSize(r,i),this._renderer.shadowMap&&(this._renderer.shadowMap.enabled=!0)}attach(){this._container.appendChild(this._renderer.domElement)}render(t,e,r=[]){if(r.length===0){this._renderer.render(t.getScene(),e.camera);return}let i=this.ensureFilterPipeline();if(!i?.isSupported()){this._renderer.render(t.getScene(),e.camera);return}this.frameId+=1,this.updateQuality(r.length,i);let n=t.getAllObjects(),a=new Map;n.forEach(h=>{let u=h.object;"visible"in u&&a.set(h.object,u.visible)});let o=new Set;r.forEach(h=>{this.collectSubtreeObjects(h.object,o)}),n.forEach(h=>{o.has(h.object)&&this.setVisible(h.object,!1)});let l=this._renderer,s=l.autoClear;l.autoClear=!0,l.setRenderTarget&&l.setRenderTarget(null),l.clear&&l.clear(!0,!0,!0),this._renderer.render(t.getScene(),e.camera),l.autoClear=!1,n.forEach(h=>{let u=a.get(h.object);typeof u<"u"&&this.setVisible(h.object,u)});let c=n.filter(h=>h.type.endsWith("Light")),m=this.supportsLayers(e.camera,n);r.forEach(h=>{let u=this.filterCache.get(h.object.id);if(!h.dirty&&u&&u.effectsKey===h.effectsKey&&u.qualityScale===this.qualityScale){u.lastUsedFrame=this.frameId,i.renderToScreen(u.target);return}let d=this.injectEffectContext(h.object.el,h.effects),g=new Set;this.collectSubtreeObjects(h.object,g);let v=[],M=null;if(m){let f=h.object.getSubtreeObjects();v=this.applyLayerMask(f,c,this.filterLayer),M=this.setCameraLayer(e.camera,this.filterLayer)}else n.forEach(f=>{if(a.get(f.object)===!1){this.setVisible(f.object,!1);return}if(f.type.endsWith("Light")){this.setVisible(f.object,!0);return}this.setVisible(f.object,g.has(f.object))});let x=i.acquireTarget();l.setRenderTarget&&l.setRenderTarget(x),l.clear&&l.clear(!0,!0,!0),this._renderer.render(t.getScene(),e.camera);let y=i.applyFilters(x,d,this.qualityScale);l.setRenderTarget&&l.setRenderTarget(null),i.renderToScreen(y),m&&(this.restoreLayerMask(v),M!==null&&this.restoreCameraLayer(e.camera,M)),y!==x&&i.releaseTarget(x);let S={target:y,effectsKey:h.effectsKey,lastUsedFrame:this.frameId,qualityScale:this.qualityScale},D=this.filterCache.get(h.object.id);D&&D.target!==y&&i.releaseTarget(D.target),this.filterCache.set(h.object.id,S)}),m||n.forEach(h=>{let u=a.get(h.object);typeof u<"u"&&this.setVisible(h.object,u)}),l.autoClear=s,this.evictCache()}resize(t){let{width:e,height:r}=this._container.getBoundingClientRect();this._width=e,this._height=r,this._renderer.setSize(e,r),t.resize(e,r),this.filterPipeline?.resize(e,r),this.invalidateFilterCache()}get width(){return this._width}get height(){return this._height}get renderer(){return this._renderer}destroy(){this._renderer.dispose(),this.filterPipeline?.dispose(),this.filterCache.clear()}ensureFilterPipeline(){return this.canCreateFilterPipeline()?(this.filterPipeline||(this.filterPipeline=new X(this.engine,this._renderer,this._width,this._height),this.filterPipeline.setScale(this.qualityScale)),this.filterPipeline):null}canCreateFilterPipeline(){return typeof this.engine.createRenderTarget=="function"&&typeof this.engine.createShaderMaterial=="function"&&typeof this._renderer.setRenderTarget=="function"}collectSubtreeObjects(t,e){e.add(t.object),t.children.forEach(r=>this.collectSubtreeObjects(r,e))}setVisible(t,e){let r=t;"visible"in r&&(r.visible=e)}getFilterCenter(t){if(!t||!this._width||!this._height)return[.5,.5];let e=t.getBoundingClientRect(),r=(e.left+e.width/2)/this._width,i=1-(e.top+e.height/2)/this._height,n=a=>Math.max(0,Math.min(1,a));return[n(r),n(i)]}injectEffectContext(t,e){if(!e.some(a=>a.type==="custom"))return e;let r=this.getFilterCenter(t),i=!1,n=e.map(a=>{if(a.type!=="custom"||a.uniforms&&"uCenter"in a.uniforms)return a;let o={...a.uniforms||{},uCenter:r};return i=!0,{...a,uniforms:o}});return i?n:e}updateQuality(t,e){let r=performance.now(),i=Math.max(.1,r-this.lastFrameTime);this.lastFrameTime=r,this.avgFrameMs=this.avgFrameMs*.9+i*.1;let n=1e3/this.avgFrameMs,a=Math.max(.75,1-Math.min(.4,t*.03)),o=a;n<48&&(o=Math.max(.75,a-.1)),n<40&&(o=Math.max(.75,a-.2)),n>58&&(o=Math.min(1,a+.05)),Math.abs(o-this.qualityScale)>=.05&&r-this.lastQualityChange>300&&(this.qualityScale=o,this.lastQualityChange=r,e.setScale(this.qualityScale),this.invalidateFilterCache())}invalidateFilterCache(){this.filterPipeline&&(this.filterCache.forEach(t=>{this.filterPipeline?.releaseTarget(t.target)}),this.filterCache.clear())}evictCache(){if(!this.filterPipeline)return;let t=120;this.filterCache.forEach((e,r)=>{this.frameId-e.lastUsedFrame>t&&(this.filterPipeline?.releaseTarget(e.target),this.filterCache.delete(r))})}supportsLayers(t,e){return!t?.layers||typeof t.layers.set!="function"?!1:e.some(r=>this.hasLayers(r.object))}hasLayers(t){return t?.layers&&typeof t.layers.set=="function"}applyLayerMask(t,e,r){let i=new Map,n=(a,o)=>{let l=a;this.hasLayers(l)&&(i.has(a)||i.set(a,l.layers.mask),o==="set"?l.layers.set(r):l.layers.enable(r))};return t.forEach(a=>n(a,"set")),e.forEach(a=>n(a.object,"enable")),Array.from(i.entries()).map(([a,o])=>({object:a,mask:o}))}restoreLayerMask(t){t.forEach(e=>{let r=e.object;this.hasLayers(r)&&(r.layers.mask=e.mask)})}setCameraLayer(t,e){if(!t?.layers||typeof t.layers.set!="function")return null;let r=t.layers.mask;return t.layers.set(e),r}restoreCameraLayer(t,e){t?.layers&&(t.layers.mask=e)}};var E=class{constructor(t,e,r,i,n={}){this._uniforms={};this._children=[];this._flatObjectsCache=null;this._subtreeCache=null;this.id=t,this.type=e,this._object=r,this.engine=i,this._material=n.material,this._geometry=n.geometry,this._texture=n.texture,this._quaternion=i.createQuaternion(),this._originalSize=i.createVector3(),this._bbox=i.createBox3(),this.updateBoundingBox()}get children(){return this._children}get object(){return this._object}get material(){return this._material}get originalSize(){return this._originalSize.clone()}get boundingBox(){return this._bbox.clone()}addChild(t){this._children.push(t),this.object.add(t.object),this.invalidateFlatCache(),this.invalidateSubtreeCache()}getWorldMatrix(){return this._object.matrixWorld.clone()}getWorldPosition(){return this.engine.createVector3().setFromMatrixPosition(this._object.matrixWorld)}getOriginalBoundingBox(){if(!this._originalBoundingBox){let t=this.object.scale.clone();this.object.scale.set(1,1,1),this.object.updateMatrixWorld(!0),this._originalBoundingBox=this.engine.computeBoundingBoxRecursively(this.object),this.object.scale.copy(t),this.object.updateMatrixWorld(!0)}return this._originalBoundingBox.clone()}syncTransformFromMatrix(t){let e=this.engine.createVector3(),r=this.engine.createQuaternion(),i=this.engine.createVector3();t.decompose(e,r,i),this._object.position.copy(e),this._object.quaternion.copy(r),this._object.scale.copy(i),this._object.updateMatrix(),this._object.updateMatrixWorld()}applyWorldTransform(t,e,r){this._object.position.copy(t),this._object.quaternion.copy(e),this._object.scale.copy(r),this._object.updateMatrix(),this._object.updateMatrixWorld()}set quaternion(t){this._quaternion.copy(t),this._object.quaternion.copy(this._quaternion),this._object.updateMatrixWorld()}set position(t){this._object.position.copy(t)}set scale(t){this._object.scale.copy(t)}set rotation(t){this._object.rotation.copy(t)}set opacity(t){let e=this._object;e.material&&"opacity"in e.material&&(e.material.opacity=t)}set metalness(t){let e=this._object;e.material&&"metalness"in e.material&&(e.material.metalness=t)}set roughness(t){let e=this._object;e.material&&"roughness"in e.material&&(e.material.roughness=t)}set texture(t){this._texture=t,this._object.isMesh&&t?.applyTexture&&t.applyTexture(this._object)}set material(t){this._material=t}set geometry(t){this._geometry=t}updateBoundingBox(){this._bbox.setFromObject(this._object),this._bbox.getSize(this._originalSize)}destroy(){this.disposeObjectResources(this._object),this._texture?.dispose?.(),this._material?.dispose(),this._geometry?.dispose(),this._subtreeCache=null}getFlatObjects(){if(this._flatObjectsCache)return this._flatObjectsCache;let t=[],e=r=>{t.push(r.object),r.children.forEach(i=>e(i))};return e(this),this._flatObjectsCache=t,t}getSubtreeObjects(){if(this._subtreeCache)return this._subtreeCache;let t=[],e=this._object;return t.push(this._object),typeof e.traverse=="function"&&e.traverse(r=>{r&&r!==this._object&&t.push(r)}),this._subtreeCache=t,t}invalidateFlatCache(){this._flatObjectsCache=null}invalidateSubtreeCache(){this._subtreeCache=null}disposeObjectResources(t){let e=t;e?.geometry?.dispose&&e.geometry.dispose();let r=e?.material;Array.isArray(r)?r.forEach(i=>i?.dispose?.()):r?.dispose&&r.dispose(),typeof e?.traverse=="function"&&e.traverse(i=>{i?.geometry?.dispose&&i.geometry.dispose();let n=i?.material;Array.isArray(n)?n.forEach(a=>a?.dispose?.()):n?.dispose&&n.dispose()})}};var A=class{constructor(t,e={}){this._objects=new Map;this._rootObjects=[];this._elementMap=new Map;this._modelLoaderCache=new Map;this.engine=t,this._modelLoader=e.modelLoader,this._modelLoaderFactory=e.modelLoaderFactory,this._scene=t.createScene()}get rootObjects(){return this._rootObjects}getScene(){return this._scene}getObject(t){return this._objects.get(t)}getAllObjects(){let t=[],e=r=>{t.push(r),r.children.forEach(i=>e(i))};return this._rootObjects.forEach(r=>e(r)),t}hasObject(t){return this._objects.has(t)}deleteObject(t){let e=this._objects.get(t);return e?(this._scene.remove(e.object),this._objects.delete(t),e.destroy(),!0):!1}createFromElement(t){let e=t.getProperty("3d");if(!e)return;let r=t.htmlElement;if(!r)return;let i=n=>{if(n){let a=t.getProperty("parentId");a==null?(this._scene.add(n.object),this._rootObjects.push(n)):this._objects.get(a)?.addChild(n),this._objects.set(t.id,n),this._elementMap.set(t.id,r),n.el=r}};switch(e){case"group":this.createGroup(t,i);break;case"pointLight":this.createLight(t,"point",i);break;case"ambientLight":this.createLight(t,"ambient",i);break;case"directionalLight":this.createLight(t,"directional",i);break;case"spotLight":this.createLight(t,"spot",i);break;case"hemisphereLight":this.createLight(t,"hemisphere",i);break;case"model":this.createModel(t,i);break;case"box":this.createBox(t,i);break;case"sphere":this.createSphere(t,i);break;case"plane":this.createPlane(t,i);break;case"cylinder":this.createCylinder(t,i);break}}createGroup(t,e){let r=this.engine.createGroup(),i=new E(t.id,"group",r,this.engine);return e(i),i}createLight(t,e,r){let i=t.getProperty("3d-color")||"#ffffff",n=t.getProperty("3d-intensity")??1,a;if(e==="point"){let s=t.getProperty("3d-distance")??1e3,c=t.getProperty("3d-decay")??0;a=this.engine.createPointLight(i,n,s,c)}else if(e==="directional")a=this.engine.createDirectionalLight(i,n);else if(e==="spot"){let s=t.getProperty("3d-distance")??0,c=t.getProperty("3d-angle")??Math.PI/3,m=t.getProperty("3d-penumbra")??0,h=t.getProperty("3d-decay")??1;a=this.engine.createSpotLight(i,n,s,c,m,h)}else if(e==="hemisphere"){let s=t.getProperty("3d-ground-color")||"#ffffff";a=this.engine.createHemisphereLight(i,s,n)}else a=this.engine.createAmbientLight(i,n);if((t.getProperty("3d-cast-shadow")??!1)&&a.shadow){a.castShadow=!0;let s=t.getProperty("3d-shadow-bias")??0,c=t.getProperty("3d-shadow-map-size")??512;a.shadow.bias=s,a.shadow.mapSize.width=c,a.shadow.mapSize.height=c}let l=new E(t.id,e+"Light",a,this.engine);return r(l),l}applyShadowProps(t,e){let r=t.getProperty("3d-cast-shadow")??!1,i=t.getProperty("3d-receive-shadow")??!1;e.castShadow=r,e.receiveShadow=i}createBox(t,e){let r=this.engine.createBoxGeometry(1,1,1),i=this.createMaterialFromObject(t),n=this.engine.createMesh(r,i);this.applyShadowProps(t,n);let a=new E(t.id,"box",n,this.engine,{geometry:r,material:i});return e(a),a}createSphere(t,e){let r=t.getProperty("3d-segments-width")??32,i=t.getProperty("3d-segments-height")??32,n=this.engine.createSphereGeometry(.5,r,i),a=this.createMaterialFromObject(t),o=this.engine.createMesh(n,a);this.applyShadowProps(t,o);let l=new E(t.id,"sphere",o,this.engine,{geometry:n,material:a});return e(l),l}createPlane(t,e){let r=this.engine.createPlaneGeometry(1,1),i=this.createMaterialFromObject(t),n=this.engine.createMesh(r,i);this.applyShadowProps(t,n);let a=new E(t.id,"plane",n,this.engine,{geometry:r,material:i});return e(a),a}createCylinder(t,e){let r=t.getProperty("3d-segments")??32,i=this.engine.createCylinderGeometry(.5,.5,1,r),n=this.createMaterialFromObject(t),a=this.engine.createMesh(i,n);this.applyShadowProps(t,a);let o=new E(t.id,"cylinder",a,this.engine,{geometry:i,material:n});return e(o),o}createModel(t,e){let r=t.getProperty("3d-model");if(!r)return;let i=t.getProperty("3d-model-loader")||void 0,n=this.resolveModelLoader(i);if(!n){console.warn("[String3D] Model loader not configured");return}let a=t.htmlElement;a&&this.applyModelTextureRemap(n,a);let o=t.getProperty("3d-model-center")??!1;n.load(r,l=>{let s=l?.scene||l?.object||l;if(!s){console.warn("[String3D] Model loader returned empty result");return}let c=a&&this.shouldOverrideModelMaterial(a)?this.createMaterialFromElement(a,t):null;typeof s.traverse=="function"&&s.traverse(h=>{h.isMesh&&(c&&(h.material=c),this.applyShadowProps(t,h))}),o&&this.centerObject(s);let m=new E(t.id,"model",s,this.engine);e(m)},l=>{console.log(l.loaded/l.total*100+"% loaded")},l=>{console.error("[String3D] Model loading error:",l)})}resolveModelLoader(t){if(t){if(this._modelLoaderCache.has(t))return this._modelLoaderCache.get(t);if(!this._modelLoaderFactory){console.warn(`[String3D] No model loader factory for type "${t}"`);return}let e=this._modelLoaderFactory(this.engine,t);return this._modelLoaderCache.set(t,e),e}if(this._modelLoader)return this._modelLoader;if(this._modelLoaderFactory)return this._modelLoaderFactory(this.engine)}centerObject(t){if(!t)return;let e=this.engine.computeBoundingBoxRecursively(t),r=this.getBoxCenter(e);t.position?.set&&t.position.set(-r.x,-r.y,-r.z),t.updateMatrixWorld(!0)}getBoxCenter(t){let e=this.engine.createVector3();return e.x=(t.min.x+t.max.x)/2,e.y=(t.min.y+t.max.y)/2,e.z=(t.min.z+t.max.z)/2,e}createMaterialFromObject(t){return this.createMaterialFromElement(t.htmlElement,t)}createMaterialFromElement(t,e){let r=e?.getProperty("3d-material")||"basic[#ffffff]",[i,n]=r.split(/\[|\]/),a=n||"#ffffff",o=e?.getProperty("3d-opacity")??1,l=e?.getProperty("3d-metalness"),s=e?.getProperty("3d-roughness"),c={color:a,transparent:o<1,opacity:o},m=t?.getAttribute("string-3d-map"),h=t?.getAttribute("string-3d-normalMap"),u=t?.getAttribute("string-3d-roughnessMap"),p=t?.getAttribute("string-3d-metalnessMap"),d=t?.getAttribute("string-3d-aoMap"),g=this.parseFlipY(e,t),v=e?.getProperty("3d-colorSpace")||t?.getAttribute("string-3d-colorSpace")||"";return i!=="standard"&&!!(m||h||u||p||d)&&(i="standard"),i==="standard"?(m&&(c.map=this.loadTexture(m,{flipY:g,colorSpace:v})),h&&(c.normalMap=this.loadTexture(h,{flipY:g})),u&&(c.roughnessMap=this.loadTexture(u,{flipY:g})),p&&(c.metalnessMap=this.loadTexture(p,{flipY:g})),d&&(c.aoMap=this.loadTexture(d,{flipY:g})),typeof l=="number"&&(c.metalness=l),typeof s=="number"&&(c.roughness=s),this.engine.createMeshStandardMaterial(c)):this.engine.createMeshBasicMaterial(c)}loadTexture(t,e={}){let i=this.engine.createTextureLoader().load(t);typeof e.flipY=="boolean"&&(i.flipY=e.flipY);let n=(e.colorSpace||"").toLowerCase().trim();return n&&"colorSpace"in i&&(i.colorSpace=n==="srgb"?"srgb":"linear"),i.needsUpdate=!0,i}parseFlipY(t,e){let r=t?.getProperty("3d-texture-flipY")??e?.getAttribute("string-3d-texture-flipY");if(r==null||r==="")return;if(typeof r=="boolean")return r;let i=String(r).toLowerCase().trim();if(i==="false"||i==="0"||i==="no")return!1;if(i==="true"||i==="1"||i==="yes")return!0}shouldOverrideModelMaterial(t){return["string-3d-material","string-3d-color","string-3d-opacity","string-3d-map","string-3d-normalMap","string-3d-roughnessMap","string-3d-metalnessMap","string-3d-aoMap","string-3d-metalness","string-3d-roughness"].some(r=>t.hasAttribute(r))}applyModelTextureRemap(t,e){let r=(e.getAttribute("string-3d-model-texture-base")||"").trim(),i=r?r.replace(/\/?$/,"/"):"",n=e.getAttribute("string-3d-model-textures"),a=null;if(n)try{a=JSON.parse(n)}catch(l){console.warn("[String3D] Invalid model texture mapping JSON:",l)}let o=t?.manager;if(!o||typeof o.setURLModifier!="function"){(a||i)&&console.warn("[String3D] Model loader does not support URL remap.");return}o.setURLModifier(l=>{let s=a&&l in a?a[l]:l;return!i||/^(blob:|data:|https?:|file:|\/)/i.test(s)?s:i+s.replace(/^\.?\//,"")})}destroy(){this._objects.forEach(t=>t.destroy()),this._objects.clear(),this._rootObjects=[]}};var G=class{sync(t,e,r,i){let n=t.getBoundingClientRect(),a=n.left+n.width/2,o=n.top+n.height/2,l=t.computedStyleMap?.(),s=null,c=()=>(s||(s=getComputedStyle(t)),s),m=(M,x)=>{let y=l?.get?.(M);if(y!==void 0){if(typeof y=="number")return y;if(typeof y=="string"){let f=Number.parseFloat(y);if(!Number.isNaN(f))return f}if(y&&typeof y=="object"){let f=y.value;if(typeof f=="number")return f;if(typeof f=="string"){let I=Number.parseFloat(f);if(!Number.isNaN(I))return I}}}let S=c().getPropertyValue(M),D=Number.parseFloat(S);return Number.isNaN(D)?x:D},h=m("--translate-z",0),u=r.camera.screenToWorld(a,o,h);e.position=u;let p=m("--scale",1);e.scale=r.engine.createVector3(p,p,p);let d=-r.engine.degToRad(m("--rotate-x",0)),g=r.engine.degToRad(m("--rotate-y",0)),v=-r.engine.degToRad(m("--rotate-z",0));return e.rotation=r.engine.createEuler(d,g,v,"XYZ"),e.object.updateMatrixWorld(!0),{scale:p}}};var _=class{sync(t,e,r,i){let n=t.getBoundingClientRect(),a=n.left+n.width/2,o=n.top+n.height/2,l=parseFloat(getComputedStyle(t).getPropertyValue("--translate-z")||"0"),s=r.camera.screenToWorld(a,o,l);e.position=s;let c=e.object,m=t.getAttribute("string-3d-color");m&&c.color&&typeof c.color.set=="function"&&c.color.set(m);let h=t.getAttribute("string-3d-intensity");h&&(c.intensity=parseFloat(h));let u=t.getAttribute("string-3d-distance");u&&typeof c.distance<"u"&&(c.distance=parseFloat(u));let p=t.getAttribute("string-3d-decay");p&&typeof c.decay<"u"&&(c.decay=parseFloat(p));let d=t.getAttribute("string-3d-angle");d&&typeof c.angle<"u"&&(c.angle=parseFloat(d));let g=t.getAttribute("string-3d-penumbra");g&&typeof c.penumbra<"u"&&(c.penumbra=parseFloat(g));let v=t.getAttribute("string-3d-ground-color");v&&c.groundColor&&typeof c.groundColor.set=="function"&&c.groundColor.set(v);let M=t.getAttribute("string-3d-cast-shadow")==="true";if(c.castShadow!==M&&(c.castShadow=M),M&&c.shadow){let y=t.getAttribute("string-3d-shadow-bias");y&&(c.shadow.bias=parseFloat(y));let S=t.getAttribute("string-3d-shadow-map-size");if(S){let D=parseFloat(S);c.shadow.mapSize.width!==D&&(c.shadow.mapSize.width=D,c.shadow.mapSize.height=D)}}let x=t.getAttribute("string-3d-target");if(x&&c.target){let y=document.querySelector(`[string-id="${x}"]`);if(y){let S=y.getBoundingClientRect(),D=S.left+S.width/2,f=S.top+S.height/2,I=parseFloat(getComputedStyle(y).getPropertyValue("--translate-z")||"0"),T=r.camera.screenToWorld(D,f,I);c.target.position.copy(T),c.target.updateMatrixWorld(!0)}}return null}};var R=class b{static applyVisualProps(t,e,r){let i=t.getAttribute("string-3d-cast-shadow")==="true",n=t.getAttribute("string-3d-receive-shadow")==="true",a=typeof r=="number"?r:NaN;if(e.object.traverse)e.object.traverse(o=>{o.isMesh&&(o.castShadow!==i&&(o.castShadow=i),o.receiveShadow!==n&&(o.receiveShadow=n),isNaN(a)||(Array.isArray(o.material)?o.material:[o.material]).forEach(s=>{s&&(s.opacity=a,s.transparent=a<1)}))});else if(e.object.isMesh){let o=e.object;o.castShadow!==i&&(o.castShadow=i),o.receiveShadow!==n&&(o.receiveShadow=n),isNaN(a)||(Array.isArray(o.material)?o.material:[o.material]).forEach(s=>{s&&(s.opacity=a,s.transparent=a<1)})}}sync(t,e,r,i){let n=t.computedStyleMap?.(),a=null,o=()=>(a||(a=getComputedStyle(t)),a),l=t.getBoundingClientRect(),s=t.offsetWidth||l.width,c=t.offsetHeight||l.height,m=(C,P)=>{let L=n?.get?.(C);if(L!==void 0){if(typeof L=="number")return L;if(typeof L=="string"){let w=Number.parseFloat(L);if(!Number.isNaN(w))return w}if(L&&typeof L=="object"){let w=L.value;if(typeof w=="number")return w;if(typeof w=="string"){let B=Number.parseFloat(w);if(!Number.isNaN(B))return B}}}let Y=o().getPropertyValue(C),F=Number.parseFloat(Y);return Number.isNaN(F)?P:F},h=m("--translate-z",0),u=m("--scale",1),p=l.left+l.width/2,d=l.top+l.height/2,g=r.camera.screenToWorld(p,d,h);e.position=g;let v=-r.engine.degToRad(m("--rotate-x",0)),M=r.engine.degToRad(m("--rotate-y",0)),x=-r.engine.degToRad(m("--rotate-z",0));e.rotation=r.engine.createEuler(v,M,x,"XYZ");let y=s*u,S=c*u,D=m("--scale-z",1),f=i?.scale||1,I=e.type,T,j,O;switch(I){case"box":case"sphere":{let C=Math.min(y,S);T=C*f,j=C*f,O=C*D*f;break}case"model":{let P=e.getOriginalBoundingBox().getSize(r.engine.createVector3()),L=(t.getAttribute("string-3d-model-fit")||"contain").toLowerCase().trim(),Y=parseFloat(t.getAttribute("string-3d-model-scale")||"1"),F=Number.isFinite(Y)?Y:1;if(P.x>0&&P.y>0){let w=y/P.x,B=S/P.y,K=L==="cover"?Math.max(w,B):Math.min(w,B);T=K*F*f,j=K*F*f,O=K*F*D*f}else{let w=Math.min(y,S);T=w*F*f,j=w*F*f,O=w*F*D*f}break}case"cylinder":{let C=y;T=C*f,j=S*f,O=C*D*f;break}case"plane":default:T=y*f,j=S*f,O=Math.min(y,S)*.5*D*f;break}e.scale=r.engine.createVector3(T,j,O);let Z=m("--opacity",NaN);return b.applyVisualProps(t,e,Z),{scale:u*f}}};var V=class{constructor(t,e,r,i){this.camera=t;this.viewportWidth=e;this.viewportHeight=r;this.engine=i;this.strategies=new Map;this.strategies.set("box",new R),this.strategies.set("sphere",new R),this.strategies.set("plane",new R),this.strategies.set("cylinder",new R),this.strategies.set("model",new R),this.strategies.set("group",new G),this.strategies.set("pointLight",new _),this.strategies.set("ambientLight",new _),this.strategies.set("directionalLight",new _),this.strategies.set("spotLight",new _),this.strategies.set("hemisphereLight",new _)}syncElement(t,e,r){let i=this.strategies.get(e.type);return i?i.sync(t,e,{camera:this.camera,viewportWidth:this.viewportWidth,viewportHeight:this.viewportHeight,engine:this.engine},r):(console.warn(`[String3D Sync] No strategy for type "${e.type}"`),null)}updateViewportSize(t,e){this.viewportWidth=t,this.viewportHeight=e}};var oe=`
115
- let wasm = null;
116
- let wasmReady = false;
117
-
118
- function degToRad(deg) {
119
- return (deg * Math.PI) / 180;
120
- }
121
-
122
- function computeTransform(item, camera) {
123
- const centerX = item.rectLeft + item.rectWidth / 2;
124
- const centerY = item.rectTop + item.rectHeight / 2;
125
-
126
- let posX = 0;
127
- let posY = 0;
128
- let posZ = item.translateZ;
129
-
130
- if (camera.mode === "orthographic") {
131
- posX = centerX - camera.width / 2;
132
- posY = -(centerY - camera.height / 2);
133
- } else {
134
- const fov = degToRad(camera.fov);
135
- const distance = Math.abs(item.translateZ - camera.cameraZ);
136
- const height = 2 * Math.tan(fov / 2) * distance;
137
- const width = height * camera.aspect;
138
- const normalizedX = centerX / camera.width;
139
- const normalizedY = centerY / camera.height;
140
- posX = (normalizedX - 0.5) * width;
141
- posY = -(normalizedY - 0.5) * height;
142
- }
143
-
144
- const rotX = -degToRad(item.rotateX);
145
- const rotY = degToRad(item.rotateY);
146
- const rotZ = -degToRad(item.rotateZ);
147
-
148
- let scaleX = 1;
149
- let scaleY = 1;
150
- let scaleZ = 1;
151
-
152
- if (item.type === "group") {
153
- scaleX = item.scale;
154
- scaleY = item.scale;
155
- scaleZ = item.scale;
156
- } else {
157
- const targetWidth = item.rectWidth * item.scale;
158
- const targetHeight = item.rectHeight * item.scale;
159
- const parentScale = item.parentScale || 1;
160
- const cssScaleZ = item.scaleZ || 1;
161
-
162
- if (item.type === "box" || item.type === "sphere") {
163
- const uniformSize = Math.min(targetWidth, targetHeight);
164
- scaleX = uniformSize * parentScale;
165
- scaleY = uniformSize * parentScale;
166
- scaleZ = uniformSize * cssScaleZ * parentScale;
167
- } else if (item.type === "model") {
168
- const sizeX = item.modelSizeX || 0;
169
- const sizeY = item.modelSizeY || 0;
170
- const fitMode = (item.fitMode || "contain").toLowerCase().trim();
171
- const modelScale = Number.isFinite(item.modelScale) ? item.modelScale : 1;
172
-
173
- if (sizeX > 0 && sizeY > 0) {
174
- const scaleToWidth = targetWidth / sizeX;
175
- const scaleToHeight = targetHeight / sizeY;
176
- const uniformScale = fitMode === "cover"
177
- ? Math.max(scaleToWidth, scaleToHeight)
178
- : Math.min(scaleToWidth, scaleToHeight);
179
- scaleX = uniformScale * modelScale * parentScale;
180
- scaleY = uniformScale * modelScale * parentScale;
181
- scaleZ = uniformScale * modelScale * cssScaleZ * parentScale;
182
- } else {
183
- const fallbackSize = Math.min(targetWidth, targetHeight);
184
- scaleX = fallbackSize * modelScale * parentScale;
185
- scaleY = fallbackSize * modelScale * parentScale;
186
- scaleZ = fallbackSize * modelScale * cssScaleZ * parentScale;
187
- }
188
- } else if (item.type === "cylinder") {
189
- const cylRadius = targetWidth;
190
- scaleX = cylRadius * parentScale;
191
- scaleY = targetHeight * parentScale;
192
- scaleZ = cylRadius * cssScaleZ * parentScale;
193
- } else {
194
- scaleX = targetWidth * parentScale;
195
- scaleY = targetHeight * parentScale;
196
- scaleZ = Math.min(targetWidth, targetHeight) * 0.5 * cssScaleZ * parentScale;
197
- }
198
- }
199
-
200
- return {
201
- id: item.id,
202
- posX,
203
- posY,
204
- posZ,
205
- rotX,
206
- rotY,
207
- rotZ,
208
- scaleX,
209
- scaleY,
210
- scaleZ,
211
- };
212
- }
213
-
214
- async function initWasm(url) {
215
- try {
216
- const res = await fetch(url);
217
- const bytes = await res.arrayBuffer();
218
- const mod = await WebAssembly.instantiate(bytes, {});
219
- wasm = mod.instance;
220
- wasmReady = true;
221
- } catch (error) {
222
- wasm = null;
223
- wasmReady = false;
224
- }
225
- }
226
-
227
- self.onmessage = async (event) => {
228
- const data = event.data || {};
229
- if (data.type === "init") {
230
- if (data.wasmUrl) {
231
- await initWasm(data.wasmUrl);
232
- }
233
- self.postMessage({ type: "ready", wasmReady });
234
- return;
235
- }
236
-
237
- if (data.type === "compute") {
238
- const items = data.items || [];
239
- const camera = data.camera || {};
240
- const results = new Array(items.length);
241
- for (let i = 0; i < items.length; i += 1) {
242
- results[i] = computeTransform(items[i], camera);
243
- }
244
- self.postMessage({ type: "result", frameId: data.frameId, results });
245
- }
246
- };
247
- `,N=class{constructor(t={}){this.worker=null;this.ready=!1;this.lastResult=null;this.pending=!1;if(typeof Worker>"u")return;let e=new Blob([oe],{type:"text/javascript"});this.worker=new Worker(URL.createObjectURL(e)),this.worker.onmessage=r=>{let i=r.data||{};if(i.type==="ready"){this.ready=!0;return}i.type==="result"&&(this.lastResult={frameId:typeof i.frameId=="number"?i.frameId:0,results:i.results||[]},this.pending=!1)},this.worker.postMessage({type:"init",wasmUrl:t.wasmUrl})}isReady(){return this.ready}isPending(){return this.pending}submit(t,e,r){!this.worker||!this.ready||this.pending||(this.pending=!0,this.worker.postMessage({type:"compute",frameId:r,items:t,camera:e}))}takeLastResult(){let t=this.lastResult;return this.lastResult=null,t}destroy(){this.worker?.terminate(),this.worker=null,this.ready=!1,this.pending=!1,this.lastResult=null}};var z=class z extends ee.StringModule{constructor(e){super(e);this.renderer=null;this.camera=null;this.scene=null;this.synchronizer=null;this.engine=null;this.canvasContainer=null;this.isLoading=new Map;this.useDirtySync=!1;this.dirtyElements=new Set;this.observedElements=new Set;this.resizeObserver=null;this.mutationObserver=null;this.lastSyncData=new WeakMap;this.transformWorker=null;this.workerHasResult=!1;this.workerObjectMap=new Map;this.domVersion=0;this.lastSubmittedVersion=0;this.scrollTicking=!1;this.onScrollBound=()=>this.handleScroll();this.filterStates=new WeakMap;this.filterWarnings=new WeakMap;this.htmlKey="3d",this.options=this.buildOptionsFromSettings(),this.attributesToMap=[...this.attributesToMap,{key:"3d",type:"string",fallback:"box"},{key:"3d-material",type:"string",fallback:"basic[#ffffff]"},{key:"3d-color",type:"string",fallback:"#ffffff"},{key:"3d-opacity",type:"number",fallback:1},{key:"3d-intensity",type:"number",fallback:1},{key:"3d-distance",type:"number",fallback:1e3},{key:"3d-decay",type:"number",fallback:0},{key:"3d-model",type:"string",fallback:""},{key:"3d-segments",type:"number",fallback:32},{key:"3d-segments-width",type:"number",fallback:32},{key:"3d-segments-height",type:"number",fallback:32},{key:"3d-model-loader",type:"string",fallback:""},{key:"3d-model-scale",type:"number",fallback:1},{key:"3d-model-center",type:"boolean",fallback:!1},{key:"3d-model-fit",type:"string",fallback:"contain"},{key:"3d-metalness",type:"number",fallback:0},{key:"3d-roughness",type:"number",fallback:1},{key:"3d-texture-flipY",type:"boolean",fallback:!0},{key:"3d-colorSpace",type:"string",fallback:""},{key:"3d-cast-shadow",type:"boolean",fallback:!1},{key:"3d-receive-shadow",type:"boolean",fallback:!1},{key:"3d-shadow-bias",type:"number",fallback:0},{key:"3d-shadow-map-size",type:"number",fallback:512},{key:"3d-angle",type:"number",fallback:Math.PI/3},{key:"3d-penumbra",type:"number",fallback:0},{key:"3d-ground-color",type:"string",fallback:"#ffffff"},{key:"3d-target",type:"string",fallback:""}]}static setProvider(e){z.provider=e}canConnect(e){let r=super.canConnect(e);return console.log("[String3D] canConnect:",e.id,"keys:",e.keys,"htmlKey:",this.htmlKey,"result:",r),r}initializeObject(e,r,i,n){super.initializeObject(e,r,i,n),r.setProperty("parentId",null);let a=i.parentElement?.closest('[string-3d="group"]');if(a){let o=a.getAttribute("string-id");o&&(r.setProperty("parentId",o),r.setProperty("parent",a))}}onResize(){this.renderer&&this.camera&&this.synchronizer&&(this.renderer.resize(this.camera),this.synchronizer.updateViewportSize(this.renderer.width,this.renderer.height),this.camera.clearScaleCache(),this.useDirtySync&&this.markAllDirty())}onInit(){if(this.options=this.buildOptionsFromSettings(),!z.provider){console.error("[String3D] No provider set. Call String3D.setProvider() before use.");return}this.engine=z.provider.getEngine(),this.canvasContainer=this.createOrGetContainer(),this.registerTypedProperties(),this.injectCSS(),this.useDirtySync=!!this.options.useDirtySync,this.useDirtySync&&(this.setupObservers(),this.setupScrollListeners()),this.renderer=new H(this.canvasContainer,this.engine),this.renderer.attach(),this.camera=new W(this.engine,"orthographic"),this.camera.setPosition(0,0,1e3),this.camera.resize(this.renderer.width,this.renderer.height);let e=this.resolveModelLoader(),r=this.resolveModelLoaderFactory();this.scene=new A(this.engine,{modelLoader:e,modelLoaderFactory:r}),this.scene.getScene().add(this.camera.camera),this.synchronizer=new V(this.camera,this.renderer.width,this.renderer.height,this.engine),this.options.useTransformWorker&&(this.transformWorker=new N({wasmUrl:this.options.transformWorkerWasmUrl})),console.info(`[String3D] Initialized with: ${z.provider.getName()}`)}onSettingsChange(){this.options=this.buildOptionsFromSettings();let e=!!this.options.useDirtySync;e&&!this.useDirtySync?(this.useDirtySync=!0,this.setupObservers(),this.setupScrollListeners(),this.observeSceneElements(),this.markAllDirty()):!e&&this.useDirtySync&&(this.useDirtySync=!1,this.removeScrollListeners(),this.resizeObserver?.disconnect(),this.mutationObserver?.disconnect(),this.dirtyElements.clear());let r=!!this.options.useTransformWorker;r&&!this.transformWorker?(this.transformWorker=new N({wasmUrl:this.options.transformWorkerWasmUrl}),this.workerHasResult=!1):!r&&this.transformWorker&&(this.transformWorker.destroy(),this.transformWorker=null,this.workerHasResult=!1)}buildOptionsFromSettings(){return{hideHTML:this.getSettingValue("hideHTML",!1),container:this.getSettingValue("container",void 0),zIndex:this.getSettingValue("zIndex",1),modelLoaderType:this.getSettingValue("modelLoaderType",void 0),modelLoader:this.getSettingValue("modelLoader",void 0),modelLoaderFactory:this.getSettingValue("modelLoaderFactory",void 0),useDirtySync:this.getSettingValue("useDirtySync",!1),useTransformWorker:this.getSettingValue("useTransformWorker",!1),transformWorkerWasmUrl:this.getSettingValue("transformWorkerWasmUrl",void 0)}}getSettingValue(e,r){return!this.settings||!(e in this.settings)?r:this.settings[e]}resolveModelLoader(){if(this.engine){if(this.options.modelLoader)return this.options.modelLoader;if(!this.options.modelLoaderFactory&&this.options.modelLoaderType)try{return this.engine.createModelLoader(this.options.modelLoaderType)}catch(e){console.warn("[String3D] Failed to create model loader:",e)}}}resolveModelLoaderFactory(){if(this.engine){if(this.options.modelLoaderFactory)return this.options.modelLoaderFactory;if(this.options.modelLoaderType)return(e,r)=>{let i=r||this.options.modelLoaderType;if(!i)throw new Error("[String3D] Model loader type not provided");return e.createModelLoader(i)}}}createOrGetContainer(){if(this.options.container instanceof HTMLElement)return this.applyContainerStyles(this.options.container),this.options.container;if(typeof this.options.container=="string"){let r=document.getElementById(this.options.container);if(r)return this.applyContainerStyles(r),r}let e=document.createElement("div");return e.id="string-3d-canvas",this.applyContainerStyles(e),document.body.insertBefore(e,document.body.firstChild),e}applyContainerStyles(e){Object.assign(e.style,{position:"fixed",left:"0",top:"0",width:"100vw",height:"100lvh",zIndex:String(this.options.zIndex),pointerEvents:"none"})}onObjectConnected(e){this.isLoading.has(e.id)||!this.scene||(this.isLoading.set(e.id,!0),this.scene.createFromElement(e),this.useDirtySync&&e.htmlElement&&(this.observeElement(e.htmlElement),this.markDirty(e.htmlElement)),this.options.hideHTML&&e.htmlElement&&(e.htmlElement.style.opacity="0",e.htmlElement.style.pointerEvents="none"))}onFrame(e){if(!this.renderer||!this.scene||!this.camera||!this.synchronizer)return;let r=this.transformWorker?.takeLastResult();r&&r.frameId===this.lastSubmittedVersion&&r.frameId>=this.domVersion&&(this.workerHasResult=!0,this.applyWorkerResults(r.results));let i=this.useDirtySync?this.dirtyElements:null,n=!i||i.size===0,a=this.transformWorker;if(a?.isReady()&&!a.isPending()){let l=[];if(this.workerObjectMap.clear(),this.scene.rootObjects.forEach(s=>{this.collectWorkerInputs(s,{scale:1},n,i,l)}),l.length>0){let s=this.domVersion;this.lastSubmittedVersion=s,a.submit(l,this.buildWorkerCameraData(),s)}}this.scene.rootObjects.forEach(l=>{this.syncRecursive(l.el,l,{scale:1},n,i)});let o=this.collectFilterTargets(performance.now(),n,i);this.renderer.render(this.scene,this.camera,o),this.useDirtySync&&this.dirtyElements.clear()}syncRecursive(e,r,i,n,a){if(!this.synchronizer||!e)return;let o=n||!a||a.has(e),l=i;if(o){let c=this.synchronizer.syncElement(e,r,i);c&&typeof c.scale=="number"&&(this.lastSyncData.set(r,c),l=c)}else{let c=this.lastSyncData.get(r);c&&(l=c)}let s=n||o;r.children.forEach(c=>this.syncRecursive(c.el,c,l,s,a))}injectCSS(){if(document.getElementById("string-3d-styles"))return;let e=document.createElement("style");e.id="string-3d-styles",e.textContent=`
114
+ `}};var ge=class{constructor(e,t){this.filterPipeline=null;this.filterCache=new Map;this.frameId=0;this.lastFrameTime=performance.now();this.avgFrameMs=16.7;this.qualityScale=1;this.lastQualityChange=0;this.filterLayer=1;this.engine=t,this._container=e;let{width:r,height:i}=e.getBoundingClientRect();this._width=r,this._height=i,this._renderer=t.createRenderer({antialias:!0,alpha:!0,logarithmicDepthBuffer:!0});let n=this._renderer;typeof n.setClearColor=="function"&&n.setClearColor(0,0),this._renderer.setPixelRatio(window.devicePixelRatio),this._renderer.setSize(r,i),this._renderer.shadowMap&&(this._renderer.shadowMap.enabled=!0)}attach(){this._container.appendChild(this._renderer.domElement)}render(e,t,r=[]){if(r.length===0){this._renderer.render(e.getScene(),t.camera);return}let i=this.ensureFilterPipeline();if(!i?.isSupported()){this._renderer.render(e.getScene(),t.camera);return}this.frameId+=1,this.updateQuality(r.length,i);let n=e.getAllObjects(),a=new Map;n.forEach(u=>{let m=u.object;"visible"in m&&a.set(u.object,m.visible)});let o=new Set;r.forEach(u=>{this.collectSubtreeObjects(u.object,o)}),n.forEach(u=>{o.has(u.object)&&this.setVisible(u.object,!1)});let s=this._renderer,l=s.autoClear;s.autoClear=!0,s.setRenderTarget&&s.setRenderTarget(null),s.clear&&s.clear(!0,!0,!0),this._renderer.render(e.getScene(),t.camera),s.autoClear=!1,n.forEach(u=>{let m=a.get(u.object);typeof m<"u"&&this.setVisible(u.object,m)});let c=n.filter(u=>u.type.endsWith("Light")),h=this.supportsLayers(t.camera,n);r.forEach(u=>{let m=this.filterCache.get(u.object.id);if(!u.dirty&&m&&m.effectsKey===u.effectsKey&&m.qualityScale===this.qualityScale){m.lastUsedFrame=this.frameId,i.renderToScreen(m.target);return}let p=this.injectEffectContext(u.object.el,u.effects),f=new Set;this.collectSubtreeObjects(u.object,f);let M=[],y=null;if(h){let E=u.object.getSubtreeObjects();M=this.applyLayerMask(E,c,this.filterLayer),y=this.setCameraLayer(t.camera,this.filterLayer)}else n.forEach(E=>{if(a.get(E.object)===!1){this.setVisible(E.object,!1);return}if(E.type.endsWith("Light")){this.setVisible(E.object,!0);return}this.setVisible(E.object,f.has(E.object))});let v=i.acquireTarget();s.setRenderTarget&&s.setRenderTarget(v),s.clear&&s.clear(!0,!0,!0),this._renderer.render(e.getScene(),t.camera);let b=i.applyFilters(v,p,this.qualityScale);s.setRenderTarget&&s.setRenderTarget(null),i.renderToScreen(b),h&&(this.restoreLayerMask(M),y!==null&&this.restoreCameraLayer(t.camera,y)),b!==v&&i.releaseTarget(v);let F={target:b,effectsKey:u.effectsKey,lastUsedFrame:this.frameId,qualityScale:this.qualityScale},R=this.filterCache.get(u.object.id);R&&R.target!==b&&i.releaseTarget(R.target),this.filterCache.set(u.object.id,F)}),h||n.forEach(u=>{let m=a.get(u.object);typeof m<"u"&&this.setVisible(u.object,m)}),s.autoClear=l,this.evictCache()}resize(e){let{width:t,height:r}=this._container.getBoundingClientRect();this._width=t,this._height=r,this._renderer.setSize(t,r),e.resize(t,r),this.filterPipeline?.resize(t,r),this.invalidateFilterCache()}get width(){return this._width}get height(){return this._height}get renderer(){return this._renderer}destroy(){this._renderer.dispose(),this.filterPipeline?.dispose(),this.filterCache.clear()}ensureFilterPipeline(){return this.canCreateFilterPipeline()?(this.filterPipeline||(this.filterPipeline=new Te(this.engine,this._renderer,this._width,this._height),this.filterPipeline.setScale(this.qualityScale)),this.filterPipeline):null}canCreateFilterPipeline(){return typeof this.engine.createRenderTarget=="function"&&typeof this.engine.createShaderMaterial=="function"&&typeof this._renderer.setRenderTarget=="function"}collectSubtreeObjects(e,t){t.add(e.object),e.children.forEach(r=>this.collectSubtreeObjects(r,t))}setVisible(e,t){let r=e;"visible"in r&&(r.visible=t)}getFilterCenter(e){if(!e||!this._width||!this._height)return[.5,.5];let t=e.__layoutCache,r=t?t.rect:e.getBoundingClientRect(),i=(r.left+r.width/2)/this._width,n=1-(r.top+r.height/2)/this._height,a=o=>Math.max(0,Math.min(1,o));return[a(i),a(n)]}injectEffectContext(e,t){if(!t.some(a=>a.type==="custom"))return t;let r=this.getFilterCenter(e),i=!1,n=t.map(a=>{if(a.type!=="custom"||a.uniforms&&"uCenter"in a.uniforms)return a;let o={...a.uniforms||{},uCenter:r};return i=!0,{...a,uniforms:o}});return i?n:t}updateQuality(e,t){let r=performance.now(),i=Math.max(.1,r-this.lastFrameTime);this.lastFrameTime=r,this.avgFrameMs=this.avgFrameMs*.9+i*.1;let n=1e3/this.avgFrameMs,a=Math.max(.75,1-Math.min(.4,e*.03)),o=a;n<48&&(o=Math.max(.75,a-.1)),n<40&&(o=Math.max(.75,a-.2)),n>58&&(o=Math.min(1,a+.05)),Math.abs(o-this.qualityScale)>=.05&&r-this.lastQualityChange>300&&(this.qualityScale=o,this.lastQualityChange=r,t.setScale(this.qualityScale),this.invalidateFilterCache())}invalidateFilterCache(){this.filterPipeline&&(this.filterCache.forEach(e=>{this.filterPipeline?.releaseTarget(e.target)}),this.filterCache.clear())}evictCache(){if(!this.filterPipeline)return;let e=120;this.filterCache.forEach((t,r)=>{this.frameId-t.lastUsedFrame>e&&(this.filterPipeline?.releaseTarget(t.target),this.filterCache.delete(r))})}supportsLayers(e,t){return!e?.layers||typeof e.layers.set!="function"?!1:t.some(r=>this.hasLayers(r.object))}hasLayers(e){return e?.layers&&typeof e.layers.set=="function"}applyLayerMask(e,t,r){let i=new Map,n=(a,o)=>{let s=a;this.hasLayers(s)&&(i.has(a)||i.set(a,s.layers.mask),o==="set"?s.layers.set(r):s.layers.enable(r))};return e.forEach(a=>n(a,"set")),t.forEach(a=>n(a.object,"enable")),Array.from(i.entries()).map(([a,o])=>({object:a,mask:o}))}restoreLayerMask(e){e.forEach(t=>{let r=t.object;this.hasLayers(r)&&(r.layers.mask=t.mask)})}setCameraLayer(e,t){if(!e?.layers||typeof e.layers.set!="function")return null;let r=e.layers.mask;return e.layers.set(t),r}restoreCameraLayer(e,t){e?.layers&&(e.layers.mask=t)}};var $=class{constructor(e,t,r,i,n={}){this._uniforms={};this._children=[];this._flatObjectsCache=null;this._subtreeCache=null;this.id=e,this.type=t,this._object=r,this.engine=i,this._material=n.material,this._geometry=n.geometry,this._texture=n.texture,this._quaternion=i.createQuaternion(),this._originalSize=i.createVector3(),this._bbox=i.createBox3(),this.updateBoundingBox()}get children(){return this._children}get object(){return this._object}get material(){return this._material}get originalSize(){return this._originalSize.clone()}get boundingBox(){return this._bbox.clone()}addChild(e){this._children.push(e),this.object.add(e.object),this.invalidateFlatCache(),this.invalidateSubtreeCache()}getWorldMatrix(){return this._object.matrixWorld.clone()}getWorldPosition(){return this.engine.createVector3().setFromMatrixPosition(this._object.matrixWorld)}getOriginalBoundingBox(){if(!this._originalBoundingBox){let e=this.object.scale.clone();this.object.scale.set(1,1,1),this.object.updateMatrixWorld(!0),this._originalBoundingBox=this.engine.computeBoundingBoxRecursively(this.object),this.object.scale.copy(e),this.object.updateMatrixWorld(!0)}return this._originalBoundingBox.clone()}syncTransformFromMatrix(e){let t=this.engine.createVector3(),r=this.engine.createQuaternion(),i=this.engine.createVector3();e.decompose(t,r,i),this._object.position.copy(t),this._object.quaternion.copy(r),this._object.scale.copy(i),this._object.updateMatrix(),this._object.updateMatrixWorld()}applyWorldTransform(e,t,r){this._object.position.copy(e),this._object.quaternion.copy(t),this._object.scale.copy(r),this._object.updateMatrix(),this._object.updateMatrixWorld()}set quaternion(e){this._quaternion.copy(e),this._object.quaternion.copy(this._quaternion),this._object.updateMatrixWorld()}set position(e){this._object.position.copy(e)}set scale(e){this._object.scale.copy(e)}set rotation(e){this._object.rotation.copy(e)}set opacity(e){let t=this._object;t.material&&"opacity"in t.material&&(t.material.opacity=e)}set metalness(e){let t=this._object;t.material&&"metalness"in t.material&&(t.material.metalness=e)}set roughness(e){let t=this._object;t.material&&"roughness"in t.material&&(t.material.roughness=e)}set texture(e){this._texture=e,this._object.isMesh&&e?.applyTexture&&e.applyTexture(this._object)}set material(e){this._material=e}set geometry(e){this._geometry=e}updateBoundingBox(){this._bbox.setFromObject(this._object),this._bbox.getSize(this._originalSize)}destroy(){this.disposeObjectResources(this._object),this._texture?.dispose?.(),this._material?.dispose(),this._geometry?.dispose(),this._subtreeCache=null}getFlatObjects(){if(this._flatObjectsCache)return this._flatObjectsCache;let e=[],t=r=>{e.push(r.object),r.children.forEach(i=>t(i))};return t(this),this._flatObjectsCache=e,e}getSubtreeObjects(){if(this._subtreeCache)return this._subtreeCache;let e=[],t=this._object;return e.push(this._object),typeof t.traverse=="function"&&t.traverse(r=>{r&&r!==this._object&&e.push(r)}),this._subtreeCache=e,e}invalidateFlatCache(){this._flatObjectsCache=null}invalidateSubtreeCache(){this._subtreeCache=null}disposeObjectResources(e){let t=e;t?.geometry?.dispose&&t.geometry.dispose();let r=t?.material;Array.isArray(r)?r.forEach(i=>i?.dispose?.()):r?.dispose&&r.dispose(),typeof t?.traverse=="function"&&t.traverse(i=>{i?.geometry?.dispose&&i.geometry.dispose();let n=i?.material;Array.isArray(n)?n.forEach(a=>a?.dispose?.()):n?.dispose&&n.dispose()})}};var se=class{constructor(e){this.styleMap=e.computedStyleMap?.(),this.style=getComputedStyle(e)}readNumber(e,t){let r=this.styleMap?.get?.(e);if(r!=null){let n=typeof r=="object"?r.value:r,a=typeof n=="number"?n:Number.parseFloat(n);if(!Number.isNaN(a))return a}let i=Number.parseFloat(this.style.getPropertyValue(e));return Number.isNaN(i)?t:i}readString(e,t=""){let r=this.styleMap?.get?.(e),i=r&&typeof r=="object"?r.value:r;if(typeof i=="string")return this.stripQuotes(i.trim())||t;let n=this.style.getPropertyValue(e).trim();return this.stripQuotes(n)||t}stripQuotes(e){return e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e}readBoolean(e,t=!1){let r=this.readString(e,"");if(!r)return t;let i=r.toLowerCase();return i==="true"||i==="1"||i==="yes"?!0:i==="false"||i==="0"||i==="no"?!1:t}};function q(g,e,t){let i=g.computedStyleMap?.()?.get?.(e);if(i!==void 0){if(typeof i=="number")return i;if(typeof i=="string"){let s=Number.parseFloat(i);if(!Number.isNaN(s))return s}if(i&&typeof i=="object"){let s=i.value;if(typeof s=="number")return s;if(typeof s=="string"){let l=Number.parseFloat(s);if(!Number.isNaN(l))return l}}}let a=getComputedStyle(g).getPropertyValue(e),o=Number.parseFloat(a);return Number.isNaN(o)?t:o}function Ge(g){return g.startsWith("'")&&g.endsWith("'")||g.startsWith('"')&&g.endsWith('"')?g.slice(1,-1):g}function ye(g,e,t=""){let i=g.computedStyleMap?.()?.get?.(e);if(typeof i=="string")return Ge(i.trim());if(i&&typeof i=="object"){let o=i.value;if(typeof o=="string")return Ge(o.trim())}let n=getComputedStyle(g).getPropertyValue(e);return(n?Ge(n.trim()):"")||t}function Le(g,e,t=!1){let r=ye(g,e,"");if(!r)return t;let i=r.toLowerCase().trim();return i==="true"||i==="1"||i==="yes"?!0:i==="false"||i==="0"||i==="no"?!1:t}function Je(g){let e=g.computedStyleMap?.(),t="",r=e?.get?.("--filter");if(r!==void 0){if(typeof r=="string")t=r;else if(r&&typeof r=="object"){let i=r.value;typeof i=="string"&&(t=i)}}return t||(t=getComputedStyle(g).getPropertyValue("--filter")||""),t=t.trim(),t}var K=class{static register(e){let t=e.name.trim().toLowerCase();if(!t)throw new Error("[String3D] Custom material name is required.");this.materials.has(t)&&console.warn(`[String3D] Material "${t}" already registered. Overwriting.`),this.materials.set(t,{...e,name:t}),this.registerCssVarsForMaterial(e)}static registerCssVarsForMaterial(e){let t=globalThis.CSS;if(!t?.registerProperty)return;let r=e.uniforms||{};for(let i of Object.values(r)){let n=i.css?.trim();if(!n||!n.startsWith("--")||this.registeredCssVars.has(n))continue;let a=this.resolveCssSyntax(i.type);try{t.registerProperty({name:n,syntax:a,inherits:!1,initialValue:this.defaultCssInitialValue(i)}),this.registeredCssVars.add(n)}catch(o){console.warn(`[String3D] Failed to register CSS property ${n}:`,o)}}}static resolveCssSyntax(e){switch(e){case"color":return"<color>";case"float":case"int":return"<number>";default:return"*"}}static defaultCssInitialValue(e){return e.type==="color"?typeof e.value=="string"?e.value:"#000000":e.type==="float"||e.type==="int"?typeof e.value=="number"?String(e.value):"0":"initial"}static get(e){return this.materials.get(e.trim().toLowerCase())}static has(e){return this.materials.has(e.trim().toLowerCase())}static list(){return Array.from(this.materials.values())}static unregister(e){return this.materials.delete(e.trim().toLowerCase())}};K.materials=new Map,K.registeredCssVars=new Set;function et(g,e){if(e==null||e===""||e==="none")return g.value;let t=e.trim();switch(g.type){case"float":case"int":{let r=parseFloat(t);return isNaN(r)?g.value:r}case"vec2":{let r=t.split(/[\s,]+/).map(i=>parseFloat(i.trim()));return r.length>=2&&r.every(i=>!isNaN(i))?[r[0],r[1]]:g.value}case"vec3":{let r=t.split(/[\s,]+/).map(i=>parseFloat(i.trim()));return r.length>=3&&r.every(i=>!isNaN(i))?[r[0],r[1],r[2]]:g.value}case"vec4":{let r=t.split(/[\s,]+/).map(i=>parseFloat(i.trim()));return r.length>=4&&r.every(i=>!isNaN(i))?[r[0],r[1],r[2],r[3]]:g.value}case"color":return ut(t)??g.value;case"texture":{let r=t.match(/url\(['"]?(.*?)['"]?\)/);return r?r[1]:t||g.value}default:return g.value}}function ut(g){if(g.startsWith("#")){let t=g.slice(1);if(t.length===3){let r=parseInt(t[0]+t[0],16)/255,i=parseInt(t[1]+t[1],16)/255,n=parseInt(t[2]+t[2],16)/255;return[r,i,n]}if(t.length===6){let r=parseInt(t.slice(0,2),16)/255,i=parseInt(t.slice(2,4),16)/255,n=parseInt(t.slice(4,6),16)/255;return[r,i,n]}}let e=g.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);return e?[parseInt(e[1])/255,parseInt(e[2])/255,parseInt(e[3])/255]:null}function $e(g,e,t){let r={};if(g.parse){let i=g.parse(e,t);Object.assign(r,i)}if(g.uniforms)for(let[i,n]of Object.entries(g.uniforms))if(n.css){let a=t.getPropertyValue(n.css).trim();r[i]=et(n,a)}else i in r||(r[i]=n.value);return r}function Ze(g){let e=new Map;for(let r of g){let i=e.get(r.point)||[];i.push(r),e.set(r.point,i)}let t=new Map;for(let[r,i]of e){let n=i.sort((a,o)=>(a.order??0)-(o.order??0));t.set(r,n.map(a=>a.code).join(`
115
+ `))}return t}var be=class{constructor(e,t={}){this._objects=new Map;this._rootObjects=[];this._elementMap=new Map;this._materialInstances=new Map;this._modelLoaderCache=new Map;this.engine=e,this._modelLoader=t.modelLoader,this._modelLoaderFactory=t.modelLoaderFactory,this._scene=e.createScene()}get rootObjects(){return this._rootObjects}getScene(){return this._scene}getObject(e){return this._objects.get(e)}getAllObjects(){let e=[],t=r=>{e.push(r),r.children.forEach(i=>t(i))};return this._rootObjects.forEach(r=>t(r)),e}hasObject(e){return this._objects.has(e)}deleteObject(e){let t=this._objects.get(e);return t?(this._scene.remove(t.object),this._objects.delete(e),this._elementMap.delete(e),this._rootObjects=this._rootObjects.filter(r=>r!==t),t.destroy(),!0):!1}createFromElement(e){let t=e.getProperty("3d");if(!t)return;let r=e.htmlElement;if(!r)return;let i=n=>{if(n){let a=e.getProperty("parentId");a==null?(this._scene.add(n.object),this._rootObjects.push(n)):this._objects.get(a)?.addChild(n),this._objects.set(e.id,n),this._elementMap.set(e.id,r),n.el=r}};switch(t){case"group":this.createGroup(e,i);break;case"pointLight":this.createLight(e,"point",i);break;case"ambientLight":this.createLight(e,"ambient",i);break;case"directionalLight":this.createLight(e,"directional",i);break;case"spotLight":this.createLight(e,"spot",i);break;case"hemisphereLight":this.createLight(e,"hemisphere",i);break;case"model":this.createModel(e,i);break;case"box":this.createBox(e,i);break;case"sphere":this.createSphere(e,i);break;case"plane":this.createPlane(e,i);break;case"cylinder":this.createCylinder(e,i);break;case"particles":this.createParticles(e,i);break;case"text":this.createText(e,i);break}}createGroup(e,t){let r=this.engine.createGroup(),i=new $(e.id,"group",r,this.engine);return t(i),i}createLight(e,t,r){let i=e.htmlElement,n=i?ye(i,"--light-color","#ffffff"):"#ffffff",a=n&&n!=="none"?n:"#ffffff",o=i?q(i,"--light-intensity",1):1,s;if(t==="point"){let h=i?q(i,"--light-distance",1e3):1e3,u=i?q(i,"--light-decay",0):0;s=this.engine.createPointLight(a,o,h,u)}else if(t==="directional")s=this.engine.createDirectionalLight(a,o);else if(t==="spot"){let h=i?q(i,"--light-distance",0):0,u=i?q(i,"--light-angle",Math.PI/3):Math.PI/3,m=i?q(i,"--light-penumbra",0):0,d=i?q(i,"--light-decay",1):1;s=this.engine.createSpotLight(a,o,h,u,m,d)}else if(t==="hemisphere"){let h=i?ye(i,"--light-ground-color","#ffffff"):"#ffffff",u=h&&h!=="none"?h:"#ffffff";s=this.engine.createHemisphereLight(a,u,o)}else s=this.engine.createAmbientLight(a,o);if((i?Le(i,"--shadow-cast",!1):!1)&&s.shadow){s.castShadow=!0;let h=i?q(i,"--shadow-bias",0):0,u=i?q(i,"--shadow-map-size",512):512;s.shadow.bias=h,s.shadow.mapSize.width=u,s.shadow.mapSize.height=u}let c=new $(e.id,t+"Light",s,this.engine);return r(c),c}applyShadowProps(e,t){let r=e.htmlElement,i=r?Le(r,"--shadow-cast",!1):!1,n=r?Le(r,"--shadow-receive",!1):!1;t.castShadow=i,t.receiveShadow=n}createBox(e,t){let r=this.engine.createBoxGeometry(1,1,1),i=this.createMaterialFromObject(e),n=this.engine.createMesh(r,i);this.applyShadowProps(e,n);let a=new $(e.id,"box",n,this.engine,{geometry:r,material:i});return t(a),a}createSphere(e,t){let r=this.getGeometryQuality(e.htmlElement),i=Math.max(3,Math.round(32*r)),n=Math.max(2,Math.round(32*r)),a=this.engine.createSphereGeometry(.5,i,n),o=this.createMaterialFromObject(e),s=this.engine.createMesh(a,o);this.applyShadowProps(e,s);let l=new $(e.id,"sphere",s,this.engine,{geometry:a,material:o});return t(l),l}createPlane(e,t){let r=this.engine.createPlaneGeometry(1,1),i=this.createMaterialFromObject(e),n=this.engine.createMesh(r,i);this.applyShadowProps(e,n);let a=new $(e.id,"plane",n,this.engine,{geometry:r,material:i});return t(a),a}createCylinder(e,t){let r=this.getGeometryQuality(e.htmlElement),i=Math.max(3,Math.round(32*r)),n=this.engine.createCylinderGeometry(.5,.5,1,i),a=this.createMaterialFromObject(e),o=this.engine.createMesh(n,a);this.applyShadowProps(e,o);let s=new $(e.id,"cylinder",o,this.engine,{geometry:n,material:a});return t(s),s}createModel(e,t){let r=e.getProperty("3d-model");if(!r)return;let i=e.getProperty("3d-model-loader")||void 0,n=this.resolveModelLoader(i);if(!n){console.warn("[String3D] Model loader not configured");return}let a=e.htmlElement;a&&this.applyModelTextureRemap(n,a);let o=e.getProperty("3d-model-center")??!1;n.load(r,s=>{let l=s?.scene||s?.object||s;if(!l){console.warn("[String3D] Model loader returned empty result");return}let c=a&&this.shouldOverrideModelMaterial(a)?this.createMaterialFromElement(a,e):null;typeof l.traverse=="function"&&l.traverse(u=>{u.isMesh&&(c&&(u.material=c),this.applyShadowProps(e,u))}),o&&this.centerObject(l);let h=new $(e.id,"model",l,this.engine);t(h)},s=>{console.log(s.loaded/s.total*100+"% loaded")},s=>{console.error("[String3D] Model loading error:",s)})}createParticles(e,t){if(!this.engine.createParticleSystem){console.warn("[String3D] Particle system not supported by engine.");return}let r=e.htmlElement,i={mode:"emitter",count:300,size:2,color:"#ffffff",opacity:1,spread:120,seed:1,emitRate:30,emitBurst:0,particleLife:2.5,particleSpeed:40,particleDirection:[0,1,0],particleGravity:[0,-30,0],particleDrag:.1,particleSizeVariation:.6,particleColorVariation:.2,particleShape:"sphere",particleModelUrl:"",particleModelLoader:"",particleModelNode:"",instanceShape:"sphere",instanceModelUrl:"",instanceModelLoader:"",instanceModelNode:"",instanceScale:1,instanceScaleVariation:.5,instanceRotationSpeed:.4,instanceJitter:.2,instanceFlow:.3,instanceDisperse:0,instanceDisperseScatter:0,instanceDisperseScatterX:0,instanceDisperseScatterY:0,instanceDisperseScatterZ:0},n=this.engine.createParticleSystem(i),a=new $(e.id,"particles",n,this.engine);t(a)}createText(e,t){if(!this.engine.createTextGeometry){console.warn("[String3D] Text geometry not supported by engine.");return}let r=this.engine.createBoxGeometry(1,1,1),i=this.createMaterialFromObject(e),n=this.engine.createMesh(r,i);this.applyShadowProps(e,n);let a=this.engine.createGroup();a.__textMesh=n,a.add(n);let o=new $(e.id,"text",a,this.engine,{geometry:r,material:i});t(o)}getGeometryQuality(e){if(!e)return 1;let t=q(e,"--geometry-quality",1);return!Number.isFinite(t)||t<=0?1:t}resolveModelLoader(e){if(e){if(this._modelLoaderCache.has(e))return this._modelLoaderCache.get(e);if(!this._modelLoaderFactory){console.warn(`[String3D] No model loader factory for type "${e}"`);return}let t=this._modelLoaderFactory(this.engine,e);return this._modelLoaderCache.set(e,t),t}if(this._modelLoader)return this._modelLoader;if(this._modelLoaderFactory)return this._modelLoaderFactory(this.engine)}centerObject(e){if(!e)return;let t=this.engine.computeBoundingBoxRecursively(e),r=this.getBoxCenter(t);e.position?.set&&e.position.set(-r.x,-r.y,-r.z),e.updateMatrixWorld(!0)}getBoxCenter(e){let t=this.engine.createVector3();return t.x=(e.min.x+e.max.x)/2,t.y=(e.min.y+e.max.y)/2,t.z=(e.min.z+e.max.z)/2,t}createMaterialFromObject(e){return this.createMaterialFromElement(e.htmlElement,e)}createMaterialFromElement(e,t){let r=e?getComputedStyle(e):null,i=S=>r?r.getPropertyValue(S).trim():"",n=(S,D,z)=>{let _=i(S);return _&&_!=="none"&&_!==""?D(_):z},a=S=>parseFloat(S),o=S=>S,s=S=>{let D=S.match(/url\(['"]?(.*?)['"]?\)/);return D?D[1]:S},l=n("--material-type",S=>S.split("[")[0]||"basic","basic"),c=this.tryCreateCustomMaterial(l,e,r,t);if(c)return c;let h=n("--material-color",o,"#ffffff"),u=n("--opacity",a,1),m=n("--material-metalness",a,0),d=n("--material-roughness",a,1),p=n("--material-emissive",o,"#000000"),f={color:h,transparent:u<1,opacity:u},M=n("--texture-map",s,""),y=n("--texture-normal",s,""),v=n("--texture-roughness",s,""),b=n("--texture-metalness",s,""),F=n("--texture-ao",s,""),R=this.parseFlipY(e),E=e?ye(e,"--texture-color-space",""):"",O=!!(M||y||v||b||F),x=l;return x!=="standard"&&O&&(x="standard"),x==="standard"?(M&&(f.map=this.loadTexture(M,{flipY:R,colorSpace:E})),y&&(f.normalMap=this.loadTexture(y,{flipY:R})),v&&(f.roughnessMap=this.loadTexture(v,{flipY:R})),b&&(f.metalnessMap=this.loadTexture(b,{flipY:R})),F&&(f.aoMap=this.loadTexture(F,{flipY:R})),f.metalness=m,f.roughness=d,f.emissive=p,this.engine.createMeshStandardMaterial(f)):this.engine.createMeshBasicMaterial(f)}tryCreateCustomMaterial(e,t,r,i){let n=K.get(e);if(!n)return null;let a=this.engine.getMaterialFactory?.();if(!a)return console.warn(`[String3D] Material factory not available for custom material "${e}"`),null;if(!a.supports(n))return console.warn(`[String3D] Material factory does not support "${e}".`),null;let o={};t&&r&&(o=a.parseUniformsFromCSS(n,t,r));let s=a.create(n,o);return i&&this._materialInstances.set(i.id,s),s.material}updateMaterialUniforms(e,t){let r=this._materialInstances.get(e);r&&r.update(t)}getMaterialInstance(e){return this._materialInstances.get(e)}loadTexture(e,t={}){let i=this.engine.createTextureLoader().load(e);typeof t.flipY=="boolean"&&(i.flipY=t.flipY);let n=(t.colorSpace||"").toLowerCase().trim();return n&&"colorSpace"in i&&(i.colorSpace=n==="srgb"?"srgb":"linear"),i.needsUpdate=!0,i}parseFlipY(e){let t=e?ye(e,"--texture-flip-y",""):"";if(t==null||t==="")return;if(typeof t=="boolean")return t;let r=String(t).toLowerCase().trim();if(r==="false"||r==="0"||r==="no")return!1;if(r==="true"||r==="1"||r==="yes")return!0}shouldOverrideModelMaterial(e){let t=getComputedStyle(e),r=n=>{let a=t.getPropertyValue(n);return a&&a!=="0"&&a!=="none"&&a!==""};return r("--material-color")||r("--texture-map")?!0:["--material-type","--material-metalness","--material-roughness","--material-emissive","--opacity","--texture-normal","--texture-roughness","--texture-metalness","--texture-ao"].some(n=>r(n))}applyModelTextureRemap(e,t){let r=(t.getAttribute("string-3d-model-texture-base")||"").trim(),i=r?r.replace(/\/?$/,"/"):"",n=t.getAttribute("string-3d-model-textures"),a=null;if(n)try{a=JSON.parse(n)}catch(s){console.warn("[String3D] Invalid model texture mapping JSON:",s)}let o=e?.manager;if(!o||typeof o.setURLModifier!="function"){(a||i)&&console.warn("[String3D] Model loader does not support URL remap.");return}o.setURLModifier(s=>{let l=a&&s in a?a[s]:s;return!i||/^(blob:|data:|https?:|file:|\/)/i.test(l)?l:i+l.replace(/^\.?\//,"")})}destroy(){this._materialInstances.forEach(e=>e.dispose()),this._materialInstances.clear(),this._objects.forEach(e=>e.destroy()),this._objects.clear(),this._rootObjects=[]}};var Z=class{constructor(){this.cache=new WeakMap;this.meta=new WeakMap}get(e,t,r){if(!!t.dirtySet&&t.forceSync===!1&&!t.dirtySet.has(e)){let s=this.cache.get(e);if(s)return s}let n=performance.now(),a=Math.max(0,t.styleReadIntervalMs??0);if(a>0){let s=this.meta.get(e),l=this.cache.get(e);if(s&&l&&n-s.time<a)return l}let o=r(e);return this.cache.set(e,o),this.meta.set(e,{time:n}),o}clear(){this.cache=new WeakMap,this.meta=new WeakMap}};var Ye=Math.PI/180,Oe=class Oe{sync(e,t,r,i){let n=e.__layoutCache,a=n?n.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r),s=a.left+a.width*.5,l=a.top+a.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(s-r.viewportWidth/2,-(l-r.viewportHeight/2),o.translateZ);else{let c=r.camera.getFrustumSizeAt(o.translateZ),h=s/r.viewportWidth,u=l/r.viewportHeight;t.object.position.set((h-.5)*c.width,-(u-.5)*c.height,o.translateZ)}return t.object.scale.set(o.scale,o.scale,o.scale),t.object.rotation.x=-o.rotateX*Ye,t.object.rotation.y=o.rotateY*Ye,t.object.rotation.z=-o.rotateZ*Ye,t.object.rotation.order="XYZ",t.object.updateMatrixWorld(!0),{scale:o.scale}}readStyleBundle(e,t){return Oe.styleCache.get(e,t,r=>{let i=new se(r);return{translateZ:i.readNumber("--translate-z",0),scale:i.readNumber("--scale",1),rotateX:i.readNumber("--rotate-x",0),rotateY:i.readNumber("--rotate-y",0),rotateZ:i.readNumber("--rotate-z",0)}})}};Oe.styleCache=new Z;var Re=Oe;var Pe=class Pe{sync(e,t,r,i){let n=e.__layoutCache,a=n?n.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r,t),s=a.left+a.width*.5,l=a.top+a.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(s-r.viewportWidth/2+o.translateX,-(l-r.viewportHeight/2)+o.translateY,o.translateZ);else{let h=r.camera.getFrustumSizeAt(o.translateZ),u=s/r.viewportWidth,m=l/r.viewportHeight;t.object.position.set((u-.5)*h.width+o.translateX,-(m-.5)*h.height+o.translateY,o.translateZ)}let c=t.object;if(o.color&&o.color!=="none"&&c.color&&typeof c.color.set=="function"&&c.color.set(o.color),c.intensity=o.intensity,typeof c.distance<"u"&&o.distance!==void 0&&(c.distance=o.distance),typeof c.decay<"u"&&o.decay!==void 0&&(c.decay=o.decay),typeof c.angle<"u"&&o.angle!==void 0&&(c.angle=o.angle),typeof c.penumbra<"u"&&o.penumbra!==void 0&&(c.penumbra=o.penumbra),o.groundColor&&o.groundColor!=="none"&&c.groundColor&&typeof c.groundColor.set=="function"&&c.groundColor.set(o.groundColor),c.castShadow!==o.castShadow&&(c.castShadow=o.castShadow),o.castShadow&&c.shadow&&(o.shadowBias!==void 0&&(c.shadow.bias=o.shadowBias),o.shadowMapSize!==void 0&&c.shadow.mapSize.width!==o.shadowMapSize&&(c.shadow.mapSize.width=o.shadowMapSize,c.shadow.mapSize.height=o.shadowMapSize)),o.targetId&&o.targetId!=="none"&&c.target){let h=document.querySelector(`[string-id="${o.targetId}"]`);if(h){let u=h.__layoutCache,m=u?u.rect:h.getBoundingClientRect(),p=new se(h).readNumber("--translate-z",0),f=m.left+m.width*.5,M=m.top+m.height*.5,y,v,b;if(r.camera.getMode()==="orthographic")y=f-r.viewportWidth/2,v=-(M-r.viewportHeight/2),b=p;else{let F=r.camera.getFrustumSizeAt(p),R=f/r.viewportWidth,E=M/r.viewportHeight;y=(R-.5)*F.width,v=-(E-.5)*F.height,b=p}o.targetOffset&&(y+=o.targetOffset.x,v+=o.targetOffset.y,b+=o.targetOffset.z),c.target.position.set(y,v,b),c.target.updateMatrixWorld(!0)}}return null}readStyleBundle(e,t,r){return Pe.styleCache.get(e,t,i=>{let n=new se(i),a=r.object,o={translateZ:n.readNumber("--translate-z",0),translateX:n.readNumber("--translate-x",0),translateY:n.readNumber("--translate-y",0),color:n.readString("--light-color","")||void 0,intensity:n.readNumber("--light-intensity",a.intensity??1),castShadow:n.readBoolean("--shadow-cast",!1)};typeof a.distance<"u"&&(o.distance=n.readNumber("--light-distance",a.distance??0)),typeof a.decay<"u"&&(o.decay=n.readNumber("--light-decay",a.decay??1)),typeof a.angle<"u"&&(o.angle=n.readNumber("--light-angle",a.angle??Math.PI/3)),typeof a.penumbra<"u"&&(o.penumbra=n.readNumber("--light-penumbra",a.penumbra??0));let s=n.readString("--light-ground-color","");s&&(o.groundColor=s),o.castShadow&&a.shadow&&(o.shadowBias=n.readNumber("--shadow-bias",a.shadow.bias??0),o.shadowMapSize=n.readNumber("--shadow-map-size",a.shadow.mapSize.width??512));let l=n.readString("--light-target","").trim();l&&(o.targetId=l);let c=n.readString("--light-target-offset","").trim();if(c){let h=this.parseTargetOffset(c);h&&(o.targetOffset=h)}return o})}parseTargetOffset(e){let t=e.split(/[\s,]+/).map(r=>r.trim()).filter(Boolean).map(r=>Number.parseFloat(r));return t.length<3||t.some(r=>Number.isNaN(r))?null:{x:t[0],y:t[1],z:t[2]}}};Pe.styleCache=new Z;var le=Pe;var Xe=Math.PI/180,U=class U{static applyVisualProps(e,t,r){let i=U.lastVisualProps.get(t);if(i){if(i.opacity===r.opacity&&i.color===r.color&&i.metalness===r.metalness&&i.roughness===r.roughness&&i.emissive===r.emissive&&i.castShadow===r.castShadow&&i.receiveShadow===r.receiveShadow)return;i.opacity=r.opacity,i.color=r.color,i.metalness=r.metalness,i.roughness=r.roughness,i.emissive=r.emissive,i.castShadow=r.castShadow,i.receiveShadow=r.receiveShadow}else U.lastVisualProps.set(t,{opacity:r.opacity,color:r.color,metalness:r.metalness,roughness:r.roughness,emissive:r.emissive,castShadow:r.castShadow,receiveShadow:r.receiveShadow});let n=r.castShadow??!1,a=r.receiveShadow??!1,o=typeof r.opacity=="number"?r.opacity:NaN,s=l=>{l&&(isNaN(o)||(l.opacity=o,l.transparent=o<1),r.color&&l.color&&l.color.set&&l.color.set(r.color),typeof r.metalness=="number"&&"metalness"in l&&(l.metalness=r.metalness),typeof r.roughness=="number"&&"roughness"in l&&(l.roughness=r.roughness),r.emissive&&l.emissive&&l.emissive.set&&l.emissive.set(r.emissive))};if(t.object.traverse)t.object.traverse(l=>{l.isMesh&&(l.castShadow!==n&&(l.castShadow=n),l.receiveShadow!==a&&(l.receiveShadow=a),(Array.isArray(l.material)?l.material:[l.material]).forEach(s))});else if(t.object.isMesh){let l=t.object;l.castShadow!==n&&(l.castShadow=n),l.receiveShadow!==a&&(l.receiveShadow=a),(Array.isArray(l.material)?l.material:[l.material]).forEach(s)}}sync(e,t,r,i){let{rect:n,width:a,height:o}=this.readLayout(e,r),s=this.readStyleBundle(e,r),{translateZ:l,cssScale:c,rotateX:h,rotateY:u,rotateZ:m,cssScaleZ:d,opacity:p,color:f,metalness:M,roughness:y,emissive:v,castShadow:b,receiveShadow:F,geometryQuality:R}=s,E=n.left+n.width*.5,O=n.top+n.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(E-r.viewportWidth/2,-(O-r.viewportHeight/2),l);else{let w=r.camera.getFrustumSizeAt(l),I=E/r.viewportWidth,T=O/r.viewportHeight;t.object.position.set((I-.5)*w.width,-(T-.5)*w.height,l)}t.object.rotation.x=-h*Xe,t.object.rotation.y=u*Xe,t.object.rotation.z=-m*Xe,t.object.rotation.order="XYZ";let x=a*c,S=o*c,D=i?.scale||1,z=d*D,_=x<S?x:S,k,B,A;switch(t.type){case"box":case"sphere":{let w=_*D;k=B=w,A=w*d;break}case"model":{let w=t.getOriginalBoundingBox();U.tempVector3||(U.tempVector3=r.engine.createVector3());let I=w.getSize(U.tempVector3),T=e.getAttribute("string-3d-model-fit"),N=parseFloat(e.getAttribute("string-3d-model-scale")||"1"),H=Number.isFinite(N)?N*D:D;if(I.x>0&&I.y>0){let P=x/I.x,W=S/I.y,j=(T==="cover"?P>W?P:W:P<W?P:W)*H;k=B=j,A=j*d}else{let P=_*H;k=B=P,A=P*d}break}case"cylinder":k=x*D,B=S*D,A=x*z;break;default:k=x*D,B=S*D,A=_*.5*z;break}return t.object.scale.set(k,B,A),U.applyVisualProps(e,t,{opacity:p,color:f&&f!=="none"?f:void 0,metalness:isNaN(M)?void 0:M,roughness:isNaN(y)?void 0:y,emissive:v&&v!=="none"?v:void 0,castShadow:b,receiveShadow:F}),this.applyGeometryQuality(t,R,r),this.updateCustomUniforms(e,t,r),{scale:c*D}}applyGeometryQuality(e,t,r){let i=r.engine,n=i?.simplifyGeometry?.bind(i);if(typeof n!="function")return;let a=Number.isFinite(t)&&t>0?t:1,o=U.lastGeometryQuality.get(e);if(typeof o=="number"&&Math.abs(o-a)<.001)return;U.lastGeometryQuality.set(e,a);let s=l=>{if(!l?.geometry)return;let c=l.userData||(l.userData={});c.__originalGeometry||(c.__originalGeometry=l.geometry);let h=c.__originalGeometry;if(a>=.999){l.geometry=h;return}c.__lodCache||(c.__lodCache=new Map);let u=a.toFixed(3);if(c.__lodCache.has(u)){l.geometry=c.__lodCache.get(u);return}let m=n(h,a);m&&(c.__lodCache.set(u,m),l.geometry=m)};e.object.traverse?e.object.traverse(l=>{l?.isMesh&&s(l)}):e.object.isMesh&&s(e.object)}updateCustomUniforms(e,t,r){let i=r.engine.getMaterialFactory?.();if(!i)return;let n=getComputedStyle(e),a=o=>{let s=o?.userData?.definition;if(!s?.uniforms)return;let l=i.parseUniformsFromCSS(s,e,n);for(let[c,h]of Object.entries(l)){let u=s.uniforms?.[c];if(!u)continue;let m=i.convertUniformValue?.bind(i),d=m?m(u.type,h):h;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=d:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=d:o.uniforms?.[c]&&(o.uniforms[c].value=d)}};if(t.object.traverse)t.object.traverse(o=>{o.isMesh&&(Array.isArray(o.material)?o.material:[o.material]).forEach(a)});else if(t.object.isMesh){let o=t.object;(Array.isArray(o.material)?o.material:[o.material]).forEach(a)}}readStyleBundle(e,t){return U.styleCache.get(e,t,r=>{let i=r.computedStyleMap?.(),n=getComputedStyle(r),a=(l,c)=>{let h=i?.get?.(l);if(h!=null){let m=typeof h=="object"&&"value"in h?h.value:h,d=typeof m=="number"?m:Number.parseFloat(String(m));if(!Number.isNaN(d))return d}let u=Number.parseFloat(n.getPropertyValue(l));return Number.isNaN(u)?c:u},o=l=>{let c=i?.get?.(l),h=c&&typeof c=="object"&&"value"in c?c.value:c;return typeof h=="string"?h.trim()||void 0:n.getPropertyValue(l).trim()||void 0},s=(l,c=!1)=>{let h=o(l);if(!h)return c;let u=h.toLowerCase();return u==="true"||u==="1"||u==="yes"?!0:u==="false"||u==="0"||u==="no"?!1:c};return{translateZ:a("--translate-z",0),cssScale:a("--scale",1),rotateX:a("--rotate-x",0),rotateY:a("--rotate-y",0),rotateZ:a("--rotate-z",0),cssScaleZ:a("--scale-z",1),opacity:a("--opacity",NaN),color:o("--material-color"),metalness:a("--material-metalness",NaN),roughness:a("--material-roughness",NaN),emissive:o("--material-emissive"),castShadow:s("--shadow-cast",!1),receiveShadow:s("--shadow-receive",!1),geometryQuality:a("--geometry-quality",1)}})}readLayout(e,t){let r=e.__layoutCache;return r||U.layoutCache.get(e,t,i=>{let n=i.getBoundingClientRect(),a=i.offsetWidth||n.width,o=i.offsetHeight||n.height;return{rect:n,width:a,height:o}})}};U.styleCache=new Z,U.layoutCache=new Z,U.tempVector3=null,U.lastVisualProps=new WeakMap,U.lastGeometryQuality=new WeakMap;var J=U;var qe=Math.PI/180,C={mode:"emitter",count:300,size:2,color:"#ffffff",opacity:1,spread:120,seed:1,emitRate:30,emitBurst:0,particleLife:2.5,particleSpeed:40,particleDirection:[0,1,0],particleGravity:[0,-30,0],particleDrag:.1,particleSizeVariation:.6,particleColorVariation:.2,particleShape:"sphere",particleModelUrl:"",particleModelLoader:"",particleModelNode:"",instanceShape:"sphere",instanceModelUrl:"",instanceModelLoader:"",instanceModelNode:"",instanceScale:1,instanceScaleVariation:.5,instanceRotationSpeed:.4,instanceJitter:.2,instanceFlow:.3,instanceDisperse:0,instanceDisperseScatter:0,instanceDisperseScatterX:0,instanceDisperseScatterY:0,instanceDisperseScatterZ:0},V=class V{sync(e,t,r,i){let n=e.__layoutCache,a=n?n.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r),s=a.left+a.width*.5,l=a.top+a.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(s-r.viewportWidth/2,-(l-r.viewportHeight/2),o.translateZ);else{let M=r.camera.getFrustumSizeAt(o.translateZ),y=s/r.viewportWidth,v=l/r.viewportHeight;t.object.position.set((y-.5)*M.width,-(v-.5)*M.height,o.translateZ)}let c=i?.scale??1,h=o.scale*c;t.object.scale.set(h,h,h),t.object.rotation.x=-o.rotateX*qe,t.object.rotation.y=o.rotateY*qe,t.object.rotation.z=-o.rotateZ*qe,t.object.rotation.order="XYZ";let u=this.buildConfig(o,a,r,i),m=V.lastConfig.get(t);(!m||!this.isSameConfig(m,u))&&(V.lastConfig.set(t,u),t.object.setConfig?.(u)),this.updateMaterialOverrides(e,t,r,o),this.updateCustomUniforms(e,t,r);let d=performance.now(),p=V.lastTime.get(t)??d,f=Math.max(0,(d-p)/1e3);return V.lastTime.set(t,d),t.object.update?.(f),{scale:i?.scale??1}}readStyleBundle(e,t){return V.styleCache.get(e,t,r=>{let i=new se(r),a=i.readString("--particles-mode",C.mode).toLowerCase()==="instanced"?"instanced":"emitter";return{...C,translateZ:i.readNumber("--translate-z",0),scale:i.readNumber("--scale",1),rotateX:i.readNumber("--rotate-x",0),rotateY:i.readNumber("--rotate-y",0),rotateZ:i.readNumber("--rotate-z",0),particlesFit:i.readNumber("--particles-fit",0)>.5,materialType:i.readString("--material-type","basic"),mode:a,count:i.readNumber("--particles-count",C.count),size:i.readNumber("--particles-size",C.size),color:i.readString("--particles-color",C.color),opacity:i.readNumber("--particles-opacity",C.opacity),spread:i.readNumber("--particles-spread",C.spread),seed:i.readNumber("--particles-seed",C.seed),emitRate:i.readNumber("--emit-rate",C.emitRate),emitBurst:i.readNumber("--emit-burst",C.emitBurst),particleLife:i.readNumber("--particle-life",C.particleLife),particleSpeed:i.readNumber("--particle-speed",C.particleSpeed),particleDirection:this.parseVec3(i.readString("--particle-direction","0 1 0"),C.particleDirection),particleGravity:this.parseVec3(i.readString("--particle-gravity","0 -30 0"),C.particleGravity),particleDrag:i.readNumber("--particle-drag",C.particleDrag),particleSizeVariation:i.readNumber("--particle-size-variation",C.particleSizeVariation),particleColorVariation:i.readNumber("--particle-color-variation",C.particleColorVariation),particleShape:this.parseShape(i.readString("--particles-shape",C.particleShape)),particleModelUrl:i.readString("--particles-model",C.particleModelUrl),particleModelLoader:i.readString("--particles-model-loader",C.particleModelLoader),particleModelNode:i.readString("--particles-model-node",C.particleModelNode),instanceShape:this.parseDistribution(i.readString("--instance-shape",C.instanceShape)),instanceModelUrl:i.readString("--instance-model",C.instanceModelUrl),instanceModelLoader:i.readString("--instance-model-loader",C.instanceModelLoader),instanceModelNode:i.readString("--instance-model-node",C.instanceModelNode),instanceScale:i.readNumber("--instance-scale",C.instanceScale),instanceScaleVariation:i.readNumber("--instance-scale-variation",C.instanceScaleVariation),instanceRotationSpeed:i.readNumber("--instance-rotation-speed",C.instanceRotationSpeed),instanceJitter:i.readNumber("--instance-jitter",C.instanceJitter),instanceFlow:i.readNumber("--instance-flow",C.instanceFlow),instanceDisperse:i.readNumber("--instance-disperse",C.instanceDisperse),instanceDisperseScatter:i.readNumber("--instance-scatter",C.instanceDisperseScatter),instanceDisperseScatterX:i.readNumber("--instance-scatter-x",C.instanceDisperseScatterX),instanceDisperseScatterY:i.readNumber("--instance-scatter-y",C.instanceDisperseScatterY),instanceDisperseScatterZ:i.readNumber("--instance-scatter-z",C.instanceDisperseScatterZ)}})}parseVec3(e,t){let r=e.split(/[\s,]+/).map(i=>Number.parseFloat(i)).filter(i=>!Number.isNaN(i));return r.length>=3?[r[0],r[1],r[2]]:t}parseShape(e){let t=e.trim().toLowerCase();return t==="box"?"box":t==="model"?"model":"sphere"}parseDistribution(e){return this.parseShape(e)}buildConfig(e,t,r,i){let a=i?.scale??1,o=Math.min(t.width,t.height),s=e.instanceShape==="box"||e.instanceShape==="model"?1:.5,l=e.particlesFit?o*s:e.spread,c=this.toWorld(l,e.translateZ,r);return{...e,count:Math.max(0,Math.floor(e.count)),size:Math.max(.1,e.size),opacity:Math.max(0,Math.min(1,e.opacity)),spread:Math.max(0,c*a),seed:Math.max(0,Math.floor(e.seed)),emitRate:Math.max(0,e.emitRate),emitBurst:Math.max(0,e.emitBurst),particleLife:Math.max(.1,e.particleLife),particleSpeed:Math.max(0,e.particleSpeed),particleDrag:Math.max(0,Math.min(1,e.particleDrag)),particleSizeVariation:Math.max(0,e.particleSizeVariation),particleColorVariation:Math.max(0,e.particleColorVariation),instanceScale:Math.max(.1,e.instanceScale),instanceScaleVariation:Math.max(0,e.instanceScaleVariation),instanceRotationSpeed:Math.max(0,e.instanceRotationSpeed),instanceJitter:Math.max(0,e.instanceJitter),instanceFlow:Math.max(0,e.instanceFlow),instanceDisperse:Math.max(0,e.instanceDisperse),instanceDisperseScatter:Math.max(0,e.instanceDisperseScatter),instanceDisperseScatterX:Math.max(0,e.instanceDisperseScatterX),instanceDisperseScatterY:Math.max(0,e.instanceDisperseScatterY),instanceDisperseScatterZ:Math.max(0,e.instanceDisperseScatterZ)}}toWorld(e,t,r){if(r.camera.getMode()==="orthographic")return e;let n=r.camera.getFrustumSizeAt(t).width/Math.max(1,r.viewportWidth);return e*n}isSameConfig(e,t){return JSON.stringify(e)===JSON.stringify(t)}updateMaterialOverrides(e,t,r,i){let a=(i.materialType||"basic").split("[")[0].trim().toLowerCase(),o=K.get(a),s=r.engine.getMaterialFactory?.();if(!o||!s||!s.supports(o)){if(!(V.materialInstances.has(t)||V.lastMaterialType.has(t)))return;let h=V.materialInstances.get(t);h&&(h.dispose(),V.materialInstances.delete(t)),V.lastMaterialType.delete(t),t.object.setMaterial?.(null,{points:!0,meshes:!0});return}if(V.lastMaterialType.get(t)!==a){let c=V.materialInstances.get(t);c&&c.dispose();let h=getComputedStyle(e),u=s.parseUniformsFromCSS(o,e,h),m=s.create(o,u);V.materialInstances.set(t,m),V.lastMaterialType.set(t,a);let d=m.material,p=!!d?.isShaderMaterial,f=t.object;f.setMaterial?.(d,{meshes:!0,points:!1}),f.setMaterial?.(p?d:null,{meshes:!1,points:!0})}}updateCustomUniforms(e,t,r){let i=r.engine.getMaterialFactory?.();if(!i)return;let n=getComputedStyle(e),a=o=>{let s=o?.userData?.definition;if(!s?.uniforms)return;let l=i.parseUniformsFromCSS(s,e,n);for(let[c,h]of Object.entries(l)){let u=s.uniforms?.[c];if(!u)continue;let m=i.convertUniformValue?.bind(i),d=m?m(u.type,h):h;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=d:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=d:o.uniforms?.[c]&&(o.uniforms[c].value=d)}};t.object.traverse&&t.object.traverse(o=>{(o.isMesh||o.isPoints)&&(Array.isArray(o.material)?o.material:[o.material]).forEach(a)})}};V.styleCache=new Z,V.lastConfig=new WeakMap,V.lastTime=new WeakMap,V.lastMaterialType=new WeakMap,V.materialInstances=new WeakMap;var je=V;var X=class{static register(e,t){let r=e.trim();r&&(this.fonts.has(r)&&console.warn(`[String3D] Font "${r}" already registered. Overwriting.`),this.fonts.set(r,{name:r,url:t}))}static setDefault(e){let t=e.trim();t&&(this.fonts.has(t)||console.warn(`[String3D] Default font "${t}" is not registered yet.`),this.defaultFont=t)}static get(e){return this.fonts.get(e.trim())}static list(){return Array.from(this.fonts.values())}static resolveFontFamily(e){if(!e)return this.getDefault();let t=e.split(",").map(r=>r.trim().replace(/^["']|["']$/g,"")).filter(Boolean);for(let r of t){let i=this.fonts.get(r);if(i)return i}return this.getDefault()}static getDefault(){return this.defaultFont&&this.fonts.get(this.defaultFont)||null}};X.fonts=new Map,X.defaultFont=null;var Ke=null,ve=null,Qe=null,Se=null;async function ht(){return ve||(Ke||(Ke=(async()=>typeof window<"u"&&window.opentype?(ve=window.opentype,ve):new Promise((g,e)=>{if(typeof document>"u"){e(new Error("[FontConverter] Cannot load opentype.js in non-browser environment"));return}let t=document.createElement("script");t.src="https://cdn.jsdelivr.net/npm/opentype.js@1.3.4/dist/opentype.min.js",t.onload=()=>{ve=window.opentype,g(ve)},t.onerror=()=>e(new Error("[FontConverter] Failed to load opentype.js")),document.head.appendChild(t)}))()),Ke)}async function mt(){return Se||(Qe||(Qe=(async()=>typeof window<"u"&&window.Module?.decompress?(Se=window.Module,Se):new Promise((g,e)=>{if(typeof document>"u"){e(new Error("[FontConverter] Cannot load woff2 decoder in non-browser environment"));return}let t=document.createElement("script");t.src="https://cdn.jsdelivr.net/npm/wawoff2@2.0.1/build/decompress_binding.js",t.onload=()=>{let r=0,i=500,n=()=>{r++;let a=window;a.Module?.decompress?(Se=a.Module,g(Se)):r>=i?e(new Error("[FontConverter] woff2 decoder initialization timeout")):setTimeout(n,10)};n()},t.onerror=()=>{e(new Error("[FontConverter] Failed to load woff2 decoder"))},document.head.appendChild(t)}))()),Qe)}async function dt(g){let e=await mt(),t=new Uint8Array(g),r=e.decompress(t);if(r instanceof Uint8Array){let i=new ArrayBuffer(r.length);return new Uint8Array(i).set(r),i}return r.buffer}function pt(g){return new DataView(g).getUint32(0,!1)===2001684018}var ee=class{static async load(e){let t=typeof e=="string"?e:"buffer-"+Date.now(),r=this.cache.get(t);if(r)return r;let i=this.loadingPromises.get(t);if(i)return i;let n=this.doLoad(e,t);this.loadingPromises.set(t,n);try{let a=await n;return this.cache.set(t,a),a}finally{this.loadingPromises.delete(t)}}static async doLoad(e,t){let r=await ht(),i;if(typeof e=="string")i=await(await fetch(e)).arrayBuffer();else if(e instanceof ArrayBuffer)i=e;else if(e instanceof Uint8Array)i=e.buffer;else throw new Error("[FontConverter] Invalid font source");pt(i)&&(i=await dt(i));let n=r.parse(i);if(!n)throw new Error("[FontConverter] Failed to parse font");return this.convertToTypeFace(n)}static convertToTypeFace(e){let t=1e3/e.unitsPerEm,r={};for(let i=0;i<e.glyphs.length;i++){let n=e.glyphs.get(i);if(!n.unicode)continue;let a=String.fromCharCode(n.unicode),o=n.getPath(0,0,e.unitsPerEm),s=this.pathToOutline(o,t),l=n.advanceWidth??n.xMax??e.unitsPerEm*.5;r[a]={ha:Math.round(l*t),x_min:n.xMin!==void 0?Math.round(n.xMin*t):0,x_max:n.xMax!==void 0?Math.round(n.xMax*t):0,o:s}}if(!r[" "]){let i=e.charToGlyph(" ");r[" "]={ha:Math.round((i?.advanceWidth||e.unitsPerEm*.25)*t),x_min:0,x_max:0,o:""}}return{glyphs:r,familyName:e.names.fontFamily?.en||e.names.fullName?.en||"Unknown",ascender:Math.round(e.ascender*t),descender:Math.round(e.descender*t),underlinePosition:Math.round((e.tables.post?.underlinePosition||-100)*t),underlineThickness:Math.round((e.tables.post?.underlineThickness||50)*t),boundingBox:{xMin:Math.round((e.tables.head?.xMin||0)*t),xMax:Math.round((e.tables.head?.xMax||1e3)*t),yMin:Math.round((e.tables.head?.yMin||-200)*t),yMax:Math.round((e.tables.head?.yMax||800)*t)},resolution:1e3,original_font_information:{format:0,copyright:e.names.copyright?.en||"",fontFamily:e.names.fontFamily?.en||"",fontSubfamily:e.names.fontSubfamily?.en||"",uniqueID:e.names.uniqueID?.en||"",fullName:e.names.fullName?.en||"",version:e.names.version?.en||"",postScriptName:e.names.postScriptName?.en||""}}}static pathToOutline(e,t){let r=[];for(let i of e.commands)switch(i.type){case"M":r.push(`m ${this.round(i.x*t)} ${this.round(i.y*t)}`);break;case"L":r.push(`l ${this.round(i.x*t)} ${this.round(i.y*t)}`);break;case"Q":r.push(`q ${this.round(i.x1*t)} ${this.round(i.y1*t)} ${this.round(i.x*t)} ${this.round(i.y*t)}`);break;case"C":r.push(`b ${this.round(i.x1*t)} ${this.round(i.y1*t)} ${this.round(i.x2*t)} ${this.round(i.y2*t)} ${this.round(i.x*t)} ${this.round(i.y*t)}`);break;case"Z":r.push("z");break}return r.join(" ")}static round(e){return Math.round(e*100)/100}static isTypefaceJson(e){let t=e.toLowerCase();return t.endsWith(".json")||t.includes("typeface")}static isFontFile(e){let t=e.toLowerCase();return t.endsWith(".ttf")||t.endsWith(".otf")||t.endsWith(".woff")||t.endsWith(".woff2")}static clearCache(){this.cache.clear()}};ee.cache=new Map,ee.loadingPromises=new Map;var Ve=Math.PI/180,ft=!1,L=class L{static log(...e){ft&&console.log("[TextSync]",...e)}static markObjectPendingFont(e,t){let r=this.pendingFontObjects.get(e);r||(r=new Set,this.pendingFontObjects.set(e,r)),r.add(t),this.log(`Marked object ${t.id} as pending font: ${e}`)}static clearObjectPendingFont(e,t){let r=this.pendingFontObjects.get(e);r&&r.delete(t)}static invalidatePendingObjects(e){let t=this.pendingFontObjects.get(e);t&&(this.log(`Font loaded: ${e}, invalidating ${t.size} pending objects`),t.forEach(r=>{this.geometryKeys.delete(r)}),t.clear())}sync(e,t,r,i){let{rect:n,width:a,height:o}=this.readLayout(e,r),s=this.readStyleBundle(e,r),{translateZ:l,cssScale:c,rotateX:h,rotateY:u,rotateZ:m,cssScaleZ:d,opacity:p,color:f,metalness:M,roughness:y,emissive:v,castShadow:b,receiveShadow:F,fontFamily:R,fontSize:E,textTransform:O,textDepth:x,textCurveSegments:S,bevelEnabled:D,bevelSize:z,bevelThickness:_,bevelOffset:k,bevelSegments:B,fontCss:A}=s,w=n.left+n.width*.5,I=n.top+n.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(w-r.viewportWidth/2,-(I-r.viewportHeight/2),l);else{let Y=r.camera.getFrustumSizeAt(l),G=w/r.viewportWidth,ie=I/r.viewportHeight;t.object.position.set((G-.5)*Y.width,-(ie-.5)*Y.height,l)}t.object.rotation.x=-h*Ve,t.object.rotation.y=u*Ve,t.object.rotation.z=-m*Ve,t.object.rotation.order="XYZ",t.object.rotation.z=-m*Ve,t.object.rotation.order="XYZ";let T=this.extractCharacterLayout(e,O),N=T.map(Y=>Y.char).join(""),H=!!A,P=this.getTextMesh(t);if(!P)return L.log("No mesh found for text object"),{scale:c*(i?.scale||1)};if(T.length===0)return L.log("Empty text content, hiding mesh"),P.visible=!1,{scale:c*(i?.scale||1)};P.visible=!0;let W=X.resolveFontFamily(R||"");if(!W){return L.warnedMissingFont||(console.warn("[String3D] No registered font found for 3D text. Font family:",R),L.warnedMissingFont=!0),{scale:c*(i?.scale||1)};return{scale:c*(i?.scale||1)}}if(!r.engine.loadFont||!r.engine.createTextGeometry)return L.warnedMissingLoader||(console.warn("[String3D] Engine does not support text geometry."),L.warnedMissingLoader=!0),{scale:c*(i?.scale||1)};let j=W.url,Q=L.fontCache.get(j);if(!Q){if(L.markObjectPendingFont(j,t),!L.fontPromises.has(j)){let Y=r.engine.loadFont(j).then(G=>(G&&(L.fontCache.set(j,G),L.invalidatePendingObjects(j)),G));L.fontPromises.set(j,Y)}return P.visible=!1,{scale:c*(i?.scale||1)}}L.clearObjectPendingFont(j,t);let te=T.length>0?`${T.length}:${T[0].x.toFixed(1)},${T[0].y.toFixed(1)}:${T[T.length-1].x.toFixed(1)},${T[T.length-1].y.toFixed(1)}`:"empty",re=[N,E.toFixed(3),A||"",n.width.toFixed(1),n.height.toFixed(1),te,x.toFixed(3),S.toFixed(3),D?"1":"0",z.toFixed(3),_.toFixed(3),k.toFixed(3),B.toFixed(3)].join("|");if(L.geometryKeys.get(t)!==re){L.log("Creating new geometry for",N.substring(0,20),"Layout:",te);let Y=H?T:(()=>{let ie=L.getFontMetrics(Q,E),ce=ie?ie.ascent:E*.8;return T.map(ne=>({...ne,y:ne.y+ce}))})(),G=r.engine.createTextGeometry(N,Q,{size:E,height:x,curveSegments:Math.max(1,Math.round(S)),bevelEnabled:D,bevelThickness:_,bevelSize:z,bevelOffset:k,bevelSegments:Math.max(0,Math.round(B)),lineHeight:0,letterSpacing:0,align:"left",layout:Y,fontCss:A,useCanvasText:!0});G&&(G.computeBoundingBox(),P.geometry&&P.geometry.dispose?.(),P.geometry=G,t.geometry=G,L.geometryKeys.set(t,re))}let De=i?.scale||1,we=r.camera.getMode()==="orthographic"?1:r.camera.getScaleAtZ(l,r.viewportHeight),oe=c*De*we,Ce=oe*d;t.object.scale.set(oe,oe,Ce);let Ee=-a*.5,he=o*.5;return P.position.set(Ee,he,0),J.applyVisualProps(e,t,{opacity:p,color:f&&f!=="none"?f:void 0,metalness:Number.isFinite(M)?M:void 0,roughness:Number.isFinite(y)?y:void 0,emissive:v&&v!=="none"?v:void 0,castShadow:b,receiveShadow:F}),this.updateCustomUniforms(e,t,r),{scale:oe}}extractCharacterLayout(e,t){let r=[];if(typeof document>"u"||!document.createRange)return r;let i=document.createRange(),n=e.getBoundingClientRect(),a=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),o;for(;o=a.nextNode();){let s=o.textContent||"";if(!(!s.trim()&&s!==" "))for(let l=0;l<s.length;l++){let c=s[l];if(c===`
116
+ `||c==="\r"||!c.trim())continue;i.setStart(o,l),i.setEnd(o,l+1);let h=i.getClientRects();if(h.length>0){let u=h[0],m=u.left-n.left,d=u.top-n.top,p=this.applyTextTransform(c,t);r.push({char:p,x:m,y:d,width:u.width,height:u.height})}}}return r}getTextMesh(e){let t=e.object;if(t?.__textMesh)return t.__textMesh;if(t?.isMesh)return t;if(Array.isArray(t?.children)){let r=t.children.find(i=>i?.isMesh);if(r)return t.__textMesh=r,r}return null}updateCustomUniforms(e,t,r){let i=r.engine.getMaterialFactory?.();if(!i)return;let n=getComputedStyle(e),a=o=>{let s=o?.userData?.definition;if(!s?.uniforms)return;let l=i.parseUniformsFromCSS(s,e,n);for(let[c,h]of Object.entries(l)){let u=s.uniforms?.[c];if(!u)continue;let m=i.convertUniformValue?.bind(i),d=m?m(u.type,h):h;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=d:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=d:o.uniforms?.[c]&&(o.uniforms[c].value=d)}};if(t.object.traverse)t.object.traverse(o=>{o.isMesh&&(Array.isArray(o.material)?o.material:[o.material]).forEach(a)});else{let o=this.getTextMesh(t);if(!o)return;(Array.isArray(o.material)?o.material:[o.material]).forEach(a)}}readStyleBundle(e,t){return L.styleCache.get(e,t,r=>{let i=r.computedStyleMap?.(),n=getComputedStyle(r),a=(x,S)=>{let D=i?.get?.(x);if(D!=null){let k=typeof D=="object"&&"value"in D?D.value:D,B=typeof k=="number"?k:Number.parseFloat(String(k));if(!Number.isNaN(B))return B}let z=n.getPropertyValue(x),_=Number.parseFloat(z);return Number.isNaN(_)?S:_},o=x=>{let S=i?.get?.(x),D=S&&typeof S=="object"&&"value"in S?S.value:S;return typeof D=="string"?D.trim():n.getPropertyValue(x).trim()},s=(x,S=!1)=>{let D=o(x);if(!D)return S;let z=D.toLowerCase();return z==="true"||z==="1"||z==="yes"?!0:z==="false"||z==="0"||z==="no"?!1:S},l=o("--material-color"),c=l&&l!=="none"?l:n.color.trim(),h=(()=>{let x=n.fontSize||"",S=Number.parseFloat(x);return Number.isFinite(S)?S:16})(),u=(()=>{let x=n.lineHeight||"";if(!x||x==="normal")return h*1.2;let S=Number.parseFloat(x);return Number.isFinite(S)?x.endsWith("px")?S:S*h:h*1.2})(),m=(()=>{let x=n.letterSpacing||"";if(!x||x==="normal")return 0;let S=Number.parseFloat(x);return Number.isFinite(S)?S:0})(),d=o("--text-fit")||"none",p=a("--text-depth",NaN),f=Number.isFinite(p)?p:Math.max(1,h*.2),M=a("--text-bevel-size",0),y=a("--text-bevel-thickness",0),v=a("--text-bevel-offset",0),b=a("--text-bevel-steps",0),F=(n.textAlign||"left").toLowerCase(),R=F==="center"?"center":F==="right"||F==="end"?"right":"left",E=n.font?.trim(),O=E&&E.length>0?E:[n.fontStyle||"normal",n.fontWeight||"normal",`${n.fontSize||"16px"}/${n.lineHeight||"normal"}`,n.fontFamily||"sans-serif"].join(" ");return{translateZ:a("--translate-z",0),cssScale:a("--scale",1),rotateX:a("--rotate-x",0),rotateY:a("--rotate-y",0),rotateZ:a("--rotate-z",0),cssScaleZ:a("--scale-z",1),opacity:a("--opacity",NaN),color:c,metalness:a("--material-metalness",NaN),roughness:a("--material-roughness",NaN),emissive:o("--material-emissive"),castShadow:s("--shadow-cast",!1),receiveShadow:s("--shadow-receive",!1),fontFamily:n.fontFamily||"",fontCss:O,fontSize:h,lineHeight:u,letterSpacing:m,textAlign:R,textTransform:(n.textTransform||"").toLowerCase(),textDepth:f,textCurveSegments:a("--text-curve-segments",8),bevelEnabled:M>0||y>0,bevelSize:M,bevelThickness:y,bevelOffset:v,bevelSegments:b,textFit:d==="cover"||d==="none"?d:"contain"}})}applyTextTransform(e,t){return!t||t==="none"?e:t==="uppercase"?e.toUpperCase():t==="lowercase"?e.toLowerCase():t==="capitalize"?e.replace(/\b(\p{L})/gu,r=>r.toUpperCase()):e}static getFontMetrics(e,t){let r=e?.data,i=Number(r?.resolution),n=Number(r?.ascender),a=Number(r?.descender);if(!Number.isFinite(i)||i<=0||!Number.isFinite(n)||!Number.isFinite(a))return null;let o=n/i*t,s=Math.abs(a)/i*t;return!Number.isFinite(o)||!Number.isFinite(s)?null:{ascent:o,descent:s}}readLayout(e,t){let r=e.__layoutCache;return r||L.layoutCache.get(e,t,i=>{let n=i.getBoundingClientRect();return{rect:n,width:n.width,height:n.height}})}};L.styleCache=new Z,L.layoutCache=new Z,L.geometryKeys=new WeakMap,L.fontCache=new Map,L.fontPromises=new Map,L.pendingFontObjects=new Map,L.warnedMissingFont=!1,L.warnedMissingLoader=!1;var ze=L;var Me=class{constructor(e,t,r,i){this.camera=e;this.viewportWidth=t;this.viewportHeight=r;this.engine=i;this.strategies=new Map;this.styleReadIntervalMs=0;this.layoutReadIntervalMs=0;this.strategies.set("box",new J),this.strategies.set("sphere",new J),this.strategies.set("plane",new J),this.strategies.set("cylinder",new J),this.strategies.set("model",new J),this.strategies.set("group",new Re),this.strategies.set("pointLight",new le),this.strategies.set("ambientLight",new le),this.strategies.set("directionalLight",new le),this.strategies.set("spotLight",new le),this.strategies.set("hemisphereLight",new le),this.strategies.set("particles",new je),this.strategies.set("text",new ze)}syncElement(e,t,r,i){let n=this.strategies.get(t.type);return n?n.sync(e,t,{camera:this.camera,viewportWidth:this.viewportWidth,viewportHeight:this.viewportHeight,engine:this.engine,dirtySet:i?.dirtySet,forceSync:i?.forceSync,styleReadIntervalMs:this.styleReadIntervalMs,layoutReadIntervalMs:this.layoutReadIntervalMs},r):(console.warn(`[String3D Sync] No strategy for type "${t.type}"`),null)}setSyncOptions(e){this.styleReadIntervalMs=Math.max(0,e.styleReadIntervalMs??0),this.layoutReadIntervalMs=Math.max(0,e.layoutReadIntervalMs??0)}updateViewportSize(e,t){this.viewportWidth=e,this.viewportHeight=t}};var Be=class{constructor(e){this.handleScrollBound=()=>this.handleScroll();this.dirtyElements=new Set;this.observedElements=new Set;this.resizeObserver=null;this.mutationObserver=null;this.enabled=!1;this.domVersion=0;this.attributeFilter=e}enable(){this.enabled||(this.enabled=!0,this.setupObservers(),this.setupScrollListeners())}disable(){this.enabled&&(this.enabled=!1,this.removeScrollListeners(),this.resizeObserver?.disconnect(),this.mutationObserver?.disconnect(),this.dirtyElements.clear(),this.observedElements.clear())}observeElement(e){!this.enabled||this.observedElements.has(e)||(this.observedElements.add(e),this.resizeObserver?.observe(e),this.mutationObserver?.observe(e,{attributes:!0,attributeFilter:this.attributeFilter}))}observeScene(e){this.enabled&&e.forEach(t=>this.observeRecursive(t))}markDirty(e){this.enabled&&(this.dirtyElements.add(e),this.bumpVersion())}markAllDirty(){this.enabled&&(this.observedElements.forEach(e=>this.dirtyElements.add(e)),this.bumpVersion())}getDirtySet(){return this.enabled?this.dirtyElements:null}clearDirty(){this.dirtyElements.clear()}getVersion(){return this.domVersion}isEnabled(){return this.enabled}observeRecursive(e){e.el instanceof HTMLElement&&this.observeElement(e.el),e.children.forEach(t=>this.observeRecursive(t))}handleScroll(){this.markAllDirty()}setupObservers(){typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(e=>{e.forEach(t=>{t.target instanceof HTMLElement&&this.markDirty(t.target)})})),typeof MutationObserver<"u"&&(this.mutationObserver=new MutationObserver(e=>{e.forEach(t=>{t.target instanceof HTMLElement&&this.markDirty(t.target)})}))}setupScrollListeners(){window.addEventListener("scroll",this.handleScrollBound,{passive:!0}),window.addEventListener("resize",this.handleScrollBound,{passive:!0}),window.visualViewport&&(window.visualViewport.addEventListener("scroll",this.handleScrollBound,{passive:!0}),window.visualViewport.addEventListener("resize",this.handleScrollBound,{passive:!0}))}removeScrollListeners(){window.removeEventListener("scroll",this.handleScrollBound),window.removeEventListener("resize",this.handleScrollBound),window.visualViewport&&(window.visualViewport.removeEventListener("scroll",this.handleScrollBound),window.visualViewport.removeEventListener("resize",this.handleScrollBound))}bumpVersion(){this.domVersion+=1}};var Ae=class{constructor(e){this.easingParser=e;this.filterStates=new WeakMap;this.filterWarnings=new WeakMap}collectTargets(e,t,r,i){let n=[],a=o=>{let s=o.el;if(s){let l=this.filterStates.get(s)?.animating===!0,c=!r||!i||i.has(s)||l,h=this.readFilterChain(s,t,c);if(h&&h.length>0){let u=!r||!i||i.has(s)||l,m=this.filterStates.get(s)?.effectsKey||this.stringifyFilterChain(h);n.push({object:o,effects:h,effectsKey:m,dirty:u});return}}o.children.forEach(l=>a(l))};return e.forEach(o=>a(o)),n}clear(){this.filterStates=new WeakMap,this.filterWarnings=new WeakMap}readFilterChain(e,t,r){let i=this.filterStates.get(e);if(!r&&i)return i.animating?this.sampleTransition(i,t):i.effects;let n=Je(e);if(!n||n==="none"){if(i){if(i.animating&&i.clearOnComplete){let p=this.sampleTransition(i,t);return i.animating?p:(this.filterStates.delete(e),null)}let{duration:u,delay:m,easing:d}=this.getFilterTransition(e);if(u<=0&&i.lastDuration>0&&(u=i.lastDuration,m=i.lastDelay,d=i.lastEasing),u>0){let p=this.makeZeroChain(i.effects);return i.from=i.effects,i.to=p,i.startTime=t+m,i.duration=u,i.easing=d,i.animating=!0,i.clearOnComplete=!0,i.lastDuration=u,i.lastDelay=m,i.lastEasing=d,this.sampleTransition(i,t)}}return this.filterStates.delete(e),null}let{effects:a,warnings:o}=this.parseFilterChain(n);if(this.warnFilterIssues(e,n,o),a.length===0)return null;let s=this.filterStates.get(e);if(!s){let{duration:u,delay:m,easing:d}=this.getFilterTransition(e);if(u>0){let p=this.makeZeroChain(a),f={raw:n,effects:a,animating:!0,from:p,to:a,startTime:t+m,duration:u,easing:d,clearOnComplete:!1,lastDuration:u,lastDelay:m,lastEasing:d};return f.effectsKey=this.stringifyFilterChain(a),this.filterStates.set(e,f),this.sampleTransition(f,t)}return this.filterStates.set(e,{raw:n,effects:a,animating:!1,from:a,to:a,startTime:0,duration:0,easing:p=>p,clearOnComplete:!1,lastDuration:0,lastDelay:0,lastEasing:p=>p,effectsKey:this.stringifyFilterChain(a)}),a}if(s.raw===n){if(s.animating){let u=this.sampleTransition(s,t);return!s.animating&&s.clearOnComplete?(this.filterStates.delete(e),null):u}return s.effects}s.pendingEffects=void 0,s.pendingRaw=void 0;let{duration:l,delay:c,easing:h}=this.getFilterTransition(e);if(l<=0&&s.lastDuration>0&&(l=s.lastDuration,c=s.lastDelay,h=s.lastEasing),l>0){let u=this.canInterpolate(s.effects,a),m=s.animating?this.getCurrentChain(s,t):s.effects;if(!u&&this.isZeroChain(a))return s.pendingRaw=n,s.pendingEffects=a,s.raw=n,s.effects=m,s.from=m,s.to=this.makeZeroChain(m),s.startTime=t+c,s.duration=l,s.easing=h,s.animating=!0,s.clearOnComplete=!1,s.lastDuration=l,s.lastDelay=c,s.lastEasing=h,s.effectsKey=this.stringifyFilterChain(a),this.sampleTransition(s,t);let d=u?m:this.makeZeroChain(a);return s.raw=n,s.effects=a,s.from=d,s.to=a,s.startTime=t+c,s.duration=l,s.easing=h,s.animating=!0,s.clearOnComplete=!1,s.lastDuration=l,s.lastDelay=c,s.lastEasing=h,s.effectsKey=this.stringifyFilterChain(a),this.sampleTransition(s,t)}return s.raw=n,s.effects=a,s.animating=!1,s.clearOnComplete=!1,s.effectsKey=this.stringifyFilterChain(a),a}warnFilterIssues(e,t,r){r.length===0||this.filterWarnings.get(e)===t||(r.forEach(n=>console.warn(n,e)),this.filterWarnings.set(e,t))}parseFilterChain(e){let t=[],r=[],i=u=>{let d=u.trim().toLowerCase().match(/^(-?\d*\.?\d+)(px)?$/);if(!d)return null;let p=Number.parseFloat(d[1]);return Number.isFinite(p)?p:null},n=u=>{let m=u.trim().toLowerCase();if(!m)return null;if(m.endsWith("%")){let p=Number.parseFloat(m.slice(0,-1));return Number.isFinite(p)?p/100:null}let d=Number.parseFloat(m);return Number.isFinite(d)?d:null},a=u=>{let m=u.trim().toLowerCase();if(!m)return null;if(m.endsWith("rad")){let f=Number.parseFloat(m.slice(0,-3));return Number.isFinite(f)?f:null}let d=m.endsWith("deg")?m.slice(0,-3):m,p=Number.parseFloat(d);return Number.isFinite(p)?p*Math.PI/180:null},o=u=>{let m=u.split(",").map(f=>f.trim()),d=i(m[0]||"");if(d===null)return null;let p=m[1]?n(m[1]):null;return{intensity:Math.max(0,d),threshold:p===null?.8:Math.max(0,Math.min(1,p))}},s=(u,m,d=!1)=>{let p=i(u);return p===null?(t.push(`[String3D] Invalid ${m} value "${u}".`),null):!d&&p<=0?(t.push(`[String3D] ${m} must be > 0.`),null):p},l=(u,m)=>{let d=n(u);return d===null?(t.push(`[String3D] Invalid ${m} value "${u}".`),null):d},c=/([a-zA-Z-]+)\(([^)]*)\)/g,h;for(;h=c.exec(e);){let u=h[1].toLowerCase(),m=(h[2]||"").trim();if(u==="blur"){let d=s(m,"blur",!0);d!==null&&r.push({type:"blur",amount:d})}else if(u==="pixel"||u==="pixelate"){let d=s(m,"pixel",!0);d!==null&&r.push({type:"pixel",size:d})}else if(u==="bloom"){let d=o(m);d?r.push({type:"bloom",...d}):t.push(`[String3D] Invalid bloom value "${m}".`)}else if(u==="brightness"){let d=l(m,"brightness");d!==null&&r.push({type:"brightness",amount:Math.max(0,d)})}else if(u==="contrast"){let d=l(m,"contrast");d!==null&&r.push({type:"contrast",amount:Math.max(0,d)})}else if(u==="saturate"){let d=l(m,"saturate");d!==null&&r.push({type:"saturate",amount:Math.max(0,d)})}else if(u==="grayscale"){let d=l(m,"grayscale");d!==null&&r.push({type:"grayscale",amount:Math.max(0,Math.min(1,d))})}else if(u==="sepia"){let d=l(m,"sepia");d!==null&&r.push({type:"sepia",amount:Math.max(0,Math.min(1,d))})}else if(u==="invert"){let d=l(m,"invert");d!==null&&r.push({type:"invert",amount:Math.max(0,Math.min(1,d))})}else if(u==="hue-rotate"){let d=a(m);d!==null?r.push({type:"hue-rotate",angle:d}):t.push(`[String3D] Invalid hue-rotate value "${m}".`)}else if(u){let d=ae.get(u);if(d){let p=d.parse?d.parse(m):{};p===null?t.push(`[String3D] Invalid custom filter "${u}" args "${m}".`):r.push({type:"custom",name:u,uniforms:p})}else t.push(`[String3D] Unknown filter "${u}".`)}}return r.length===0&&t.push("[String3D] No valid filters parsed from --filter."),{effects:r,warnings:t}}getFilterTransition(e){let t=getComputedStyle(e),r=this.splitTransitionList(t.transitionProperty),i=this.splitTransitionList(t.transitionDuration),n=this.splitTransitionList(t.transitionDelay),a=this.splitTransitionList(t.transitionTimingFunction),o=this.findTransitionIndex(r,"--filter");if(o===-1){let h=this.parseTransitionShorthand(t.transition),u=h.get("--filter")||h.get("all");return u||{duration:0,delay:0,easing:m=>m}}let s=this.parseTime(i[o]||i[i.length-1]||"0s"),l=this.parseTime(n[o]||n[n.length-1]||"0s"),c=a[o]||a[a.length-1]||"linear";return{duration:s,delay:l,easing:this.parseEasing(c)}}splitTransitionList(e){let t=[],r="",i=0;for(let n=0;n<e.length;n+=1){let a=e[n];a==="("&&(i+=1),a===")"&&(i=Math.max(0,i-1)),a===","&&i===0?(t.push(r.trim()),r=""):r+=a}return r.trim()&&t.push(r.trim()),t.length>0?t:["all"]}findTransitionIndex(e,t){let r=e.map(n=>n.trim().toLowerCase()),i=r.indexOf(t);return i===-1&&(i=r.indexOf("all")),i}parseTime(e){let t=e.trim().toLowerCase();if(t.endsWith("ms")){let i=Number.parseFloat(t.slice(0,-2));return Number.isFinite(i)?i:0}if(t.endsWith("s")){let i=Number.parseFloat(t.slice(0,-1));return Number.isFinite(i)?i*1e3:0}let r=Number.parseFloat(t);return Number.isFinite(r)?r:0}parseTransitionShorthand(e){let t=new Map;return this.splitTransitionList(e).forEach(i=>{if(!i)return;let n=i.trim().split(/\s+(?![^()]*\))/g),a="",o="",s="",l="";n.forEach(c=>{let h=c.toLowerCase();h.endsWith("ms")||h.endsWith("s")||/^[0-9.]+$/.test(h)?o?s||(s=h):o=h:h.startsWith("cubic-bezier")||h.startsWith("steps")||h==="linear"||h==="ease"||h==="ease-in"||h==="ease-out"||h==="ease-in-out"?l=c:a||(a=c)}),a&&t.set(a.trim().toLowerCase(),{duration:this.parseTime(o||"0s"),delay:this.parseTime(s||"0s"),easing:this.parseEasing(l||"linear")})}),t}parseEasing(e){let t=e.trim();if(!t)return r=>r;if(!this.easingParser)return r=>r;try{let r=this.easingParser(t);return typeof r=="function"?r:i=>i}catch{return r=>r}}canInterpolate(e,t){return e.length!==t.length?!1:e.every((r,i)=>{let n=t[i];if(r.type!==n.type)return!1;if(r.type==="custom"&&n.type==="custom"){if(r.name!==n.name)return!1;let a=Object.keys(r.uniforms||{}),o=Object.keys(n.uniforms||{});return a.length!==o.length?!1:a.every(s=>s in(n.uniforms||{})&&this.isNumeric(r.uniforms?.[s]))}return!0})}makeZeroChain(e){return e.map(t=>{switch(t.type){case"blur":return{type:"blur",amount:0};case"pixel":return{type:"pixel",size:0};case"bloom":return{type:"bloom",intensity:0,threshold:t.threshold};case"brightness":return{type:"brightness",amount:1};case"contrast":return{type:"contrast",amount:1};case"saturate":return{type:"saturate",amount:1};case"grayscale":return{type:"grayscale",amount:0};case"sepia":return{type:"sepia",amount:0};case"invert":return{type:"invert",amount:0};case"hue-rotate":return{type:"hue-rotate",angle:0};case"custom":{let r={};return Object.entries(t.uniforms||{}).forEach(([i,n])=>{r[i]=this.isNumeric(n)?0:n}),{type:"custom",name:t.name,uniforms:r}}default:return t}})}sampleTransition(e,t){if(!e.animating)return e.effects;if(t<e.startTime)return e.from;let r=t-e.startTime,i=Math.max(1,e.duration),n=Math.min(1,Math.max(0,r/i)),a=e.easing(n),o=this.interpolateChain(e.from,e.to,a);return n>=1&&(e.animating=!1,e.from=e.to,e.pendingEffects&&e.pendingRaw===e.raw?(e.effects=e.pendingEffects,e.raw=e.pendingRaw||e.raw,e.pendingEffects=void 0,e.pendingRaw=void 0):e.pendingEffects&&(e.pendingEffects=void 0,e.pendingRaw=void 0)),o}getCurrentChain(e,t){if(!e.animating)return e.effects;if(t<e.startTime)return e.from;let r=t-e.startTime,i=Math.max(1,e.duration),n=Math.min(1,Math.max(0,r/i)),a=e.easing(n);return this.interpolateChain(e.from,e.to,a)}interpolateChain(e,t,r){return this.canInterpolate(e,t)?e.map((i,n)=>this.interpolateEffect(i,t[n],r)):t}interpolateEffect(e,t,r){let i=(n,a)=>n+(a-n)*r;if(e.type==="blur"&&t.type==="blur")return{type:"blur",amount:i(e.amount,t.amount)};if(e.type==="pixel"&&t.type==="pixel")return{type:"pixel",size:i(e.size,t.size)};if(e.type==="bloom"&&t.type==="bloom")return{type:"bloom",intensity:i(e.intensity,t.intensity),threshold:i(e.threshold,t.threshold)};if(e.type==="brightness"&&t.type==="brightness")return{type:"brightness",amount:i(e.amount,t.amount)};if(e.type==="contrast"&&t.type==="contrast")return{type:"contrast",amount:i(e.amount,t.amount)};if(e.type==="saturate"&&t.type==="saturate")return{type:"saturate",amount:i(e.amount,t.amount)};if(e.type==="grayscale"&&t.type==="grayscale")return{type:"grayscale",amount:i(e.amount,t.amount)};if(e.type==="sepia"&&t.type==="sepia")return{type:"sepia",amount:i(e.amount,t.amount)};if(e.type==="invert"&&t.type==="invert")return{type:"invert",amount:i(e.amount,t.amount)};if(e.type==="hue-rotate"&&t.type==="hue-rotate")return{type:"hue-rotate",angle:i(e.angle,t.angle)};if(e.type==="custom"&&t.type==="custom"&&e.name===t.name){let n={};return Object.entries(t.uniforms||{}).forEach(([a,o])=>{let s=e.uniforms?.[a];this.isNumeric(s)&&this.isNumeric(o)?n[a]=i(s,o):n[a]=o}),{type:"custom",name:t.name,uniforms:n}}return t}stringifyFilterChain(e){return e.map(r=>{if(r.type==="blur")return`blur:${r.amount}`;if(r.type==="pixel")return`pixel:${r.size}`;if(r.type==="bloom")return`bloom:${r.intensity},${r.threshold}`;if(r.type==="brightness")return`brightness:${r.amount}`;if(r.type==="contrast")return`contrast:${r.amount}`;if(r.type==="saturate")return`saturate:${r.amount}`;if(r.type==="grayscale")return`grayscale:${r.amount}`;if(r.type==="sepia")return`sepia:${r.amount}`;if(r.type==="invert")return`invert:${r.amount}`;if(r.type==="hue-rotate")return`hue-rotate:${r.angle}`;if(r.type==="custom"){let i=Object.keys(r.uniforms||{}).sort().map(n=>`${n}=${r.uniforms[n]}`).join(",");return`custom:${r.name}:${i}`}return"unknown"}).join("|")}isNumeric(e){return typeof e=="number"&&Number.isFinite(e)}isZeroChain(e){return e.every(t=>{switch(t.type){case"blur":return t.amount<=0;case"pixel":return t.size<=0;case"bloom":return t.intensity<=0;case"brightness":return t.amount===1;case"contrast":return t.amount===1;case"saturate":return t.amount===1;case"grayscale":return t.amount===0;case"sepia":return t.amount===0;case"invert":return t.amount===0;case"hue-rotate":return t.angle===0;case"custom":return!1;default:return!1}})}};var ue=class ue extends tt.StringModule{constructor(t){super(t);this.renderer=null;this.camera=null;this.scene=null;this.synchronizer=null;this.engine=null;this.canvasContainer=null;this.isLoading=new Map;this.useDirtySync=!1;this.lastSyncData=new WeakMap;this.htmlKey="3d",this.options=this.buildOptionsFromSettings(),this.dirtySyncManager=new Be(["style","class","string-3d","string-3d-model-fit","string-3d-model-scale"]),this.filterController=new Ae(r=>this.tools.easingFunction.process({easing:r})),this.attributesToMap=[...this.attributesToMap,{key:"3d",type:"string",fallback:"box"},{key:"3d-model",type:"string",fallback:""},{key:"3d-segments",type:"number",fallback:32},{key:"3d-segments-width",type:"number",fallback:32},{key:"3d-segments-height",type:"number",fallback:32},{key:"3d-model-loader",type:"string",fallback:""},{key:"3d-model-scale",type:"number",fallback:1},{key:"3d-model-center",type:"boolean",fallback:!1},{key:"3d-model-fit",type:"string",fallback:"contain"}]}static setProvider(t){ue.provider=t}static registerFont(t,r,i={}){X.register(t,r),i.default&&X.setDefault(t)}static setDefaultFont(t){X.setDefault(t)}canConnect(t){return super.canConnect(t)}initializeObject(t,r,i,n){super.initializeObject(t,r,i,n),r.setProperty("parentId",null);let a=i.parentElement?.closest('[string-3d="group"]');if(a){let o=a.getAttribute("string-id");o&&(r.setProperty("parentId",o),r.setProperty("parent",a))}}onResize(){this.renderer&&this.camera&&this.synchronizer&&(this.renderer.resize(this.camera),this.synchronizer.updateViewportSize(this.renderer.width,this.renderer.height),this.camera.clearScaleCache(),this.useDirtySync&&this.dirtySyncManager.markAllDirty())}onInit(){if(this.options=this.buildOptionsFromSettings(),!ue.provider){console.error("[String3D] No provider set. Call String3D.setProvider() before use.");return}this.engine=ue.provider.getEngine(),this.canvasContainer=this.createOrGetContainer(),this.registerTypedProperties(),this.injectCSS(),this.useDirtySync=!!this.options.useDirtySync,this.useDirtySync&&this.dirtySyncManager.enable(),this.renderer=new ge(this.canvasContainer,this.engine),this.renderer.attach(),this.camera=new fe(this.engine,"orthographic"),this.camera.setPosition(0,0,1e3),this.camera.resize(this.renderer.width,this.renderer.height);let t=this.resolveModelLoader(),r=this.resolveModelLoaderFactory();this.scene=new be(this.engine,{modelLoader:t,modelLoaderFactory:r}),this.scene.getScene().add(this.camera.camera),this.synchronizer=new Me(this.camera,this.renderer.width,this.renderer.height,this.engine),this.synchronizer.setSyncOptions({styleReadIntervalMs:this.options.styleReadIntervalMs,layoutReadIntervalMs:this.options.layoutReadIntervalMs}),console.info(`[String3D] Initialized with: ${ue.provider.getName()}`)}onSettingsChange(){this.options=this.buildOptionsFromSettings();let t=!!this.options.useDirtySync;t&&!this.useDirtySync?(this.useDirtySync=!0,this.dirtySyncManager.enable(),this.scene&&this.dirtySyncManager.observeScene(this.scene.rootObjects),this.dirtySyncManager.markAllDirty()):!t&&this.useDirtySync&&(this.useDirtySync=!1,this.dirtySyncManager.disable()),this.synchronizer?.setSyncOptions({styleReadIntervalMs:this.options.styleReadIntervalMs,layoutReadIntervalMs:this.options.layoutReadIntervalMs})}buildOptionsFromSettings(){return{hideHTML:this.getSettingValue("hideHTML",!1),container:this.getSettingValue("container",void 0),zIndex:this.getSettingValue("zIndex",1),modelLoaderType:this.getSettingValue("modelLoaderType",void 0),modelLoader:this.getSettingValue("modelLoader",void 0),modelLoaderFactory:this.getSettingValue("modelLoaderFactory",void 0),useDirtySync:this.getSettingValue("useDirtySync",!1),styleReadIntervalMs:this.getSettingValue("styleReadIntervalMs",0),layoutReadIntervalMs:this.getSettingValue("layoutReadIntervalMs",0)}}getSettingValue(t,r){return!this.settings||!(t in this.settings)?r:this.settings[t]}resolveModelLoader(){if(this.engine){if(this.options.modelLoader)return this.options.modelLoader;if(!this.options.modelLoaderFactory&&this.options.modelLoaderType)try{return this.engine.createModelLoader(this.options.modelLoaderType)}catch(t){console.warn("[String3D] Failed to create model loader:",t)}}}resolveModelLoaderFactory(){if(this.engine){if(this.options.modelLoaderFactory)return this.options.modelLoaderFactory;if(this.options.modelLoaderType)return(t,r)=>{let i=r||this.options.modelLoaderType;if(!i)throw new Error("[String3D] Model loader type not provided");return t.createModelLoader(i)}}}createOrGetContainer(){if(this.options.container instanceof HTMLElement)return this.applyContainerStyles(this.options.container),this.options.container;if(typeof this.options.container=="string"){let r=document.getElementById(this.options.container);if(r)return this.applyContainerStyles(r),r}let t=document.createElement("div");return t.id="string-3d-canvas",this.applyContainerStyles(t),document.body.insertBefore(t,document.body.firstChild),t}applyContainerStyles(t){Object.assign(t.style,{position:"fixed",left:"0",top:"0",width:"100vw",height:"100lvh",zIndex:String(this.options.zIndex),pointerEvents:"none"})}onObjectConnected(t){this.isLoading.has(t.id)||!this.scene||(this.isLoading.set(t.id,!0),this.scene.createFromElement(t),this.useDirtySync&&t.htmlElement&&(this.dirtySyncManager.observeElement(t.htmlElement),this.dirtySyncManager.markDirty(t.htmlElement)),this.options.hideHTML&&t.htmlElement&&(t.htmlElement.style.opacity="0",t.htmlElement.style.pointerEvents="none"))}onFrame(t){if(!this.renderer||!this.scene||!this.camera||!this.synchronizer)return;let r=this.useDirtySync?this.dirtySyncManager.getDirtySet():null,i=!r||r.size===0;this.batchReadLayouts(this.scene.rootObjects,i,r),this.scene.rootObjects.forEach(a=>{this.syncRecursive(a.el,a,{scale:1},i,r)});let n=this.filterController.collectTargets(this.scene.rootObjects,performance.now(),this.useDirtySync,r);this.renderer.render(this.scene,this.camera,n),this.useDirtySync&&this.dirtySyncManager.clearDirty()}batchReadLayouts(t,r,i){let n=a=>{if(a.el&&(r||!i||i.has(a.el))){let s=a.el.getBoundingClientRect(),l=a.el.offsetWidth||s.width,c=a.el.offsetHeight||s.height;a.el.__layoutCache={rect:s,width:l,height:c}}a.children.forEach(n)};t.forEach(n)}syncRecursive(t,r,i,n,a){if(!this.synchronizer||!t)return;let o=r.type==="particles"||r.type==="text"||n||!a||a.has(t),s=i;if(o){let c=this.synchronizer.syncElement(t,r,i,{dirtySet:a,forceSync:n});c&&typeof c.scale=="number"&&(this.lastSyncData.set(r,c),s=c)}else{let c=this.lastSyncData.get(r);c&&(s=c)}let l=n||o;r.children.forEach(c=>this.syncRecursive(c.el,c,s,l,a))}injectCSS(){if(document.getElementById("string-3d-styles"))return;let t=document.createElement("style");t.id="string-3d-styles",t.textContent=`
248
117
  @property --translate-x { syntax: "<number>"; inherits: false; initial-value: 0; }
249
118
  @property --translate-y { syntax: "<number>"; inherits: false; initial-value: 0; }
250
119
  @property --translate-z { syntax: "<number>"; inherits: false; initial-value: 0; }
@@ -257,11 +126,86 @@ self.onmessage = async (event) => {
257
126
  @property --scale-z { syntax: "<number>"; inherits: false; initial-value: 1; }
258
127
  @property --opacity { syntax: "<number>"; inherits: false; initial-value: 1; }
259
128
  @property --filter { syntax: "*"; inherits: false; initial-value: none; }
129
+ @property --light-color { syntax: "<color>"; inherits: false; initial-value: #ffffff; }
130
+ @property --light-intensity { syntax: "<number>"; inherits: false; initial-value: 1; }
131
+ @property --light-distance { syntax: "<number>"; inherits: false; initial-value: 1000; }
132
+ @property --light-decay { syntax: "<number>"; inherits: false; initial-value: 0; }
133
+ @property --light-angle { syntax: "<number>"; inherits: false; initial-value: 1.0472; }
134
+ @property --light-penumbra { syntax: "<number>"; inherits: false; initial-value: 0; }
135
+ @property --light-ground-color { syntax: "<color>"; inherits: false; initial-value: #ffffff; }
136
+ @property --light-target { syntax: "*"; inherits: false; initial-value: none; }
137
+ @property --shadow-cast { syntax: "<number>"; inherits: false; initial-value: 0; }
138
+ @property --shadow-receive { syntax: "<number>"; inherits: false; initial-value: 0; }
139
+ @property --shadow-bias { syntax: "<number>"; inherits: false; initial-value: 0; }
140
+ @property --shadow-map-size { syntax: "<number>"; inherits: false; initial-value: 512; }
141
+ @property --texture-flip-y { syntax: "<number>"; inherits: false; initial-value: 1; }
142
+ @property --texture-color-space { syntax: "*"; inherits: false; initial-value: none; }
143
+ @property --particles-mode { syntax: "*"; inherits: false; initial-value: emitter; }
144
+ @property --particles-count { syntax: "<number>"; inherits: false; initial-value: 300; }
145
+ @property --particles-size { syntax: "<number>"; inherits: false; initial-value: 2; }
146
+ @property --particles-color { syntax: "<color>"; inherits: false; initial-value: #ffffff; }
147
+ @property --particles-opacity { syntax: "<number>"; inherits: false; initial-value: 1; }
148
+ @property --particles-spread { syntax: "<number>"; inherits: false; initial-value: 120; }
149
+ @property --particles-seed { syntax: "<number>"; inherits: false; initial-value: 1; }
150
+ @property --particles-shape { syntax: "*"; inherits: false; initial-value: sphere; }
151
+ @property --particles-fit { syntax: "<number>"; inherits: false; initial-value: 0; }
152
+ @property --particles-model { syntax: "*"; inherits: false; initial-value: none; }
153
+ @property --particles-model-loader { syntax: "*"; inherits: false; initial-value: none; }
154
+ @property --particles-model-node { syntax: "*"; inherits: false; initial-value: none; }
155
+ @property --instance-model { syntax: "*"; inherits: false; initial-value: none; }
156
+ @property --instance-model-loader { syntax: "*"; inherits: false; initial-value: none; }
157
+ @property --instance-model-node { syntax: "*"; inherits: false; initial-value: none; }
158
+ @property --emit-rate { syntax: "<number>"; inherits: false; initial-value: 30; }
159
+ @property --emit-burst { syntax: "<number>"; inherits: false; initial-value: 0; }
160
+ @property --particle-life { syntax: "<number>"; inherits: false; initial-value: 2.5; }
161
+ @property --particle-speed { syntax: "<number>"; inherits: false; initial-value: 40; }
162
+ @property --particle-direction { syntax: "*"; inherits: false; initial-value: 0 1 0; }
163
+ @property --particle-gravity { syntax: "*"; inherits: false; initial-value: 0 -30 0; }
164
+ @property --particle-drag { syntax: "<number>"; inherits: false; initial-value: 0.1; }
165
+ @property --particle-size-variation { syntax: "<number>"; inherits: false; initial-value: 0.6; }
166
+ @property --particle-color-variation { syntax: "<number>"; inherits: false; initial-value: 0.2; }
167
+ @property --instance-shape { syntax: "*"; inherits: false; initial-value: sphere; }
168
+ @property --instance-scale { syntax: "<number>"; inherits: false; initial-value: 1; }
169
+ @property --instance-scale-variation { syntax: "<number>"; inherits: false; initial-value: 0.5; }
170
+ @property --instance-rotation-speed { syntax: "<number>"; inherits: false; initial-value: 0.4; }
171
+ @property --instance-jitter { syntax: "<number>"; inherits: false; initial-value: 0.2; }
172
+ @property --instance-flow { syntax: "<number>"; inherits: false; initial-value: 0.3; }
173
+ @property --instance-disperse { syntax: "<number>"; inherits: false; initial-value: 0; }
174
+ @property --instance-scatter { syntax: "<number>"; inherits: false; initial-value: 0; }
175
+ @property --instance-scatter-x { syntax: "<number>"; inherits: false; initial-value: 0; }
176
+ @property --instance-scatter-y { syntax: "<number>"; inherits: false; initial-value: 0; }
177
+ @property --instance-scatter-z { syntax: "<number>"; inherits: false; initial-value: 0; }
178
+ @property --text-depth { syntax: "<number>"; inherits: false; initial-value: 8; }
179
+ @property --text-curve-segments { syntax: "<number>"; inherits: false; initial-value: 8; }
180
+ @property --text-bevel-size { syntax: "<number>"; inherits: false; initial-value: 0; }
181
+ @property --text-bevel-thickness { syntax: "<number>"; inherits: false; initial-value: 0; }
182
+ @property --text-bevel-offset { syntax: "<number>"; inherits: false; initial-value: 0; }
183
+ @property --text-bevel-steps { syntax: "<number>"; inherits: false; initial-value: 0; }
184
+ @property --text-fit { syntax: "*"; inherits: false; initial-value: contain; }
260
185
 
261
- [string-3d] {
186
+ :where([string-3d]) {
262
187
  --translate-x: 0; --translate-y: 0; --translate-z: 0;
263
188
  --rotate-x: 0; --rotate-y: 0; --rotate-z: 0;
264
- --scale: 1; --scale-x: 1; --scale-y: 1; --scale-z: 1;--opacity: 1; --filter: none;
189
+ --scale: 1; --scale-x: 1; --scale-y: 1; --scale-z: 1; --opacity: 1; --filter: none;
190
+ --light-color: #ffffff; --light-intensity: 1; --light-distance: 1000; --light-decay: 0;
191
+ --light-angle: 1.0472; --light-penumbra: 0; --light-ground-color: #ffffff; --light-target: none;
192
+ --shadow-cast: 0; --shadow-receive: 0; --shadow-bias: 0; --shadow-map-size: 512;
193
+ --texture-flip-y: 1; --texture-color-space: none;
194
+ --particles-mode: emitter; --particles-count: 300; --particles-size: 2; --particles-color: #ffffff;
195
+ --particles-opacity: 1; --particles-spread: 120; --particles-seed: 1; --particles-shape: sphere;
196
+ --particles-fit: 0;
197
+ --particles-model: none; --particles-model-loader: none; --particles-model-node: none;
198
+ --instance-model: none; --instance-model-loader: none; --instance-model-node: none;
199
+ --emit-rate: 30; --emit-burst: 0; --particle-life: 2.5; --particle-speed: 40;
200
+ --particle-direction: 0 1 0; --particle-gravity: 0 -30 0; --particle-drag: 0.1;
201
+ --particle-size-variation: 0.6; --particle-color-variation: 0.2;
202
+ --instance-shape: sphere; --instance-scale: 1; --instance-scale-variation: 0.5;
203
+ --instance-rotation-speed: 0.4; --instance-jitter: 0.2; --instance-flow: 0.3;
204
+ --instance-disperse: 0;
205
+ --instance-scatter: 0;
206
+ --instance-scatter-x: 0; --instance-scatter-y: 0; --instance-scatter-z: 0;
207
+ --text-depth: 8; --text-curve-segments: 8; --text-bevel-size: 0; --text-bevel-thickness: 0;
208
+ --text-bevel-offset: 0; --text-bevel-steps: 0; --text-fit: contain;
265
209
  transform-style: preserve-3d;
266
210
  }
267
211
 
@@ -273,5 +217,58 @@ self.onmessage = async (event) => {
273
217
  rotateZ(calc(var(--rotate-z) * 1deg))
274
218
  scale3d(calc(var(--scale) * var(--scale-x)), calc(var(--scale) * var(--scale-y)), calc(var(--scale) * var(--scale-z)));
275
219
  }
276
- `,document.head.appendChild(e)}registerTypedProperties(){let e=globalThis.CSS;if(!e?.registerProperty)return;[{name:"--translate-x",initialValue:"0"},{name:"--translate-y",initialValue:"0"},{name:"--translate-z",initialValue:"0"},{name:"--rotate-x",initialValue:"0"},{name:"--rotate-y",initialValue:"0"},{name:"--rotate-z",initialValue:"0"},{name:"--scale",initialValue:"1"},{name:"--scale-x",initialValue:"1"},{name:"--scale-y",initialValue:"1"},{name:"--scale-z",initialValue:"1"},{name:"--opacity",initialValue:"1"},{name:"--filter",initialValue:"none"}].forEach(({name:i,initialValue:n})=>{try{e.registerProperty({name:i,syntax:i==="--filter"?"*":"<number>",inherits:!1,initialValue:n})}catch{}})}setupObservers(){typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(e=>{e.forEach(r=>{r.target instanceof HTMLElement&&this.markDirty(r.target)})})),typeof MutationObserver<"u"&&(this.mutationObserver=new MutationObserver(e=>{e.forEach(r=>{r.target instanceof HTMLElement&&this.markDirty(r.target)})}))}setupScrollListeners(){window.addEventListener("scroll",this.onScrollBound,{passive:!0}),window.addEventListener("resize",this.onScrollBound,{passive:!0}),window.visualViewport&&(window.visualViewport.addEventListener("scroll",this.onScrollBound,{passive:!0}),window.visualViewport.addEventListener("resize",this.onScrollBound,{passive:!0}))}removeScrollListeners(){window.removeEventListener("scroll",this.onScrollBound),window.removeEventListener("resize",this.onScrollBound),window.visualViewport&&(window.visualViewport.removeEventListener("scroll",this.onScrollBound),window.visualViewport.removeEventListener("resize",this.onScrollBound))}handleScroll(){this.useDirtySync&&this.markAllDirty()}observeElement(e){this.observedElements.has(e)||(this.observedElements.add(e),this.resizeObserver?.observe(e),this.mutationObserver?.observe(e,{attributes:!0,attributeFilter:["style","class","string-3d","string-3d-model-fit","string-3d-model-scale","string-3d-cast-shadow","string-3d-receive-shadow","string-3d-opacity","string-3d-target"]}))}observeSceneElements(){this.scene&&this.scene.rootObjects.forEach(e=>{this.observeRecursive(e)})}observeRecursive(e){e.el instanceof HTMLElement&&this.observeElement(e.el),e.children.forEach(r=>this.observeRecursive(r))}markDirty(e){this.dirtyElements.add(e),this.domVersion+=1}markAllDirty(){this.observedElements.forEach(e=>this.dirtyElements.add(e)),this.domVersion+=1}readNumberStyle(e,r,i){let a=e.computedStyleMap?.()?.get?.(r);if(a!==void 0){if(typeof a=="number")return a;if(typeof a=="string"){let c=Number.parseFloat(a);if(!Number.isNaN(c))return c}if(a&&typeof a=="object"){let c=a.value;if(typeof c=="number")return c;if(typeof c=="string"){let m=Number.parseFloat(c);if(!Number.isNaN(m))return m}}}let l=getComputedStyle(e).getPropertyValue(r),s=Number.parseFloat(l);return Number.isNaN(s)?i:s}readFilterRaw(e){let r=e.computedStyleMap?.(),i="",n=r?.get?.("--filter");if(n!==void 0){if(typeof n=="string")i=n;else if(n&&typeof n=="object"){let a=n.value;typeof a=="string"&&(i=a)}}return i||(i=getComputedStyle(e).getPropertyValue("--filter")||""),i=i.trim(),i}parseFilterChain(e){let r=[],i=[],n=u=>{let d=u.trim().toLowerCase().match(/^(-?\d*\.?\d+)(px)?$/);if(!d)return null;let g=Number.parseFloat(d[1]);return Number.isFinite(g)?g:null},a=u=>{let p=u.trim().toLowerCase();if(!p)return null;if(p.endsWith("%")){let g=Number.parseFloat(p.slice(0,-1));return Number.isFinite(g)?g/100:null}let d=Number.parseFloat(p);return Number.isFinite(d)?d:null},o=u=>{let p=u.trim().toLowerCase();if(!p)return null;if(p.endsWith("rad")){let v=Number.parseFloat(p.slice(0,-3));return Number.isFinite(v)?v:null}let d=p.endsWith("deg")?p.slice(0,-3):p,g=Number.parseFloat(d);return Number.isFinite(g)?g*Math.PI/180:null},l=u=>{let p=u.split(",").map(v=>v.trim()),d=n(p[0]||"");if(d===null)return null;let g=p[1]?a(p[1]):null;return{intensity:Math.max(0,d),threshold:g===null?.8:Math.max(0,Math.min(1,g))}},s=(u,p,d=!1)=>{let g=n(u);return g===null?(r.push(`[String3D] Invalid ${p} value "${u}".`),null):!d&&g<=0?(r.push(`[String3D] ${p} must be > 0.`),null):g},c=(u,p)=>{let d=a(u);return d===null?(r.push(`[String3D] Invalid ${p} value "${u}".`),null):d},m=/([a-zA-Z-]+)\(([^)]*)\)/g,h;for(;h=m.exec(e);){let u=h[1].toLowerCase(),p=(h[2]||"").trim();if(u==="blur"){let d=s(p,"blur",!0);d!==null&&i.push({type:"blur",amount:d})}else if(u==="pixel"||u==="pixelate"){let d=s(p,"pixel",!0);d!==null&&i.push({type:"pixel",size:d})}else if(u==="bloom"){let d=l(p);d?i.push({type:"bloom",...d}):r.push(`[String3D] Invalid bloom value "${p}".`)}else if(u==="brightness"){let d=c(p,"brightness");d!==null&&i.push({type:"brightness",amount:Math.max(0,d)})}else if(u==="contrast"){let d=c(p,"contrast");d!==null&&i.push({type:"contrast",amount:Math.max(0,d)})}else if(u==="saturate"){let d=c(p,"saturate");d!==null&&i.push({type:"saturate",amount:Math.max(0,d)})}else if(u==="grayscale"){let d=c(p,"grayscale");d!==null&&i.push({type:"grayscale",amount:Math.max(0,Math.min(1,d))})}else if(u==="sepia"){let d=c(p,"sepia");d!==null&&i.push({type:"sepia",amount:Math.max(0,Math.min(1,d))})}else if(u==="invert"){let d=c(p,"invert");d!==null&&i.push({type:"invert",amount:Math.max(0,Math.min(1,d))})}else if(u==="hue-rotate"){let d=o(p);d!==null?i.push({type:"hue-rotate",angle:d}):r.push(`[String3D] Invalid hue-rotate value "${p}".`)}else if(u){let d=k.get(u);if(d){let g=d.parse?d.parse(p):{};g===null?r.push(`[String3D] Invalid custom filter "${u}" args "${p}".`):i.push({type:"custom",name:u,uniforms:g})}else r.push(`[String3D] Unknown filter "${u}".`)}}return i.length===0&&r.push("[String3D] No valid filters parsed from --filter."),{effects:i,warnings:r}}warnFilterIssues(e,r,i){i.length===0||this.filterWarnings.get(e)===r||(i.forEach(a=>console.warn(a,e)),this.filterWarnings.set(e,r))}readFilterChain(e,r,i){let n=this.filterStates.get(e);if(!i&&n)return n.animating?this.sampleTransition(n,r):n.effects;let a=this.readFilterRaw(e);if(!a||a==="none"){if(n){if(n.animating&&n.clearOnComplete){let g=this.sampleTransition(n,r);return n.animating?g:(this.filterStates.delete(e),null)}let{duration:u,delay:p,easing:d}=this.getFilterTransition(e);if(u<=0&&n.lastDuration>0&&(u=n.lastDuration,p=n.lastDelay,d=n.lastEasing),u>0){let g=this.makeZeroChain(n.effects);return n.from=n.effects,n.to=g,n.startTime=r+p,n.duration=u,n.easing=d,n.animating=!0,n.clearOnComplete=!0,n.lastDuration=u,n.lastDelay=p,n.lastEasing=d,this.sampleTransition(n,r)}}return this.filterStates.delete(e),null}let{effects:o,warnings:l}=this.parseFilterChain(a);if(this.warnFilterIssues(e,a,l),o.length===0)return null;let s=this.filterStates.get(e);if(!s){let{duration:u,delay:p,easing:d}=this.getFilterTransition(e);if(u>0){let g=this.makeZeroChain(o),v={raw:a,effects:o,animating:!0,from:g,to:o,startTime:r+p,duration:u,easing:d,clearOnComplete:!1,lastDuration:u,lastDelay:p,lastEasing:d};return v.effectsKey=this.stringifyFilterChain(o),this.filterStates.set(e,v),this.sampleTransition(v,r)}return this.filterStates.set(e,{raw:a,effects:o,animating:!1,from:o,to:o,startTime:0,duration:0,easing:g=>g,clearOnComplete:!1,lastDuration:0,lastDelay:0,lastEasing:g=>g,effectsKey:this.stringifyFilterChain(o)}),o}if(s.raw===a){if(s.animating){let u=this.sampleTransition(s,r);return!s.animating&&s.clearOnComplete?(this.filterStates.delete(e),null):u}return s.effects}s.pendingEffects=void 0,s.pendingRaw=void 0;let{duration:c,delay:m,easing:h}=this.getFilterTransition(e);if(c<=0&&s.lastDuration>0&&(c=s.lastDuration,m=s.lastDelay,h=s.lastEasing),c>0){let u=this.canInterpolate(s.effects,o),p=s.animating?this.getCurrentChain(s,r):s.effects;if(!u&&this.isZeroChain(o))return s.pendingRaw=a,s.pendingEffects=o,s.raw=a,s.effects=p,s.from=p,s.to=this.makeZeroChain(p),s.startTime=r+m,s.duration=c,s.easing=h,s.animating=!0,s.clearOnComplete=!1,s.lastDuration=c,s.lastDelay=m,s.lastEasing=h,s.effectsKey=this.stringifyFilterChain(o),this.sampleTransition(s,r);let d=u?p:this.makeZeroChain(o);return s.raw=a,s.effects=o,s.from=d,s.to=o,s.startTime=r+m,s.duration=c,s.easing=h,s.animating=!0,s.clearOnComplete=!1,s.lastDuration=c,s.lastDelay=m,s.lastEasing=h,s.effectsKey=this.stringifyFilterChain(o),this.sampleTransition(s,r)}return s.raw=a,s.effects=o,s.animating=!1,s.clearOnComplete=!1,s.effectsKey=this.stringifyFilterChain(o),o}collectFilterTargets(e,r,i){if(!this.scene)return[];let n=[],a=o=>{let l=o.el;if(l){let s=!this.useDirtySync||!i||i.has(l)||this.filterStates.get(l)?.animating===!0,c=this.readFilterChain(l,e,s);if(c&&c.length>0){let m=!this.useDirtySync||!i||i.has(l)||this.filterStates.get(l)?.animating===!0,h=this.filterStates.get(l)?.effectsKey||this.stringifyFilterChain(c);n.push({object:o,effects:c,effectsKey:h,dirty:m});return}}o.children.forEach(s=>a(s))};return this.scene.rootObjects.forEach(o=>a(o)),n}stringifyFilterChain(e){return e.map(i=>{if(i.type==="blur")return`blur:${i.amount}`;if(i.type==="pixel")return`pixel:${i.size}`;if(i.type==="bloom")return`bloom:${i.intensity},${i.threshold}`;if(i.type==="brightness")return`brightness:${i.amount}`;if(i.type==="contrast")return`contrast:${i.amount}`;if(i.type==="saturate")return`saturate:${i.amount}`;if(i.type==="grayscale")return`grayscale:${i.amount}`;if(i.type==="sepia")return`sepia:${i.amount}`;if(i.type==="invert")return`invert:${i.amount}`;if(i.type==="hue-rotate")return`hue-rotate:${i.angle}`;if(i.type==="custom"){let n=Object.keys(i.uniforms||{}).sort().map(a=>`${a}=${i.uniforms[a]}`).join(",");return`custom:${i.name}:${n}`}return"unknown"}).join("|")}getFilterTransition(e){let r=getComputedStyle(e),i=this.splitTransitionList(r.transitionProperty),n=this.splitTransitionList(r.transitionDuration),a=this.splitTransitionList(r.transitionDelay),o=this.splitTransitionList(r.transitionTimingFunction),l=this.findTransitionIndex(i,"--filter");if(l===-1){let h=this.parseTransitionShorthand(r.transition),u=h.get("--filter")||h.get("all");return u||{duration:0,delay:0,easing:p=>p}}let s=this.parseTime(n[l]||n[n.length-1]||"0s"),c=this.parseTime(a[l]||a[a.length-1]||"0s"),m=o[l]||o[o.length-1]||"linear";return{duration:s,delay:c,easing:this.parseEasing(m)}}splitTransitionList(e){let r=[],i="",n=0;for(let a=0;a<e.length;a+=1){let o=e[a];o==="("&&(n+=1),o===")"&&(n=Math.max(0,n-1)),o===","&&n===0?(r.push(i.trim()),i=""):i+=o}return i.trim()&&r.push(i.trim()),r.length>0?r:["all"]}findTransitionIndex(e,r){let i=e.map(a=>a.trim().toLowerCase()),n=i.indexOf(r);return n===-1&&(n=i.indexOf("all")),n}parseTime(e){let r=e.trim().toLowerCase();if(r.endsWith("ms")){let n=Number.parseFloat(r.slice(0,-2));return Number.isFinite(n)?n:0}if(r.endsWith("s")){let n=Number.parseFloat(r.slice(0,-1));return Number.isFinite(n)?n*1e3:0}let i=Number.parseFloat(r);return Number.isFinite(i)?i:0}parseTransitionShorthand(e){let r=new Map;return this.splitTransitionList(e).forEach(n=>{if(!n)return;let a=n.trim().split(/\s+(?![^()]*\))/g),o="",l="",s="",c="";a.forEach(m=>{let h=m.toLowerCase();h.endsWith("ms")||h.endsWith("s")||/^[0-9.]+$/.test(h)?l?s||(s=h):l=h:h.startsWith("cubic-bezier")||h.startsWith("steps")||h==="linear"||h==="ease"||h==="ease-in"||h==="ease-out"||h==="ease-in-out"?c=m:o||(o=m)}),o&&r.set(o.trim().toLowerCase(),{duration:this.parseTime(l||"0s"),delay:this.parseTime(s||"0s"),easing:this.parseEasing(c||"linear")})}),r}parseEasing(e){let r=e.trim().toLowerCase();if(r==="linear")return i=>i;if(r==="ease")return this.cubicBezier(.25,.1,.25,1);if(r==="ease-in")return this.cubicBezier(.42,0,1,1);if(r==="ease-out")return this.cubicBezier(0,0,.58,1);if(r==="ease-in-out")return this.cubicBezier(.42,0,.58,1);if(r.startsWith("cubic-bezier")){let i=r.match(/cubic-bezier\(([^)]+)\)/);if(i){let n=i[1].split(",").map(a=>Number.parseFloat(a.trim()));if(n.length===4&&n.every(a=>Number.isFinite(a)))return this.cubicBezier(n[0],n[1],n[2],n[3])}}return i=>i}cubicBezier(e,r,i,n){let a=s=>{let c=1-s;return 3*c*c*s*e+3*c*s*s*i+s*s*s},o=s=>{let c=1-s;return 3*c*c*s*r+3*c*s*s*n+s*s*s},l=s=>{let c=s;for(let m=0;m<5;m+=1){let h=a(c)-s,u=3*(1-c)*(1-c)*e+6*(1-c)*c*(i-e)+3*c*c*(1-i);if(Math.abs(h)<1e-5||u===0)break;c-=h/u}return c};return s=>{let c=Math.min(1,Math.max(0,s)),m=l(c);return Math.min(1,Math.max(0,o(m)))}}canInterpolate(e,r){return e.length!==r.length?!1:e.every((i,n)=>{let a=r[n];if(i.type!==a.type)return!1;if(i.type==="custom"&&a.type==="custom"){if(i.name!==a.name)return!1;let o=Object.keys(i.uniforms||{}),l=Object.keys(a.uniforms||{});return o.length!==l.length?!1:o.every(s=>s in a.uniforms&&this.isNumeric(i.uniforms[s]))}return!0})}makeZeroChain(e){return e.map(r=>{switch(r.type){case"blur":return{type:"blur",amount:0};case"pixel":return{type:"pixel",size:0};case"bloom":return{type:"bloom",intensity:0,threshold:r.threshold};case"brightness":return{type:"brightness",amount:1};case"contrast":return{type:"contrast",amount:1};case"saturate":return{type:"saturate",amount:1};case"grayscale":return{type:"grayscale",amount:0};case"sepia":return{type:"sepia",amount:0};case"invert":return{type:"invert",amount:0};case"hue-rotate":return{type:"hue-rotate",angle:0};case"custom":{let i={};return Object.entries(r.uniforms||{}).forEach(([n,a])=>{i[n]=this.isNumeric(a)?0:a}),{type:"custom",name:r.name,uniforms:i}}default:return r}})}sampleTransition(e,r){if(!e.animating)return e.effects;if(r<e.startTime)return e.from;let i=r-e.startTime,n=Math.max(1,e.duration),a=Math.min(1,Math.max(0,i/n)),o=e.easing(a),l=this.interpolateChain(e.from,e.to,o);return a>=1&&(e.animating=!1,e.from=e.to,e.pendingEffects&&e.pendingRaw===e.raw?(e.effects=e.pendingEffects,e.raw=e.pendingRaw||e.raw,e.pendingEffects=void 0,e.pendingRaw=void 0):e.pendingEffects&&(e.pendingEffects=void 0,e.pendingRaw=void 0)),l}getCurrentChain(e,r){if(!e.animating)return e.effects;if(r<e.startTime)return e.from;let i=r-e.startTime,n=Math.max(1,e.duration),a=Math.min(1,Math.max(0,i/n)),o=e.easing(a);return this.interpolateChain(e.from,e.to,o)}interpolateChain(e,r,i){return this.canInterpolate(e,r)?e.map((n,a)=>this.interpolateEffect(n,r[a],i)):r}interpolateEffect(e,r,i){let n=(a,o)=>a+(o-a)*i;if(e.type==="blur"&&r.type==="blur")return{type:"blur",amount:n(e.amount,r.amount)};if(e.type==="pixel"&&r.type==="pixel")return{type:"pixel",size:n(e.size,r.size)};if(e.type==="bloom"&&r.type==="bloom")return{type:"bloom",intensity:n(e.intensity,r.intensity),threshold:n(e.threshold,r.threshold)};if(e.type==="brightness"&&r.type==="brightness")return{type:"brightness",amount:n(e.amount,r.amount)};if(e.type==="contrast"&&r.type==="contrast")return{type:"contrast",amount:n(e.amount,r.amount)};if(e.type==="saturate"&&r.type==="saturate")return{type:"saturate",amount:n(e.amount,r.amount)};if(e.type==="grayscale"&&r.type==="grayscale")return{type:"grayscale",amount:n(e.amount,r.amount)};if(e.type==="sepia"&&r.type==="sepia")return{type:"sepia",amount:n(e.amount,r.amount)};if(e.type==="invert"&&r.type==="invert")return{type:"invert",amount:n(e.amount,r.amount)};if(e.type==="hue-rotate"&&r.type==="hue-rotate")return{type:"hue-rotate",angle:n(e.angle,r.angle)};if(e.type==="custom"&&r.type==="custom"&&e.name===r.name){let a={};return Object.entries(r.uniforms||{}).forEach(([o,l])=>{let s=e.uniforms?.[o];this.isNumeric(s)&&this.isNumeric(l)?a[o]=n(s,l):a[o]=l}),{type:"custom",name:r.name,uniforms:a}}return r}isNumeric(e){return typeof e=="number"&&Number.isFinite(e)}isZeroChain(e){return e.every(r=>{switch(r.type){case"blur":return r.amount<=0;case"pixel":return r.size<=0;case"bloom":return r.intensity<=0;case"brightness":return r.amount===1;case"contrast":return r.amount===1;case"saturate":return r.amount===1;case"grayscale":return r.amount===0;case"sepia":return r.amount===0;case"invert":return r.amount===0;case"hue-rotate":return r.angle===0;case"custom":return!1;default:return!1}})}buildWorkerCameraData(){return{mode:this.camera.getMode(),width:this.renderer.width,height:this.renderer.height,cameraZ:this.camera.getPositionZ(),fov:this.camera.getPerspectiveFov(),aspect:this.renderer.width/this.renderer.height}}collectWorkerInputs(e,r,i,n,a){if(!this.synchronizer||!e.el)return;let o=e.el,l=i||!n||n.has(o),s=r;if(e.type.endsWith("Light")){l&&this.synchronizer.syncElement(o,e,r);return}if(l){let m=o.getBoundingClientRect(),h=o.offsetWidth||m.width,u=o.offsetHeight||m.height,p=this.readNumberStyle(o,"--translate-z",0),d=this.readNumberStyle(o,"--scale",1),g=this.readNumberStyle(o,"--scale-z",1),v=this.readNumberStyle(o,"--rotate-x",0),M=this.readNumberStyle(o,"--rotate-y",0),x=this.readNumberStyle(o,"--rotate-z",0),y=this.readNumberStyle(o,"--opacity",NaN);e.type!=="group"&&R.applyVisualProps(o,e,y);let S,D,f,I;if(e.type==="model"){let O=e.getOriginalBoundingBox().getSize(this.engine.createVector3());S=O.x,D=O.y;let Z=parseFloat(o.getAttribute("string-3d-model-scale")||"1");f=Number.isFinite(Z)?Z:1,I=(o.getAttribute("string-3d-model-fit")||"contain").toLowerCase().trim()}let T=e.type==="group"?d:d*r.scale;this.lastSyncData.set(e,{scale:T}),s={scale:T},this.workerObjectMap.set(e.id,{object:e,el:o}),a.push({id:e.id,type:e.type,rectLeft:m.left,rectTop:m.top,rectWidth:h,rectHeight:u,translateZ:p,scale:d,scaleZ:g,rotateX:v,rotateY:M,rotateZ:x,parentScale:r.scale,modelSizeX:S,modelSizeY:D,modelScale:f,fitMode:I})}else{let m=this.lastSyncData.get(e);m&&(s=m)}let c=i||l;e.children.forEach(m=>{this.collectWorkerInputs(m,s,c,n,a)})}applyWorkerResults(e){this.engine&&e.forEach(r=>{let i=this.workerObjectMap.get(r.id);if(!i)return;let n=i.object;n.position=this.engine.createVector3(r.posX,r.posY,r.posZ),n.rotation=this.engine.createEuler(r.rotX,r.rotY,r.rotZ,"XYZ"),n.scale=this.engine.createVector3(r.scaleX,r.scaleY,r.scaleZ),n.type==="group"&&n.object.updateMatrixWorld(!0)})}destroy(){this.renderer?.destroy(),this.scene?.destroy(),this.isLoading.clear(),this.transformWorker?.destroy(),this.transformWorker=null,this.removeScrollListeners(),this.resizeObserver?.disconnect(),this.mutationObserver?.disconnect(),this.observedElements.clear(),this.dirtyElements.clear(),this.workerObjectMap.clear(),this.lastSyncData=new WeakMap,document.getElementById("string-3d-styles")?.remove(),this.canvasContainer?.id==="string-3d-canvas"&&this.canvasContainer.remove(),super.destroy()}};z.provider=null;var $=z;var U=class{constructor(t,e={}){this.THREE=t,this.loaders=e}createVector3(t=0,e=0,r=0){return new this.THREE.Vector3(t,e,r)}createVector2(t=0,e=0){return new this.THREE.Vector2(t,e)}createQuaternion(t=0,e=0,r=0,i=1){return new this.THREE.Quaternion(t,e,r,i)}createEuler(t=0,e=0,r=0,i="XYZ"){return new this.THREE.Euler(t,e,r,i)}createMatrix4(){return new this.THREE.Matrix4}createBox3(t,e){return new this.THREE.Box3(t,e)}createScene(){return new this.THREE.Scene}createRenderer(t){let e=new this.THREE.WebGLRenderer(t);return e.outputEncoding=this.THREE.sRGBEncoding,e}createPerspectiveCamera(t=45,e=1,r=.1,i=2e3){return new this.THREE.PerspectiveCamera(t,e,r,i)}createOrthographicCamera(t,e,r,i,n=.1,a=1e4){return new this.THREE.OrthographicCamera(t,e,r,i,n,a)}createGroup(){return new this.THREE.Group}createMesh(t,e){return new this.THREE.Mesh(t,e)}createBoxGeometry(t,e,r){return new this.THREE.BoxGeometry(t,e,r)}createSphereGeometry(t,e=32,r=32){return new this.THREE.SphereGeometry(t,e,r)}createPlaneGeometry(t,e){return new this.THREE.PlaneGeometry(t,e)}createCylinderGeometry(t,e,r,i=32){return new this.THREE.CylinderGeometry(t,e,r,i)}createMeshBasicMaterial(t){return new this.THREE.MeshBasicMaterial(t)}createMeshStandardMaterial(t){return new this.THREE.MeshStandardMaterial(t)}createShaderMaterial(t){return new this.THREE.ShaderMaterial(t)}createPointLight(t,e=1,r=0,i=2){return new this.THREE.PointLight(t,e,r,i)}createSpotLight(t,e=1,r=0,i=Math.PI/3,n=0,a=1){return new this.THREE.SpotLight(t,e,r,i,n,a)}createHemisphereLight(t,e,r=1){return new this.THREE.HemisphereLight(t,e,r)}createAmbientLight(t,e=1){return new this.THREE.AmbientLight(t,e)}createDirectionalLight(t,e=1){return new this.THREE.DirectionalLight(t,e)}createTextureLoader(){return new this.THREE.TextureLoader}createModelLoader(t){let e=this.loaders[t];if(!e)throw new Error(`[ThreeJSEngine] Model loader "${t}" not registered`);return new e}createRenderTarget(t,e,r={}){let i={minFilter:this.THREE.LinearFilter,magFilter:this.THREE.LinearFilter,format:this.THREE.RGBAFormat,depthBuffer:!0,stencilBuffer:!1};return new this.THREE.WebGLRenderTarget(t,e,{...i,...r})}degToRad(t){return this.THREE.MathUtils.degToRad(t)}radToDeg(t){return this.THREE.MathUtils.radToDeg(t)}computeBoundingBoxRecursively(t){let e=new this.THREE.Box3,r=!1;return t.traverse&&t.traverse(i=>{if(i.visible&&i.geometry){typeof i.geometry.computeBoundingBox=="function"&&i.geometry.computeBoundingBox();let n=i.geometry.boundingBox;if(n){let a=n.clone().applyMatrix4(i.matrixWorld);e.union(a),r=!0}}}),r?e:new this.THREE.Box3}},q=class{constructor(t,e={}){this.engine=new U(t,e)}getEngine(){return this.engine}getName(){return"Three.js"}};0&&(module.exports={String3D,String3DCamera,String3DCustomFilterRegistry,String3DObject,String3DRenderer,String3DScene,String3DSynchronizer,ThreeJSEngine,ThreeJSProvider});
220
+ `,document.head.appendChild(t)}registerTypedProperties(){let t=globalThis.CSS;if(!t?.registerProperty)return;[{name:"--translate-x",initialValue:"0"},{name:"--translate-y",initialValue:"0"},{name:"--translate-z",initialValue:"0"},{name:"--rotate-x",initialValue:"0"},{name:"--rotate-y",initialValue:"0"},{name:"--rotate-z",initialValue:"0"},{name:"--scale",initialValue:"1"},{name:"--scale-x",initialValue:"1"},{name:"--scale-y",initialValue:"1"},{name:"--scale-z",initialValue:"1"},{name:"--opacity",initialValue:"1"},{name:"--filter",initialValue:"none"},{name:"--material-type",initialValue:"basic"},{name:"--material-color",initialValue:"#ffffff"},{name:"--material-metalness",initialValue:"0"},{name:"--material-roughness",initialValue:"1"},{name:"--material-emissive",initialValue:"#000000"},{name:"--rim-color",initialValue:"#00c8ff"},{name:"--rim-power",initialValue:"1.5"},{name:"--rim-strength",initialValue:"1"},{name:"--uv-strength",initialValue:"0.7"},{name:"--texture-map",initialValue:"none"},{name:"--texture-normal",initialValue:"none"},{name:"--texture-roughness",initialValue:"none"},{name:"--texture-metalness",initialValue:"none"},{name:"--texture-ao",initialValue:"none"},{name:"--light-color",initialValue:"#ffffff"},{name:"--light-intensity",initialValue:"1"},{name:"--light-distance",initialValue:"1000"},{name:"--light-decay",initialValue:"0"},{name:"--light-angle",initialValue:"1.0472"},{name:"--light-penumbra",initialValue:"0"},{name:"--light-ground-color",initialValue:"#ffffff"},{name:"--light-target",initialValue:"none"},{name:"--shadow-cast",initialValue:"0"},{name:"--shadow-receive",initialValue:"0"},{name:"--shadow-bias",initialValue:"0"},{name:"--shadow-map-size",initialValue:"512"},{name:"--texture-flip-y",initialValue:"1"},{name:"--texture-color-space",initialValue:"none"},{name:"--particles-mode",initialValue:"emitter"},{name:"--particles-count",initialValue:"300"},{name:"--particles-size",initialValue:"2"},{name:"--particles-color",initialValue:"#ffffff"},{name:"--particles-opacity",initialValue:"1"},{name:"--particles-spread",initialValue:"120"},{name:"--particles-seed",initialValue:"1"},{name:"--particles-shape",initialValue:"sphere"},{name:"--particles-fit",initialValue:"0"},{name:"--particles-model",initialValue:"none"},{name:"--particles-model-loader",initialValue:"none"},{name:"--particles-model-node",initialValue:"none"},{name:"--instance-model",initialValue:"none"},{name:"--instance-model-loader",initialValue:"none"},{name:"--instance-model-node",initialValue:"none"},{name:"--emit-rate",initialValue:"30"},{name:"--emit-burst",initialValue:"0"},{name:"--particle-life",initialValue:"2.5"},{name:"--particle-speed",initialValue:"40"},{name:"--particle-direction",initialValue:"0 1 0"},{name:"--particle-gravity",initialValue:"0 -30 0"},{name:"--particle-drag",initialValue:"0.1"},{name:"--particle-size-variation",initialValue:"0.6"},{name:"--particle-color-variation",initialValue:"0.2"},{name:"--instance-shape",initialValue:"sphere"},{name:"--instance-scale",initialValue:"1"},{name:"--instance-scale-variation",initialValue:"0.5"},{name:"--instance-rotation-speed",initialValue:"0.4"},{name:"--instance-jitter",initialValue:"0.2"},{name:"--instance-flow",initialValue:"0.3"},{name:"--instance-disperse",initialValue:"0"},{name:"--instance-scatter",initialValue:"0"},{name:"--instance-scatter-x",initialValue:"0"},{name:"--instance-scatter-y",initialValue:"0"},{name:"--instance-scatter-z",initialValue:"0"},{name:"--text-depth",initialValue:"8"},{name:"--text-curve-segments",initialValue:"8"},{name:"--text-bevel-size",initialValue:"0"},{name:"--text-bevel-thickness",initialValue:"0"},{name:"--text-bevel-offset",initialValue:"0"},{name:"--text-bevel-steps",initialValue:"0"},{name:"--text-fit",initialValue:"contain"}].forEach(({name:i,initialValue:n})=>{try{t.registerProperty({name:i,syntax:i==="--filter"||i==="--light-target"||i.startsWith("--texture-")||i==="--material-type"||i==="--particles-mode"||i==="--particles-shape"||i==="--particles-model"||i==="--particles-model-loader"||i==="--particles-model-node"||i==="--instance-model"||i==="--instance-model-loader"||i==="--instance-model-node"||i==="--particle-direction"||i==="--particle-gravity"||i==="--instance-shape"||i==="--text-fit"?"*":i.includes("color")||i.includes("emissive")?"<color>":"<number>",inherits:!1,initialValue:n})}catch{}})}destroy(){this.renderer?.destroy(),this.scene?.destroy(),this.isLoading.clear(),this.dirtySyncManager.disable(),this.filterController.clear(),this.lastSyncData=new WeakMap,document.getElementById("string-3d-styles")?.remove(),this.canvasContainer?.id==="string-3d-canvas"&&this.canvasContainer.remove(),super.destroy()}};ue.provider=null;var Ne=ue;var xe=class{constructor(e){this.textureCache=new Map;this.THREE=e,this.textureLoader=new e.TextureLoader}supports(e){return!0}create(e,t){let r=this.buildUniforms(e,t),i;return e.extends==="shader"||!e.extends&&e.vertexShader?i=this.createShaderMaterial(e,r):i=this.createExtendedMaterial(e,r),this.applyMaterialProperties(i,e),{material:i,definition:e,update:o=>{this.updateUniforms(i,e,o)},dispose:()=>{i.dispose()}}}parseUniformsFromCSS(e,t,r){return $e(e,t,r)}buildUniforms(e,t){let r={};if(e.uniforms)for(let[i,n]of Object.entries(e.uniforms)){let a=t?.[i]??n.value;a=this.convertUniformValue(n.type,a),r[i]={value:a}}return r}convertUniformValue(e,t){switch(e){case"vec2":return Array.isArray(t)?new this.THREE.Vector2(t[0],t[1]):t;case"vec3":return Array.isArray(t)?new this.THREE.Vector3(t[0],t[1],t[2]):t;case"vec4":return Array.isArray(t)?new this.THREE.Vector4(t[0],t[1],t[2],t[3]):t;case"color":return Array.isArray(t)?new this.THREE.Color(t[0],t[1],t[2]):typeof t=="string"?new this.THREE.Color(t):t;case"texture":return typeof t=="string"&&t?this.loadTexture(t):t;default:return t}}loadTexture(e){if(this.textureCache.has(e))return this.textureCache.get(e);let t=this.textureLoader.load(e);return this.textureCache.set(e,t),t}createShaderMaterial(e,t){let r=new this.THREE.ShaderMaterial({uniforms:t,vertexShader:e.vertexShader||this.getDefaultVertexShader(),fragmentShader:e.fragmentShader||this.getDefaultFragmentShader(),lights:e.lights??!1,transparent:e.properties?.transparent??!1});return r.userData.customUniforms=t,r.userData.definition=e,r}createExtendedMaterial(e,t){let r=e.extends||"standard",i;switch(r){case"basic":i=this.THREE.MeshBasicMaterial;break;case"physical":i=this.THREE.MeshPhysicalMaterial;break;case"standard":default:i=this.THREE.MeshStandardMaterial;break}let n=new i({transparent:e.properties?.transparent??!1});if(e.injections&&e.injections.length>0){let a=Ze(e.injections);n.onBeforeCompile=o=>{Object.assign(o.uniforms,t),o.vertexShader=this.injectVertexShader(o.vertexShader,a,t),o.fragmentShader=this.injectFragmentShader(o.fragmentShader,a,t),n.userData.shader=o}}return n.userData.customUniforms=t,n.userData.definition=e,n}injectVertexShader(e,t,r){let i=e,n=t.get("vertex_pars");n&&(i=i.replace("#include <common>",`#include <common>
221
+ ${n}`));let a=t.get("vertex_header");if(a){let l=this.generateUniformDeclarations(r);i=i.replace("void main() {",`${l}
222
+ ${a}
223
+ void main() {`)}let o=t.get("vertex_transform");o&&(i=i.replace("#include <begin_vertex>",`#include <begin_vertex>
224
+ ${o}`));let s=t.get("vertex_output");return s&&(i=i.replace("#include <project_vertex>",`${s}
225
+ #include <project_vertex>`)),i}injectFragmentShader(e,t,r){let i=e,n=t.get("fragment_pars");n&&(i=i.replace("#include <common>",`#include <common>
226
+ ${n}`));let a=t.get("fragment_header");if(a){let h=this.generateUniformDeclarations(r);i=i.replace("void main() {",`${h}
227
+ ${a}
228
+ void main() {`)}let o=t.get("fragment_color");o&&(i=i.replace("#include <color_fragment>",`#include <color_fragment>
229
+ ${o}`));let s=t.get("fragment_normal");s&&(i=i.replace("#include <normal_fragment_maps>",`#include <normal_fragment_maps>
230
+ ${s}`));let l=t.get("fragment_emissive");l&&(i=i.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
231
+ ${l}`));let c=t.get("fragment_output");return c&&(i=i.replace("#include <dithering_fragment>",`${c}
232
+ #include <dithering_fragment>`)),i}generateUniformDeclarations(e){let t=[];for(let[r,i]of Object.entries(e)){let n=this.inferGLSLType(i.value);t.push(`uniform ${n} ${r};`)}return t.join(`
233
+ `)}inferGLSLType(e){return typeof e=="number"?"float":typeof e=="boolean"?"bool":e instanceof this.THREE.Vector2?"vec2":e instanceof this.THREE.Vector3?"vec3":e instanceof this.THREE.Vector4?"vec4":e instanceof this.THREE.Color?"vec3":e instanceof this.THREE.Matrix3?"mat3":e instanceof this.THREE.Matrix4?"mat4":e?.isTexture?"sampler2D":"float"}applyMaterialProperties(e,t){let r=t.properties;if(r){if(r.transparent!==void 0&&(e.transparent=r.transparent),r.side!==void 0)switch(r.side){case"front":e.side=this.THREE.FrontSide;break;case"back":e.side=this.THREE.BackSide;break;case"double":e.side=this.THREE.DoubleSide;break}if(r.depthWrite!==void 0&&(e.depthWrite=r.depthWrite),r.depthTest!==void 0&&(e.depthTest=r.depthTest),r.blending!==void 0)switch(r.blending){case"additive":e.blending=this.THREE.AdditiveBlending;break;case"subtractive":e.blending=this.THREE.SubtractiveBlending;break;case"multiply":e.blending=this.THREE.MultiplyBlending;break;default:e.blending=this.THREE.NormalBlending}r.wireframe!==void 0&&(e.wireframe=r.wireframe)}}updateUniforms(e,t,r){let i=e.userData?.shader,n=e.userData?.customUniforms;if(i?.uniforms)for(let[a,o]of Object.entries(r)){let s=t.uniforms?.[a];s&&i.uniforms[a]&&(i.uniforms[a].value=this.convertUniformValue(s.type,o))}else if(n)for(let[a,o]of Object.entries(r)){let s=t.uniforms?.[a];s&&n[a]&&(n[a].value=this.convertUniformValue(s.type,o))}if(e.uniforms)for(let[a,o]of Object.entries(r)){let s=t.uniforms?.[a];s&&e.uniforms[a]&&(e.uniforms[a].value=this.convertUniformValue(s.type,o))}}getDefaultVertexShader(){return`
234
+ varying vec2 vUv;
235
+ varying vec3 vNormal;
236
+ varying vec3 vPosition;
237
+
238
+ void main() {
239
+ vUv = uv;
240
+ vNormal = normalize(normalMatrix * normal);
241
+ vPosition = (modelMatrix * vec4(position, 1.0)).xyz;
242
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
243
+ }
244
+ `}getDefaultFragmentShader(){return`
245
+ varying vec2 vUv;
246
+ varying vec3 vNormal;
247
+ varying vec3 vPosition;
248
+
249
+ void main() {
250
+ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
251
+ }
252
+ `}dispose(){this.textureCache.forEach(e=>e.dispose()),this.textureCache.clear()}};var Fe=class{constructor(e,t={}){this.materialFactory=null;this.particleModelCache=new Map;this.particleModelPromiseCache=new Map;this.fontCache=new Map;this.fontPromiseCache=new Map;this.fontMetricsCache=new Map;this.THREE=e,this.loaders=t,this.materialFactory=new xe(e)}getMaterialFactory(){return this.materialFactory}createVector3(e=0,t=0,r=0){return new this.THREE.Vector3(e,t,r)}createVector2(e=0,t=0){return new this.THREE.Vector2(e,t)}createQuaternion(e=0,t=0,r=0,i=1){return new this.THREE.Quaternion(e,t,r,i)}createEuler(e=0,t=0,r=0,i="XYZ"){return new this.THREE.Euler(e,t,r,i)}createMatrix4(){return new this.THREE.Matrix4}createBox3(e,t){return new this.THREE.Box3(e,t)}createScene(){return new this.THREE.Scene}createRenderer(e){let t=new this.THREE.WebGLRenderer(e);return t.outputEncoding=this.THREE.sRGBEncoding,t}createPerspectiveCamera(e=45,t=1,r=.1,i=2e3){return new this.THREE.PerspectiveCamera(e,t,r,i)}createOrthographicCamera(e,t,r,i,n=.1,a=1e4){return new this.THREE.OrthographicCamera(e,t,r,i,n,a)}createGroup(){return new this.THREE.Group}createMesh(e,t){return new this.THREE.Mesh(e,t)}createBoxGeometry(e,t,r){return new this.THREE.BoxGeometry(e,t,r)}createSphereGeometry(e,t=32,r=32){return new this.THREE.SphereGeometry(e,t,r)}createPlaneGeometry(e,t){return new this.THREE.PlaneGeometry(e,t)}createCylinderGeometry(e,t,r,i=32){return new this.THREE.CylinderGeometry(e,t,r,i)}createMeshBasicMaterial(e){return new this.THREE.MeshBasicMaterial(e)}createMeshStandardMaterial(e){return new this.THREE.MeshStandardMaterial(e)}createShaderMaterial(e){return new this.THREE.ShaderMaterial(e)}createPointLight(e,t=1,r=0,i=2){return new this.THREE.PointLight(e,t,r,i)}createSpotLight(e,t=1,r=0,i=Math.PI/3,n=0,a=1){return new this.THREE.SpotLight(e,t,r,i,n,a)}createHemisphereLight(e,t,r=1){return new this.THREE.HemisphereLight(e,t,r)}createAmbientLight(e,t=1){return new this.THREE.AmbientLight(e,t)}createDirectionalLight(e,t=1){return new this.THREE.DirectionalLight(e,t)}createTextureLoader(){return new this.THREE.TextureLoader}createModelLoader(e){let t=this.loaders[e];if(!t)throw new Error(`[ThreeJSEngine] Model loader "${e}" not registered`);return new t}createRenderTarget(e,t,r={}){let i={minFilter:this.THREE.LinearFilter,magFilter:this.THREE.LinearFilter,format:this.THREE.RGBAFormat,depthBuffer:!0,stencilBuffer:!1};return new this.THREE.WebGLRenderTarget(e,t,{...i,...r})}loadFont(e){let t=e.trim();if(!t||t==="none")return Promise.resolve(null);if(this.fontCache.has(t))return Promise.resolve(this.fontCache.get(t));let r=this.fontPromiseCache.get(t);if(r)return r;let i=ee.isFontFile(t),n;return i?n=this.loadFontWithConverter(t):n=this.loadFontWithLoader(t),this.fontPromiseCache.set(t,n),n}async loadFontWithConverter(e){try{let t=await ee.load(e),r=this.createFontFromData(t);return this.fontCache.set(e,r),r}catch(t){return console.warn("[String3D] Font conversion error:",t),null}}loadFontWithLoader(e){let t=this.loaders.font||this.loaders.FontLoader;if(!t)return console.warn("[String3D] No FontLoader registered."),Promise.resolve(null);let r=new t;return new Promise(i=>{r.load(e,n=>{this.fontCache.set(e,n),i(n)},void 0,n=>{console.warn("[String3D] Font loading error:",n),i(null)})})}createFontFromData(e){return{data:e,generateShapes:(r,i)=>this.generateShapesFromFontData(e,r,i)}}generateShapesFromFontData(e,t,r){let i=[],n=r/e.resolution,a=t[0];if(!a)return i;let o=e.glyphs[a];if(!o||!o.o)return i;let s=this.parseOutlineToShapes(o.o,n,0);return i.push(...s),i}parseOutlineToShapes(e,t,r=0){if(!e)return[];let i=new this.THREE.ShapePath,n=e.split(" "),a=0;for(;a<n.length;)switch(n[a]){case"m":{let l=parseFloat(n[a+1])*t+r,c=-parseFloat(n[a+2])*t;i.moveTo(l,c),a+=3}break;case"l":{let l=parseFloat(n[a+1])*t+r,c=-parseFloat(n[a+2])*t;i.lineTo(l,c),a+=3}break;case"q":{let l=parseFloat(n[a+3])*t+r,c=-parseFloat(n[a+4])*t;i.quadraticCurveTo(parseFloat(n[a+1])*t+r,-parseFloat(n[a+2])*t,l,c),a+=5}break;case"b":{let l=parseFloat(n[a+5])*t+r,c=-parseFloat(n[a+6])*t;i.bezierCurveTo(parseFloat(n[a+1])*t+r,-parseFloat(n[a+2])*t,parseFloat(n[a+3])*t+r,-parseFloat(n[a+4])*t,l,c),a+=7}break;case"z":typeof i.closePath=="function"?i.closePath():i.currentPath&&typeof i.currentPath.closePath=="function"&&i.currentPath.closePath(),a+=1;break;default:a++;break}return i.toShapes(!0)}reversePath(e){let t=new this.THREE.Path;if(!e.curves||e.curves.length===0)return t;let r=e.curves[e.curves.length-1],i=r.v2||r.v3||(r.getPoint?r.getPoint(1):null);i&&t.moveTo(i.x,i.y);for(let n=e.curves.length-1;n>=0;n--){let a=e.curves[n];a.isLineCurve||a.type==="LineCurve"||a.type==="LineCurve3"?t.lineTo(a.v1.x,a.v1.y):a.isQuadraticBezierCurve||a.type==="QuadraticBezierCurve"||a.type==="QuadraticBezierCurve3"?t.quadraticCurveTo(a.v1.x,a.v1.y,a.v0.x,a.v0.y):(a.isCubicBezierCurve||a.type==="CubicBezierCurve"||a.type==="CubicBezierCurve3")&&t.bezierCurveTo(a.v2.x,a.v2.y,a.v1.x,a.v1.y,a.v0.x,a.v0.y)}return t}createTextGeometry(e,t,r){if(!e||!t)return null;let i=Math.max(.001,r.size||16),n=Math.max(0,r.height||0),a=Math.max(.001,r.lineHeight||i*1.2),o=Number.isFinite(r.letterSpacing)?r.letterSpacing:0,s=r.align||"left",l=!!r.bevelEnabled,c=Math.max(0,r.bevelThickness||0),h=Math.max(0,r.bevelSize||0),u=r.bevelOffset||0,m=Math.max(0,r.bevelSegments||0),d=Math.max(1,Math.round(r.curveSegments||8)),p=r.useCanvasText&&typeof r.fontCss=="string"&&r.fontCss.length>0;if(p&&typeof document<"u"&&document.fonts){let b=r.fontCss;if(!document.fonts.check(b,e))return document.fonts.load(b,e).catch(()=>null),null}let f=String(e).split(/\r?\n/),M=[];f.forEach((b,F)=>{});let y=p?this.measureFontMetrics(r.fontCss):null;if(r.layout?r.layout.forEach(b=>{let F=p?this.buildGlyphShapesFromCanvas(b.char,r.fontCss,r.pixelRatio):[],R=p?F:this.buildLineShapes(b.char,t,i,0).shapes,E=b.x,O=p?Number.isFinite(b.height)&&y?Math.max(0,b.height-y.descent):y?.ascent||0:0,x=p?-(b.y+O):-b.y;R.forEach(S=>{let D=this.translateShape(S,E,x);b.scale&&b.scale!==1&&(D=this.scaleShape(D,b.scale)),M.push(D)})}):f.forEach((b,F)=>{let{shapes:R,width:E}=this.buildLineShapes(b,t,i,o),O=0;s==="center"?O=-E*.5:s==="right"&&(O=-E);let x=-F*a;R.forEach(S=>{M.push(this.translateShape(S,O,x))})}),!M.length)return null;let v=new this.THREE.ExtrudeGeometry(M,{depth:n,curveSegments:d,bevelEnabled:l,bevelThickness:c,bevelSize:h,bevelOffset:u,bevelSegments:m});return v.computeBoundingBox(),v}buildLineShapes(e,t,r,i){let n=[],a=0,o=Array.from(e),s=[];return o.forEach((l,c)=>{t.generateShapes(l,r).forEach(m=>{let d=this.translateShape(m,a,0);n.push(d)});let u=this.getGlyphAdvance(t,l,r);s.length<10&&s.push({char:l,advance:u}),a+=u,i!==0&&c<o.length-1&&(a+=i)}),{shapes:n,width:a}}getGlyphAdvance(e,t,r){let i=e?.data,n=i?.glyphs||{},o=(n[t]||n[t.charCodeAt(0)]||n["?"])?.ha??i?.ha,s=i?.resolution||1e3;return typeof o=="number"?o/s*r:r*.5}translateShape(e,t,r){if(!e||!t&&!r)return e;if(typeof e.translate=="function")return e.translate(t,r),e;if(typeof e.applyMatrix4=="function"){let i=new this.THREE.Matrix4().makeTranslation(t,r,0);return e.applyMatrix4(i),e}if(typeof e.extractPoints=="function"){let{shape:i,holes:n}=e.extractPoints(12),a=s=>new this.THREE.Vector2((s.x||0)+t,(s.y||0)+r),o=new this.THREE.Shape(i.map(a));return Array.isArray(n)&&n.forEach(s=>{let l=new this.THREE.Path;l.setFromPoints(s.map(a)),o.holes.push(l)}),o}return e}scaleShape(e,t){if(t===1)return e;if(typeof e.scale=="function")return e.scale(t,t),e;if(typeof e.applyMatrix4=="function"){let r=new this.THREE.Matrix4().makeScale(t,t,1);return e.applyMatrix4(r),e}if(typeof e.extractPoints=="function"){let{shape:r,holes:i}=e.extractPoints(12),n=o=>new this.THREE.Vector2((o.x||0)*t,(o.y||0)*t),a=new this.THREE.Shape(r.map(n));return Array.isArray(i)&&i.forEach(o=>{let s=new this.THREE.Path;s.setFromPoints(o.map(n)),a.holes.push(s)}),a}return e}buildGlyphShapesFromCanvas(e,t,r){if(!e||!t)return[];if(!e.trim())return[];if(typeof document>"u")return[];let i=typeof r=="number"?Math.max(1,Math.min(3,r)):typeof window<"u"?Math.max(1,Math.min(3,window.devicePixelRatio||1)):1,n=document.createElement("canvas"),a=n.getContext("2d",{willReadFrequently:!0});if(!a)return[];a.font=t,a.textBaseline="alphabetic",a.textAlign="left";let o=a.measureText(e),s=Number.isFinite(o.actualBoundingBoxLeft)?o.actualBoundingBoxLeft*i:0,l=Number.isFinite(o.actualBoundingBoxAscent)?o.actualBoundingBoxAscent*i:0,c=Math.max(1,Math.ceil(((o.actualBoundingBoxLeft||0)+(o.actualBoundingBoxRight||0))*i)),h=Math.max(1,Math.ceil(((o.actualBoundingBoxAscent||0)+(o.actualBoundingBoxDescent||0))*i)),u=Math.ceil(2*i);n.width=c+u*2,n.height=h+u*2,a.clearRect(0,0,n.width,n.height),a.font=t,a.textBaseline="alphabetic",a.textAlign="left",a.fillStyle="#000";let m=u+s,d=u+l;a.fillText(e,m,d);let p=a.getImageData(0,0,n.width,n.height),f=this.traceContoursFromAlpha(p.data,n.width,n.height,16);if(!f.length)return[];let M=1/i;return this.contoursToShapes(f,M,u+s,u+l)}measureFontMetrics(e){if(!e)return{ascent:0,descent:0};let t=this.fontMetricsCache.get(e);if(t)return t;if(typeof document>"u"){let l={ascent:0,descent:0};return this.fontMetricsCache.set(e,l),l}let i=document.createElement("canvas").getContext("2d");if(!i){let l={ascent:0,descent:0};return this.fontMetricsCache.set(e,l),l}i.font=e,i.textBaseline="alphabetic";let n=i.measureText("Mg"),a=Number.isFinite(n.actualBoundingBoxAscent)?n.actualBoundingBoxAscent:0,o=Number.isFinite(n.actualBoundingBoxDescent)?n.actualBoundingBoxDescent:0,s={ascent:a,descent:o};return this.fontMetricsCache.set(e,s),s}traceContoursFromAlpha(e,t,r,i){let n=(u,m)=>{if(u<0||m<0||u>=t||m>=r)return!1;let d=(m*t+u)*4+3;return e[d]>=i},a=new Map,o=[],s=(u,m,d,p)=>{let f=`${u},${m}`,M=`${d},${p}`,y=a.get(f);y||(y=[],a.set(f,y)),y.push(M),o.push(`${f}|${M}`)};for(let u=0;u<r;u+=1)for(let m=0;m<t;m+=1)n(m,u)&&(n(m,u-1)||s(m+1,u,m,u),n(m+1,u)||s(m+1,u+1,m+1,u),n(m,u+1)||s(m,u+1,m+1,u+1),n(m-1,u)||s(m,u,m,u+1));let l=new Set,c=[],h=u=>{let[m,d]=u.split(",");return{x:Number(m),y:Number(d)}};for(let u of o){if(l.has(u))continue;let[m,d]=u.split("|"),p=[];l.add(u),p.push(h(m));let f=d,M=0;for(;f!==m&&M<t*r*4;){p.push(h(f));let y=a.get(f);if(!y||y.length===0)break;let v=null;for(let b of y){let F=`${f}|${b}`;if(!l.has(F)){v=b,l.add(F);break}}if(!v)break;f=v,M+=1}if(p.length>=3){let y=this.simplifyCollinear(p),v=this.simplifyRdp(y,.75);v.length>=3&&c.push(v)}}return c}simplifyCollinear(e){if(e.length<4)return e;let t=[],r=e.length;for(let i=0;i<r;i+=1){let n=e[(i-1+r)%r],a=e[i],o=e[(i+1)%r],s=a.x-n.x,l=a.y-n.y,c=o.x-a.x,h=o.y-a.y,u=s*h-l*c;Math.abs(u)>0&&t.push(a)}return t}simplifyRdp(e,t){if(e.length<3)return e;let r=e.length-1,i=0,n=0,a=e[0],o=e[r];for(let c=1;c<r;c+=1){let h=this.pointLineDistance(e[c],a,o);h>i&&(i=h,n=c)}if(i<=t)return[a,o];let s=this.simplifyRdp(e.slice(0,n+1),t),l=this.simplifyRdp(e.slice(n),t);return s.slice(0,-1).concat(l)}pointLineDistance(e,t,r){let i=r.x-t.x,n=r.y-t.y;if(i===0&&n===0){let u=e.x-t.x,m=e.y-t.y;return Math.sqrt(u*u+m*m)}let a=((e.x-t.x)*i+(e.y-t.y)*n)/(i*i+n*n),o=Math.max(0,Math.min(1,a)),s=t.x+o*i,l=t.y+o*n,c=e.x-s,h=e.y-l;return Math.sqrt(c*c+h*h)}contoursToShapes(e,t,r=0,i=0){if(!e.length)return[];let n=[],a=[],o=c=>{let h=0;for(let u=0;u<c.length;u+=1){let m=c[u],d=c[(u+1)%c.length];h+=m.x*d.y-d.x*m.y}return h*.5},s=c=>c.map(h=>({x:(h.x-r)*t,y:-(h.y-i)*t}));for(let c of e){if(c.length<3)continue;let h=s(c);if(o(h)>=0){let m=new this.THREE.Shape;m.moveTo(h[0].x,h[0].y);for(let d=1;d<h.length;d+=1)m.lineTo(h[d].x,h[d].y);typeof m.closePath=="function"&&m.closePath(),n.push({shape:m,points:h})}else{let m=new this.THREE.Path;m.moveTo(h[0].x,h[0].y);for(let d=1;d<h.length;d+=1)m.lineTo(h[d].x,h[d].y);typeof m.closePath=="function"&&m.closePath(),a.push({path:m,point:h[0]})}}let l=(c,h)=>{let u=!1;for(let m=0,d=h.length-1;m<h.length;d=m++){let p=h[m].x,f=h[m].y,M=h[d].x,y=h[d].y;f>c.y!=y>c.y&&c.x<(M-p)*(c.y-f)/(y-f+Number.EPSILON)+p&&(u=!u)}return u};for(let c of a){let h=!1;for(let u of n)if(l(c.point,u.points)){u.shape.holes.push(c.path),h=!0;break}!h&&n.length>0&&n[0].shape.holes.push(c.path)}return n.map(c=>c.shape)}resolveParticleModelGeometry(e,t,r){let i=e.trim();if(!i||i==="none")return Promise.resolve(null);let n=t&&t!=="none"?t:this.loaders.gltf?"gltf":Object.keys(this.loaders)[0];if(!n)return console.warn("[String3D] No model loader registered for particle models."),Promise.resolve(null);let a=(r||"").trim(),o=`${n}|${i}|${a}`;if(this.particleModelCache.has(o))return Promise.resolve(this.particleModelCache.get(o));let s=this.particleModelPromiseCache.get(o);if(s)return s;let l=new Promise(c=>{let h=null;try{h=this.createModelLoader(n)}catch(u){console.warn("[String3D] Failed to create model loader:",u),c(null);return}h.load(i,u=>{let m=u?.scene||u?.object||u;if(!m){c(null);return}let d=null;if(a){if(m.getObjectByName){let f=m.getObjectByName(a);f?.isMesh&&(d=f)}!d&&m.traverse&&m.traverse(f=>{d||f?.isMesh&&f?.name===a&&(d=f)})}d||(m.isMesh?d=m:m.traverse&&m.traverse(f=>{!d&&f?.isMesh&&(d=f)}));let p=d?.geometry||null;if(!p){c(null);return}this.particleModelCache.set(o,p),c(p)},void 0,u=>{console.warn("[String3D] Particle model loading error:",u),c(null)})});return this.particleModelPromiseCache.set(o,l),l}createParticleSystem(e){let t=this.THREE,r=this,i=a=>{let o=Math.max(1,a|0);return()=>(o^=o<<13,o^=o>>17,o^=o<<5,(o>>>0)%1e5/1e5)};class n extends t.Object3D{constructor(s){super();this.rng=i(e.seed);this.points=null;this.instanced=null;this.positions=new Float32Array(0);this.velocities=new Float32Array(0);this.life=new Float32Array(0);this.colors=new Float32Array(0);this.sizeFactors=new Float32Array(0);this.alive=0;this.emitRemainder=0;this.pendingBurst=0;this.basePositions=new Float32Array(0);this.baseScales=new Float32Array(0);this.baseJitter=new Float32Array(0);this.basePhase=new Float32Array(0);this.elapsed=0;this.modelGeometry=null;this.modelKey="";this.instancedUsesSharedGeometry=!1;this.distributionGeometry=null;this.distributionKey="";this.materialOverride=null;this.materialOverrideForPoints=null;this.defaultEmitterMaterial=null;this.defaultInstancedMaterial=null;this.cfg={...s},this.refreshModelGeometry(),this.rebuild()}setConfig(s){let l=this.cfg;this.cfg={...s};let c=this.cfg.mode==="emitter"&&(l.emitRate!==this.cfg.emitRate||l.emitBurst!==this.cfg.emitBurst||l.particleLife!==this.cfg.particleLife||l.particleSpeed!==this.cfg.particleSpeed||!this.isVec3Equal(l.particleDirection,this.cfg.particleDirection)||!this.isVec3Equal(l.particleGravity,this.cfg.particleGravity)||l.particleDrag!==this.cfg.particleDrag||l.particleSizeVariation!==this.cfg.particleSizeVariation||l.particleColorVariation!==this.cfg.particleColorVariation||l.color!==this.cfg.color);if(l.mode!==this.cfg.mode||l.count!==this.cfg.count||l.seed!==this.cfg.seed||l.spread!==this.cfg.spread||l.particleShape!==this.cfg.particleShape||l.particleModelUrl!==this.cfg.particleModelUrl||l.particleModelLoader!==this.cfg.particleModelLoader||l.particleModelNode!==this.cfg.particleModelNode||l.instanceShape!==this.cfg.instanceShape||l.instanceModelUrl!==this.cfg.instanceModelUrl||l.instanceModelLoader!==this.cfg.instanceModelLoader||l.instanceModelNode!==this.cfg.instanceModelNode||l.instanceScale!==this.cfg.instanceScale||l.instanceScaleVariation!==this.cfg.instanceScaleVariation){this.refreshModelGeometry(),this.refreshDistributionGeometry(),this.rebuild();return}if(c&&this.resetEmitter(),this.points){let u=this.points.material.uniforms;u&&(u.uOpacity&&(u.uOpacity.value=this.cfg.opacity),u.uSize&&(u.uSize.value=this.cfg.size),u.uSizeVar&&(u.uSizeVar.value=this.cfg.particleSizeVariation),u.uPointSize&&(u.uPointSize.value=this.cfg.size))}this.instanced&&(this.instanced.material.opacity=this.cfg.opacity,this.instanced.material.color=new t.Color(this.cfg.color)),this.pendingBurst=this.cfg.emitBurst}update(s){s<=0||(this.elapsed+=s,this.cfg.mode==="emitter"?this.updateEmitter(s):this.updateInstanced(this.elapsed))}dispose(){this.points&&(this.points.geometry.dispose(),this.points.material.dispose()),this.instanced&&(this.instancedUsesSharedGeometry||this.instanced.geometry.dispose(),this.instanced.material.dispose())}rebuild(){this.points&&(this.remove(this.points),this.points.geometry.dispose(),this.points.material.dispose(),this.points=null),this.instanced&&(this.remove(this.instanced),this.instancedUsesSharedGeometry||this.instanced.geometry.dispose(),this.instanced.material.dispose(),this.instanced=null),this.elapsed=0,this.cfg.mode==="emitter"?this.buildEmitter():(this.refreshDistributionGeometry(),this.buildInstanced()),this.applyMaterialOverrides()}buildEmitter(){let s=Math.max(1,this.cfg.count);this.positions=new Float32Array(s*3),this.velocities=new Float32Array(s*3),this.life=new Float32Array(s),this.colors=new Float32Array(s*3),this.sizeFactors=new Float32Array(s);let l=1e6;for(let u=0;u<s;u+=1){let m=u*3;this.positions[m]=l,this.positions[m+1]=l,this.positions[m+2]=l}this.alive=0,this.emitRemainder=0,this.pendingBurst=this.cfg.emitBurst;let c=new t.BufferGeometry;c.setAttribute("position",new t.BufferAttribute(this.positions,3)),c.setAttribute("color",new t.BufferAttribute(this.colors,3)),c.setAttribute("sizeFactor",new t.BufferAttribute(this.sizeFactors,1));let h=new t.ShaderMaterial({transparent:this.cfg.opacity<1,depthWrite:!1,uniforms:{uOpacity:{value:this.cfg.opacity},uSize:{value:this.cfg.size},uSizeVar:{value:this.cfg.particleSizeVariation}},vertexShader:`
253
+ attribute vec3 color;
254
+ attribute float sizeFactor;
255
+ varying vec3 vColor;
256
+ uniform float uSize;
257
+ uniform float uSizeVar;
258
+ void main() {
259
+ vColor = color;
260
+ float size = uSize * mix(1.0 - uSizeVar, 1.0, sizeFactor);
261
+ gl_PointSize = size;
262
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
263
+ }
264
+ `,fragmentShader:`
265
+ varying vec3 vColor;
266
+ uniform float uOpacity;
267
+ void main() {
268
+ float dist = length(gl_PointCoord - vec2(0.5));
269
+ if (dist > 0.5) discard;
270
+ gl_FragColor = vec4(vColor, uOpacity);
271
+ }
272
+ `});this.points=new t.Points(c,h),this.defaultEmitterMaterial=h,this.add(this.points)}buildInstanced(){let s=Math.max(1,this.cfg.count),l=this.cfg.particleShape==="model"&&this.modelGeometry,c=this.cfg.particleShape==="model"&&this.modelGeometry?this.modelGeometry:this.cfg.particleShape==="box"?new t.BoxGeometry(1,1,1):new t.SphereGeometry(.5,8,8);this.instancedUsesSharedGeometry=l;let h=new t.MeshStandardMaterial({color:new t.Color(this.cfg.color),transparent:this.cfg.opacity<1,opacity:this.cfg.opacity});this.defaultInstancedMaterial=h,this.instanced=new t.InstancedMesh(c,h,s),this.basePositions=new Float32Array(s*3),this.baseScales=new Float32Array(s),this.baseJitter=new Float32Array(s*3),this.basePhase=new Float32Array(s),this.fillBasePositions(s),this.applyInstancedTransforms(0),this.add(this.instanced)}setMaterial(s,l={}){let c=l.points??!0;(l.meshes??!0)&&(this.materialOverride=s),c&&(this.materialOverrideForPoints=s),this.applyMaterialOverrides()}updateEmitter(s){let l=this.cfg.count,c=this.normalize(this.cfg.particleDirection),h=this.cfg.particleGravity,u=Math.max(0,Math.min(1,this.cfg.particleDrag)),d=this.cfg.emitRate*s+this.emitRemainder,p=Math.floor(d);this.emitRemainder=d-p;let f=!1,M=1e6;for(let y=0;y<p;y+=1)this.spawnParticle(c);for(;this.pendingBurst>0;)this.spawnParticle(c),this.pendingBurst-=1;for(let y=0;y<l;y+=1){if(this.life[y]<=0)continue;if(this.life[y]-=s,this.life[y]<=0){this.life[y]=0;let b=y*3;this.positions[b]=M,this.positions[b+1]=M,this.positions[b+2]=M,this.colors[b]=0,this.colors[b+1]=0,this.colors[b+2]=0,f=!0;continue}let v=y*3;this.velocities[v]+=h[0]*s,this.velocities[v+1]+=h[1]*s,this.velocities[v+2]+=h[2]*s,this.velocities[v]*=1-u*s,this.velocities[v+1]*=1-u*s,this.velocities[v+2]*=1-u*s,this.positions[v]+=this.velocities[v]*s,this.positions[v+1]+=this.velocities[v+1]*s,this.positions[v+2]+=this.velocities[v+2]*s}this.points&&(this.points.geometry.attributes.position.needsUpdate=!0,f&&(this.points.geometry.attributes.color.needsUpdate=!0))}spawnParticle(s){let l=this.cfg.count,c=-1;for(let f=0;f<l;f+=1)if(this.life[f]<=0){c=f;break}if(c===-1)return;let h=this.randomInSphere(this.cfg.spread),u=this.cfg.particleSpeed*(1-this.cfg.particleSizeVariation+this.rng()*this.cfg.particleSizeVariation),m=[s[0]*u+(this.rng()-.5)*u*.2,s[1]*u+(this.rng()-.5)*u*.2,s[2]*u+(this.rng()-.5)*u*.2],d=c*3;this.positions.set(h,d),this.velocities.set(m,d),this.life[c]=this.cfg.particleLife,this.sizeFactors[c]=this.rng();let p=new t.Color(this.cfg.color);this.cfg.particleColorVariation>0&&p.offsetHSL((this.rng()-.5)*this.cfg.particleColorVariation,0,0),this.colors[d]=p.r,this.colors[d+1]=p.g,this.colors[d+2]=p.b,this.points&&(this.points.geometry.attributes.color.needsUpdate=!0,this.points.geometry.attributes.sizeFactor.needsUpdate=!0)}updateInstanced(s){this.applyInstancedTransforms(s),this.instanced&&(this.instanced.instanceMatrix.needsUpdate=!0)}applyInstancedTransforms(s){if(!this.instanced)return;let l=this.cfg.count,c=this.cfg.instanceJitter,h=this.cfg.instanceFlow,u=Math.max(0,this.cfg.instanceDisperse),m=Math.max(0,this.cfg.instanceDisperseScatter),d=this.cfg.instanceDisperseScatterX>0?this.cfg.instanceDisperseScatterX:m,p=this.cfg.instanceDisperseScatterY>0?this.cfg.instanceDisperseScatterY:m,f=this.cfg.instanceDisperseScatterZ>0?this.cfg.instanceDisperseScatterZ:m,M=this.cfg.instanceRotationSpeed,y=new t.Object3D;for(let v=0;v<l;v+=1){let b=v*3,F=this.basePositions[b],R=this.basePositions[b+1],E=this.basePositions[b+2],O=this.basePhase[v],x=Math.sin((R+s*1.4)*.7+O)*h*this.cfg.spread,S=Math.cos((F-s*1.1)*.6+O)*h*this.cfg.spread,D=Math.sin((E+s*1.2)*.8+O)*h*this.cfg.spread,z=Math.sin(s*2.1+O+this.baseJitter[b]*2.5)*c,_=Math.cos(s*1.7+O+this.baseJitter[b+1]*2.5)*c,k=Math.sin(s*1.9+O+this.baseJitter[b+2]*2.5)*c,B=1+u,A=this.baseJitter[b],w=this.baseJitter[b+1],I=this.baseJitter[b+2],T=Math.sqrt(A*A+w*w+I*I)||1,N=u*this.cfg.spread,H=A/T*d*N,P=w/T*p*N,W=I/T*f*N;y.position.set(F*B+H+x+z,R*B+P+S+_,E*B+W+D+k),y.rotation.set(this.baseJitter[b]*.5,s*M+v*.1,this.baseJitter[b+2]*.5);let j=this.baseScales[v]*this.cfg.size;y.scale.set(j,j,j),y.updateMatrix(),this.instanced.setMatrixAt(v,y.matrix)}}applyMaterialOverrides(){if(this.points){let s=this.materialOverrideForPoints||this.defaultEmitterMaterial;s&&this.points.material!==s&&(this.points.material=s,this.ensurePointMaterial(s))}if(this.instanced){let s=this.materialOverride||this.defaultInstancedMaterial;s&&this.instanced.material!==s&&(this.instanced.material=s)}}ensurePointMaterial(s){s?.isShaderMaterial&&(s.uniforms||(s.uniforms={}),s.uniforms.uPointSize||(s.uniforms.uPointSize={value:this.cfg.size}),s.uniforms.uOpacity||(s.uniforms.uOpacity={value:this.cfg.opacity}),s.vertexShader.includes("gl_PointSize")||(s.vertexShader.includes("uPointSize")||(s.vertexShader=`uniform float uPointSize;
273
+ ${s.vertexShader}`),s.vertexShader=s.vertexShader.replace(/void\\s+main\\s*\\(\\)\\s*\\{/,"void main() {\\n gl_PointSize = uPointSize;"),s.needsUpdate=!0))}refreshModelGeometry(){if(this.cfg.particleShape!=="model"){this.modelGeometry=null,this.modelKey="";return}let s=this.cfg.particleModelUrl?.trim();if(!s||s==="none"){this.modelGeometry=null,this.modelKey="";return}let l=`${this.cfg.particleModelLoader}|${s}|${this.cfg.particleModelNode}`;this.modelKey===l&&this.modelGeometry||(this.modelKey=l,r.resolveParticleModelGeometry(s,this.cfg.particleModelLoader,this.cfg.particleModelNode).then(c=>{c&&this.modelKey===l&&(this.modelGeometry=c,this.cfg.mode==="instanced"&&this.cfg.particleShape==="model"&&this.rebuild())}))}refreshDistributionGeometry(){if(this.cfg.instanceShape!=="model"){this.distributionGeometry=null,this.distributionKey="";return}let s=this.cfg.instanceModelUrl?.trim();if(!s||s==="none"){this.distributionGeometry=null,this.distributionKey="";return}let l=`${this.cfg.instanceModelLoader}|${s}|${this.cfg.instanceModelNode}`;this.distributionKey===l&&this.distributionGeometry||(this.distributionKey=l,r.resolveParticleModelGeometry(s,this.cfg.instanceModelLoader,this.cfg.instanceModelNode).then(c=>{c&&this.distributionKey===l&&(this.distributionGeometry=c,this.cfg.mode==="instanced"&&this.cfg.instanceShape==="model"&&this.rebuild())}))}fillBasePositions(s){if(this.cfg.instanceShape==="model"&&this.distributionGeometry)this.fillFromModel(s,this.distributionGeometry);else for(let c=0;c<s;c+=1){let h=this.cfg.instanceShape==="box"?this.randomInBox(this.cfg.spread):this.randomInSphere(this.cfg.spread);this.basePositions.set(h,c*3)}for(let c=0;c<s;c+=1){let h=c*3;this.baseJitter[h]=this.rng()*2-1,this.baseJitter[h+1]=this.rng()*2-1,this.baseJitter[h+2]=this.rng()*2-1,this.basePhase[c]=this.rng()*Math.PI*2;let u=this.cfg.instanceScale*(1-this.cfg.instanceScaleVariation+this.rng()*this.cfg.instanceScaleVariation);this.baseScales[c]=u}}fillFromModel(s,l){let c=l?.attributes?.position;if(!c?.array||c.itemSize<3){for(let w=0;w<s;w+=1){let I=this.randomInSphere(this.cfg.spread);this.basePositions.set(I,w*3)}return}let h=c.array,u=c.itemSize,m=Math.floor(h.length/u);if(m<=0)return;let d=l?.index?.array,p=Math.floor(d?d.length/3:m/3);if(p<=0)return;let f=1/0,M=1/0,y=1/0,v=-1/0,b=-1/0,F=-1/0;for(let w=0;w<m;w+=1){let I=w*u,T=h[I],N=h[I+1],H=h[I+2];f=Math.min(f,T),M=Math.min(M,N),y=Math.min(y,H),v=Math.max(v,T),b=Math.max(b,N),F=Math.max(F,H)}let R=Math.max(1e-6,v-f),E=Math.max(1e-6,b-M),O=Math.max(1e-6,F-y),x=Math.max(R,E,O),S=this.cfg.spread*2,D=S>0?S/x:1,z=(f+v)*.5,_=(M+b)*.5,k=(y+F)*.5,B=new Float32Array(p),A=0;for(let w=0;w<p;w+=1){let I=w*3,T=d?d[I]:I,N=d?d[I+1]:I+1,H=d?d[I+2]:I+2,P=T*u,W=N*u,j=H*u,Q=h[P],te=h[P+1],re=h[P+2],Ie=h[W],De=h[W+1],we=h[W+2],oe=h[j],Ce=h[j+1],Ee=h[j+2],he=Ie-Q,Y=De-te,G=we-re,ie=oe-Q,ce=Ce-te,ne=Ee-re,me=Y*ne-G*ce,de=G*ie-he*ne,pe=he*ce-Y*ie,He=Math.sqrt(me*me+de*de+pe*pe)*.5;A+=He,B[w]=A}if(A<=0){for(let w=0;w<s;w+=1){let I=this.randomInSphere(this.cfg.spread);this.basePositions.set(I,w*3)}return}for(let w=0;w<s;w+=1){let I=this.rng()*A,T=0,N=p-1;for(;T<N;){let ke=Math.floor((T+N)/2);I<=B[ke]?N=ke:T=ke+1}let H=T*3,P=d?d[H]:H,W=d?d[H+1]:H+1,j=d?d[H+2]:H+2,Q=P*u,te=W*u,re=j*u,Ie=h[Q],De=h[Q+1],we=h[Q+2],oe=h[te],Ce=h[te+1],Ee=h[te+2],he=h[re],Y=h[re+1],G=h[re+2],ie=this.rng(),ce=this.rng(),ne=Math.sqrt(ie),me=1-ne,de=ne*(1-ce),pe=ne*ce,He=(Ie*me+oe*de+he*pe-z)*D,rt=(De*me+Ce*de+Y*pe-_)*D,it=(we*me+Ee*de+G*pe-k)*D;this.basePositions[w*3]=He,this.basePositions[w*3+1]=rt,this.basePositions[w*3+2]=it}}resetEmitter(){if(!this.points)return;let s=1e6;for(let l=0;l<this.positions.length;l+=3)this.positions[l]=s,this.positions[l+1]=s,this.positions[l+2]=s;this.velocities.fill(0),this.life.fill(0),this.colors.fill(0),this.sizeFactors.fill(0),this.alive=0,this.emitRemainder=0,this.pendingBurst=this.cfg.emitBurst,this.points.geometry.attributes.position.needsUpdate=!0,this.points.geometry.attributes.color.needsUpdate=!0,this.points.geometry.attributes.sizeFactor.needsUpdate=!0}normalize(s){let l=Math.sqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2])||1;return[s[0]/l,s[1]/l,s[2]/l]}isVec3Equal(s,l){return s[0]===l[0]&&s[1]===l[1]&&s[2]===l[2]}randomInSphere(s){let l=this.rng(),c=this.rng(),h=l*Math.PI*2,u=Math.acos(2*c-1),m=Math.cbrt(this.rng())*s;return[m*Math.sin(u)*Math.cos(h),m*Math.sin(u)*Math.sin(h),m*Math.cos(u)]}randomInBox(s){let l=s*.5;return[(this.rng()*2-1)*l,(this.rng()*2-1)*l,(this.rng()*2-1)*l]}}return new n(e)}simplifyGeometry(e,t){let r=this.THREE?.SimplifyModifier;if(!r)return null;let i=e,n=i?.attributes?.position?.count;if(!Number.isFinite(n))return null;let a=Math.max(.05,Math.min(1,t)),o=Math.max(3,Math.floor(n*a));if(o>=n)return e;try{return new r().modify(i,o)}catch{return null}}degToRad(e){return this.THREE.MathUtils.degToRad(e)}radToDeg(e){return this.THREE.MathUtils.radToDeg(e)}computeBoundingBoxRecursively(e){let t=new this.THREE.Box3,r=!1;return e.traverse&&e.traverse(i=>{if(i.visible&&i.geometry){typeof i.geometry.computeBoundingBox=="function"&&i.geometry.computeBoundingBox();let n=i.geometry.boundingBox;if(n){let a=n.clone().applyMatrix4(i.matrixWorld);t.union(a),r=!0}}}),r?t:new this.THREE.Box3}},_e=class{constructor(e,t={}){this.engine=new Fe(e,t)}getEngine(){return this.engine}getName(){return"Three.js"}};0&&(module.exports={FontConverter,String3D,String3DCamera,String3DCustomFilterRegistry,String3DCustomMaterialRegistry,String3DFontRegistry,String3DObject,String3DRenderer,String3DScene,String3DSynchronizer,ThreeJSEngine,ThreeJSMaterialFactory,ThreeJSProvider});
277
274
  //# sourceMappingURL=index.cjs.map