string-tune-3d 0.0.5 → 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 +243 -132
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +369 -29
- package/dist/index.d.ts +369 -29
- package/dist/index.js +243 -132
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +243 -132
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/readme.md +191 -107
package/dist/index.js
CHANGED
|
@@ -1,137 +1,119 @@
|
|
|
1
|
-
"use strict";var StringTune3D=(()=>{var Q=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ne=Object.prototype.hasOwnProperty;var oe=(a,e)=>{for(var t in e)Q(a,t,{get:e[t],enumerable:!0})},ae=(a,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of se(e))!ne.call(a,i)&&i!==t&&Q(a,i,{get:()=>e[i],enumerable:!(r=ie(e,i))||r.enumerable});return a};var le=a=>ae(Q({},"__esModule",{value:!0}),a);var ge={};oe(ge,{String3D:()=>G,String3DCamera:()=>N,String3DObject:()=>P,String3DRenderer:()=>z,String3DScene:()=>_,String3DSynchronizer:()=>W,ThreeJSEngine:()=>B,ThreeJSProvider:()=>Z});var ce=class{constructor(){this.desktop={rebuild:{width:!0,height:!0,scrollHeight:!0}},this.mobile={rebuild:{width:!0,height:!0,scrollHeight:!0}}}},U=class{constructor(a){this.objectMapOnPage=new Map,this.objectsOnPage=[],this.objectMap=new Map,this.objects=[],this.htmlKey="",this._type=1,this.permissions=new ce,this.tools=a.tools,this.data=a.data,this.settings=a.settings,this.events=a.events,this.centers=a.centers,this.hover=a.hover,this.attributesToMap=[{key:"active",type:"boolean",fallback:this.settings.active},{key:"fixed",type:"boolean",fallback:this.settings.fixed},{key:"outside-container",type:"boolean",fallback:this.settings["outside-container"]},{key:"repeat",type:"boolean",fallback:this.settings.repeat},{key:"self-disable",type:"boolean",fallback:this.settings["self-disable"]},{key:"abs",type:"boolean",fallback:this.settings.abs},{key:"key",type:"string",fallback:this.settings.key},{key:"offset-top",type:"dimension",fallback:this.settings["offset-top"]},{key:"offset-bottom",type:"dimension",fallback:this.settings["offset-bottom"]},{key:"inview-top",type:"dimension",fallback:this.settings["inview-top"]},{key:"inview-bottom",type:"dimension",fallback:this.settings["inview-bottom"]},{key:"start",type:"number",fallback:(e,t,r)=>{let i=r.top;return Math.floor(i)+this.data.scroll.container.scrollTop*this.data.viewport.transformScale}},{key:"end",type:"number",fallback:(e,t,r)=>{let i=r.top,s=r.height;return i+s-this.data.scroll.transformedCurrent}},{key:"size",type:"number",fallback:(e,t,r)=>r.height},{key:"half-width",type:"number",fallback:(e,t,r)=>r.width/2},{key:"half-height",type:"number",fallback:(e,t,r)=>r.height/2},{key:"enter-el",type:"string",fallback:this.settings["enter-el"]},{key:"enter-vp",type:"string",fallback:this.settings["enter-vp"]},{key:"exit-el",type:"string",fallback:this.settings["exit-el"]},{key:"exit-vp",type:"string",fallback:this.settings["exit-vp"]}]}get type(){return this._type}initializeObject(a,e,t,r){let i=this.tools.boundingClientRect.process({element:t});for(let{key:s,type:n,fallback:o,transform:l}of this.attributesToMap){let h=typeof o=="function"?o(t,e,i):o,c=this.tools.domAttribute.process({element:t,key:s,fallback:r[s]??this.settings[s]??h}),d=this.parseAttribute(c,n,{element:t,boundingRect:i,viewportHeight:this.data.viewport.windowHeight,baseRem:this.data.viewport.baseRem});l&&(d=l(d)),e.setProperty(s,d)}}calculatePositions(a,e){let t=a.getProperty("start"),r=a.getProperty("size"),i=a.getProperty("offset-bottom"),s=a.getProperty("offset-top"),n=a.getProperty("enter-el"),o=a.getProperty("enter-vp"),l=a.getProperty("exit-el"),h=a.getProperty("exit-vp"),c=0,d=0,f=0,y=0;n==="top"&&o==="top"||n==="left"&&o==="left"?(f=-e+1,c=t-i):n==="top"&&o==="bottom"||n==="left"&&o==="right"?c=t-e-i:n==="bottom"&&o==="top"||n==="right"&&o==="left"?(f=-e-r+1,c=t+r-i):(n==="bottom"&&o==="bottom"||n==="right"&&o==="right")&&(f=-r+1,c=t-e+r-i),l==="top"&&h==="top"||l==="left"&&h==="left"?(y=-r+1,d=t+s):l==="top"&&h==="bottom"||l==="left"&&h==="right"?(y=-e-r+1,d=t-e+s):l==="bottom"&&h==="top"||l==="right"&&h==="left"?d=t+r+s:(l==="bottom"&&h==="bottom"||l==="right"&&h==="right")&&(y=-e+1,d=t-e+r+s),a.setProperty("start-bias",f),a.setProperty("end-bias",y),a.setProperty("start-position",c-this.data.scroll.topPosition),a.setProperty("end-position",d-this.data.scroll.topPosition),a.setProperty("difference-position",d-c);let v=a.getProperty("inview-top")??0,g=a.getProperty("inview-bottom")??0;a.setProperty("inview-start-position",a.getProperty("start-position")+v),a.setProperty("inview-end-position",a.getProperty("end-position")+g)}parseAttribute(a,e,t={}){if(a==null)return null;if(typeof e=="object"&&e.type==="enum")return e.values.includes(a)?a:e.values[0];switch(e){case"number":return parseFloat(a);case"boolean":return a===""||a==="true";case"json":try{return JSON.parse(a)}catch{return null}case"tuple":return a.trim().split(/\s+/);case"easing":return this.tools.easingFunction.process({easing:a});case"color":return this.tools.colorParser.process({value:a});case"dimension":return a=="0"?0:t.element!=null&&t.viewportHeight!=null&&t.baseRem!=null&&t.boundingRect!=null?this.tools.unitParser.process({value:a,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem}):0;case"breakpoint-dimension":if(t.element!=null&&t.viewportHeight!=null&&t.baseRem!=null&&t.boundingRect!=null){let r=a.trim().split("|"),i=[];for(let s of r)if(s.includes(":")){let[n,o]=s.split(":");i.push({breakpoint:parseInt(n),value:this.tools.unitParser.process({value:`${o}|`,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem})})}else i.push({breakpoint:0,value:this.tools.unitParser.process({value:s,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem})});return i}default:return a}}canConnect(a){return a.keys.includes(this.htmlKey)}connectObject(a){a.connect(this),this.onObjectConnected(a)}enterObject(a,e){this.objectMap.has(a)||(this.objectMap.set(a,e),this.objects.push(e))}exitObject(a){let e=this.objectMap.get(a);if(!e)return;this.objectMap.delete(a);let t=this.objects.indexOf(e);t!==-1&&this.objects.splice(t,1)}addObject(a,e){this.objectMapOnPage.has(a)||(this.objectMapOnPage.set(a,e),this.objectsOnPage.push(e))}removeObject(a){let e=this.objectMapOnPage.get(a);if(!e)return;this.objectMapOnPage.delete(a);let t=this.objectsOnPage.indexOf(e);t!==-1&&this.objectsOnPage.splice(t,1),this.onObjectDisconnected(e)}onObjectConnected(a){}onObjectDisconnected(a){}applyToElementAndConnects(a,e,t=e){a.getProperty("self-disable")!==!0&&e(a.htmlElement),a.mirrorObjects.forEach(r=>t(r.htmlElement,r))}destroy(){this.objects=[],this.objectMap=new Map}onInit(){}onFrame(a){}onMutate(a){}onScrollMeasure(a){}onMouseMoveMeasure(a){}onResize(){}onResizeWidth(){}onScroll(a){}onDirectionChange(){}onScrollStart(){}onScrollStop(){}onScrollDirectionChange(){}onAxisChange(){}onDeviceChange(){}onScrollConfigChange(){}onSettingsChange(){}onDOMRebuild(){}onMouseMove(a){}onWheel(a){}onDOMMutate(a,e){}};var he=class{constructor(){this.pendingVars=new Map,this.pendingProps=new Map,this.isOpen=!1}begin(){this.isOpen||(this.isOpen=!0)}setVars(a,e){if(!this.isOpen){console.warn("StyleTxn: call begin() first to set custom properties.");return}let t=this.pendingVars.get(a)??{};for(let[r,i]of Object.entries(e))t[r]!==i&&(t[r]=i);this.pendingVars.set(a,t)}setProps(a,e){if(!this.isOpen){console.warn("StyleTxn: call begin() first to set standard properties.");return}let t=this.pendingProps.get(a)??{};for(let[r,i]of Object.entries(e))t[r]!==i&&(t[r]=i);this.pendingProps.set(a,t)}run(a){let e=this.isOpen;e||this.begin();try{a(),e||this.commit()}catch(t){throw e||this.cancel(),t}}commit(){if(this.isOpen){this.isOpen=!1;for(let[a,e]of this.pendingVars){let t=a.style;for(let[r,i]of Object.entries(e))t.setProperty(r,String(i))}this.pendingVars.clear();for(let[a,e]of this.pendingProps){let t=a.style;for(let[r,i]of Object.entries(e))t[r]=String(i)}this.pendingProps.clear()}}cancel(){this.pendingVars.clear(),this.pendingProps.clear(),this.isOpen=!1}},ee=new he;var be=1/240;var de=class{constructor(){this.measureQueue=[],this.mutateQueue=[],this.scheduled=!1}measure(a){this.measureQueue.push(a),this.schedule()}mutate(a){this.mutateQueue.push(a),this.schedule()}schedule(){this.scheduled||(this.scheduled=!0,requestAnimationFrame(()=>{let a=this.measureQueue;this.measureQueue=[];for(let t=0;t<a.length;t++)try{a[t]()}catch(r){console.error("Error in frameDOM measure task:",r)}let e=this.mutateQueue;this.mutateQueue=[];for(let t=0;t<e.length;t++)try{e[t]()}catch(r){console.error("Error in frameDOM mutate task:",r)}this.scheduled=!1}))}},fe=new de;var ve=Math.PI*2,Se=180/Math.PI;var te=(a=>(a.ACTIVE="-active",a.ENTERING="-entering",a.LEAVING="-leaving",a.DISABLED="-disabled",a))(te||{}),ue={PROGRESS:"--sequence-progress",DIRECTION:"--sequence-direction"},pe=class re extends U{constructor(e){super(e),this.activeStep=new Map,this.leavingStep=new Map,this.transitions=new Map,this.elementIndex=new Map,this.triggerElements=new Map,this.globalSettings=new Map,this.initialized=!1,this.onTriggerClick=t=>{let r=this.triggerElements.get(t.currentTarget);if(!r)return;let i=this.activeStep.get(r.slider)??0,s=this.getMaxStep(r.slider),n,o;if(r.step==="next"){if(n=i+1,o=1,!this.elementIndex.has(`${r.slider}[${n}]`))if(r.loop&&s>=0)n=0;else return}else if(r.step==="prev"){if(n=i-1,o=-1,n<0)if(r.loop&&s>=0)n=s;else return;if(!this.elementIndex.has(`${r.slider}[${n}]`))return}else{if(n=r.step,i===n)return;o=n>i?1:-1}this.startTransition(r.slider,n,o)},this.htmlKey="sequence",this.defaultDuration=this.settings["sequence-duration"]??600,this.attributesToMap=[...this.attributesToMap,{key:"sequence",type:"string",fallback:""},{key:"sequence-trigger",type:"string",fallback:""},{key:"entering-easing",type:"string",fallback:""},{key:"leaving-easing",type:"string",fallback:""},{key:"entering-duration",type:"string",fallback:""},{key:"leaving-duration",type:"string",fallback:""},{key:"sequence-duration",type:"string",fallback:""},{key:"active-step",type:"string",fallback:""}]}onInit(){super.onInit(),this.events.on("sequence",this.onSequenceEvent.bind(this)),this.scanStandaloneTriggers()}scanStandaloneTriggers(){let e=document.querySelectorAll("[string-sequence-trigger]:not([string-inited])");for(let t of e){let r=t.getAttribute("string-sequence-trigger"),i=r?this.parseTriggerKey(r):null;i&&(this.triggerElements.set(t,i),t.addEventListener("click",this.onTriggerClick))}}parseGlobalSettingsFromObject(e){let t=i=>e.getProperty(i),r=t("sequence-duration");this.tryParseGlobalSetting(r,"enteringDuration"),this.tryParseGlobalSetting(r,"leavingDuration"),this.tryParseGlobalSetting(t("entering-duration"),"enteringDuration"),this.tryParseGlobalSetting(t("leaving-duration"),"leavingDuration"),this.tryParseGlobalSetting(t("entering-easing"),"enteringEasing"),this.tryParseGlobalSetting(t("leaving-easing"),"leavingEasing"),this.tryParseGlobalSetting(t("active-step"),"activeStep")}tryParseGlobalSetting(e,t){if(!e)return;let r=e.match(/^(.+)\[(.+)\]$/);if(!r)return;let[,i,s]=r,n=this.globalSettings.get(i)??{};this.globalSettings.set(i,n),n[t]=t==="enteringEasing"||t==="leavingEasing"?s:parseFloat(s),this.applyGlobalSettingsToExistingObjects(i)}applyGlobalSettingsToExistingObjects(e){let t=this.globalSettings.get(e);if(t){for(let[r,i]of this.elementIndex)if(this.parseSequenceKey(r)?.slider===e){t.enteringDuration!==void 0&&(i.enteringDuration=t.enteringDuration),t.leavingDuration!==void 0&&(i.leavingDuration=t.leavingDuration);for(let s of i.objects)this.resolveEasings(s,r)}}}initializeSliders(){let e=new Set;for(let t of this.elementIndex.keys()){let r=this.parseSequenceKey(t);r&&e.add(r.slider)}for(let t of e){if(this.activeStep.has(t))continue;let r=this.globalSettings.get(t)?.activeStep??0;this.elementIndex.has(`${t}[${r}]`)||(r=0),this.switchInstant(t,r,1)}}tryApplyPendingActiveStep(e){if(this.activeStep.has(e))return;let t=this.globalSettings.get(e)?.activeStep;t!==void 0&&this.elementIndex.has(`${e}[${t}]`)&&this.switchInstant(e,t,1)}canConnect(e){return e.keys.includes("sequence")||e.keys.includes("sequence-trigger")}onObjectConnected(e){super.onObjectConnected(e),this.parseGlobalSettingsFromObject(e);let t=e.getProperty("sequence"),r=e.getProperty("sequence-trigger");if(!t&&r){let i=this.parseTriggerKey(r);i&&typeof i.step=="number"&&(t=`${i.slider}[${i.step}]`,e.setProperty("sequence",t))}if(t){let i=this.parseSequenceKey(t);if(i){let s=this.elementIndex.get(t);if(!s){let{enteringDuration:o,leavingDuration:l}=this.resolveDurations(e,t);s={objects:[],enteringDuration:o,leavingDuration:l},this.elementIndex.set(t,s)}s.objects.push(e),this.resolveEasings(e,t);let n=this.activeStep.get(i.slider);this.setState(e,n===i.step?"-active":"-disabled",n===i.step?1:0,1),this.tryApplyPendingActiveStep(i.slider)}}if(r){let i=this.parseTriggerKey(r);i&&(this.triggerElements.set(e.htmlElement,i),e.htmlElement.addEventListener("click",this.onTriggerClick))}}parseTriggerKey(e){let t=e.match(/^(.+)\[(next|prev|\d+)(\|loop)?\]$/);if(!t)return null;let r=t[2]==="next"||t[2]==="prev"?t[2]:parseInt(t[2],10);return{slider:t[1],step:r,loop:t[3]==="|loop"}}getMaxStep(e){let t=-1;for(let r of this.elementIndex.keys()){let i=this.parseSequenceKey(r);i?.slider===e&&i.step>t&&(t=i.step)}return t}resolveDuration(e,t,r,i){let s=e.getProperty(i),n=e.getProperty("sequence-duration"),o=this.globalSettings.get(t)?.[r];if(s&&!s.includes("[")){let l=parseFloat(s);if(!isNaN(l))return l}if(n&&!n.includes("[")){let l=parseFloat(n);if(!isNaN(l))return l}return o??this.defaultDuration}resolveDurations(e,t){let r=this.parseSequenceKey(t)?.slider??"";return{enteringDuration:this.resolveDuration(e,r,"enteringDuration","entering-duration"),leavingDuration:this.resolveDuration(e,r,"leavingDuration","leaving-duration")}}resolveEasing(e,t,r,i){let s=e.getProperty(i);(!s||typeof s=="string"&&s.includes("["))&&(s=this.globalSettings.get(t)?.[r]??this.settings.easing??"ease-out"),typeof s=="string"&&e.setProperty(i,this.tools.easingFunction.process({easing:s}))}resolveEasings(e,t){let r=this.parseSequenceKey(t)?.slider;r&&(this.resolveEasing(e,r,"enteringEasing","entering-easing"),this.resolveEasing(e,r,"leavingEasing","leaving-easing"))}onObjectDisconnected(e){super.onObjectDisconnected(e);let t=e.getProperty("sequence");if(t){let r=this.elementIndex.get(t);if(r){let i=r.objects.indexOf(e);i!==-1&&r.objects.splice(i,1),r.objects.length||this.elementIndex.delete(t)}}this.triggerElements.has(e.htmlElement)&&(e.htmlElement.removeEventListener("click",this.onTriggerClick),this.triggerElements.delete(e.htmlElement))}parseSequenceKey(e){let t=e.match(/^(.+)\[(\d+)\]$/);return t?{slider:t[1],step:parseInt(t[2],10)}:null}onSequenceEvent(e){let{slider:t,step:r,transitionProgress:i,direction:s=1,duration:n,instant:o}=e;this.activeStep.get(t)===r&&i===void 0||(i!==void 0?this.handleScrub(t,r,i,s):o?this.switchInstant(t,r,s):this.startTransition(t,r,s,n))}startTransition(e,t,r,i){let s=this.activeStep.get(e),n=this.leavingStep.get(e);n!==void 0&&n!==s&&this.setStepState(e,n,"-disabled",0,r);let o=this.elementIndex.get(`${e}[${t}]`),l=s!==void 0?this.elementIndex.get(`${e}[${s}]`):null;s!==void 0&&this.leavingStep.set(e,s),this.activeStep.set(e,t),this.transitions.set(e,{fromStep:s??t,toStep:t,direction:r,startTime:this.data.time.now,enteringDuration:i??o?.enteringDuration??this.defaultDuration,leavingDuration:i??l?.leavingDuration??this.defaultDuration})}handleScrub(e,t,r,i){this.transitions.delete(e);let s=this.activeStep.get(e);if(s!==t){let n=this.leavingStep.get(e);n!==void 0&&this.setStepState(e,n,"-disabled",0,i),s!==void 0&&this.leavingStep.set(e,s),this.activeStep.set(e,t)}this.applyProgress(e,r,r,i)}switchInstant(e,t,r){this.transitions.delete(e);let i=this.activeStep.get(e),s=this.leavingStep.get(e);s!==void 0&&this.setStepState(e,s,"-disabled",0,r),i!==void 0&&i!==t&&this.setStepState(e,i,"-disabled",0,r),this.activeStep.set(e,t),this.leavingStep.delete(e),this.setStepState(e,t,"-active",1,r)}applyProgress(e,t,r,i){let s=this.activeStep.get(e),n=this.leavingStep.get(e);this.setStepState(e,s,t>=1?"-active":"-entering",t,i),n!==void 0&&n!==s&&(r>=1?(this.setStepState(e,n,"-disabled",0,i),this.leavingStep.delete(e)):this.setStepState(e,n,"-leaving",r,i))}setStepState(e,t,r,i,s){let n=this.elementIndex.get(`${e}[${t}]`);if(n)for(let o of n.objects)this.setState(o,r,i,s)}setState(e,t,r,i){let s=e.htmlElement,n=e.getProperty("_state"),o=e.getProperty("_direction"),l=e.getProperty(t==="-leaving"?"leaving-easing":"entering-easing"),h=typeof l=="function"?l(r):r;n!==t&&(s.classList.remove(...re.ALL_STATES),s.classList.add(t),e.setProperty("_state",t)),o!==i&&(e.setProperty("_direction",i),ee.run(()=>ee.setVars(s,{[ue.DIRECTION]:i.toString()})))}onFrame(e){super.onFrame(e),this.initialized||(this.initialized=!0,this.initializeSliders());for(let[t,r]of this.transitions){let i=e.time.now-r.startTime,s=Math.min(1,i/r.enteringDuration),n=Math.min(1,i/r.leavingDuration);this.applyProgress(t,s,n,r.direction),s>=1&&n>=1&&this.transitions.delete(t)}}};pe.ALL_STATES=Object.values(te);var J=class q extends U{constructor(e){super(e),this.htmlKey="form"}initializeObject(e,t,r,i){super.initializeObject(e,t,r,i);let s=t.getProperty("form-events")??[];s.forEach(c=>{c.eventElement.removeEventListener(c.eventType,c.eventCallback)}),s.length=0,t.setProperty("form-events",s),super.onObjectConnected(t);let n=t.htmlElement,o=[],l={};this.getInteractiveFields(n).forEach((c,d)=>this.registerField(c,n,o,l,s,d));let h=c=>{c.preventDefault();let d=!0,f={},y=new Set;for(let v of o){let g=v.field;if(!g.isConnected||!this.shouldValidateField(g))continue;if(this.isRadioField(g)){if(y.has(v.key))continue;y.add(v.key)}let{key:m,rules:M,needsContext:u}=v,w=this.getFieldValue(g);f[m]=w,l[m]=w;let{valid:p,errors:b}=this.tools.validation.process({rules:M,value:w,context:this.buildContext(u,m,l)});this.applyValidationState(n,g,m,p,b,"submit"),p||(d=!1)}if(d)this.events.emit(`form:submit:${t.id}`,f);else{let v=new Set,g=o.find(m=>{let M=m.field;if(!M.isConnected||!this.shouldValidateField(M))return!1;if(this.isRadioField(M)){if(v.has(m.key))return!1;v.add(m.key)}let{key:u,rules:w,needsContext:p}=m,b=this.getFieldValue(M);l[u]=b;let{valid:E}=this.tools.validation.process({rules:w,value:b,context:this.buildContext(p,u,l)});return!E});g?.field&&typeof g.field.focus=="function"&&g.field.focus(),this.events.emit(`form:invalid:${t.id}`)}};n.addEventListener("submit",h),s.push({eventElement:n,eventType:"submit",eventCallback:h}),t.setProperty("form-field-entries",o),t.setProperty("form-field-values",l)}onObjectConnected(e){}onDOMMutate(e,t){this.objects.length!==0&&(e.length>0&&this.handleMutationAdditions(e),t.length>0&&this.handleMutationRemovals(t))}applyValidationState(e,t,r,i,s,n){let o=e.querySelector(`[string-input="error[${r}]"]`),l=e.querySelector(`[string-input="group[${r}]"]`);o&&(o.innerHTML="",s.forEach(c=>{let d=document.createElement("span");d.textContent=c,o.appendChild(d)})),n==="live"?(t.classList.toggle("-invalid",!i),t.classList.remove("-error")):(t.classList.remove("-invalid"),t.classList.toggle("-error",!i)),t.classList.toggle("-valid",i),l&&(n==="live"?(l.classList.toggle("-invalid",!i),l.classList.remove("-error")):(l.classList.remove("-invalid"),l.classList.toggle("-error",!i)),l.classList.toggle("-valid",i));let h=i?"valid":n==="live"?"invalid":"error";this.events.emit(`form:field:${h}:${r}`,{key:r,field:t,errors:s,phase:n,valid:i})}getInteractiveFields(e){return Array.from(e.querySelectorAll("[string-input]")).filter(t=>!this.isServiceFieldAttribute(t.getAttribute("string-input")||"")).filter(t=>this.isFormFieldElement(t)).map(t=>t)}getFieldRules(e){let t=this.tools.domAttribute.process({element:e,key:"input"})??"";return this.tools.ruleParser.process({value:t})}registerField(e,t,r,i,s,n){if(!this.isFormFieldElement(e)||e.closest("form")!==t||r.some(g=>g.field===e))return;let o=this.registerFieldIndex(e,n??r.length),l=this.getInputKey(e,o),h=this.getFieldRules(e),c=this.supportsBeforeInputValidation(h),d=this.requiresContext(h),f=this.getInputEventType(e),y={field:e,key:l,rules:h,supportsRealtime:c,needsContext:d,inputEventType:f,inputHandler:()=>{}},v=g=>{let m=g.currentTarget||g.target;if(!m||!m.isConnected||!this.shouldValidateField(m))return;let M=this.getFieldValue(m);i[y.key]=M;let u=this.buildContext(y.needsContext,y.key,i),{valid:w,errors:p}=this.tools.validation.process({rules:y.rules,value:M,context:u});this.applyValidationState(t,m,y.key,w,p,"live")};if(y.inputHandler=v,e.addEventListener(f,v),s.push({eventElement:e,eventType:f,eventCallback:v}),c&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)){let g=m=>{let M=m;if(M.isComposing||M.inputType?.startsWith("insertComposition"))return;let u=m.currentTarget||m.target;if(!u||!(u instanceof HTMLInputElement||u instanceof HTMLTextAreaElement)||!u.isConnected)return;let w=u.selectionStart??0,p=u.selectionEnd??0,b=u.value;switch(M.inputType){case"deleteContentBackward":b=w===p&&w>0?u.value.slice(0,w-1)+u.value.slice(p):u.value.slice(0,w)+u.value.slice(p);break;case"deleteContentForward":b=w===p&&w<u.value.length?u.value.slice(0,w)+u.value.slice(w+1):u.value.slice(0,w)+u.value.slice(p);break;case"insertFromPaste":case"insertFromDrop":case"insertReplacementText":b=u.value.slice(0,w)+(M.data||"")+u.value.slice(p);break;default:typeof M.data=="string"&&(b=u.value.slice(0,w)+M.data+u.value.slice(p))}let{errors:E}=this.tools.validation.process({rules:y.rules,value:b,type:"beforeinput",context:this.buildContext(y.needsContext,y.key,i,{applied:!0,value:b})});E.length>0&&m.cancelable&&m.preventDefault()};y.beforeInputHandler=g,e.addEventListener("beforeinput",g),s.push({eventElement:e,eventType:"beforeinput",eventCallback:g})}e.classList.add("-inited"),r.push(y),i[l]=this.getFieldValue(e)}unregisterField(e,t,r,i){let s=t.findIndex(o=>o.field===e);if(s===-1)return;let n=t[s];n.inputHandler&&e.removeEventListener(n.inputEventType,n.inputHandler),n.beforeInputHandler&&e.removeEventListener("beforeinput",n.beforeInputHandler),delete r[n.key],t.splice(s,1);for(let o=i.length-1;o>=0;o--){let l=i[o];l.eventElement===e&&(l.eventCallback===n.inputHandler||n.beforeInputHandler&&l.eventCallback===n.beforeInputHandler)&&i.splice(o,1)}e.classList.remove("-inited")}collectInteractiveFieldsFromNode(e){let t=[];return e instanceof Element?(e.hasAttribute("string-input")&&t.push(e),t.push(...Array.from(e.querySelectorAll("[string-input]")))):e instanceof DocumentFragment&&t.push(...Array.from(e.querySelectorAll("[string-input]"))),t.filter(r=>!this.isServiceFieldAttribute(r.getAttribute("string-input")||"")).filter(r=>this.isFormFieldElement(r))}isRadioField(e){return e instanceof HTMLInputElement&&e.type==="radio"}handleMutationAdditions(e){e.forEach(t=>{this.collectInteractiveFieldsFromNode(t).forEach(r=>{let i=this.getFormStateByContainment(r);i&&this.registerField(r,i.form,i.entries,i.values,i.events)})})}handleMutationRemovals(e){e.forEach(t=>{this.collectInteractiveFieldsFromNode(t).forEach(r=>{let i=this.getFormStateByReference(r);i&&this.unregisterField(r,i.entries,i.values,i.events)})})}getFormStateByContainment(e){let t=this.objects.find(r=>r.htmlElement instanceof HTMLFormElement&&r.htmlElement.contains(e));return t?this.buildFormState(t):null}getFormStateByReference(e){for(let t of this.objects){let r=t.getProperty("form-field-entries");if(r&&r.some(i=>i.field===e))return this.buildFormState(t,r)}return null}buildFormState(e,t){let r=e.htmlElement;if(!(r instanceof HTMLFormElement))return null;let i=t??e.getProperty("form-field-entries"),s=e.getProperty("form-field-values"),n=e.getProperty("form-events");return!i||!s||!n?null:{object:e,form:r,entries:i,values:s,events:n}}registerFieldIndex(e,t){let r=e.getAttribute("data-string-form-index");return r!==null?Number(r):(e.setAttribute("data-string-form-index",String(t)),t)}getFieldIndex(e,t){let r=e.getAttribute("data-string-form-index");if(r!==null){let i=Number(r);return Number.isNaN(i)?t:i}return this.registerFieldIndex(e,t)}shouldValidateField(e){return!(e.disabled||e instanceof HTMLInputElement&&e.type==="hidden")}supportsBeforeInputValidation(e){return e.some(t=>q.beforeInputRuleKeys.has(t.key))}requiresContext(e){return e.some(t=>q.crossFieldRuleKeys.has(t.key))}buildContext(e,t,r,i){if(!e)return{fieldKey:t};let s=!!i?.applied,n=s?{...r,[t]:i.value}:r;return{fieldKey:t,values:n,getValue:o=>s&&o===t?i.value:n[o]}}getInputKey(e,t){return this.tools.domAttribute.process({element:e,key:"id"})||e.getAttribute("name")||e.getAttribute("id")||`input-${t}`}getFieldValue(e){if(e instanceof HTMLInputElement){if(e.type==="checkbox"){if(e.name){let t=e.form||e.closest("form"),r=t?Array.from(t.querySelectorAll(`input[type="checkbox"][name="${e.name}"]:checked`)):[e];return r.length>1?r.map(i=>i.value):r.length===1?r[0].value:""}return e.checked}if(e.type==="radio"){if(e.name){let t=(e.form||e.closest("form"))?.querySelector(`input[type="radio"][name="${e.name}"]:checked`);return t?t.value:""}return e.checked?e.value:""}return e.type==="file"&&e.files&&e.files.length>0?e.multiple?Array.from(e.files):e.files[0]:e.value}return e instanceof HTMLSelectElement?e.multiple?Array.from(e.selectedOptions).map(t=>t.value):e.value:e instanceof HTMLTextAreaElement?e.value:""}isServiceFieldAttribute(e){return q.serviceAttributePrefixes.some(t=>e.startsWith(`${t}[`))}isFormFieldElement(e){return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement}getInputEventType(e){return e instanceof HTMLSelectElement||e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio")?"change":"input"}};J.beforeInputRuleKeys=new Set(["number","integer","email","phone","letters","lettersSpaces","lettersNumbers","alpha","alpha_num","alpha_dash","digits","url","pattern"]),J.crossFieldRuleKeys=new Set(["same","different","after","before"]),J.serviceAttributePrefixes=["error","group"];var N=class{constructor(e,t="orthographic",r=50,i=.1,s=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,s):this._camera=e.createPerspectiveCamera(r,1,i,s),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,s=-(t-this._height/2);return this.engine.createVector3(i,s,r)}else{let{width:i,height:s}=this.getFrustumSizeAt(r),n=e/this._width,o=t/this._height,l=(n-.5)*i,h=-(o-.5)*s;return this.engine.createVector3(l,h,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),s=i/t;return this.scaleCache.set(r,s),s}clearScaleCache(){this.scaleCache.clear()}getMode(){return this.mode}getPerspectiveFov(){return this.perspectiveFov}getPositionZ(){return this._position.z}};var z=class{constructor(e,t){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}),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){this._renderer.render(e.getScene(),t.camera)}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)}get width(){return this._width}get height(){return this._height}get renderer(){return this._renderer}destroy(){this._renderer.dispose()}};var P=class{constructor(e,t,r,i,s={}){this._uniforms={};this._children=[];this.id=e,this.type=t,this._object=r,this.engine=i,this._material=s.material,this._geometry=s.geometry,this._texture=s.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)}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()}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 s=i?.material;Array.isArray(s)?s.forEach(n=>n?.dispose?.()):s?.dispose&&s.dispose()})}};var _=class{constructor(e,t={}){this._objects=new Map;this._rootObjects=[];this._elementMap=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)}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),t.destroy(),!0):!1}createFromElement(e){let t=e.getProperty("3d");if(!t)return;let r=e.htmlElement;if(!r)return;let i=s=>{if(s){let n=e.getProperty("parentId");n==null?(this._scene.add(s.object),this._rootObjects.push(s)):this._objects.get(n)?.addChild(s),this._objects.set(e.id,s),this._elementMap.set(e.id,r),s.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}}createGroup(e,t){let r=this.engine.createGroup(),i=new P(e.id,"group",r,this.engine);return t(i),i}createLight(e,t,r){let i=e.getProperty("3d-color")||"#ffffff",s=e.getProperty("3d-intensity")??1,n;if(t==="point"){let h=e.getProperty("3d-distance")??1e3,c=e.getProperty("3d-decay")??0;n=this.engine.createPointLight(i,s,h,c)}else if(t==="directional")n=this.engine.createDirectionalLight(i,s);else if(t==="spot"){let h=e.getProperty("3d-distance")??0,c=e.getProperty("3d-angle")??Math.PI/3,d=e.getProperty("3d-penumbra")??0,f=e.getProperty("3d-decay")??1;n=this.engine.createSpotLight(i,s,h,c,d,f)}else if(t==="hemisphere"){let h=e.getProperty("3d-ground-color")||"#ffffff";n=this.engine.createHemisphereLight(i,h,s)}else n=this.engine.createAmbientLight(i,s);if((e.getProperty("3d-cast-shadow")??!1)&&n.shadow){n.castShadow=!0;let h=e.getProperty("3d-shadow-bias")??0,c=e.getProperty("3d-shadow-map-size")??512;n.shadow.bias=h,n.shadow.mapSize.width=c,n.shadow.mapSize.height=c}let l=new P(e.id,t+"Light",n,this.engine);return r(l),l}applyShadowProps(e,t){let r=e.getProperty("3d-cast-shadow")??!1,i=e.getProperty("3d-receive-shadow")??!1;t.castShadow=r,t.receiveShadow=i}createBox(e,t){let r=this.engine.createBoxGeometry(1,1,1),i=this.createMaterialFromObject(e),s=this.engine.createMesh(r,i);this.applyShadowProps(e,s);let n=new P(e.id,"box",s,this.engine,{geometry:r,material:i});return t(n),n}createSphere(e,t){let r=e.getProperty("3d-segments-width")??32,i=e.getProperty("3d-segments-height")??32,s=this.engine.createSphereGeometry(.5,r,i),n=this.createMaterialFromObject(e),o=this.engine.createMesh(s,n);this.applyShadowProps(e,o);let l=new P(e.id,"sphere",o,this.engine,{geometry:s,material:n});return t(l),l}createPlane(e,t){let r=this.engine.createPlaneGeometry(1,1),i=this.createMaterialFromObject(e),s=this.engine.createMesh(r,i);this.applyShadowProps(e,s);let n=new P(e.id,"plane",s,this.engine,{geometry:r,material:i});return t(n),n}createCylinder(e,t){let r=e.getProperty("3d-segments")??32,i=this.engine.createCylinderGeometry(.5,.5,1,r),s=this.createMaterialFromObject(e),n=this.engine.createMesh(i,s);this.applyShadowProps(e,n);let o=new P(e.id,"cylinder",n,this.engine,{geometry:i,material:s});return t(o),o}createModel(e,t){let r=e.getProperty("3d-model");if(!r)return;let i=e.getProperty("3d-model-loader")||void 0,s=this.resolveModelLoader(i);if(!s){console.warn("[String3D] Model loader not configured");return}let n=e.htmlElement;n&&this.applyModelTextureRemap(s,n);let o=e.getProperty("3d-model-center")??!1;s.load(r,l=>{let h=l?.scene||l?.object||l;if(!h){console.warn("[String3D] Model loader returned empty result");return}let c=n&&this.shouldOverrideModelMaterial(n)?this.createMaterialFromElement(n,e):null;typeof h.traverse=="function"&&h.traverse(f=>{f.isMesh&&(c&&(f.material=c),this.applyShadowProps(e,f))}),o&&this.centerObject(h);let d=new P(e.id,"model",h,this.engine);t(d)},l=>{console.log(l.loaded/l.total*100+"% loaded")},l=>{console.error("[String3D] Model loading error:",l)})}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=t?.getProperty("3d-material")||"basic[#ffffff]",[i,s]=r.split(/\[|\]/),n=s||"#ffffff",o=t?.getProperty("3d-opacity")??1,l=t?.getProperty("3d-metalness"),h=t?.getProperty("3d-roughness"),c={color:n,transparent:o<1,opacity:o},d=e?.getAttribute("string-3d-map"),f=e?.getAttribute("string-3d-normalMap"),y=e?.getAttribute("string-3d-roughnessMap"),v=e?.getAttribute("string-3d-metalnessMap"),g=e?.getAttribute("string-3d-aoMap"),m=this.parseFlipY(t,e),M=t?.getProperty("3d-colorSpace")||e?.getAttribute("string-3d-colorSpace")||"";return i!=="standard"&&!!(d||f||y||v||g)&&(i="standard"),i==="standard"?(d&&(c.map=this.loadTexture(d,{flipY:m,colorSpace:M})),f&&(c.normalMap=this.loadTexture(f,{flipY:m})),y&&(c.roughnessMap=this.loadTexture(y,{flipY:m})),v&&(c.metalnessMap=this.loadTexture(v,{flipY:m})),g&&(c.aoMap=this.loadTexture(g,{flipY:m})),typeof l=="number"&&(c.metalness=l),typeof h=="number"&&(c.roughness=h),this.engine.createMeshStandardMaterial(c)):this.engine.createMeshBasicMaterial(c)}loadTexture(e,t={}){let i=this.engine.createTextureLoader().load(e);typeof t.flipY=="boolean"&&(i.flipY=t.flipY);let s=(t.colorSpace||"").toLowerCase().trim();return s&&"colorSpace"in i&&(i.colorSpace=s==="srgb"?"srgb":"linear"),i.needsUpdate=!0,i}parseFlipY(e,t){let r=e?.getProperty("3d-texture-flipY")??t?.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(e){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=>e.hasAttribute(r))}applyModelTextureRemap(e,t){let r=(t.getAttribute("string-3d-model-texture-base")||"").trim(),i=r?r.replace(/\/?$/,"/"):"",s=t.getAttribute("string-3d-model-textures"),n=null;if(s)try{n=JSON.parse(s)}catch(l){console.warn("[String3D] Invalid model texture mapping JSON:",l)}let o=e?.manager;if(!o||typeof o.setURLModifier!="function"){(n||i)&&console.warn("[String3D] Model loader does not support URL remap.");return}o.setURLModifier(l=>{let h=n&&l in n?n[l]:l;return!i||/^(blob:|data:|https?:|file:|\/)/i.test(h)?h:i+h.replace(/^\.?\//,"")})}destroy(){this._objects.forEach(e=>e.destroy()),this._objects.clear(),this._rootObjects=[]}};var X=class{sync(e,t,r,i){let s=e.getBoundingClientRect(),n=s.left+s.width/2,o=s.top+s.height/2,l=e.computedStyleMap?.(),h=null,c=()=>(h||(h=getComputedStyle(e)),h),d=(u,w)=>{let p=l?.get?.(u);if(p!==void 0){if(typeof p=="number")return p;if(typeof p=="string"){let S=Number.parseFloat(p);if(!Number.isNaN(S))return S}if(p&&typeof p=="object"){let S=p.value;if(typeof S=="number")return S;if(typeof S=="string"){let T=Number.parseFloat(S);if(!Number.isNaN(T))return T}}}let b=c().getPropertyValue(u),E=Number.parseFloat(b);return Number.isNaN(E)?w:E},f=d("--translate-z",0),y=r.camera.screenToWorld(n,o,f);t.position=y;let v=d("--scale",1);t.scale=r.engine.createVector3(v,v,v);let g=-r.engine.degToRad(d("--rotate-x",0)),m=r.engine.degToRad(d("--rotate-y",0)),M=-r.engine.degToRad(d("--rotate-z",0));return t.rotation=r.engine.createEuler(g,m,M,"XYZ"),t.object.updateMatrixWorld(!0),{scale:v}}};var A=class{sync(e,t,r,i){let s=e.getBoundingClientRect(),n=s.left+s.width/2,o=s.top+s.height/2,l=parseFloat(getComputedStyle(e).getPropertyValue("--translate-z")||"0"),h=r.camera.screenToWorld(n,o,l);t.position=h;let c=t.object,d=e.getAttribute("string-3d-color");d&&c.color&&typeof c.color.set=="function"&&c.color.set(d);let f=e.getAttribute("string-3d-intensity");f&&(c.intensity=parseFloat(f));let y=e.getAttribute("string-3d-distance");y&&typeof c.distance<"u"&&(c.distance=parseFloat(y));let v=e.getAttribute("string-3d-decay");v&&typeof c.decay<"u"&&(c.decay=parseFloat(v));let g=e.getAttribute("string-3d-angle");g&&typeof c.angle<"u"&&(c.angle=parseFloat(g));let m=e.getAttribute("string-3d-penumbra");m&&typeof c.penumbra<"u"&&(c.penumbra=parseFloat(m));let M=e.getAttribute("string-3d-ground-color");M&&c.groundColor&&typeof c.groundColor.set=="function"&&c.groundColor.set(M);let u=e.getAttribute("string-3d-cast-shadow")==="true";if(c.castShadow!==u&&(c.castShadow=u),u&&c.shadow){let p=e.getAttribute("string-3d-shadow-bias");p&&(c.shadow.bias=parseFloat(p));let b=e.getAttribute("string-3d-shadow-map-size");if(b){let E=parseFloat(b);c.shadow.mapSize.width!==E&&(c.shadow.mapSize.width=E,c.shadow.mapSize.height=E)}}let w=e.getAttribute("string-3d-target");if(w&&c.target){let p=document.querySelector(`[string-id="${w}"]`);if(p){let b=p.getBoundingClientRect(),E=b.left+b.width/2,S=b.top+b.height/2,T=parseFloat(getComputedStyle(p).getPropertyValue("--translate-z")||"0"),D=r.camera.screenToWorld(E,S,T);c.target.position.copy(D),c.target.updateMatrixWorld(!0)}}return null}};var C=class a{static applyVisualProps(e,t,r){let i=e.getAttribute("string-3d-cast-shadow")==="true",s=e.getAttribute("string-3d-receive-shadow")==="true",n=typeof r=="number"?r:NaN;if(t.object.traverse)t.object.traverse(o=>{o.isMesh&&(o.castShadow!==i&&(o.castShadow=i),o.receiveShadow!==s&&(o.receiveShadow=s),isNaN(n)||(Array.isArray(o.material)?o.material:[o.material]).forEach(h=>{h&&(h.opacity=n,h.transparent=n<1)}))});else if(t.object.isMesh){let o=t.object;o.castShadow!==i&&(o.castShadow=i),o.receiveShadow!==s&&(o.receiveShadow=s),isNaN(n)||(Array.isArray(o.material)?o.material:[o.material]).forEach(h=>{h&&(h.opacity=n,h.transparent=n<1)})}}sync(e,t,r,i){let s=e.computedStyleMap?.(),n=null,o=()=>(n||(n=getComputedStyle(e)),n),l=e.getBoundingClientRect(),h=e.offsetWidth||l.width,c=e.offsetHeight||l.height,d=(k,F)=>{let L=s?.get?.(k);if(L!==void 0){if(typeof L=="number")return L;if(typeof L=="string"){let x=Number.parseFloat(L);if(!Number.isNaN(x))return x}if(L&&typeof L=="object"){let x=L.value;if(typeof x=="number")return x;if(typeof x=="string"){let H=Number.parseFloat(x);if(!Number.isNaN(H))return H}}}let Y=o().getPropertyValue(k),I=Number.parseFloat(Y);return Number.isNaN(I)?F:I},f=d("--translate-z",0),y=d("--scale",1),v=l.left+l.width/2,g=l.top+l.height/2,m=r.camera.screenToWorld(v,g,f);t.position=m;let M=-r.engine.degToRad(d("--rotate-x",0)),u=r.engine.degToRad(d("--rotate-y",0)),w=-r.engine.degToRad(d("--rotate-z",0));t.rotation=r.engine.createEuler(M,u,w,"XYZ");let p=h*y,b=c*y,E=d("--scale-z",1),S=i?.scale||1,T=t.type,D,R,O;switch(T){case"box":case"sphere":{let k=Math.min(p,b);D=k*S,R=k*S,O=k*E*S;break}case"model":{let F=t.getOriginalBoundingBox().getSize(r.engine.createVector3()),L=(e.getAttribute("string-3d-model-fit")||"contain").toLowerCase().trim(),Y=parseFloat(e.getAttribute("string-3d-model-scale")||"1"),I=Number.isFinite(Y)?Y:1;if(F.x>0&&F.y>0){let x=p/F.x,H=b/F.y,K=L==="cover"?Math.max(x,H):Math.min(x,H);D=K*I*S,R=K*I*S,O=K*I*E*S}else{let x=Math.min(p,b);D=x*I*S,R=x*I*S,O=x*I*E*S}break}case"cylinder":{let k=p;D=k*S,R=b*S,O=k*E*S;break}case"plane":default:D=p*S,R=b*S,O=Math.min(p,b)*.5*E*S;break}t.scale=r.engine.createVector3(D,R,O);let $=d("--opacity",NaN);return a.applyVisualProps(e,t,$),{scale:y*S}}};var W=class{constructor(e,t,r,i){this.camera=e;this.viewportWidth=t;this.viewportHeight=r;this.engine=i;this.strategies=new Map;this.strategies.set("box",new C),this.strategies.set("sphere",new C),this.strategies.set("plane",new C),this.strategies.set("cylinder",new C),this.strategies.set("model",new C),this.strategies.set("group",new X),this.strategies.set("pointLight",new A),this.strategies.set("ambientLight",new A),this.strategies.set("directionalLight",new A),this.strategies.set("spotLight",new A),this.strategies.set("hemisphereLight",new A)}syncElement(e,t,r){let i=this.strategies.get(t.type);return i?i.sync(e,t,{camera:this.camera,viewportWidth:this.viewportWidth,viewportHeight:this.viewportHeight,engine:this.engine},r):(console.warn(`[String3D Sync] No strategy for type "${t.type}"`),null)}updateViewportSize(e,t){this.viewportWidth=e,this.viewportHeight=t}};var me=`
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";var StringTune3D=(()=>{var Ue=Object.defineProperty;var ct=Object.getOwnPropertyDescriptor;var ht=Object.getOwnPropertyNames;var ut=Object.prototype.hasOwnProperty;var dt=(m,e)=>{for(var t in e)Ue(m,t,{get:e[t],enumerable:!0})},pt=(m,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ht(e))!ut.call(m,i)&&i!==t&&Ue(m,i,{get:()=>e[i],enumerable:!(r=ct(e,i))||r.enumerable});return m};var mt=m=>pt(Ue({},"__esModule",{value:!0}),m);var Ct={};dt(Ct,{FontConverter:()=>ee,String3D:()=>_e,String3DCamera:()=>ge,String3DCustomFilterRegistry:()=>ne,String3DCustomMaterialRegistry:()=>Z,String3DFontRegistry:()=>X,String3DObject:()=>q,String3DRenderer:()=>fe,String3DScene:()=>be,String3DSynchronizer:()=>Me,ThreeJSEngine:()=>Pe,ThreeJSMaterialFactory:()=>xe,ThreeJSProvider:()=>He});var gt=class{constructor(){this.desktop={rebuild:{width:!0,height:!0,scrollHeight:!0}},this.mobile={rebuild:{width:!0,height:!0,scrollHeight:!0}}}},Le=class{constructor(m){this.objectMapOnPage=new Map,this.objectsOnPage=[],this.objectMap=new Map,this.objects=[],this.htmlKey="",this._type=1,this.permissions=new gt,this.tools=m.tools,this.data=m.data,this.settings=m.settings,this.events=m.events,this.centers=m.centers,this.hover=m.hover,this.attributesToMap=[{key:"active",type:"boolean",fallback:this.settings.active},{key:"fixed",type:"boolean",fallback:this.settings.fixed},{key:"outside-container",type:"boolean",fallback:this.settings["outside-container"]},{key:"repeat",type:"boolean",fallback:this.settings.repeat},{key:"self-disable",type:"boolean",fallback:this.settings["self-disable"]},{key:"abs",type:"boolean",fallback:this.settings.abs},{key:"key",type:"string",fallback:this.settings.key},{key:"offset-top",type:"dimension",fallback:this.settings["offset-top"]},{key:"offset-bottom",type:"dimension",fallback:this.settings["offset-bottom"]},{key:"inview-top",type:"dimension",fallback:this.settings["inview-top"]},{key:"inview-bottom",type:"dimension",fallback:this.settings["inview-bottom"]},{key:"start",type:"number",fallback:(e,t,r)=>{let i=r.top;return Math.floor(i)+this.data.scroll.container.scrollTop*this.data.viewport.transformScale}},{key:"end",type:"number",fallback:(e,t,r)=>{let i=r.top,s=r.height;return i+s-this.data.scroll.transformedCurrent}},{key:"size",type:"number",fallback:(e,t,r)=>r.height},{key:"half-width",type:"number",fallback:(e,t,r)=>r.width/2},{key:"half-height",type:"number",fallback:(e,t,r)=>r.height/2},{key:"enter-el",type:"string",fallback:this.settings["enter-el"]},{key:"enter-vp",type:"string",fallback:this.settings["enter-vp"]},{key:"exit-el",type:"string",fallback:this.settings["exit-el"]},{key:"exit-vp",type:"string",fallback:this.settings["exit-vp"]}]}get type(){return this._type}initializeObject(m,e,t,r){let i=this.tools.boundingClientRect.process({element:t});for(let{key:s,type:n,fallback:o,transform:a}of this.attributesToMap){let l=typeof o=="function"?o(t,e,i):o,c=this.tools.domAttribute.process({element:t,key:s,fallback:r[s]??this.settings[s]??l}),u=this.parseAttribute(c,n,{element:t,boundingRect:i,viewportHeight:this.data.viewport.windowHeight,baseRem:this.data.viewport.baseRem});a&&(u=a(u)),e.setProperty(s,u)}}calculatePositions(m,e){let t=m.getProperty("start"),r=m.getProperty("size"),i=m.getProperty("offset-bottom"),s=m.getProperty("offset-top"),n=m.getProperty("enter-el"),o=m.getProperty("enter-vp"),a=m.getProperty("exit-el"),l=m.getProperty("exit-vp"),c=0,u=0,h=0,d=0;n==="top"&&o==="top"||n==="left"&&o==="left"?(h=-e+1,c=t-i):n==="top"&&o==="bottom"||n==="left"&&o==="right"?c=t-e-i:n==="bottom"&&o==="top"||n==="right"&&o==="left"?(h=-e-r+1,c=t+r-i):(n==="bottom"&&o==="bottom"||n==="right"&&o==="right")&&(h=-r+1,c=t-e+r-i),a==="top"&&l==="top"||a==="left"&&l==="left"?(d=-r+1,u=t+s):a==="top"&&l==="bottom"||a==="left"&&l==="right"?(d=-e-r+1,u=t-e+s):a==="bottom"&&l==="top"||a==="right"&&l==="left"?u=t+r+s:(a==="bottom"&&l==="bottom"||a==="right"&&l==="right")&&(d=-e+1,u=t-e+r+s),m.setProperty("start-bias",h),m.setProperty("end-bias",d),m.setProperty("start-position",c-this.data.scroll.topPosition),m.setProperty("end-position",u-this.data.scroll.topPosition),m.setProperty("difference-position",u-c);let p=m.getProperty("inview-top")??0,g=m.getProperty("inview-bottom")??0;m.setProperty("inview-start-position",m.getProperty("start-position")+p),m.setProperty("inview-end-position",m.getProperty("end-position")+g)}parseAttribute(m,e,t={}){if(m==null)return null;if(typeof e=="object"&&e.type==="enum")return e.values.includes(m)?m:e.values[0];switch(e){case"number":return parseFloat(m);case"boolean":return m===""||m==="true";case"json":try{return JSON.parse(m)}catch{return null}case"tuple":return m.trim().split(/\s+/);case"easing":return this.tools.easingFunction.process({easing:m});case"color":return this.tools.colorParser.process({value:m});case"dimension":return m=="0"?0:t.element!=null&&t.viewportHeight!=null&&t.baseRem!=null&&t.boundingRect!=null?this.tools.unitParser.process({value:m,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem}):0;case"breakpoint-dimension":if(t.element!=null&&t.viewportHeight!=null&&t.baseRem!=null&&t.boundingRect!=null){let r=m.trim().split("|"),i=[];for(let s of r)if(s.includes(":")){let[n,o]=s.split(":");i.push({breakpoint:parseInt(n),value:this.tools.unitParser.process({value:`${o}|`,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem})})}else i.push({breakpoint:0,value:this.tools.unitParser.process({value:s,element:t.element,viewportHeight:t.viewportHeight,boundingRect:t.boundingRect,baseRem:t.baseRem})});return i}default:return m}}canConnect(m){return m.keys.includes(this.htmlKey)}connectObject(m){m.connect(this),this.onObjectConnected(m)}enterObject(m,e){this.objectMap.has(m)||(this.objectMap.set(m,e),this.objects.push(e))}exitObject(m){let e=this.objectMap.get(m);if(!e)return;this.objectMap.delete(m);let t=this.objects.indexOf(e);t!==-1&&this.objects.splice(t,1)}addObject(m,e){this.objectMapOnPage.has(m)||(this.objectMapOnPage.set(m,e),this.objectsOnPage.push(e))}removeObject(m){let e=this.objectMapOnPage.get(m);if(!e)return;this.objectMapOnPage.delete(m);let t=this.objectsOnPage.indexOf(e);t!==-1&&this.objectsOnPage.splice(t,1),this.onObjectDisconnected(e)}onObjectConnected(m){}onObjectDisconnected(m){}applyToElementAndConnects(m,e,t=e){m.getProperty("self-disable")!==!0&&e(m.htmlElement),m.mirrorObjects.forEach(r=>t(r.htmlElement,r))}destroy(){this.objects=[],this.objectMap=new Map}onInit(){}onFrame(m){}onMutate(m){}onScrollMeasure(m){}onMouseMoveMeasure(m){}onResize(){}onResizeWidth(){}onScroll(m){}onDirectionChange(){}onScrollStart(){}onScrollStop(){}onScrollDirectionChange(){}onAxisChange(){}onDeviceChange(){}onScrollConfigChange(){}onSettingsChange(){}onDOMRebuild(){}onMouseMove(m){}onWheel(m){}onDOMMutate(m,e){}};var ft=class{constructor(){this.pendingVars=new Map,this.pendingProps=new Map,this.isOpen=!1}begin(){this.isOpen||(this.isOpen=!0)}setVars(m,e){if(!this.isOpen){console.warn("StyleTxn: call begin() first to set custom properties.");return}let t=this.pendingVars.get(m)??{};for(let[r,i]of Object.entries(e))t[r]!==i&&(t[r]=i);this.pendingVars.set(m,t)}setProps(m,e){if(!this.isOpen){console.warn("StyleTxn: call begin() first to set standard properties.");return}let t=this.pendingProps.get(m)??{};for(let[r,i]of Object.entries(e))t[r]!==i&&(t[r]=i);this.pendingProps.set(m,t)}run(m){let e=this.isOpen;e||this.begin();try{m(),e||this.commit()}catch(t){throw e||this.cancel(),t}}commit(){if(this.isOpen){this.isOpen=!1;for(let[m,e]of this.pendingVars){let t=m.style;for(let[r,i]of Object.entries(e))t.setProperty(r,String(i))}this.pendingVars.clear();for(let[m,e]of this.pendingProps){let t=m.style;for(let[r,i]of Object.entries(e))t[r]=String(i)}this.pendingProps.clear()}}cancel(){this.pendingVars.clear(),this.pendingProps.clear(),this.isOpen=!1}},rt=new ft;var Tt=1/240;var yt=class{constructor(){this.measureQueue=[],this.mutateQueue=[],this.scheduled=!1}measure(m){this.measureQueue.push(m),this.schedule()}mutate(m){this.mutateQueue.push(m),this.schedule()}schedule(){this.scheduled||(this.scheduled=!0,requestAnimationFrame(()=>{let m=this.measureQueue;this.measureQueue=[];for(let t=0;t<m.length;t++)try{m[t]()}catch(r){console.error("Error in frameDOM measure task:",r)}let e=this.mutateQueue;this.mutateQueue=[];for(let t=0;t<e.length;t++)try{e[t]()}catch(r){console.error("Error in frameDOM mutate task:",r)}this.scheduled=!1}))}},Ft=new yt;var Lt=Math.PI*2,It=180/Math.PI;var it=(m=>(m.ACTIVE="-active",m.ENTERING="-entering",m.LEAVING="-leaving",m.DISABLED="-disabled",m))(it||{}),bt={PROGRESS:"--sequence-progress",DIRECTION:"--sequence-direction"},vt=class st extends Le{constructor(e){super(e),this.activeStep=new Map,this.leavingStep=new Map,this.transitions=new Map,this.elementIndex=new Map,this.triggerElements=new Map,this.globalSettings=new Map,this.initialized=!1,this.onTriggerClick=t=>{let r=this.triggerElements.get(t.currentTarget);if(!r)return;let i=this.activeStep.get(r.slider)??0,s=this.getMaxStep(r.slider),n,o;if(r.step==="next"){if(n=i+1,o=1,!this.elementIndex.has(`${r.slider}[${n}]`))if(r.loop&&s>=0)n=0;else return}else if(r.step==="prev"){if(n=i-1,o=-1,n<0)if(r.loop&&s>=0)n=s;else return;if(!this.elementIndex.has(`${r.slider}[${n}]`))return}else{if(n=r.step,i===n)return;o=n>i?1:-1}this.startTransition(r.slider,n,o)},this.htmlKey="sequence",this.defaultDuration=this.settings["sequence-duration"]??600,this.attributesToMap=[...this.attributesToMap,{key:"sequence",type:"string",fallback:""},{key:"sequence-trigger",type:"string",fallback:""},{key:"entering-easing",type:"string",fallback:""},{key:"leaving-easing",type:"string",fallback:""},{key:"entering-duration",type:"string",fallback:""},{key:"leaving-duration",type:"string",fallback:""},{key:"sequence-duration",type:"string",fallback:""},{key:"active-step",type:"string",fallback:""}]}onInit(){super.onInit(),this.events.on("sequence",this.onSequenceEvent.bind(this)),this.scanStandaloneTriggers()}scanStandaloneTriggers(){let e=document.querySelectorAll("[string-sequence-trigger]:not([string-inited])");for(let t of e){let r=t.getAttribute("string-sequence-trigger"),i=r?this.parseTriggerKey(r):null;i&&(this.triggerElements.set(t,i),t.addEventListener("click",this.onTriggerClick))}}parseGlobalSettingsFromObject(e){let t=i=>e.getProperty(i),r=t("sequence-duration");this.tryParseGlobalSetting(r,"enteringDuration"),this.tryParseGlobalSetting(r,"leavingDuration"),this.tryParseGlobalSetting(t("entering-duration"),"enteringDuration"),this.tryParseGlobalSetting(t("leaving-duration"),"leavingDuration"),this.tryParseGlobalSetting(t("entering-easing"),"enteringEasing"),this.tryParseGlobalSetting(t("leaving-easing"),"leavingEasing"),this.tryParseGlobalSetting(t("active-step"),"activeStep")}tryParseGlobalSetting(e,t){if(!e)return;let r=e.match(/^(.+)\[(.+)\]$/);if(!r)return;let[,i,s]=r,n=this.globalSettings.get(i)??{};this.globalSettings.set(i,n),n[t]=t==="enteringEasing"||t==="leavingEasing"?s:parseFloat(s),this.applyGlobalSettingsToExistingObjects(i)}applyGlobalSettingsToExistingObjects(e){let t=this.globalSettings.get(e);if(t){for(let[r,i]of this.elementIndex)if(this.parseSequenceKey(r)?.slider===e){t.enteringDuration!==void 0&&(i.enteringDuration=t.enteringDuration),t.leavingDuration!==void 0&&(i.leavingDuration=t.leavingDuration);for(let s of i.objects)this.resolveEasings(s,r)}}}initializeSliders(){let e=new Set;for(let t of this.elementIndex.keys()){let r=this.parseSequenceKey(t);r&&e.add(r.slider)}for(let t of e){if(this.activeStep.has(t))continue;let r=this.globalSettings.get(t)?.activeStep??0;this.elementIndex.has(`${t}[${r}]`)||(r=0),this.switchInstant(t,r,1)}}tryApplyPendingActiveStep(e){if(this.activeStep.has(e))return;let t=this.globalSettings.get(e)?.activeStep;t!==void 0&&this.elementIndex.has(`${e}[${t}]`)&&this.switchInstant(e,t,1)}canConnect(e){return e.keys.includes("sequence")||e.keys.includes("sequence-trigger")}onObjectConnected(e){super.onObjectConnected(e),this.parseGlobalSettingsFromObject(e);let t=e.getProperty("sequence"),r=e.getProperty("sequence-trigger");if(!t&&r){let i=this.parseTriggerKey(r);i&&typeof i.step=="number"&&(t=`${i.slider}[${i.step}]`,e.setProperty("sequence",t))}if(t){let i=this.parseSequenceKey(t);if(i){let s=this.elementIndex.get(t);if(!s){let{enteringDuration:o,leavingDuration:a}=this.resolveDurations(e,t);s={objects:[],enteringDuration:o,leavingDuration:a},this.elementIndex.set(t,s)}s.objects.push(e),this.resolveEasings(e,t);let n=this.activeStep.get(i.slider);this.setState(e,n===i.step?"-active":"-disabled",n===i.step?1:0,1),this.tryApplyPendingActiveStep(i.slider)}}if(r){let i=this.parseTriggerKey(r);i&&(this.triggerElements.set(e.htmlElement,i),e.htmlElement.addEventListener("click",this.onTriggerClick))}}parseTriggerKey(e){let t=e.match(/^(.+)\[(next|prev|\d+)(\|loop)?\]$/);if(!t)return null;let r=t[2]==="next"||t[2]==="prev"?t[2]:parseInt(t[2],10);return{slider:t[1],step:r,loop:t[3]==="|loop"}}getMaxStep(e){let t=-1;for(let r of this.elementIndex.keys()){let i=this.parseSequenceKey(r);i?.slider===e&&i.step>t&&(t=i.step)}return t}resolveDuration(e,t,r,i){let s=e.getProperty(i),n=e.getProperty("sequence-duration"),o=this.globalSettings.get(t)?.[r];if(s&&!s.includes("[")){let a=parseFloat(s);if(!isNaN(a))return a}if(n&&!n.includes("[")){let a=parseFloat(n);if(!isNaN(a))return a}return o??this.defaultDuration}resolveDurations(e,t){let r=this.parseSequenceKey(t)?.slider??"";return{enteringDuration:this.resolveDuration(e,r,"enteringDuration","entering-duration"),leavingDuration:this.resolveDuration(e,r,"leavingDuration","leaving-duration")}}resolveEasing(e,t,r,i){let s=e.getProperty(i);(!s||typeof s=="string"&&s.includes("["))&&(s=this.globalSettings.get(t)?.[r]??this.settings.easing??"ease-out"),typeof s=="string"&&e.setProperty(i,this.tools.easingFunction.process({easing:s}))}resolveEasings(e,t){let r=this.parseSequenceKey(t)?.slider;r&&(this.resolveEasing(e,r,"enteringEasing","entering-easing"),this.resolveEasing(e,r,"leavingEasing","leaving-easing"))}onObjectDisconnected(e){super.onObjectDisconnected(e);let t=e.getProperty("sequence");if(t){let r=this.elementIndex.get(t);if(r){let i=r.objects.indexOf(e);i!==-1&&r.objects.splice(i,1),r.objects.length||this.elementIndex.delete(t)}}this.triggerElements.has(e.htmlElement)&&(e.htmlElement.removeEventListener("click",this.onTriggerClick),this.triggerElements.delete(e.htmlElement))}parseSequenceKey(e){let t=e.match(/^(.+)\[(\d+)\]$/);return t?{slider:t[1],step:parseInt(t[2],10)}:null}onSequenceEvent(e){let{slider:t,step:r,transitionProgress:i,direction:s=1,duration:n,instant:o}=e;this.activeStep.get(t)===r&&i===void 0||(i!==void 0?this.handleScrub(t,r,i,s):o?this.switchInstant(t,r,s):this.startTransition(t,r,s,n))}startTransition(e,t,r,i){let s=this.activeStep.get(e),n=this.leavingStep.get(e);n!==void 0&&n!==s&&this.setStepState(e,n,"-disabled",0,r);let o=this.elementIndex.get(`${e}[${t}]`),a=s!==void 0?this.elementIndex.get(`${e}[${s}]`):null;s!==void 0&&this.leavingStep.set(e,s),this.activeStep.set(e,t),this.transitions.set(e,{fromStep:s??t,toStep:t,direction:r,startTime:this.data.time.now,enteringDuration:i??o?.enteringDuration??this.defaultDuration,leavingDuration:i??a?.leavingDuration??this.defaultDuration})}handleScrub(e,t,r,i){this.transitions.delete(e);let s=this.activeStep.get(e);if(s!==t){let n=this.leavingStep.get(e);n!==void 0&&this.setStepState(e,n,"-disabled",0,i),s!==void 0&&this.leavingStep.set(e,s),this.activeStep.set(e,t)}this.applyProgress(e,r,r,i)}switchInstant(e,t,r){this.transitions.delete(e);let i=this.activeStep.get(e),s=this.leavingStep.get(e);s!==void 0&&this.setStepState(e,s,"-disabled",0,r),i!==void 0&&i!==t&&this.setStepState(e,i,"-disabled",0,r),this.activeStep.set(e,t),this.leavingStep.delete(e),this.setStepState(e,t,"-active",1,r)}applyProgress(e,t,r,i){let s=this.activeStep.get(e),n=this.leavingStep.get(e);this.setStepState(e,s,t>=1?"-active":"-entering",t,i),n!==void 0&&n!==s&&(r>=1?(this.setStepState(e,n,"-disabled",0,i),this.leavingStep.delete(e)):this.setStepState(e,n,"-leaving",r,i))}setStepState(e,t,r,i,s){let n=this.elementIndex.get(`${e}[${t}]`);if(n)for(let o of n.objects)this.setState(o,r,i,s)}setState(e,t,r,i){let s=e.htmlElement,n=e.getProperty("_state"),o=e.getProperty("_direction"),a=e.getProperty(t==="-leaving"?"leaving-easing":"entering-easing"),l=typeof a=="function"?a(r):r;n!==t&&(s.classList.remove(...st.ALL_STATES),s.classList.add(t),e.setProperty("_state",t)),o!==i&&(e.setProperty("_direction",i),rt.run(()=>rt.setVars(s,{[bt.DIRECTION]:i.toString()})))}onFrame(e){super.onFrame(e),this.initialized||(this.initialized=!0,this.initializeSliders());for(let[t,r]of this.transitions){let i=e.time.now-r.startTime,s=Math.min(1,i/r.enteringDuration),n=Math.min(1,i/r.leavingDuration);this.applyProgress(t,s,n,r.direction),s>=1&&n>=1&&this.transitions.delete(t)}}};vt.ALL_STATES=Object.values(it);var qe=class Fe extends Le{constructor(e){super(e),this.htmlKey="form"}initializeObject(e,t,r,i){super.initializeObject(e,t,r,i);let s=t.getProperty("form-events")??[];s.forEach(c=>{c.eventElement.removeEventListener(c.eventType,c.eventCallback)}),s.length=0,t.setProperty("form-events",s),super.onObjectConnected(t);let n=t.htmlElement,o=[],a={};this.getInteractiveFields(n).forEach((c,u)=>this.registerField(c,n,o,a,s,u));let l=c=>{c.preventDefault();let u=!0,h={},d=new Set;for(let p of o){let g=p.field;if(!g.isConnected||!this.shouldValidateField(g))continue;if(this.isRadioField(g)){if(d.has(p.key))continue;d.add(p.key)}let{key:f,rules:S,needsContext:y}=p,b=this.getFieldValue(g);h[f]=b,a[f]=b;let{valid:v,errors:x}=this.tools.validation.process({rules:S,value:b,context:this.buildContext(y,f,a)});this.applyValidationState(n,g,f,v,x,"submit"),v||(u=!1)}if(u)this.events.emit(`form:submit:${t.id}`,h);else{let p=new Set,g=o.find(f=>{let S=f.field;if(!S.isConnected||!this.shouldValidateField(S))return!1;if(this.isRadioField(S)){if(p.has(f.key))return!1;p.add(f.key)}let{key:y,rules:b,needsContext:v}=f,x=this.getFieldValue(S);a[y]=x;let{valid:T}=this.tools.validation.process({rules:b,value:x,context:this.buildContext(v,y,a)});return!T});g?.field&&typeof g.field.focus=="function"&&g.field.focus(),this.events.emit(`form:invalid:${t.id}`)}};n.addEventListener("submit",l),s.push({eventElement:n,eventType:"submit",eventCallback:l}),t.setProperty("form-field-entries",o),t.setProperty("form-field-values",a)}onObjectConnected(e){}onDOMMutate(e,t){this.objects.length!==0&&(e.length>0&&this.handleMutationAdditions(e),t.length>0&&this.handleMutationRemovals(t))}applyValidationState(e,t,r,i,s,n){let o=e.querySelector(`[string-input="error[${r}]"]`),a=e.querySelector(`[string-input="group[${r}]"]`);o&&(o.innerHTML="",s.forEach(c=>{let u=document.createElement("span");u.textContent=c,o.appendChild(u)})),n==="live"?(t.classList.toggle("-invalid",!i),t.classList.remove("-error")):(t.classList.remove("-invalid"),t.classList.toggle("-error",!i)),t.classList.toggle("-valid",i),a&&(n==="live"?(a.classList.toggle("-invalid",!i),a.classList.remove("-error")):(a.classList.remove("-invalid"),a.classList.toggle("-error",!i)),a.classList.toggle("-valid",i));let l=i?"valid":n==="live"?"invalid":"error";this.events.emit(`form:field:${l}:${r}`,{key:r,field:t,errors:s,phase:n,valid:i})}getInteractiveFields(e){return Array.from(e.querySelectorAll("[string-input]")).filter(t=>!this.isServiceFieldAttribute(t.getAttribute("string-input")||"")).filter(t=>this.isFormFieldElement(t)).map(t=>t)}getFieldRules(e){let t=this.tools.domAttribute.process({element:e,key:"input"})??"";return this.tools.ruleParser.process({value:t})}registerField(e,t,r,i,s,n){if(!this.isFormFieldElement(e)||e.closest("form")!==t||r.some(g=>g.field===e))return;let o=this.registerFieldIndex(e,n??r.length),a=this.getInputKey(e,o),l=this.getFieldRules(e),c=this.supportsBeforeInputValidation(l),u=this.requiresContext(l),h=this.getInputEventType(e),d={field:e,key:a,rules:l,supportsRealtime:c,needsContext:u,inputEventType:h,inputHandler:()=>{}},p=g=>{let f=g.currentTarget||g.target;if(!f||!f.isConnected||!this.shouldValidateField(f))return;let S=this.getFieldValue(f);i[d.key]=S;let y=this.buildContext(d.needsContext,d.key,i),{valid:b,errors:v}=this.tools.validation.process({rules:d.rules,value:S,context:y});this.applyValidationState(t,f,d.key,b,v,"live")};if(d.inputHandler=p,e.addEventListener(h,p),s.push({eventElement:e,eventType:h,eventCallback:p}),c&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)){let g=f=>{let S=f;if(S.isComposing||S.inputType?.startsWith("insertComposition"))return;let y=f.currentTarget||f.target;if(!y||!(y instanceof HTMLInputElement||y instanceof HTMLTextAreaElement)||!y.isConnected)return;let b=y.selectionStart??0,v=y.selectionEnd??0,x=y.value;switch(S.inputType){case"deleteContentBackward":x=b===v&&b>0?y.value.slice(0,b-1)+y.value.slice(v):y.value.slice(0,b)+y.value.slice(v);break;case"deleteContentForward":x=b===v&&b<y.value.length?y.value.slice(0,b)+y.value.slice(b+1):y.value.slice(0,b)+y.value.slice(v);break;case"insertFromPaste":case"insertFromDrop":case"insertReplacementText":x=y.value.slice(0,b)+(S.data||"")+y.value.slice(v);break;default:typeof S.data=="string"&&(x=y.value.slice(0,b)+S.data+y.value.slice(v))}let{errors:T}=this.tools.validation.process({rules:d.rules,value:x,type:"beforeinput",context:this.buildContext(d.needsContext,d.key,i,{applied:!0,value:x})});T.length>0&&f.cancelable&&f.preventDefault()};d.beforeInputHandler=g,e.addEventListener("beforeinput",g),s.push({eventElement:e,eventType:"beforeinput",eventCallback:g})}e.classList.add("-inited"),r.push(d),i[a]=this.getFieldValue(e)}unregisterField(e,t,r,i){let s=t.findIndex(o=>o.field===e);if(s===-1)return;let n=t[s];n.inputHandler&&e.removeEventListener(n.inputEventType,n.inputHandler),n.beforeInputHandler&&e.removeEventListener("beforeinput",n.beforeInputHandler),delete r[n.key],t.splice(s,1);for(let o=i.length-1;o>=0;o--){let a=i[o];a.eventElement===e&&(a.eventCallback===n.inputHandler||n.beforeInputHandler&&a.eventCallback===n.beforeInputHandler)&&i.splice(o,1)}e.classList.remove("-inited")}collectInteractiveFieldsFromNode(e){let t=[];return e instanceof Element?(e.hasAttribute("string-input")&&t.push(e),t.push(...Array.from(e.querySelectorAll("[string-input]")))):e instanceof DocumentFragment&&t.push(...Array.from(e.querySelectorAll("[string-input]"))),t.filter(r=>!this.isServiceFieldAttribute(r.getAttribute("string-input")||"")).filter(r=>this.isFormFieldElement(r))}isRadioField(e){return e instanceof HTMLInputElement&&e.type==="radio"}handleMutationAdditions(e){e.forEach(t=>{this.collectInteractiveFieldsFromNode(t).forEach(r=>{let i=this.getFormStateByContainment(r);i&&this.registerField(r,i.form,i.entries,i.values,i.events)})})}handleMutationRemovals(e){e.forEach(t=>{this.collectInteractiveFieldsFromNode(t).forEach(r=>{let i=this.getFormStateByReference(r);i&&this.unregisterField(r,i.entries,i.values,i.events)})})}getFormStateByContainment(e){let t=this.objects.find(r=>r.htmlElement instanceof HTMLFormElement&&r.htmlElement.contains(e));return t?this.buildFormState(t):null}getFormStateByReference(e){for(let t of this.objects){let r=t.getProperty("form-field-entries");if(r&&r.some(i=>i.field===e))return this.buildFormState(t,r)}return null}buildFormState(e,t){let r=e.htmlElement;if(!(r instanceof HTMLFormElement))return null;let i=t??e.getProperty("form-field-entries"),s=e.getProperty("form-field-values"),n=e.getProperty("form-events");return!i||!s||!n?null:{object:e,form:r,entries:i,values:s,events:n}}registerFieldIndex(e,t){let r=e.getAttribute("data-string-form-index");return r!==null?Number(r):(e.setAttribute("data-string-form-index",String(t)),t)}getFieldIndex(e,t){let r=e.getAttribute("data-string-form-index");if(r!==null){let i=Number(r);return Number.isNaN(i)?t:i}return this.registerFieldIndex(e,t)}shouldValidateField(e){return!(e.disabled||e instanceof HTMLInputElement&&e.type==="hidden")}supportsBeforeInputValidation(e){return e.some(t=>Fe.beforeInputRuleKeys.has(t.key))}requiresContext(e){return e.some(t=>Fe.crossFieldRuleKeys.has(t.key))}buildContext(e,t,r,i){if(!e)return{fieldKey:t};let s=!!i?.applied,n=s?{...r,[t]:i.value}:r;return{fieldKey:t,values:n,getValue:o=>s&&o===t?i.value:n[o]}}getInputKey(e,t){return this.tools.domAttribute.process({element:e,key:"id"})||e.getAttribute("name")||e.getAttribute("id")||`input-${t}`}getFieldValue(e){if(e instanceof HTMLInputElement){if(e.type==="checkbox"){if(e.name){let t=e.form||e.closest("form"),r=t?Array.from(t.querySelectorAll(`input[type="checkbox"][name="${e.name}"]:checked`)):[e];return r.length>1?r.map(i=>i.value):r.length===1?r[0].value:""}return e.checked}if(e.type==="radio"){if(e.name){let t=(e.form||e.closest("form"))?.querySelector(`input[type="radio"][name="${e.name}"]:checked`);return t?t.value:""}return e.checked?e.value:""}return e.type==="file"&&e.files&&e.files.length>0?e.multiple?Array.from(e.files):e.files[0]:e.value}return e instanceof HTMLSelectElement?e.multiple?Array.from(e.selectedOptions).map(t=>t.value):e.value:e instanceof HTMLTextAreaElement?e.value:""}isServiceFieldAttribute(e){return Fe.serviceAttributePrefixes.some(t=>e.startsWith(`${t}[`))}isFormFieldElement(e){return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement}getInputEventType(e){return e instanceof HTMLSelectElement||e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio")?"change":"input"}};qe.beforeInputRuleKeys=new Set(["number","integer","email","phone","letters","lettersSpaces","lettersNumbers","alpha","alpha_num","alpha_dash","digits","url","pattern"]),qe.crossFieldRuleKeys=new Set(["same","different","after","before"]),qe.serviceAttributePrefixes=["error","group"];var ge=class{constructor(e,t="perspective",r=50,i=.1,s=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,s):this._camera=e.createPerspectiveCamera(r,1,i,s),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,s=-(t-this._height/2);return this.engine.createVector3(i,s,r)}else{let{width:i,height:s}=this.getFrustumSizeAt(r),n=e/this._width,o=t/this._height,a=(n-.5)*i,l=-(o-.5)*s;return this.engine.createVector3(a,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),s=i/t;return this.scaleCache.set(r,s),s}clearScaleCache(){this.scaleCache.clear()}getMode(){return this.mode}getPerspectiveFov(){return this.perspectiveFov}getPositionZ(){return this._position.z}};var ne=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())}};ne.filters=new Map;var Ge=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=[]}},Ie=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 s=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(s,this.copyMaterial),this.scene.add(this.quad);let n=(o,a)=>{if(!this.engine.createRenderTarget)throw new Error("[String3DFilterPipeline] Render target support missing.");return this.engine.createRenderTarget(o,a)};this.pool=new Ge(n)}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,s=[],n=a=>{let l=s.indexOf(a);l>=0&&(s.splice(l,1),this.pool.release(a))},o=()=>{let{width:a,height:l}=this.getScaledSize(),c=this.pool.acquire(a,l);return s.push(c),c};return t.forEach(a=>{if(a.type==="blur"){let l=a.amount*r;if(l<=1e-4)return;let c=o();this.renderPass(this.blurMaterial,i,c,{uDirection:[1,0],uRadius:l});let u=o();this.renderPass(this.blurMaterial,c,u,{uDirection:[0,1],uRadius:l}),n(c),i!==e&&n(i),i=u}else if(a.type==="pixel"){if(a.size<=.5)return;let l=o();this.renderPass(this.pixelMaterial,i,l,{uPixelSize:a.size}),i!==e&&n(i),i=l}else if(a.type==="bloom"){let l=a.intensity;if(l<=1e-4||a.threshold>=.99)return;let c=Math.max(1,4*r),u=o();this.renderPass(this.bloomExtractMaterial,i,u,{uThreshold:a.threshold});let h=o();this.renderPass(this.blurMaterial,u,h,{uDirection:[1,0],uRadius:c});let d=o();this.renderPass(this.blurMaterial,h,d,{uDirection:[0,1],uRadius:c}),n(u),n(h);let p=o();this.renderAddPass(i,d,p,l),n(d),i!==e&&n(i),i=p}else if(a.type==="brightness"||a.type==="contrast"||a.type==="saturate"||a.type==="grayscale"||a.type==="sepia"||a.type==="invert"||a.type==="hue-rotate"){let l=o(),c=this.getColorMode(a.type),u=a.type==="hue-rotate"?a.angle:a.amount;this.renderPass(this.colorMaterial,i,l,{uMode:c,uAmount:u}),i!==e&&n(i),i=l}else if(a.type==="custom"){let l=o(),c=this.getCustomMaterial(a.name);c?(this.renderPass(c,i,l,a.uniforms),i!==e&&n(i),i=l):n(l)}}),s.forEach(a=>{a!==i&&this.pool.release(a)}),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={},s=!0){let n=this.renderer;n.setRenderTarget&&n.setRenderTarget(r),this.setMaterial(this.quad,e),this.setUniform(e,"tDiffuse",t.texture);let{width:o,height:a}=this.getScaledSize();this.setUniform(e,"uResolution",[o,a]),this.setUniform(e,"uTexel",[1/o,1/a]),Object.entries(i).forEach(([l,c])=>this.setUniform(e,l,c)),s&&n.clear&&n.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera)}renderAddPass(e,t,r,i){let s=this.renderer;s.setRenderTarget&&s.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:n,height:o}=this.getScaledSize();this.setUniform(this.bloomAddMaterial,"uResolution",[n,o]),s.clear&&s.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
|
+
varying vec2 vUv;
|
|
3
|
+
uniform sampler2D tDiffuse;
|
|
4
|
+
void main() {
|
|
5
|
+
gl_FragColor = texture2D(tDiffuse, vUv);
|
|
6
|
+
}
|
|
7
|
+
`,transparent:!0,depthTest:!1,depthWrite:!1})}createPixelMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null},uResolution:{value:[this.width,this.height]},uPixelSize:{value:1}},vertexShader:this.getVertexShader(),fragmentShader:`
|
|
8
|
+
varying vec2 vUv;
|
|
9
|
+
uniform sampler2D tDiffuse;
|
|
10
|
+
uniform vec2 uResolution;
|
|
11
|
+
uniform float uPixelSize;
|
|
12
|
+
void main() {
|
|
13
|
+
vec2 pixel = uPixelSize / uResolution;
|
|
14
|
+
vec2 coord = floor(vUv / pixel) * pixel + pixel * 0.5;
|
|
15
|
+
gl_FragColor = texture2D(tDiffuse, coord);
|
|
16
|
+
}
|
|
17
|
+
`,transparent:!0,depthTest:!1,depthWrite:!1})}createBlurMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null},uTexel:{value:[1/this.width,1/this.height]},uDirection:{value:[1,0]},uRadius:{value:2}},vertexShader:this.getVertexShader(),fragmentShader:`
|
|
18
|
+
varying vec2 vUv;
|
|
19
|
+
uniform sampler2D tDiffuse;
|
|
20
|
+
uniform vec2 uTexel;
|
|
21
|
+
uniform vec2 uDirection;
|
|
22
|
+
uniform float uRadius;
|
|
23
|
+
void main() {
|
|
24
|
+
vec2 off1 = uDirection * uTexel * uRadius;
|
|
25
|
+
vec2 off2 = uDirection * uTexel * uRadius * 2.0;
|
|
26
|
+
vec2 off3 = uDirection * uTexel * uRadius * 3.0;
|
|
27
|
+
vec2 off4 = uDirection * uTexel * uRadius * 4.0;
|
|
28
|
+
vec4 color = texture2D(tDiffuse, vUv) * 0.227027;
|
|
29
|
+
color += texture2D(tDiffuse, vUv + off1) * 0.1945946;
|
|
30
|
+
color += texture2D(tDiffuse, vUv - off1) * 0.1945946;
|
|
31
|
+
color += texture2D(tDiffuse, vUv + off2) * 0.1216216;
|
|
32
|
+
color += texture2D(tDiffuse, vUv - off2) * 0.1216216;
|
|
33
|
+
color += texture2D(tDiffuse, vUv + off3) * 0.054054;
|
|
34
|
+
color += texture2D(tDiffuse, vUv - off3) * 0.054054;
|
|
35
|
+
color += texture2D(tDiffuse, vUv + off4) * 0.016216;
|
|
36
|
+
color += texture2D(tDiffuse, vUv - off4) * 0.016216;
|
|
37
|
+
gl_FragColor = color;
|
|
38
|
+
}
|
|
39
|
+
`,transparent:!0,depthTest:!1,depthWrite:!1})}createBloomExtractMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null},uThreshold:{value:.8}},vertexShader:this.getVertexShader(),fragmentShader:`
|
|
40
|
+
varying vec2 vUv;
|
|
41
|
+
uniform sampler2D tDiffuse;
|
|
42
|
+
uniform float uThreshold;
|
|
43
|
+
void main() {
|
|
44
|
+
vec4 color = texture2D(tDiffuse, vUv);
|
|
45
|
+
float brightness = max(max(color.r, color.g), color.b);
|
|
46
|
+
gl_FragColor = brightness > uThreshold ? color : vec4(0.0);
|
|
47
|
+
}
|
|
48
|
+
`,transparent:!0,depthTest:!1,depthWrite:!1})}createBloomAddMaterial(){return this.createShaderMaterial({uniforms:{tBase:{value:null},tBloom:{value:null},uIntensity:{value:1},uResolution:{value:[this.width,this.height]}},vertexShader:this.getVertexShader(),fragmentShader:`
|
|
49
|
+
varying vec2 vUv;
|
|
50
|
+
uniform sampler2D tBase;
|
|
51
|
+
uniform sampler2D tBloom;
|
|
52
|
+
uniform float uIntensity;
|
|
53
|
+
void main() {
|
|
54
|
+
vec4 base = texture2D(tBase, vUv);
|
|
55
|
+
vec4 bloom = texture2D(tBloom, vUv);
|
|
56
|
+
gl_FragColor = vec4(base.rgb + bloom.rgb * uIntensity, base.a);
|
|
57
|
+
}
|
|
58
|
+
`,transparent:!0,depthTest:!1,depthWrite:!1})}createColorMaterial(){return this.createShaderMaterial({uniforms:{tDiffuse:{value:null},uMode:{value:0},uAmount:{value:1}},vertexShader:this.getVertexShader(),fragmentShader:`
|
|
59
|
+
varying vec2 vUv;
|
|
60
|
+
uniform sampler2D tDiffuse;
|
|
61
|
+
uniform int uMode;
|
|
62
|
+
uniform float uAmount;
|
|
4
63
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
64
|
+
vec3 applyHueRotate(vec3 color, float angle) {
|
|
65
|
+
float cosA = cos(angle);
|
|
66
|
+
float sinA = sin(angle);
|
|
67
|
+
mat3 m = mat3(
|
|
68
|
+
0.213 + cosA * 0.787 - sinA * 0.213,
|
|
69
|
+
0.715 - cosA * 0.715 - sinA * 0.715,
|
|
70
|
+
0.072 - cosA * 0.072 + sinA * 0.928,
|
|
71
|
+
0.213 - cosA * 0.213 + sinA * 0.143,
|
|
72
|
+
0.715 + cosA * 0.285 + sinA * 0.140,
|
|
73
|
+
0.072 - cosA * 0.072 - sinA * 0.283,
|
|
74
|
+
0.213 - cosA * 0.213 - sinA * 0.787,
|
|
75
|
+
0.715 - cosA * 0.715 + sinA * 0.715,
|
|
76
|
+
0.072 + cosA * 0.928 + sinA * 0.072
|
|
77
|
+
);
|
|
78
|
+
return clamp(m * color, 0.0, 1.0);
|
|
79
|
+
}
|
|
8
80
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
81
|
+
void main() {
|
|
82
|
+
vec4 color = texture2D(tDiffuse, vUv);
|
|
83
|
+
float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
|
12
84
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
85
|
+
if (uMode == 1) {
|
|
86
|
+
color.rgb *= uAmount;
|
|
87
|
+
} else if (uMode == 2) {
|
|
88
|
+
color.rgb = (color.rgb - 0.5) * uAmount + 0.5;
|
|
89
|
+
} else if (uMode == 3) {
|
|
90
|
+
color.rgb = mix(vec3(luma), color.rgb, uAmount);
|
|
91
|
+
} else if (uMode == 4) {
|
|
92
|
+
color.rgb = mix(color.rgb, vec3(luma), uAmount);
|
|
93
|
+
} else if (uMode == 5) {
|
|
94
|
+
vec3 sepia = vec3(
|
|
95
|
+
dot(color.rgb, vec3(0.393, 0.769, 0.189)),
|
|
96
|
+
dot(color.rgb, vec3(0.349, 0.686, 0.168)),
|
|
97
|
+
dot(color.rgb, vec3(0.272, 0.534, 0.131))
|
|
98
|
+
);
|
|
99
|
+
color.rgb = mix(color.rgb, sepia, uAmount);
|
|
100
|
+
} else if (uMode == 6) {
|
|
101
|
+
color.rgb = mix(color.rgb, vec3(1.0) - color.rgb, uAmount);
|
|
102
|
+
} else if (uMode == 7) {
|
|
103
|
+
color.rgb = applyHueRotate(color.rgb, uAmount);
|
|
104
|
+
}
|
|
16
105
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const width = height * camera.aspect;
|
|
25
|
-
const normalizedX = centerX / camera.width;
|
|
26
|
-
const normalizedY = centerY / camera.height;
|
|
27
|
-
posX = (normalizedX - 0.5) * width;
|
|
28
|
-
posY = -(normalizedY - 0.5) * height;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const rotX = -degToRad(item.rotateX);
|
|
32
|
-
const rotY = degToRad(item.rotateY);
|
|
33
|
-
const rotZ = -degToRad(item.rotateZ);
|
|
34
|
-
|
|
35
|
-
let scaleX = 1;
|
|
36
|
-
let scaleY = 1;
|
|
37
|
-
let scaleZ = 1;
|
|
38
|
-
|
|
39
|
-
if (item.type === "group") {
|
|
40
|
-
scaleX = item.scale;
|
|
41
|
-
scaleY = item.scale;
|
|
42
|
-
scaleZ = item.scale;
|
|
43
|
-
} else {
|
|
44
|
-
const targetWidth = item.rectWidth * item.scale;
|
|
45
|
-
const targetHeight = item.rectHeight * item.scale;
|
|
46
|
-
const parentScale = item.parentScale || 1;
|
|
47
|
-
const cssScaleZ = item.scaleZ || 1;
|
|
48
|
-
|
|
49
|
-
if (item.type === "box" || item.type === "sphere") {
|
|
50
|
-
const uniformSize = Math.min(targetWidth, targetHeight);
|
|
51
|
-
scaleX = uniformSize * parentScale;
|
|
52
|
-
scaleY = uniformSize * parentScale;
|
|
53
|
-
scaleZ = uniformSize * cssScaleZ * parentScale;
|
|
54
|
-
} else if (item.type === "model") {
|
|
55
|
-
const sizeX = item.modelSizeX || 0;
|
|
56
|
-
const sizeY = item.modelSizeY || 0;
|
|
57
|
-
const fitMode = (item.fitMode || "contain").toLowerCase().trim();
|
|
58
|
-
const modelScale = Number.isFinite(item.modelScale) ? item.modelScale : 1;
|
|
59
|
-
|
|
60
|
-
if (sizeX > 0 && sizeY > 0) {
|
|
61
|
-
const scaleToWidth = targetWidth / sizeX;
|
|
62
|
-
const scaleToHeight = targetHeight / sizeY;
|
|
63
|
-
const uniformScale = fitMode === "cover"
|
|
64
|
-
? Math.max(scaleToWidth, scaleToHeight)
|
|
65
|
-
: Math.min(scaleToWidth, scaleToHeight);
|
|
66
|
-
scaleX = uniformScale * modelScale * parentScale;
|
|
67
|
-
scaleY = uniformScale * modelScale * parentScale;
|
|
68
|
-
scaleZ = uniformScale * modelScale * cssScaleZ * parentScale;
|
|
69
|
-
} else {
|
|
70
|
-
const fallbackSize = Math.min(targetWidth, targetHeight);
|
|
71
|
-
scaleX = fallbackSize * modelScale * parentScale;
|
|
72
|
-
scaleY = fallbackSize * modelScale * parentScale;
|
|
73
|
-
scaleZ = fallbackSize * modelScale * cssScaleZ * parentScale;
|
|
106
|
+
gl_FragColor = color;
|
|
107
|
+
}
|
|
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=ne.get(t);if(!r)return null;let i={tDiffuse:{value:null}},{width:s,height:n}=this.getScaledSize();i.uResolution={value:[s,n]},i.uTexel={value:[1/s,1/n]},Object.entries(r.uniforms||{}).forEach(([a,l])=>{i[a]={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
|
+
varying vec2 vUv;
|
|
110
|
+
void main() {
|
|
111
|
+
vUv = uv;
|
|
112
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
74
113
|
}
|
|
75
|
-
} else if (item.type === "cylinder") {
|
|
76
|
-
const cylRadius = targetWidth;
|
|
77
|
-
scaleX = cylRadius * parentScale;
|
|
78
|
-
scaleY = targetHeight * parentScale;
|
|
79
|
-
scaleZ = cylRadius * cssScaleZ * parentScale;
|
|
80
|
-
} else {
|
|
81
|
-
scaleX = targetWidth * parentScale;
|
|
82
|
-
scaleY = targetHeight * parentScale;
|
|
83
|
-
scaleZ = Math.min(targetWidth, targetHeight) * 0.5 * cssScaleZ * parentScale;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
id: item.id,
|
|
89
|
-
posX,
|
|
90
|
-
posY,
|
|
91
|
-
posZ,
|
|
92
|
-
rotX,
|
|
93
|
-
rotY,
|
|
94
|
-
rotZ,
|
|
95
|
-
scaleX,
|
|
96
|
-
scaleY,
|
|
97
|
-
scaleZ,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function initWasm(url) {
|
|
102
|
-
try {
|
|
103
|
-
const res = await fetch(url);
|
|
104
|
-
const bytes = await res.arrayBuffer();
|
|
105
|
-
const mod = await WebAssembly.instantiate(bytes, {});
|
|
106
|
-
wasm = mod.instance;
|
|
107
|
-
wasmReady = true;
|
|
108
|
-
} catch (error) {
|
|
109
|
-
wasm = null;
|
|
110
|
-
wasmReady = false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
self.onmessage = async (event) => {
|
|
115
|
-
const data = event.data || {};
|
|
116
|
-
if (data.type === "init") {
|
|
117
|
-
if (data.wasmUrl) {
|
|
118
|
-
await initWasm(data.wasmUrl);
|
|
119
|
-
}
|
|
120
|
-
self.postMessage({ type: "ready", wasmReady });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (data.type === "compute") {
|
|
125
|
-
const items = data.items || [];
|
|
126
|
-
const camera = data.camera || {};
|
|
127
|
-
const results = new Array(items.length);
|
|
128
|
-
for (let i = 0; i < items.length; i += 1) {
|
|
129
|
-
results[i] = computeTransform(items[i], camera);
|
|
130
|
-
}
|
|
131
|
-
self.postMessage({ type: "result", frameId: data.frameId, results });
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
`,V=class{constructor(e={}){this.worker=null;this.ready=!1;this.lastResult=null;this.pending=!1;if(typeof Worker>"u")return;let t=new Blob([me],{type:"text/javascript"});this.worker=new Worker(URL.createObjectURL(t)),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:e.wasmUrl})}isReady(){return this.ready}isPending(){return this.pending}submit(e,t,r){!this.worker||!this.ready||this.pending||(this.pending=!0,this.worker.postMessage({type:"compute",frameId:r,items:e,camera:t}))}takeLastResult(){let e=this.lastResult;return this.lastResult=null,e}destroy(){this.worker?.terminate(),this.worker=null,this.ready=!1,this.pending=!1,this.lastResult=null}};var j=class j extends U{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.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.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(t){j.provider=t}canConnect(t){let r=super.canConnect(t);return console.log("[String3D] canConnect:",t.id,"keys:",t.keys,"htmlKey:",this.htmlKey,"result:",r),r}initializeObject(t,r,i,s){super.initializeObject(t,r,i,s),r.setProperty("parentId",null);let n=i.parentElement?.closest('[string-3d="group"]');if(n){let o=n.getAttribute("string-id");o&&(r.setProperty("parentId",o),r.setProperty("parent",n))}}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(),!j.provider){console.error("[String3D] No provider set. Call String3D.setProvider() before use.");return}this.engine=j.provider.getEngine(),this.canvasContainer=this.createOrGetContainer(),this.registerTypedProperties(),this.injectCSS(),this.useDirtySync=!!this.options.useDirtySync,this.useDirtySync&&(this.setupObservers(),this.setupScrollListeners()),this.renderer=new z(this.canvasContainer,this.engine),this.renderer.attach(),this.camera=new N(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 _(this.engine,{modelLoader:t,modelLoaderFactory:r}),this.scene.getScene().add(this.camera.camera),this.synchronizer=new W(this.camera,this.renderer.width,this.renderer.height,this.engine),this.options.useTransformWorker&&(this.transformWorker=new V({wasmUrl:this.options.transformWorkerWasmUrl})),console.info(`[String3D] Initialized with: ${j.provider.getName()}`)}onSettingsChange(){this.options=this.buildOptionsFromSettings();let t=!!this.options.useDirtySync;t&&!this.useDirtySync?(this.useDirtySync=!0,this.setupObservers(),this.setupScrollListeners(),this.observeSceneElements(),this.markAllDirty()):!t&&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 V({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(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.observeElement(t.htmlElement),this.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.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,s=!i||i.size===0,n=this.transformWorker;if(n?.isReady()&&!n.isPending()){let o=[];if(this.workerObjectMap.clear(),this.scene.rootObjects.forEach(l=>{this.collectWorkerInputs(l,{scale:1},s,i,o)}),o.length>0){let l=this.domVersion;this.lastSubmittedVersion=l,n.submit(o,this.buildWorkerCameraData(),l)}}this.scene.rootObjects.forEach(o=>{this.syncRecursive(o.el,o,{scale:1},s,i)}),this.useDirtySync&&this.dirtyElements.clear(),this.renderer.render(this.scene,this.camera)}syncRecursive(t,r,i,s,n){if(!this.synchronizer||!t)return;let o=s||!n||n.has(t),l=i;if(o){let c=this.synchronizer.syncElement(t,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 h=s||o;r.children.forEach(c=>this.syncRecursive(c.el,c,l,h,n))}injectCSS(){if(document.getElementById("string-3d-styles"))return;let t=document.createElement("style");t.id="string-3d-styles",t.textContent=`
|
|
114
|
+
`}};var fe=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 s=this._renderer;typeof s.setClearColor=="function"&&s.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 s=e.getAllObjects(),n=new Map;s.forEach(h=>{let d=h.object;"visible"in d&&n.set(h.object,d.visible)});let o=new Set;r.forEach(h=>{this.collectSubtreeObjects(h.object,o)}),s.forEach(h=>{o.has(h.object)&&this.setVisible(h.object,!1)});let a=this._renderer,l=a.autoClear;a.autoClear=!0,a.setRenderTarget&&a.setRenderTarget(null),a.clear&&a.clear(!0,!0,!0),this._renderer.render(e.getScene(),t.camera),a.autoClear=!1,s.forEach(h=>{let d=n.get(h.object);typeof d<"u"&&this.setVisible(h.object,d)});let c=s.filter(h=>h.type.endsWith("Light")),u=this.supportsLayers(t.camera,s);r.forEach(h=>{let d=this.filterCache.get(h.object.id);if(!h.dirty&&d&&d.effectsKey===h.effectsKey&&d.qualityScale===this.qualityScale){d.lastUsedFrame=this.frameId,i.renderToScreen(d.target);return}let g=this.injectEffectContext(h.object.el,h.effects),f=new Set;this.collectSubtreeObjects(h.object,f);let S=[],y=null;if(u){let P=h.object.getSubtreeObjects();S=this.applyLayerMask(P,c,this.filterLayer),y=this.setCameraLayer(t.camera,this.filterLayer)}else s.forEach(P=>{if(n.get(P.object)===!1){this.setVisible(P.object,!1);return}if(P.type.endsWith("Light")){this.setVisible(P.object,!0);return}this.setVisible(P.object,f.has(P.object))});let b=i.acquireTarget();a.setRenderTarget&&a.setRenderTarget(b),a.clear&&a.clear(!0,!0,!0),this._renderer.render(e.getScene(),t.camera);let v=i.applyFilters(b,g,this.qualityScale);a.setRenderTarget&&a.setRenderTarget(null),i.renderToScreen(v),u&&(this.restoreLayerMask(S),y!==null&&this.restoreCameraLayer(t.camera,y)),v!==b&&i.releaseTarget(b);let x={target:v,effectsKey:h.effectsKey,lastUsedFrame:this.frameId,qualityScale:this.qualityScale},T=this.filterCache.get(h.object.id);T&&T.target!==v&&i.releaseTarget(T.target),this.filterCache.set(h.object.id,x)}),u||s.forEach(h=>{let d=n.get(h.object);typeof d<"u"&&this.setVisible(h.object,d)}),a.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 Ie(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,s=1-(r.top+r.height/2)/this._height,n=o=>Math.max(0,Math.min(1,o));return[n(i),n(s)]}injectEffectContext(e,t){if(!t.some(n=>n.type==="custom"))return t;let r=this.getFilterCenter(e),i=!1,s=t.map(n=>{if(n.type!=="custom"||n.uniforms&&"uCenter"in n.uniforms)return n;let o={...n.uniforms||{},uCenter:r};return i=!0,{...n,uniforms:o}});return i?s: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 s=1e3/this.avgFrameMs,n=Math.max(.75,1-Math.min(.4,e*.03)),o=n;s<48&&(o=Math.max(.75,n-.1)),s<40&&(o=Math.max(.75,n-.2)),s>58&&(o=Math.min(1,n+.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,s=(n,o)=>{let a=n;this.hasLayers(a)&&(i.has(n)||i.set(n,a.layers.mask),o==="set"?a.layers.set(r):a.layers.enable(r))};return e.forEach(n=>s(n,"set")),t.forEach(n=>s(n.object,"enable")),Array.from(i.entries()).map(([n,o])=>({object:n,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 q=class{constructor(e,t,r,i,s={}){this._uniforms={};this._children=[];this._flatObjectsCache=null;this._subtreeCache=null;this.id=e,this.type=t,this._object=r,this.engine=i,this._material=s.material,this._geometry=s.geometry,this._texture=s.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 s=i?.material;Array.isArray(s)?s.forEach(n=>n?.dispose?.()):s?.dispose&&s.dispose()})}};var ae=class{constructor(e){this.styleMap=e.computedStyleMap?.(),this.style=getComputedStyle(e)}readNumber(e,t){let r=this.styleMap?.get?.(e);if(r!=null){let s=typeof r=="object"?r.value:r,n=typeof s=="number"?s:Number.parseFloat(s);if(!Number.isNaN(n))return n}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 s=this.style.getPropertyValue(e).trim();return this.stripQuotes(s)||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 K(m,e,t){let i=m.computedStyleMap?.()?.get?.(e);if(i!==void 0){if(typeof i=="number")return i;if(typeof i=="string"){let a=Number.parseFloat(i);if(!Number.isNaN(a))return a}if(i&&typeof i=="object"){let a=i.value;if(typeof a=="number")return a;if(typeof a=="string"){let l=Number.parseFloat(a);if(!Number.isNaN(l))return l}}}let n=getComputedStyle(m).getPropertyValue(e),o=Number.parseFloat(n);return Number.isNaN(o)?t:o}function Ye(m){return m.startsWith("'")&&m.endsWith("'")||m.startsWith('"')&&m.endsWith('"')?m.slice(1,-1):m}function ye(m,e,t=""){let i=m.computedStyleMap?.()?.get?.(e);if(typeof i=="string")return Ye(i.trim());if(i&&typeof i=="object"){let o=i.value;if(typeof o=="string")return Ye(o.trim())}let s=getComputedStyle(m).getPropertyValue(e);return(s?Ye(s.trim()):"")||t}function Oe(m,e,t=!1){let r=ye(m,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 nt(m){let e=m.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(m).getPropertyValue("--filter")||""),t=t.trim(),t}var Z=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 s=i.css?.trim();if(!s||!s.startsWith("--")||this.registeredCssVars.has(s))continue;let n=this.resolveCssSyntax(i.type);try{t.registerProperty({name:s,syntax:n,inherits:!1,initialValue:this.defaultCssInitialValue(i)}),this.registeredCssVars.add(s)}catch(o){console.warn(`[String3D] Failed to register CSS property ${s}:`,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())}};Z.materials=new Map,Z.registeredCssVars=new Set;function at(m,e){if(e==null||e===""||e==="none")return m.value;let t=e.trim();switch(m.type){case"float":case"int":{let r=parseFloat(t);return isNaN(r)?m.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]]:m.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]]:m.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]]:m.value}case"color":return St(t)??m.value;case"texture":{let r=t.match(/url\(['"]?(.*?)['"]?\)/);return r?r[1]:t||m.value}default:return m.value}}function St(m){if(m.startsWith("#")){let t=m.slice(1);if(t.length===3){let r=parseInt(t[0]+t[0],16)/255,i=parseInt(t[1]+t[1],16)/255,s=parseInt(t[2]+t[2],16)/255;return[r,i,s]}if(t.length===6){let r=parseInt(t.slice(0,2),16)/255,i=parseInt(t.slice(2,4),16)/255,s=parseInt(t.slice(4,6),16)/255;return[r,i,s]}}let e=m.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 Xe(m,e,t){let r={};if(m.parse){let i=m.parse(e,t);Object.assign(r,i)}if(m.uniforms)for(let[i,s]of Object.entries(m.uniforms))if(s.css){let n=t.getPropertyValue(s.css).trim();r[i]=at(s,n)}else i in r||(r[i]=s.value);return r}function Ke(m){let e=new Map;for(let r of m){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 s=i.sort((n,o)=>(n.order??0)-(o.order??0));t.set(r,s.map(n=>n.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=s=>{if(s){let n=e.getProperty("parentId");n==null?(this._scene.add(s.object),this._rootObjects.push(s)):this._objects.get(n)?.addChild(s),this._objects.set(e.id,s),this._elementMap.set(e.id,r),s.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 q(e.id,"group",r,this.engine);return t(i),i}createLight(e,t,r){let i=e.htmlElement,s=i?ye(i,"--light-color","#ffffff"):"#ffffff",n=s&&s!=="none"?s:"#ffffff",o=i?K(i,"--light-intensity",1):1,a;if(t==="point"){let u=i?K(i,"--light-distance",1e3):1e3,h=i?K(i,"--light-decay",0):0;a=this.engine.createPointLight(n,o,u,h)}else if(t==="directional")a=this.engine.createDirectionalLight(n,o);else if(t==="spot"){let u=i?K(i,"--light-distance",0):0,h=i?K(i,"--light-angle",Math.PI/3):Math.PI/3,d=i?K(i,"--light-penumbra",0):0,p=i?K(i,"--light-decay",1):1;a=this.engine.createSpotLight(n,o,u,h,d,p)}else if(t==="hemisphere"){let u=i?ye(i,"--light-ground-color","#ffffff"):"#ffffff",h=u&&u!=="none"?u:"#ffffff";a=this.engine.createHemisphereLight(n,h,o)}else a=this.engine.createAmbientLight(n,o);if((i?Oe(i,"--shadow-cast",!1):!1)&&a.shadow){a.castShadow=!0;let u=i?K(i,"--shadow-bias",0):0,h=i?K(i,"--shadow-map-size",512):512;a.shadow.bias=u,a.shadow.mapSize.width=h,a.shadow.mapSize.height=h}let c=new q(e.id,t+"Light",a,this.engine);return r(c),c}applyShadowProps(e,t){let r=e.htmlElement,i=r?Oe(r,"--shadow-cast",!1):!1,s=r?Oe(r,"--shadow-receive",!1):!1;t.castShadow=i,t.receiveShadow=s}createBox(e,t){let r=this.engine.createBoxGeometry(1,1,1),i=this.createMaterialFromObject(e),s=this.engine.createMesh(r,i);this.applyShadowProps(e,s);let n=new q(e.id,"box",s,this.engine,{geometry:r,material:i});return t(n),n}createSphere(e,t){let r=this.getGeometryQuality(e.htmlElement),i=Math.max(3,Math.round(32*r)),s=Math.max(2,Math.round(32*r)),n=this.engine.createSphereGeometry(.5,i,s),o=this.createMaterialFromObject(e),a=this.engine.createMesh(n,o);this.applyShadowProps(e,a);let l=new q(e.id,"sphere",a,this.engine,{geometry:n,material:o});return t(l),l}createPlane(e,t){let r=this.engine.createPlaneGeometry(1,1),i=this.createMaterialFromObject(e),s=this.engine.createMesh(r,i);this.applyShadowProps(e,s);let n=new q(e.id,"plane",s,this.engine,{geometry:r,material:i});return t(n),n}createCylinder(e,t){let r=this.getGeometryQuality(e.htmlElement),i=Math.max(3,Math.round(32*r)),s=this.engine.createCylinderGeometry(.5,.5,1,i),n=this.createMaterialFromObject(e),o=this.engine.createMesh(s,n);this.applyShadowProps(e,o);let a=new q(e.id,"cylinder",o,this.engine,{geometry:s,material:n});return t(a),a}createModel(e,t){let r=e.getProperty("3d-model");if(!r)return;let i=e.getProperty("3d-model-loader")||void 0,s=this.resolveModelLoader(i);if(!s){console.warn("[String3D] Model loader not configured");return}let n=e.htmlElement;n&&this.applyModelTextureRemap(s,n);let o=e.getProperty("3d-model-center")??!1;s.load(r,a=>{let l=a?.scene||a?.object||a;if(!l){console.warn("[String3D] Model loader returned empty result");return}let c=n&&this.shouldOverrideModelMaterial(n)?this.createMaterialFromElement(n,e):null;typeof l.traverse=="function"&&l.traverse(h=>{h.isMesh&&(c&&(h.material=c),this.applyShadowProps(e,h))}),o&&this.centerObject(l);let u=new q(e.id,"model",l,this.engine);t(u)},a=>{console.log(a.loaded/a.total*100+"% loaded")},a=>{console.error("[String3D] Model loading error:",a)})}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},s=this.engine.createParticleSystem(i),n=new q(e.id,"particles",s,this.engine);t(n)}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),s=this.engine.createMesh(r,i);this.applyShadowProps(e,s);let n=this.engine.createGroup();n.__textMesh=s,n.add(s);let o=new q(e.id,"text",n,this.engine,{geometry:r,material:i});t(o)}getGeometryQuality(e){if(!e)return 1;let t=K(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=M=>r?r.getPropertyValue(M).trim():"",s=(M,E,j)=>{let B=i(M);return B&&B!=="none"&&B!==""?E(B):j},n=M=>parseFloat(M),o=M=>M,a=M=>{let E=M.match(/url\(['"]?(.*?)['"]?\)/);return E?E[1]:M},l=s("--material-type",M=>M.split("[")[0]||"basic","basic"),c=this.tryCreateCustomMaterial(l,e,r,t);if(c)return c;let u=s("--material-color",o,"#ffffff"),h=s("--opacity",n,1),d=s("--material-metalness",n,0),p=s("--material-roughness",n,1),g=s("--material-emissive",o,"#000000"),f={color:u,transparent:h<1,opacity:h},S=s("--texture-map",a,""),y=s("--texture-normal",a,""),b=s("--texture-roughness",a,""),v=s("--texture-metalness",a,""),x=s("--texture-ao",a,""),T=this.parseFlipY(e),P=e?ye(e,"--texture-color-space",""):"",O=!!(S||y||b||v||x),w=l;return w!=="standard"&&O&&(w="standard"),w==="standard"?(S&&(f.map=this.loadTexture(S,{flipY:T,colorSpace:P})),y&&(f.normalMap=this.loadTexture(y,{flipY:T})),b&&(f.roughnessMap=this.loadTexture(b,{flipY:T})),v&&(f.metalnessMap=this.loadTexture(v,{flipY:T})),x&&(f.aoMap=this.loadTexture(x,{flipY:T})),f.metalness=d,f.roughness=p,f.emissive=g,this.engine.createMeshStandardMaterial(f)):this.engine.createMeshBasicMaterial(f)}tryCreateCustomMaterial(e,t,r,i){let s=Z.get(e);if(!s)return null;let n=this.engine.getMaterialFactory?.();if(!n)return console.warn(`[String3D] Material factory not available for custom material "${e}"`),null;if(!n.supports(s))return console.warn(`[String3D] Material factory does not support "${e}".`),null;let o={};t&&r&&(o=n.parseUniformsFromCSS(s,t,r));let a=n.create(s,o);return i&&this._materialInstances.set(i.id,a),a.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 s=(t.colorSpace||"").toLowerCase().trim();return s&&"colorSpace"in i&&(i.colorSpace=s==="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=s=>{let n=t.getPropertyValue(s);return n&&n!=="0"&&n!=="none"&&n!==""};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(s=>r(s))}applyModelTextureRemap(e,t){let r=(t.getAttribute("string-3d-model-texture-base")||"").trim(),i=r?r.replace(/\/?$/,"/"):"",s=t.getAttribute("string-3d-model-textures"),n=null;if(s)try{n=JSON.parse(s)}catch(a){console.warn("[String3D] Invalid model texture mapping JSON:",a)}let o=e?.manager;if(!o||typeof o.setURLModifier!="function"){(n||i)&&console.warn("[String3D] Model loader does not support URL remap.");return}o.setURLModifier(a=>{let l=n&&a in n?n[a]:a;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 G=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 a=this.cache.get(e);if(a)return a}let s=performance.now(),n=Math.max(0,t.styleReadIntervalMs??0);if(n>0){let a=this.meta.get(e),l=this.cache.get(e);if(a&&l&&s-a.time<n)return l}let o=r(e);return this.cache.set(e,o),this.meta.set(e,{time:s}),o}clear(){this.cache=new WeakMap,this.meta=new WeakMap}};var Ze=Math.PI/180,Ae=class Ae{sync(e,t,r,i){let s=e.__layoutCache,n=s?s.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r),a=n.left+n.width*.5,l=n.top+n.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(a-r.viewportWidth/2,-(l-r.viewportHeight/2),o.translateZ);else{let c=r.camera.getFrustumSizeAt(o.translateZ),u=a/r.viewportWidth,h=l/r.viewportHeight;t.object.position.set((u-.5)*c.width,-(h-.5)*c.height,o.translateZ)}return t.object.scale.set(o.scale,o.scale,o.scale),t.object.rotation.x=-o.rotateX*Ze,t.object.rotation.y=o.rotateY*Ze,t.object.rotation.z=-o.rotateZ*Ze,t.object.rotation.order="XYZ",t.object.updateMatrixWorld(!0),{scale:o.scale}}readStyleBundle(e,t){return Ae.styleCache.get(e,t,r=>{let i=new ae(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)}})}};Ae.styleCache=new G;var Re=Ae;var ke=class ke{sync(e,t,r,i){let s=e.__layoutCache,n=s?s.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r,t),a=n.left+n.width*.5,l=n.top+n.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(a-r.viewportWidth/2+o.translateX,-(l-r.viewportHeight/2)+o.translateY,o.translateZ);else{let u=r.camera.getFrustumSizeAt(o.translateZ),h=a/r.viewportWidth,d=l/r.viewportHeight;t.object.position.set((h-.5)*u.width+o.translateX,-(d-.5)*u.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 u=document.querySelector(`[string-id="${o.targetId}"]`);if(u){let h=u.__layoutCache,d=h?h.rect:u.getBoundingClientRect(),g=new ae(u).readNumber("--translate-z",0),f=d.left+d.width*.5,S=d.top+d.height*.5,y,b,v;if(r.camera.getMode()==="orthographic")y=f-r.viewportWidth/2,b=-(S-r.viewportHeight/2),v=g;else{let x=r.camera.getFrustumSizeAt(g),T=f/r.viewportWidth,P=S/r.viewportHeight;y=(T-.5)*x.width,b=-(P-.5)*x.height,v=g}o.targetOffset&&(y+=o.targetOffset.x,b+=o.targetOffset.y,v+=o.targetOffset.z),c.target.position.set(y,b,v),c.target.updateMatrixWorld(!0)}}return null}readStyleBundle(e,t,r){return ke.styleCache.get(e,t,i=>{let s=new ae(i),n=r.object,o={translateZ:s.readNumber("--translate-z",0),translateX:s.readNumber("--translate-x",0),translateY:s.readNumber("--translate-y",0),color:s.readString("--light-color","")||void 0,intensity:s.readNumber("--light-intensity",n.intensity??1),castShadow:s.readBoolean("--shadow-cast",!1)};typeof n.distance<"u"&&(o.distance=s.readNumber("--light-distance",n.distance??0)),typeof n.decay<"u"&&(o.decay=s.readNumber("--light-decay",n.decay??1)),typeof n.angle<"u"&&(o.angle=s.readNumber("--light-angle",n.angle??Math.PI/3)),typeof n.penumbra<"u"&&(o.penumbra=s.readNumber("--light-penumbra",n.penumbra??0));let a=s.readString("--light-ground-color","");a&&(o.groundColor=a),o.castShadow&&n.shadow&&(o.shadowBias=s.readNumber("--shadow-bias",n.shadow.bias??0),o.shadowMapSize=s.readNumber("--shadow-map-size",n.shadow.mapSize.width??512));let l=s.readString("--light-target","").trim();l&&(o.targetId=l);let c=s.readString("--light-target-offset","").trim();if(c){let u=this.parseTargetOffset(c);u&&(o.targetOffset=u)}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]}}};ke.styleCache=new G;var le=ke;var Qe=Math.PI/180,W=class W{static applyVisualProps(e,t,r){let i=W.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 W.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 s=r.castShadow??!1,n=r.receiveShadow??!1,o=typeof r.opacity=="number"?r.opacity:NaN,a=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!==s&&(l.castShadow=s),l.receiveShadow!==n&&(l.receiveShadow=n),(Array.isArray(l.material)?l.material:[l.material]).forEach(a))});else if(t.object.isMesh){let l=t.object;l.castShadow!==s&&(l.castShadow=s),l.receiveShadow!==n&&(l.receiveShadow=n),(Array.isArray(l.material)?l.material:[l.material]).forEach(a)}}sync(e,t,r,i){let{rect:s,width:n,height:o}=this.readLayout(e,r),a=this.readStyleBundle(e,r),{translateZ:l,cssScale:c,rotateX:u,rotateY:h,rotateZ:d,cssScaleZ:p,opacity:g,color:f,metalness:S,roughness:y,emissive:b,castShadow:v,receiveShadow:x,geometryQuality:T}=a,P=s.left+s.width*.5,O=s.top+s.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(P-r.viewportWidth/2,-(O-r.viewportHeight/2),l);else{let D=r.camera.getFrustumSizeAt(l),F=P/r.viewportWidth,L=O/r.viewportHeight;t.object.position.set((F-.5)*D.width,-(L-.5)*D.height,l)}t.object.rotation.x=-u*Qe,t.object.rotation.y=h*Qe,t.object.rotation.z=-d*Qe,t.object.rotation.order="XYZ";let w=n*c,M=o*c,E=i?.scale||1,j=p*E,B=w<M?w:M,H,N,V;switch(t.type){case"box":case"sphere":{let D=B*E;H=N=D,V=D*p;break}case"model":{let D=t.getOriginalBoundingBox();W.tempVector3||(W.tempVector3=r.engine.createVector3());let F=D.getSize(W.tempVector3),L=e.getAttribute("string-3d-model-fit"),z=parseFloat(e.getAttribute("string-3d-model-scale")||"1"),_=Number.isFinite(z)?z*E:E;if(F.x>0&&F.y>0){let R=w/F.x,$=M/F.y,A=(L==="cover"?R>$?R:$:R<$?R:$)*_;H=N=A,V=A*p}else{let R=B*_;H=N=R,V=R*p}break}case"cylinder":H=w*E,N=M*E,V=w*j;break;default:H=w*E,N=M*E,V=B*.5*j;break}return t.object.scale.set(H,N,V),W.applyVisualProps(e,t,{opacity:g,color:f&&f!=="none"?f:void 0,metalness:isNaN(S)?void 0:S,roughness:isNaN(y)?void 0:y,emissive:b&&b!=="none"?b:void 0,castShadow:v,receiveShadow:x}),this.applyGeometryQuality(t,T,r),this.updateCustomUniforms(e,t,r),{scale:c*E}}applyGeometryQuality(e,t,r){let i=r.engine,s=i?.simplifyGeometry?.bind(i);if(typeof s!="function")return;let n=Number.isFinite(t)&&t>0?t:1,o=W.lastGeometryQuality.get(e);if(typeof o=="number"&&Math.abs(o-n)<.001)return;W.lastGeometryQuality.set(e,n);let a=l=>{if(!l?.geometry)return;let c=l.userData||(l.userData={});c.__originalGeometry||(c.__originalGeometry=l.geometry);let u=c.__originalGeometry;if(n>=.999){l.geometry=u;return}c.__lodCache||(c.__lodCache=new Map);let h=n.toFixed(3);if(c.__lodCache.has(h)){l.geometry=c.__lodCache.get(h);return}let d=s(u,n);d&&(c.__lodCache.set(h,d),l.geometry=d)};e.object.traverse?e.object.traverse(l=>{l?.isMesh&&a(l)}):e.object.isMesh&&a(e.object)}updateCustomUniforms(e,t,r){let i=r.engine.getMaterialFactory?.();if(!i)return;let s=getComputedStyle(e),n=o=>{let a=o?.userData?.definition;if(!a?.uniforms)return;let l=i.parseUniformsFromCSS(a,e,s);for(let[c,u]of Object.entries(l)){let h=a.uniforms?.[c];if(!h)continue;let d=i.convertUniformValue?.bind(i),p=d?d(h.type,u):u;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=p:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=p:o.uniforms?.[c]&&(o.uniforms[c].value=p)}};if(t.object.traverse)t.object.traverse(o=>{o.isMesh&&(Array.isArray(o.material)?o.material:[o.material]).forEach(n)});else if(t.object.isMesh){let o=t.object;(Array.isArray(o.material)?o.material:[o.material]).forEach(n)}}readStyleBundle(e,t){return W.styleCache.get(e,t,r=>{let i=r.computedStyleMap?.(),s=getComputedStyle(r),n=(l,c)=>{let u=i?.get?.(l);if(u!=null){let d=typeof u=="object"&&"value"in u?u.value:u,p=typeof d=="number"?d:Number.parseFloat(String(d));if(!Number.isNaN(p))return p}let h=Number.parseFloat(s.getPropertyValue(l));return Number.isNaN(h)?c:h},o=l=>{let c=i?.get?.(l),u=c&&typeof c=="object"&&"value"in c?c.value:c;return typeof u=="string"?u.trim()||void 0:s.getPropertyValue(l).trim()||void 0},a=(l,c=!1)=>{let u=o(l);if(!u)return c;let h=u.toLowerCase();return h==="true"||h==="1"||h==="yes"?!0:h==="false"||h==="0"||h==="no"?!1:c};return{translateZ:n("--translate-z",0),cssScale:n("--scale",1),rotateX:n("--rotate-x",0),rotateY:n("--rotate-y",0),rotateZ:n("--rotate-z",0),cssScaleZ:n("--scale-z",1),opacity:n("--opacity",NaN),color:o("--material-color"),metalness:n("--material-metalness",NaN),roughness:n("--material-roughness",NaN),emissive:o("--material-emissive"),castShadow:a("--shadow-cast",!1),receiveShadow:a("--shadow-receive",!1),geometryQuality:n("--geometry-quality",1)}})}readLayout(e,t){let r=e.__layoutCache;return r||W.layoutCache.get(e,t,i=>{let s=i.getBoundingClientRect(),n=i.offsetWidth||s.width,o=i.offsetHeight||s.height;return{rect:s,width:n,height:o}})}};W.styleCache=new G,W.layoutCache=new G,W.tempVector3=null,W.lastVisualProps=new WeakMap,W.lastGeometryQuality=new WeakMap;var J=W;var Je=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},k=class k{sync(e,t,r,i){let s=e.__layoutCache,n=s?s.rect:e.getBoundingClientRect(),o=this.readStyleBundle(e,r),a=n.left+n.width*.5,l=n.top+n.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(a-r.viewportWidth/2,-(l-r.viewportHeight/2),o.translateZ);else{let S=r.camera.getFrustumSizeAt(o.translateZ),y=a/r.viewportWidth,b=l/r.viewportHeight;t.object.position.set((y-.5)*S.width,-(b-.5)*S.height,o.translateZ)}let c=i?.scale??1,u=o.scale*c;t.object.scale.set(u,u,u),t.object.rotation.x=-o.rotateX*Je,t.object.rotation.y=o.rotateY*Je,t.object.rotation.z=-o.rotateZ*Je,t.object.rotation.order="XYZ";let h=this.buildConfig(o,n,r,i),d=k.lastConfig.get(t);(!d||!this.isSameConfig(d,h))&&(k.lastConfig.set(t,h),t.object.setConfig?.(h)),this.updateMaterialOverrides(e,t,r,o),this.updateCustomUniforms(e,t,r);let p=performance.now(),g=k.lastTime.get(t)??p,f=Math.max(0,(p-g)/1e3);return k.lastTime.set(t,p),t.object.update?.(f),{scale:i?.scale??1}}readStyleBundle(e,t){return k.styleCache.get(e,t,r=>{let i=new ae(r),n=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:n,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 n=i?.scale??1,o=Math.min(t.width,t.height),a=e.instanceShape==="box"||e.instanceShape==="model"?1:.5,l=e.particlesFit?o*a: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*n),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 s=r.camera.getFrustumSizeAt(t).width/Math.max(1,r.viewportWidth);return e*s}isSameConfig(e,t){return JSON.stringify(e)===JSON.stringify(t)}updateMaterialOverrides(e,t,r,i){let n=(i.materialType||"basic").split("[")[0].trim().toLowerCase(),o=Z.get(n),a=r.engine.getMaterialFactory?.();if(!o||!a||!a.supports(o)){if(!(k.materialInstances.has(t)||k.lastMaterialType.has(t)))return;let u=k.materialInstances.get(t);u&&(u.dispose(),k.materialInstances.delete(t)),k.lastMaterialType.delete(t),t.object.setMaterial?.(null,{points:!0,meshes:!0});return}if(k.lastMaterialType.get(t)!==n){let c=k.materialInstances.get(t);c&&c.dispose();let u=getComputedStyle(e),h=a.parseUniformsFromCSS(o,e,u),d=a.create(o,h);k.materialInstances.set(t,d),k.lastMaterialType.set(t,n);let p=d.material,g=!!p?.isShaderMaterial,f=t.object;f.setMaterial?.(p,{meshes:!0,points:!1}),f.setMaterial?.(g?p:null,{meshes:!1,points:!0})}}updateCustomUniforms(e,t,r){let i=r.engine.getMaterialFactory?.();if(!i)return;let s=getComputedStyle(e),n=o=>{let a=o?.userData?.definition;if(!a?.uniforms)return;let l=i.parseUniformsFromCSS(a,e,s);for(let[c,u]of Object.entries(l)){let h=a.uniforms?.[c];if(!h)continue;let d=i.convertUniformValue?.bind(i),p=d?d(h.type,u):u;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=p:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=p:o.uniforms?.[c]&&(o.uniforms[c].value=p)}};t.object.traverse&&t.object.traverse(o=>{(o.isMesh||o.isPoints)&&(Array.isArray(o.material)?o.material:[o.material]).forEach(n)})}};k.styleCache=new G,k.lastConfig=new WeakMap,k.lastTime=new WeakMap,k.lastMaterialType=new WeakMap,k.materialInstances=new WeakMap;var je=k;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 et=null,ve=null,tt=null,Se=null;async function Mt(){return ve||(et||(et=(async()=>typeof window<"u"&&window.opentype?(ve=window.opentype,ve):new Promise((m,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,m(ve)},t.onerror=()=>e(new Error("[FontConverter] Failed to load opentype.js")),document.head.appendChild(t)}))()),et)}async function xt(){return Se||(tt||(tt=(async()=>typeof window<"u"&&window.Module?.decompress?(Se=window.Module,Se):new Promise((m,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,s=()=>{r++;let n=window;n.Module?.decompress?(Se=n.Module,m(Se)):r>=i?e(new Error("[FontConverter] woff2 decoder initialization timeout")):setTimeout(s,10)};s()},t.onerror=()=>{e(new Error("[FontConverter] Failed to load woff2 decoder"))},document.head.appendChild(t)}))()),tt)}async function wt(m){let e=await xt(),t=new Uint8Array(m),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 Et(m){return new DataView(m).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 s=this.doLoad(e,t);this.loadingPromises.set(t,s);try{let n=await s;return this.cache.set(t,n),n}finally{this.loadingPromises.delete(t)}}static async doLoad(e,t){let r=await Mt(),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");Et(i)&&(i=await wt(i));let s=r.parse(i);if(!s)throw new Error("[FontConverter] Failed to parse font");return this.convertToTypeFace(s)}static convertToTypeFace(e){let t=1e3/e.unitsPerEm,r={};for(let i=0;i<e.glyphs.length;i++){let s=e.glyphs.get(i);if(!s.unicode)continue;let n=String.fromCharCode(s.unicode),o=s.getPath(0,0,e.unitsPerEm),a=this.pathToOutline(o,t),l=s.advanceWidth??s.xMax??e.unitsPerEm*.5;r[n]={ha:Math.round(l*t),x_min:s.xMin!==void 0?Math.round(s.xMin*t):0,x_max:s.xMax!==void 0?Math.round(s.xMax*t):0,o:a}}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 Ne=Math.PI/180,Dt=!1,I=class I{static log(...e){Dt&&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:s,width:n,height:o}=this.readLayout(e,r),a=this.readStyleBundle(e,r),{translateZ:l,cssScale:c,rotateX:u,rotateY:h,rotateZ:d,cssScaleZ:p,opacity:g,color:f,metalness:S,roughness:y,emissive:b,castShadow:v,receiveShadow:x,fontFamily:T,fontSize:P,textTransform:O,textDepth:w,textCurveSegments:M,bevelEnabled:E,bevelSize:j,bevelThickness:B,bevelOffset:H,bevelSegments:N,fontCss:V}=a,D=s.left+s.width*.5,F=s.top+s.height*.5;if(r.camera.getMode()==="orthographic")t.object.position.set(D-r.viewportWidth/2,-(F-r.viewportHeight/2),l);else{let Y=r.camera.getFrustumSizeAt(l),U=D/r.viewportWidth,ie=F/r.viewportHeight;t.object.position.set((U-.5)*Y.width,-(ie-.5)*Y.height,l)}t.object.rotation.x=-u*Ne,t.object.rotation.y=h*Ne,t.object.rotation.z=-d*Ne,t.object.rotation.order="XYZ",t.object.rotation.z=-d*Ne,t.object.rotation.order="XYZ";let L=this.extractCharacterLayout(e,O),z=L.map(Y=>Y.char).join(""),_=!!V,R=this.getTextMesh(t);if(!R)return I.log("No mesh found for text object"),{scale:c*(i?.scale||1)};if(L.length===0)return I.log("Empty text content, hiding mesh"),R.visible=!1,{scale:c*(i?.scale||1)};R.visible=!0;let $=X.resolveFontFamily(T||"");if(!$){return I.warnedMissingFont||(console.warn("[String3D] No registered font found for 3D text. Font family:",T),I.warnedMissingFont=!0),{scale:c*(i?.scale||1)};return{scale:c*(i?.scale||1)}}if(!r.engine.loadFont||!r.engine.createTextGeometry)return I.warnedMissingLoader||(console.warn("[String3D] Engine does not support text geometry."),I.warnedMissingLoader=!0),{scale:c*(i?.scale||1)};let A=$.url,Q=I.fontCache.get(A);if(!Q){if(I.markObjectPendingFont(A,t),!I.fontPromises.has(A)){let Y=r.engine.loadFont(A).then(U=>(U&&(I.fontCache.set(A,U),I.invalidatePendingObjects(A)),U));I.fontPromises.set(A,Y)}return R.visible=!1,{scale:c*(i?.scale||1)}}I.clearObjectPendingFont(A,t);let te=L.length>0?`${L.length}:${L[0].x.toFixed(1)},${L[0].y.toFixed(1)}:${L[L.length-1].x.toFixed(1)},${L[L.length-1].y.toFixed(1)}`:"empty",re=[z,P.toFixed(3),V||"",s.width.toFixed(1),s.height.toFixed(1),te,w.toFixed(3),M.toFixed(3),E?"1":"0",j.toFixed(3),B.toFixed(3),H.toFixed(3),N.toFixed(3)].join("|");if(I.geometryKeys.get(t)!==re){I.log("Creating new geometry for",z.substring(0,20),"Layout:",te);let Y=_?L:(()=>{let ie=I.getFontMetrics(Q,P),ce=ie?ie.ascent:P*.8;return L.map(se=>({...se,y:se.y+ce}))})(),U=r.engine.createTextGeometry(z,Q,{size:P,height:w,curveSegments:Math.max(1,Math.round(M)),bevelEnabled:E,bevelThickness:B,bevelSize:j,bevelOffset:H,bevelSegments:Math.max(0,Math.round(N)),lineHeight:0,letterSpacing:0,align:"left",layout:Y,fontCss:V,useCanvasText:!0});U&&(U.computeBoundingBox(),R.geometry&&R.geometry.dispose?.(),R.geometry=U,t.geometry=U,I.geometryKeys.set(t,re))}let we=i?.scale||1,Ee=r.camera.getMode()==="orthographic"?1:r.camera.getScaleAtZ(l,r.viewportHeight),oe=c*we*Ee,De=oe*p;t.object.scale.set(oe,oe,De);let Ce=-n*.5,ue=o*.5;return R.position.set(Ce,ue,0),J.applyVisualProps(e,t,{opacity:g,color:f&&f!=="none"?f:void 0,metalness:Number.isFinite(S)?S:void 0,roughness:Number.isFinite(y)?y:void 0,emissive:b&&b!=="none"?b:void 0,castShadow:v,receiveShadow:x}),this.updateCustomUniforms(e,t,r),{scale:oe}}extractCharacterLayout(e,t){let r=[];if(typeof document>"u"||!document.createRange)return r;let i=document.createRange(),s=e.getBoundingClientRect(),n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),o;for(;o=n.nextNode();){let a=o.textContent||"";if(!(!a.trim()&&a!==" "))for(let l=0;l<a.length;l++){let c=a[l];if(c===`
|
|
116
|
+
`||c==="\r"||!c.trim())continue;i.setStart(o,l),i.setEnd(o,l+1);let u=i.getClientRects();if(u.length>0){let h=u[0],d=h.left-s.left,p=h.top-s.top,g=this.applyTextTransform(c,t);r.push({char:g,x:d,y:p,width:h.width,height:h.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 s=getComputedStyle(e),n=o=>{let a=o?.userData?.definition;if(!a?.uniforms)return;let l=i.parseUniformsFromCSS(a,e,s);for(let[c,u]of Object.entries(l)){let h=a.uniforms?.[c];if(!h)continue;let d=i.convertUniformValue?.bind(i),p=d?d(h.type,u):u;o.userData?.shader?.uniforms?.[c]?o.userData.shader.uniforms[c].value=p:o.userData?.customUniforms?.[c]?o.userData.customUniforms[c].value=p:o.uniforms?.[c]&&(o.uniforms[c].value=p)}};if(t.object.traverse)t.object.traverse(o=>{o.isMesh&&(Array.isArray(o.material)?o.material:[o.material]).forEach(n)});else{let o=this.getTextMesh(t);if(!o)return;(Array.isArray(o.material)?o.material:[o.material]).forEach(n)}}readStyleBundle(e,t){return I.styleCache.get(e,t,r=>{let i=r.computedStyleMap?.(),s=getComputedStyle(r),n=(w,M)=>{let E=i?.get?.(w);if(E!=null){let H=typeof E=="object"&&"value"in E?E.value:E,N=typeof H=="number"?H:Number.parseFloat(String(H));if(!Number.isNaN(N))return N}let j=s.getPropertyValue(w),B=Number.parseFloat(j);return Number.isNaN(B)?M:B},o=w=>{let M=i?.get?.(w),E=M&&typeof M=="object"&&"value"in M?M.value:M;return typeof E=="string"?E.trim():s.getPropertyValue(w).trim()},a=(w,M=!1)=>{let E=o(w);if(!E)return M;let j=E.toLowerCase();return j==="true"||j==="1"||j==="yes"?!0:j==="false"||j==="0"||j==="no"?!1:M},l=o("--material-color"),c=l&&l!=="none"?l:s.color.trim(),u=(()=>{let w=s.fontSize||"",M=Number.parseFloat(w);return Number.isFinite(M)?M:16})(),h=(()=>{let w=s.lineHeight||"";if(!w||w==="normal")return u*1.2;let M=Number.parseFloat(w);return Number.isFinite(M)?w.endsWith("px")?M:M*u:u*1.2})(),d=(()=>{let w=s.letterSpacing||"";if(!w||w==="normal")return 0;let M=Number.parseFloat(w);return Number.isFinite(M)?M:0})(),p=o("--text-fit")||"none",g=n("--text-depth",NaN),f=Number.isFinite(g)?g:Math.max(1,u*.2),S=n("--text-bevel-size",0),y=n("--text-bevel-thickness",0),b=n("--text-bevel-offset",0),v=n("--text-bevel-steps",0),x=(s.textAlign||"left").toLowerCase(),T=x==="center"?"center":x==="right"||x==="end"?"right":"left",P=s.font?.trim(),O=P&&P.length>0?P:[s.fontStyle||"normal",s.fontWeight||"normal",`${s.fontSize||"16px"}/${s.lineHeight||"normal"}`,s.fontFamily||"sans-serif"].join(" ");return{translateZ:n("--translate-z",0),cssScale:n("--scale",1),rotateX:n("--rotate-x",0),rotateY:n("--rotate-y",0),rotateZ:n("--rotate-z",0),cssScaleZ:n("--scale-z",1),opacity:n("--opacity",NaN),color:c,metalness:n("--material-metalness",NaN),roughness:n("--material-roughness",NaN),emissive:o("--material-emissive"),castShadow:a("--shadow-cast",!1),receiveShadow:a("--shadow-receive",!1),fontFamily:s.fontFamily||"",fontCss:O,fontSize:u,lineHeight:h,letterSpacing:d,textAlign:T,textTransform:(s.textTransform||"").toLowerCase(),textDepth:f,textCurveSegments:n("--text-curve-segments",8),bevelEnabled:S>0||y>0,bevelSize:S,bevelThickness:y,bevelOffset:b,bevelSegments:v,textFit:p==="cover"||p==="none"?p:"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),s=Number(r?.ascender),n=Number(r?.descender);if(!Number.isFinite(i)||i<=0||!Number.isFinite(s)||!Number.isFinite(n))return null;let o=s/i*t,a=Math.abs(n)/i*t;return!Number.isFinite(o)||!Number.isFinite(a)?null:{ascent:o,descent:a}}readLayout(e,t){let r=e.__layoutCache;return r||I.layoutCache.get(e,t,i=>{let s=i.getBoundingClientRect();return{rect:s,width:s.width,height:s.height}})}};I.styleCache=new G,I.layoutCache=new G,I.geometryKeys=new WeakMap,I.fontCache=new Map,I.fontPromises=new Map,I.pendingFontObjects=new Map,I.warnedMissingFont=!1,I.warnedMissingLoader=!1;var Ve=I;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 Ve)}syncElement(e,t,r,i){let s=this.strategies.get(t.type);return s?s.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 ze=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 Be=class{constructor(e){this.easingParser=e;this.filterStates=new WeakMap;this.filterWarnings=new WeakMap}collectTargets(e,t,r,i){let s=[],n=o=>{let a=o.el;if(a){let l=this.filterStates.get(a)?.animating===!0,c=!r||!i||i.has(a)||l,u=this.readFilterChain(a,t,c);if(u&&u.length>0){let h=!r||!i||i.has(a)||l,d=this.filterStates.get(a)?.effectsKey||this.stringifyFilterChain(u);s.push({object:o,effects:u,effectsKey:d,dirty:h});return}}o.children.forEach(l=>n(l))};return e.forEach(o=>n(o)),s}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 s=nt(e);if(!s||s==="none"){if(i){if(i.animating&&i.clearOnComplete){let g=this.sampleTransition(i,t);return i.animating?g:(this.filterStates.delete(e),null)}let{duration:h,delay:d,easing:p}=this.getFilterTransition(e);if(h<=0&&i.lastDuration>0&&(h=i.lastDuration,d=i.lastDelay,p=i.lastEasing),h>0){let g=this.makeZeroChain(i.effects);return i.from=i.effects,i.to=g,i.startTime=t+d,i.duration=h,i.easing=p,i.animating=!0,i.clearOnComplete=!0,i.lastDuration=h,i.lastDelay=d,i.lastEasing=p,this.sampleTransition(i,t)}}return this.filterStates.delete(e),null}let{effects:n,warnings:o}=this.parseFilterChain(s);if(this.warnFilterIssues(e,s,o),n.length===0)return null;let a=this.filterStates.get(e);if(!a){let{duration:h,delay:d,easing:p}=this.getFilterTransition(e);if(h>0){let g=this.makeZeroChain(n),f={raw:s,effects:n,animating:!0,from:g,to:n,startTime:t+d,duration:h,easing:p,clearOnComplete:!1,lastDuration:h,lastDelay:d,lastEasing:p};return f.effectsKey=this.stringifyFilterChain(n),this.filterStates.set(e,f),this.sampleTransition(f,t)}return this.filterStates.set(e,{raw:s,effects:n,animating:!1,from:n,to:n,startTime:0,duration:0,easing:g=>g,clearOnComplete:!1,lastDuration:0,lastDelay:0,lastEasing:g=>g,effectsKey:this.stringifyFilterChain(n)}),n}if(a.raw===s){if(a.animating){let h=this.sampleTransition(a,t);return!a.animating&&a.clearOnComplete?(this.filterStates.delete(e),null):h}return a.effects}a.pendingEffects=void 0,a.pendingRaw=void 0;let{duration:l,delay:c,easing:u}=this.getFilterTransition(e);if(l<=0&&a.lastDuration>0&&(l=a.lastDuration,c=a.lastDelay,u=a.lastEasing),l>0){let h=this.canInterpolate(a.effects,n),d=a.animating?this.getCurrentChain(a,t):a.effects;if(!h&&this.isZeroChain(n))return a.pendingRaw=s,a.pendingEffects=n,a.raw=s,a.effects=d,a.from=d,a.to=this.makeZeroChain(d),a.startTime=t+c,a.duration=l,a.easing=u,a.animating=!0,a.clearOnComplete=!1,a.lastDuration=l,a.lastDelay=c,a.lastEasing=u,a.effectsKey=this.stringifyFilterChain(n),this.sampleTransition(a,t);let p=h?d:this.makeZeroChain(n);return a.raw=s,a.effects=n,a.from=p,a.to=n,a.startTime=t+c,a.duration=l,a.easing=u,a.animating=!0,a.clearOnComplete=!1,a.lastDuration=l,a.lastDelay=c,a.lastEasing=u,a.effectsKey=this.stringifyFilterChain(n),this.sampleTransition(a,t)}return a.raw=s,a.effects=n,a.animating=!1,a.clearOnComplete=!1,a.effectsKey=this.stringifyFilterChain(n),n}warnFilterIssues(e,t,r){r.length===0||this.filterWarnings.get(e)===t||(r.forEach(s=>console.warn(s,e)),this.filterWarnings.set(e,t))}parseFilterChain(e){let t=[],r=[],i=h=>{let p=h.trim().toLowerCase().match(/^(-?\d*\.?\d+)(px)?$/);if(!p)return null;let g=Number.parseFloat(p[1]);return Number.isFinite(g)?g:null},s=h=>{let d=h.trim().toLowerCase();if(!d)return null;if(d.endsWith("%")){let g=Number.parseFloat(d.slice(0,-1));return Number.isFinite(g)?g/100:null}let p=Number.parseFloat(d);return Number.isFinite(p)?p:null},n=h=>{let d=h.trim().toLowerCase();if(!d)return null;if(d.endsWith("rad")){let f=Number.parseFloat(d.slice(0,-3));return Number.isFinite(f)?f:null}let p=d.endsWith("deg")?d.slice(0,-3):d,g=Number.parseFloat(p);return Number.isFinite(g)?g*Math.PI/180:null},o=h=>{let d=h.split(",").map(f=>f.trim()),p=i(d[0]||"");if(p===null)return null;let g=d[1]?s(d[1]):null;return{intensity:Math.max(0,p),threshold:g===null?.8:Math.max(0,Math.min(1,g))}},a=(h,d,p=!1)=>{let g=i(h);return g===null?(t.push(`[String3D] Invalid ${d} value "${h}".`),null):!p&&g<=0?(t.push(`[String3D] ${d} must be > 0.`),null):g},l=(h,d)=>{let p=s(h);return p===null?(t.push(`[String3D] Invalid ${d} value "${h}".`),null):p},c=/([a-zA-Z-]+)\(([^)]*)\)/g,u;for(;u=c.exec(e);){let h=u[1].toLowerCase(),d=(u[2]||"").trim();if(h==="blur"){let p=a(d,"blur",!0);p!==null&&r.push({type:"blur",amount:p})}else if(h==="pixel"||h==="pixelate"){let p=a(d,"pixel",!0);p!==null&&r.push({type:"pixel",size:p})}else if(h==="bloom"){let p=o(d);p?r.push({type:"bloom",...p}):t.push(`[String3D] Invalid bloom value "${d}".`)}else if(h==="brightness"){let p=l(d,"brightness");p!==null&&r.push({type:"brightness",amount:Math.max(0,p)})}else if(h==="contrast"){let p=l(d,"contrast");p!==null&&r.push({type:"contrast",amount:Math.max(0,p)})}else if(h==="saturate"){let p=l(d,"saturate");p!==null&&r.push({type:"saturate",amount:Math.max(0,p)})}else if(h==="grayscale"){let p=l(d,"grayscale");p!==null&&r.push({type:"grayscale",amount:Math.max(0,Math.min(1,p))})}else if(h==="sepia"){let p=l(d,"sepia");p!==null&&r.push({type:"sepia",amount:Math.max(0,Math.min(1,p))})}else if(h==="invert"){let p=l(d,"invert");p!==null&&r.push({type:"invert",amount:Math.max(0,Math.min(1,p))})}else if(h==="hue-rotate"){let p=n(d);p!==null?r.push({type:"hue-rotate",angle:p}):t.push(`[String3D] Invalid hue-rotate value "${d}".`)}else if(h){let p=ne.get(h);if(p){let g=p.parse?p.parse(d):{};g===null?t.push(`[String3D] Invalid custom filter "${h}" args "${d}".`):r.push({type:"custom",name:h,uniforms:g})}else t.push(`[String3D] Unknown filter "${h}".`)}}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),s=this.splitTransitionList(t.transitionDelay),n=this.splitTransitionList(t.transitionTimingFunction),o=this.findTransitionIndex(r,"--filter");if(o===-1){let u=this.parseTransitionShorthand(t.transition),h=u.get("--filter")||u.get("all");return h||{duration:0,delay:0,easing:d=>d}}let a=this.parseTime(i[o]||i[i.length-1]||"0s"),l=this.parseTime(s[o]||s[s.length-1]||"0s"),c=n[o]||n[n.length-1]||"linear";return{duration:a,delay:l,easing:this.parseEasing(c)}}splitTransitionList(e){let t=[],r="",i=0;for(let s=0;s<e.length;s+=1){let n=e[s];n==="("&&(i+=1),n===")"&&(i=Math.max(0,i-1)),n===","&&i===0?(t.push(r.trim()),r=""):r+=n}return r.trim()&&t.push(r.trim()),t.length>0?t:["all"]}findTransitionIndex(e,t){let r=e.map(s=>s.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 s=i.trim().split(/\s+(?![^()]*\))/g),n="",o="",a="",l="";s.forEach(c=>{let u=c.toLowerCase();u.endsWith("ms")||u.endsWith("s")||/^[0-9.]+$/.test(u)?o?a||(a=u):o=u:u.startsWith("cubic-bezier")||u.startsWith("steps")||u==="linear"||u==="ease"||u==="ease-in"||u==="ease-out"||u==="ease-in-out"?l=c:n||(n=c)}),n&&t.set(n.trim().toLowerCase(),{duration:this.parseTime(o||"0s"),delay:this.parseTime(a||"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 s=t[i];if(r.type!==s.type)return!1;if(r.type==="custom"&&s.type==="custom"){if(r.name!==s.name)return!1;let n=Object.keys(r.uniforms||{}),o=Object.keys(s.uniforms||{});return n.length!==o.length?!1:n.every(a=>a in(s.uniforms||{})&&this.isNumeric(r.uniforms?.[a]))}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,s])=>{r[i]=this.isNumeric(s)?0:s}),{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),s=Math.min(1,Math.max(0,r/i)),n=e.easing(s),o=this.interpolateChain(e.from,e.to,n);return s>=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),s=Math.min(1,Math.max(0,r/i)),n=e.easing(s);return this.interpolateChain(e.from,e.to,n)}interpolateChain(e,t,r){return this.canInterpolate(e,t)?e.map((i,s)=>this.interpolateEffect(i,t[s],r)):t}interpolateEffect(e,t,r){let i=(s,n)=>s+(n-s)*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 s={};return Object.entries(t.uniforms||{}).forEach(([n,o])=>{let a=e.uniforms?.[n];this.isNumeric(a)&&this.isNumeric(o)?s[n]=i(a,o):s[n]=o}),{type:"custom",name:t.name,uniforms:s}}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(s=>`${s}=${r.uniforms[s]}`).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 he=class he extends Le{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 ze(["style","class","string-3d","string-3d-model-fit","string-3d-model-scale"]),this.filterController=new Be(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){he.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,s){super.initializeObject(t,r,i,s),r.setProperty("parentId",null);let n=i.parentElement?.closest('[string-3d="group"]');if(n){let o=n.getAttribute("string-id");o&&(r.setProperty("parentId",o),r.setProperty("parent",n))}}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(),!he.provider){console.error("[String3D] No provider set. Call String3D.setProvider() before use.");return}this.engine=he.provider.getEngine(),this.canvasContainer=this.createOrGetContainer(),this.registerTypedProperties(),this.injectCSS(),this.useDirtySync=!!this.options.useDirtySync,this.useDirtySync&&this.dirtySyncManager.enable(),this.renderer=new fe(this.canvasContainer,this.engine),this.renderer.attach(),this.camera=new ge(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: ${he.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(n=>{this.syncRecursive(n.el,n,{scale:1},i,r)});let s=this.filterController.collectTargets(this.scene.rootObjects,performance.now(),this.useDirtySync,r);this.renderer.render(this.scene,this.camera,s),this.useDirtySync&&this.dirtySyncManager.clearDirty()}batchReadLayouts(t,r,i){let s=n=>{if(n.el&&(r||!i||i.has(n.el))){let a=n.el.getBoundingClientRect(),l=n.el.offsetWidth||a.width,c=n.el.offsetHeight||a.height;n.el.__layoutCache={rect:a,width:l,height:c}}n.children.forEach(s)};t.forEach(s)}syncRecursive(t,r,i,s,n){if(!this.synchronizer||!t)return;let o=r.type==="particles"||r.type==="text"||s||!n||n.has(t),a=i;if(o){let c=this.synchronizer.syncElement(t,r,i,{dirtySet:n,forceSync:s});c&&typeof c.scale=="number"&&(this.lastSyncData.set(r,c),a=c)}else{let c=this.lastSyncData.get(r);c&&(a=c)}let l=s||o;r.children.forEach(c=>this.syncRecursive(c.el,c,a,l,n))}injectCSS(){if(document.getElementById("string-3d-styles"))return;let t=document.createElement("style");t.id="string-3d-styles",t.textContent=`
|
|
135
117
|
@property --translate-x { syntax: "<number>"; inherits: false; initial-value: 0; }
|
|
136
118
|
@property --translate-y { syntax: "<number>"; inherits: false; initial-value: 0; }
|
|
137
119
|
@property --translate-z { syntax: "<number>"; inherits: false; initial-value: 0; }
|
|
@@ -143,11 +125,87 @@ self.onmessage = async (event) => {
|
|
|
143
125
|
@property --scale-y { syntax: "<number>"; inherits: false; initial-value: 1; }
|
|
144
126
|
@property --scale-z { syntax: "<number>"; inherits: false; initial-value: 1; }
|
|
145
127
|
@property --opacity { syntax: "<number>"; inherits: false; initial-value: 1; }
|
|
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; }
|
|
146
185
|
|
|
147
|
-
[string-3d] {
|
|
186
|
+
:where([string-3d]) {
|
|
148
187
|
--translate-x: 0; --translate-y: 0; --translate-z: 0;
|
|
149
188
|
--rotate-x: 0; --rotate-y: 0; --rotate-z: 0;
|
|
150
|
-
--scale: 1; --scale-x: 1; --scale-y: 1; --scale-z: 1
|
|
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;
|
|
151
209
|
transform-style: preserve-3d;
|
|
152
210
|
}
|
|
153
211
|
|
|
@@ -159,5 +217,58 @@ self.onmessage = async (event) => {
|
|
|
159
217
|
rotateZ(calc(var(--rotate-z) * 1deg))
|
|
160
218
|
scale3d(calc(var(--scale) * var(--scale-x)), calc(var(--scale) * var(--scale-y)), calc(var(--scale) * var(--scale-z)));
|
|
161
219
|
}
|
|
162
|
-
`,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"}
|
|
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:s})=>{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:s})}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()}};he.provider=null;var _e=he;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 Xe(e,t,r)}buildUniforms(e,t){let r={};if(e.uniforms)for(let[i,s]of Object.entries(e.uniforms)){let n=t?.[i]??s.value;n=this.convertUniformValue(s.type,n),r[i]={value:n}}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 s=new i({transparent:e.properties?.transparent??!1});if(e.injections&&e.injections.length>0){let n=Ke(e.injections);s.onBeforeCompile=o=>{Object.assign(o.uniforms,t),o.vertexShader=this.injectVertexShader(o.vertexShader,n,t),o.fragmentShader=this.injectFragmentShader(o.fragmentShader,n,t),s.userData.shader=o}}return s.userData.customUniforms=t,s.userData.definition=e,s}injectVertexShader(e,t,r){let i=e,s=t.get("vertex_pars");s&&(i=i.replace("#include <common>",`#include <common>
|
|
221
|
+
${s}`));let n=t.get("vertex_header");if(n){let l=this.generateUniformDeclarations(r);i=i.replace("void main() {",`${l}
|
|
222
|
+
${n}
|
|
223
|
+
void main() {`)}let o=t.get("vertex_transform");o&&(i=i.replace("#include <begin_vertex>",`#include <begin_vertex>
|
|
224
|
+
${o}`));let a=t.get("vertex_output");return a&&(i=i.replace("#include <project_vertex>",`${a}
|
|
225
|
+
#include <project_vertex>`)),i}injectFragmentShader(e,t,r){let i=e,s=t.get("fragment_pars");s&&(i=i.replace("#include <common>",`#include <common>
|
|
226
|
+
${s}`));let n=t.get("fragment_header");if(n){let u=this.generateUniformDeclarations(r);i=i.replace("void main() {",`${u}
|
|
227
|
+
${n}
|
|
228
|
+
void main() {`)}let o=t.get("fragment_color");o&&(i=i.replace("#include <color_fragment>",`#include <color_fragment>
|
|
229
|
+
${o}`));let a=t.get("fragment_normal");a&&(i=i.replace("#include <normal_fragment_maps>",`#include <normal_fragment_maps>
|
|
230
|
+
${a}`));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 s=this.inferGLSLType(i.value);t.push(`uniform ${s} ${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,s=e.userData?.customUniforms;if(i?.uniforms)for(let[n,o]of Object.entries(r)){let a=t.uniforms?.[n];a&&i.uniforms[n]&&(i.uniforms[n].value=this.convertUniformValue(a.type,o))}else if(s)for(let[n,o]of Object.entries(r)){let a=t.uniforms?.[n];a&&s[n]&&(s[n].value=this.convertUniformValue(a.type,o))}if(e.uniforms)for(let[n,o]of Object.entries(r)){let a=t.uniforms?.[n];a&&e.uniforms[n]&&(e.uniforms[n].value=this.convertUniformValue(a.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 Pe=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,s=.1,n=1e4){return new this.THREE.OrthographicCamera(e,t,r,i,s,n)}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,s=0,n=1){return new this.THREE.SpotLight(e,t,r,i,s,n)}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),s;return i?s=this.loadFontWithConverter(t):s=this.loadFontWithLoader(t),this.fontPromiseCache.set(t,s),s}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,s=>{this.fontCache.set(e,s),i(s)},void 0,s=>{console.warn("[String3D] Font loading error:",s),i(null)})})}createFontFromData(e){return{data:e,generateShapes:(r,i)=>this.generateShapesFromFontData(e,r,i)}}generateShapesFromFontData(e,t,r){let i=[],s=r/e.resolution,n=t[0];if(!n)return i;let o=e.glyphs[n];if(!o||!o.o)return i;let a=this.parseOutlineToShapes(o.o,s,0);return i.push(...a),i}parseOutlineToShapes(e,t,r=0){if(!e)return[];let i=new this.THREE.ShapePath,s=e.split(" "),n=0;for(;n<s.length;)switch(s[n]){case"m":{let l=parseFloat(s[n+1])*t+r,c=-parseFloat(s[n+2])*t;i.moveTo(l,c),n+=3}break;case"l":{let l=parseFloat(s[n+1])*t+r,c=-parseFloat(s[n+2])*t;i.lineTo(l,c),n+=3}break;case"q":{let l=parseFloat(s[n+3])*t+r,c=-parseFloat(s[n+4])*t;i.quadraticCurveTo(parseFloat(s[n+1])*t+r,-parseFloat(s[n+2])*t,l,c),n+=5}break;case"b":{let l=parseFloat(s[n+5])*t+r,c=-parseFloat(s[n+6])*t;i.bezierCurveTo(parseFloat(s[n+1])*t+r,-parseFloat(s[n+2])*t,parseFloat(s[n+3])*t+r,-parseFloat(s[n+4])*t,l,c),n+=7}break;case"z":typeof i.closePath=="function"?i.closePath():i.currentPath&&typeof i.currentPath.closePath=="function"&&i.currentPath.closePath(),n+=1;break;default:n++;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 s=e.curves.length-1;s>=0;s--){let n=e.curves[s];n.isLineCurve||n.type==="LineCurve"||n.type==="LineCurve3"?t.lineTo(n.v1.x,n.v1.y):n.isQuadraticBezierCurve||n.type==="QuadraticBezierCurve"||n.type==="QuadraticBezierCurve3"?t.quadraticCurveTo(n.v1.x,n.v1.y,n.v0.x,n.v0.y):(n.isCubicBezierCurve||n.type==="CubicBezierCurve"||n.type==="CubicBezierCurve3")&&t.bezierCurveTo(n.v2.x,n.v2.y,n.v1.x,n.v1.y,n.v0.x,n.v0.y)}return t}createTextGeometry(e,t,r){if(!e||!t)return null;let i=Math.max(.001,r.size||16),s=Math.max(0,r.height||0),n=Math.max(.001,r.lineHeight||i*1.2),o=Number.isFinite(r.letterSpacing)?r.letterSpacing:0,a=r.align||"left",l=!!r.bevelEnabled,c=Math.max(0,r.bevelThickness||0),u=Math.max(0,r.bevelSize||0),h=r.bevelOffset||0,d=Math.max(0,r.bevelSegments||0),p=Math.max(1,Math.round(r.curveSegments||8)),g=r.useCanvasText&&typeof r.fontCss=="string"&&r.fontCss.length>0;if(g&&typeof document<"u"&&document.fonts){let v=r.fontCss;if(!document.fonts.check(v,e))return document.fonts.load(v,e).catch(()=>null),null}let f=String(e).split(/\r?\n/),S=[];f.forEach((v,x)=>{});let y=g?this.measureFontMetrics(r.fontCss):null;if(r.layout?r.layout.forEach(v=>{let x=g?this.buildGlyphShapesFromCanvas(v.char,r.fontCss,r.pixelRatio):[],T=g?x:this.buildLineShapes(v.char,t,i,0).shapes,P=v.x,O=g?Number.isFinite(v.height)&&y?Math.max(0,v.height-y.descent):y?.ascent||0:0,w=g?-(v.y+O):-v.y;T.forEach(M=>{let E=this.translateShape(M,P,w);v.scale&&v.scale!==1&&(E=this.scaleShape(E,v.scale)),S.push(E)})}):f.forEach((v,x)=>{let{shapes:T,width:P}=this.buildLineShapes(v,t,i,o),O=0;a==="center"?O=-P*.5:a==="right"&&(O=-P);let w=-x*n;T.forEach(M=>{S.push(this.translateShape(M,O,w))})}),!S.length)return null;let b=new this.THREE.ExtrudeGeometry(S,{depth:s,curveSegments:p,bevelEnabled:l,bevelThickness:c,bevelSize:u,bevelOffset:h,bevelSegments:d});return b.computeBoundingBox(),b}buildLineShapes(e,t,r,i){let s=[],n=0,o=Array.from(e),a=[];return o.forEach((l,c)=>{t.generateShapes(l,r).forEach(d=>{let p=this.translateShape(d,n,0);s.push(p)});let h=this.getGlyphAdvance(t,l,r);a.length<10&&a.push({char:l,advance:h}),n+=h,i!==0&&c<o.length-1&&(n+=i)}),{shapes:s,width:n}}getGlyphAdvance(e,t,r){let i=e?.data,s=i?.glyphs||{},o=(s[t]||s[t.charCodeAt(0)]||s["?"])?.ha??i?.ha,a=i?.resolution||1e3;return typeof o=="number"?o/a*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:s}=e.extractPoints(12),n=a=>new this.THREE.Vector2((a.x||0)+t,(a.y||0)+r),o=new this.THREE.Shape(i.map(n));return Array.isArray(s)&&s.forEach(a=>{let l=new this.THREE.Path;l.setFromPoints(a.map(n)),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),s=o=>new this.THREE.Vector2((o.x||0)*t,(o.y||0)*t),n=new this.THREE.Shape(r.map(s));return Array.isArray(i)&&i.forEach(o=>{let a=new this.THREE.Path;a.setFromPoints(o.map(s)),n.holes.push(a)}),n}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,s=document.createElement("canvas"),n=s.getContext("2d",{willReadFrequently:!0});if(!n)return[];n.font=t,n.textBaseline="alphabetic",n.textAlign="left";let o=n.measureText(e),a=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)),u=Math.max(1,Math.ceil(((o.actualBoundingBoxAscent||0)+(o.actualBoundingBoxDescent||0))*i)),h=Math.ceil(2*i);s.width=c+h*2,s.height=u+h*2,n.clearRect(0,0,s.width,s.height),n.font=t,n.textBaseline="alphabetic",n.textAlign="left",n.fillStyle="#000";let d=h+a,p=h+l;n.fillText(e,d,p);let g=n.getImageData(0,0,s.width,s.height),f=this.traceContoursFromAlpha(g.data,s.width,s.height,16);if(!f.length)return[];let S=1/i;return this.contoursToShapes(f,S,h+a,h+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 s=i.measureText("Mg"),n=Number.isFinite(s.actualBoundingBoxAscent)?s.actualBoundingBoxAscent:0,o=Number.isFinite(s.actualBoundingBoxDescent)?s.actualBoundingBoxDescent:0,a={ascent:n,descent:o};return this.fontMetricsCache.set(e,a),a}traceContoursFromAlpha(e,t,r,i){let s=(h,d)=>{if(h<0||d<0||h>=t||d>=r)return!1;let p=(d*t+h)*4+3;return e[p]>=i},n=new Map,o=[],a=(h,d,p,g)=>{let f=`${h},${d}`,S=`${p},${g}`,y=n.get(f);y||(y=[],n.set(f,y)),y.push(S),o.push(`${f}|${S}`)};for(let h=0;h<r;h+=1)for(let d=0;d<t;d+=1)s(d,h)&&(s(d,h-1)||a(d+1,h,d,h),s(d+1,h)||a(d+1,h+1,d+1,h),s(d,h+1)||a(d,h+1,d+1,h+1),s(d-1,h)||a(d,h,d,h+1));let l=new Set,c=[],u=h=>{let[d,p]=h.split(",");return{x:Number(d),y:Number(p)}};for(let h of o){if(l.has(h))continue;let[d,p]=h.split("|"),g=[];l.add(h),g.push(u(d));let f=p,S=0;for(;f!==d&&S<t*r*4;){g.push(u(f));let y=n.get(f);if(!y||y.length===0)break;let b=null;for(let v of y){let x=`${f}|${v}`;if(!l.has(x)){b=v,l.add(x);break}}if(!b)break;f=b,S+=1}if(g.length>=3){let y=this.simplifyCollinear(g),b=this.simplifyRdp(y,.75);b.length>=3&&c.push(b)}}return c}simplifyCollinear(e){if(e.length<4)return e;let t=[],r=e.length;for(let i=0;i<r;i+=1){let s=e[(i-1+r)%r],n=e[i],o=e[(i+1)%r],a=n.x-s.x,l=n.y-s.y,c=o.x-n.x,u=o.y-n.y,h=a*u-l*c;Math.abs(h)>0&&t.push(n)}return t}simplifyRdp(e,t){if(e.length<3)return e;let r=e.length-1,i=0,s=0,n=e[0],o=e[r];for(let c=1;c<r;c+=1){let u=this.pointLineDistance(e[c],n,o);u>i&&(i=u,s=c)}if(i<=t)return[n,o];let a=this.simplifyRdp(e.slice(0,s+1),t),l=this.simplifyRdp(e.slice(s),t);return a.slice(0,-1).concat(l)}pointLineDistance(e,t,r){let i=r.x-t.x,s=r.y-t.y;if(i===0&&s===0){let h=e.x-t.x,d=e.y-t.y;return Math.sqrt(h*h+d*d)}let n=((e.x-t.x)*i+(e.y-t.y)*s)/(i*i+s*s),o=Math.max(0,Math.min(1,n)),a=t.x+o*i,l=t.y+o*s,c=e.x-a,u=e.y-l;return Math.sqrt(c*c+u*u)}contoursToShapes(e,t,r=0,i=0){if(!e.length)return[];let s=[],n=[],o=c=>{let u=0;for(let h=0;h<c.length;h+=1){let d=c[h],p=c[(h+1)%c.length];u+=d.x*p.y-p.x*d.y}return u*.5},a=c=>c.map(u=>({x:(u.x-r)*t,y:-(u.y-i)*t}));for(let c of e){if(c.length<3)continue;let u=a(c);if(o(u)>=0){let d=new this.THREE.Shape;d.moveTo(u[0].x,u[0].y);for(let p=1;p<u.length;p+=1)d.lineTo(u[p].x,u[p].y);typeof d.closePath=="function"&&d.closePath(),s.push({shape:d,points:u})}else{let d=new this.THREE.Path;d.moveTo(u[0].x,u[0].y);for(let p=1;p<u.length;p+=1)d.lineTo(u[p].x,u[p].y);typeof d.closePath=="function"&&d.closePath(),n.push({path:d,point:u[0]})}}let l=(c,u)=>{let h=!1;for(let d=0,p=u.length-1;d<u.length;p=d++){let g=u[d].x,f=u[d].y,S=u[p].x,y=u[p].y;f>c.y!=y>c.y&&c.x<(S-g)*(c.y-f)/(y-f+Number.EPSILON)+g&&(h=!h)}return h};for(let c of n){let u=!1;for(let h of s)if(l(c.point,h.points)){h.shape.holes.push(c.path),u=!0;break}!u&&s.length>0&&s[0].shape.holes.push(c.path)}return s.map(c=>c.shape)}resolveParticleModelGeometry(e,t,r){let i=e.trim();if(!i||i==="none")return Promise.resolve(null);let s=t&&t!=="none"?t:this.loaders.gltf?"gltf":Object.keys(this.loaders)[0];if(!s)return console.warn("[String3D] No model loader registered for particle models."),Promise.resolve(null);let n=(r||"").trim(),o=`${s}|${i}|${n}`;if(this.particleModelCache.has(o))return Promise.resolve(this.particleModelCache.get(o));let a=this.particleModelPromiseCache.get(o);if(a)return a;let l=new Promise(c=>{let u=null;try{u=this.createModelLoader(s)}catch(h){console.warn("[String3D] Failed to create model loader:",h),c(null);return}u.load(i,h=>{let d=h?.scene||h?.object||h;if(!d){c(null);return}let p=null;if(n){if(d.getObjectByName){let f=d.getObjectByName(n);f?.isMesh&&(p=f)}!p&&d.traverse&&d.traverse(f=>{p||f?.isMesh&&f?.name===n&&(p=f)})}p||(d.isMesh?p=d:d.traverse&&d.traverse(f=>{!p&&f?.isMesh&&(p=f)}));let g=p?.geometry||null;if(!g){c(null);return}this.particleModelCache.set(o,g),c(g)},void 0,h=>{console.warn("[String3D] Particle model loading error:",h),c(null)})});return this.particleModelPromiseCache.set(o,l),l}createParticleSystem(e){let t=this.THREE,r=this,i=n=>{let o=Math.max(1,n|0);return()=>(o^=o<<13,o^=o>>17,o^=o<<5,(o>>>0)%1e5/1e5)};class s extends t.Object3D{constructor(a){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={...a},this.refreshModelGeometry(),this.rebuild()}setConfig(a){let l=this.cfg;this.cfg={...a};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 h=this.points.material.uniforms;h&&(h.uOpacity&&(h.uOpacity.value=this.cfg.opacity),h.uSize&&(h.uSize.value=this.cfg.size),h.uSizeVar&&(h.uSizeVar.value=this.cfg.particleSizeVariation),h.uPointSize&&(h.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(a){a<=0||(this.elapsed+=a,this.cfg.mode==="emitter"?this.updateEmitter(a):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 a=Math.max(1,this.cfg.count);this.positions=new Float32Array(a*3),this.velocities=new Float32Array(a*3),this.life=new Float32Array(a),this.colors=new Float32Array(a*3),this.sizeFactors=new Float32Array(a);let l=1e6;for(let h=0;h<a;h+=1){let d=h*3;this.positions[d]=l,this.positions[d+1]=l,this.positions[d+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 u=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,u),this.defaultEmitterMaterial=u,this.add(this.points)}buildInstanced(){let a=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 u=new t.MeshStandardMaterial({color:new t.Color(this.cfg.color),transparent:this.cfg.opacity<1,opacity:this.cfg.opacity});this.defaultInstancedMaterial=u,this.instanced=new t.InstancedMesh(c,u,a),this.basePositions=new Float32Array(a*3),this.baseScales=new Float32Array(a),this.baseJitter=new Float32Array(a*3),this.basePhase=new Float32Array(a),this.fillBasePositions(a),this.applyInstancedTransforms(0),this.add(this.instanced)}setMaterial(a,l={}){let c=l.points??!0;(l.meshes??!0)&&(this.materialOverride=a),c&&(this.materialOverrideForPoints=a),this.applyMaterialOverrides()}updateEmitter(a){let l=this.cfg.count,c=this.normalize(this.cfg.particleDirection),u=this.cfg.particleGravity,h=Math.max(0,Math.min(1,this.cfg.particleDrag)),p=this.cfg.emitRate*a+this.emitRemainder,g=Math.floor(p);this.emitRemainder=p-g;let f=!1,S=1e6;for(let y=0;y<g;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]-=a,this.life[y]<=0){this.life[y]=0;let v=y*3;this.positions[v]=S,this.positions[v+1]=S,this.positions[v+2]=S,this.colors[v]=0,this.colors[v+1]=0,this.colors[v+2]=0,f=!0;continue}let b=y*3;this.velocities[b]+=u[0]*a,this.velocities[b+1]+=u[1]*a,this.velocities[b+2]+=u[2]*a,this.velocities[b]*=1-h*a,this.velocities[b+1]*=1-h*a,this.velocities[b+2]*=1-h*a,this.positions[b]+=this.velocities[b]*a,this.positions[b+1]+=this.velocities[b+1]*a,this.positions[b+2]+=this.velocities[b+2]*a}this.points&&(this.points.geometry.attributes.position.needsUpdate=!0,f&&(this.points.geometry.attributes.color.needsUpdate=!0))}spawnParticle(a){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 u=this.randomInSphere(this.cfg.spread),h=this.cfg.particleSpeed*(1-this.cfg.particleSizeVariation+this.rng()*this.cfg.particleSizeVariation),d=[a[0]*h+(this.rng()-.5)*h*.2,a[1]*h+(this.rng()-.5)*h*.2,a[2]*h+(this.rng()-.5)*h*.2],p=c*3;this.positions.set(u,p),this.velocities.set(d,p),this.life[c]=this.cfg.particleLife,this.sizeFactors[c]=this.rng();let g=new t.Color(this.cfg.color);this.cfg.particleColorVariation>0&&g.offsetHSL((this.rng()-.5)*this.cfg.particleColorVariation,0,0),this.colors[p]=g.r,this.colors[p+1]=g.g,this.colors[p+2]=g.b,this.points&&(this.points.geometry.attributes.color.needsUpdate=!0,this.points.geometry.attributes.sizeFactor.needsUpdate=!0)}updateInstanced(a){this.applyInstancedTransforms(a),this.instanced&&(this.instanced.instanceMatrix.needsUpdate=!0)}applyInstancedTransforms(a){if(!this.instanced)return;let l=this.cfg.count,c=this.cfg.instanceJitter,u=this.cfg.instanceFlow,h=Math.max(0,this.cfg.instanceDisperse),d=Math.max(0,this.cfg.instanceDisperseScatter),p=this.cfg.instanceDisperseScatterX>0?this.cfg.instanceDisperseScatterX:d,g=this.cfg.instanceDisperseScatterY>0?this.cfg.instanceDisperseScatterY:d,f=this.cfg.instanceDisperseScatterZ>0?this.cfg.instanceDisperseScatterZ:d,S=this.cfg.instanceRotationSpeed,y=new t.Object3D;for(let b=0;b<l;b+=1){let v=b*3,x=this.basePositions[v],T=this.basePositions[v+1],P=this.basePositions[v+2],O=this.basePhase[b],w=Math.sin((T+a*1.4)*.7+O)*u*this.cfg.spread,M=Math.cos((x-a*1.1)*.6+O)*u*this.cfg.spread,E=Math.sin((P+a*1.2)*.8+O)*u*this.cfg.spread,j=Math.sin(a*2.1+O+this.baseJitter[v]*2.5)*c,B=Math.cos(a*1.7+O+this.baseJitter[v+1]*2.5)*c,H=Math.sin(a*1.9+O+this.baseJitter[v+2]*2.5)*c,N=1+h,V=this.baseJitter[v],D=this.baseJitter[v+1],F=this.baseJitter[v+2],L=Math.sqrt(V*V+D*D+F*F)||1,z=h*this.cfg.spread,_=V/L*p*z,R=D/L*g*z,$=F/L*f*z;y.position.set(x*N+_+w+j,T*N+R+M+B,P*N+$+E+H),y.rotation.set(this.baseJitter[v]*.5,a*S+b*.1,this.baseJitter[v+2]*.5);let A=this.baseScales[b]*this.cfg.size;y.scale.set(A,A,A),y.updateMatrix(),this.instanced.setMatrixAt(b,y.matrix)}}applyMaterialOverrides(){if(this.points){let a=this.materialOverrideForPoints||this.defaultEmitterMaterial;a&&this.points.material!==a&&(this.points.material=a,this.ensurePointMaterial(a))}if(this.instanced){let a=this.materialOverride||this.defaultInstancedMaterial;a&&this.instanced.material!==a&&(this.instanced.material=a)}}ensurePointMaterial(a){a?.isShaderMaterial&&(a.uniforms||(a.uniforms={}),a.uniforms.uPointSize||(a.uniforms.uPointSize={value:this.cfg.size}),a.uniforms.uOpacity||(a.uniforms.uOpacity={value:this.cfg.opacity}),a.vertexShader.includes("gl_PointSize")||(a.vertexShader.includes("uPointSize")||(a.vertexShader=`uniform float uPointSize;
|
|
273
|
+
${a.vertexShader}`),a.vertexShader=a.vertexShader.replace(/void\\s+main\\s*\\(\\)\\s*\\{/,"void main() {\\n gl_PointSize = uPointSize;"),a.needsUpdate=!0))}refreshModelGeometry(){if(this.cfg.particleShape!=="model"){this.modelGeometry=null,this.modelKey="";return}let a=this.cfg.particleModelUrl?.trim();if(!a||a==="none"){this.modelGeometry=null,this.modelKey="";return}let l=`${this.cfg.particleModelLoader}|${a}|${this.cfg.particleModelNode}`;this.modelKey===l&&this.modelGeometry||(this.modelKey=l,r.resolveParticleModelGeometry(a,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 a=this.cfg.instanceModelUrl?.trim();if(!a||a==="none"){this.distributionGeometry=null,this.distributionKey="";return}let l=`${this.cfg.instanceModelLoader}|${a}|${this.cfg.instanceModelNode}`;this.distributionKey===l&&this.distributionGeometry||(this.distributionKey=l,r.resolveParticleModelGeometry(a,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(a){if(this.cfg.instanceShape==="model"&&this.distributionGeometry)this.fillFromModel(a,this.distributionGeometry);else for(let c=0;c<a;c+=1){let u=this.cfg.instanceShape==="box"?this.randomInBox(this.cfg.spread):this.randomInSphere(this.cfg.spread);this.basePositions.set(u,c*3)}for(let c=0;c<a;c+=1){let u=c*3;this.baseJitter[u]=this.rng()*2-1,this.baseJitter[u+1]=this.rng()*2-1,this.baseJitter[u+2]=this.rng()*2-1,this.basePhase[c]=this.rng()*Math.PI*2;let h=this.cfg.instanceScale*(1-this.cfg.instanceScaleVariation+this.rng()*this.cfg.instanceScaleVariation);this.baseScales[c]=h}}fillFromModel(a,l){let c=l?.attributes?.position;if(!c?.array||c.itemSize<3){for(let D=0;D<a;D+=1){let F=this.randomInSphere(this.cfg.spread);this.basePositions.set(F,D*3)}return}let u=c.array,h=c.itemSize,d=Math.floor(u.length/h);if(d<=0)return;let p=l?.index?.array,g=Math.floor(p?p.length/3:d/3);if(g<=0)return;let f=1/0,S=1/0,y=1/0,b=-1/0,v=-1/0,x=-1/0;for(let D=0;D<d;D+=1){let F=D*h,L=u[F],z=u[F+1],_=u[F+2];f=Math.min(f,L),S=Math.min(S,z),y=Math.min(y,_),b=Math.max(b,L),v=Math.max(v,z),x=Math.max(x,_)}let T=Math.max(1e-6,b-f),P=Math.max(1e-6,v-S),O=Math.max(1e-6,x-y),w=Math.max(T,P,O),M=this.cfg.spread*2,E=M>0?M/w:1,j=(f+b)*.5,B=(S+v)*.5,H=(y+x)*.5,N=new Float32Array(g),V=0;for(let D=0;D<g;D+=1){let F=D*3,L=p?p[F]:F,z=p?p[F+1]:F+1,_=p?p[F+2]:F+2,R=L*h,$=z*h,A=_*h,Q=u[R],te=u[R+1],re=u[R+2],Te=u[$],we=u[$+1],Ee=u[$+2],oe=u[A],De=u[A+1],Ce=u[A+2],ue=Te-Q,Y=we-te,U=Ee-re,ie=oe-Q,ce=De-te,se=Ce-re,de=Y*se-U*ce,pe=U*ie-ue*se,me=ue*ce-Y*ie,We=Math.sqrt(de*de+pe*pe+me*me)*.5;V+=We,N[D]=V}if(V<=0){for(let D=0;D<a;D+=1){let F=this.randomInSphere(this.cfg.spread);this.basePositions.set(F,D*3)}return}for(let D=0;D<a;D+=1){let F=this.rng()*V,L=0,z=g-1;for(;L<z;){let $e=Math.floor((L+z)/2);F<=N[$e]?z=$e:L=$e+1}let _=L*3,R=p?p[_]:_,$=p?p[_+1]:_+1,A=p?p[_+2]:_+2,Q=R*h,te=$*h,re=A*h,Te=u[Q],we=u[Q+1],Ee=u[Q+2],oe=u[te],De=u[te+1],Ce=u[te+2],ue=u[re],Y=u[re+1],U=u[re+2],ie=this.rng(),ce=this.rng(),se=Math.sqrt(ie),de=1-se,pe=se*(1-ce),me=se*ce,We=(Te*de+oe*pe+ue*me-j)*E,ot=(we*de+De*pe+Y*me-B)*E,lt=(Ee*de+Ce*pe+U*me-H)*E;this.basePositions[D*3]=We,this.basePositions[D*3+1]=ot,this.basePositions[D*3+2]=lt}}resetEmitter(){if(!this.points)return;let a=1e6;for(let l=0;l<this.positions.length;l+=3)this.positions[l]=a,this.positions[l+1]=a,this.positions[l+2]=a;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(a){let l=Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])||1;return[a[0]/l,a[1]/l,a[2]/l]}isVec3Equal(a,l){return a[0]===l[0]&&a[1]===l[1]&&a[2]===l[2]}randomInSphere(a){let l=this.rng(),c=this.rng(),u=l*Math.PI*2,h=Math.acos(2*c-1),d=Math.cbrt(this.rng())*a;return[d*Math.sin(h)*Math.cos(u),d*Math.sin(h)*Math.sin(u),d*Math.cos(h)]}randomInBox(a){let l=a*.5;return[(this.rng()*2-1)*l,(this.rng()*2-1)*l,(this.rng()*2-1)*l]}}return new s(e)}simplifyGeometry(e,t){let r=this.THREE?.SimplifyModifier;if(!r)return null;let i=e,s=i?.attributes?.position?.count;if(!Number.isFinite(s))return null;let n=Math.max(.05,Math.min(1,t)),o=Math.max(3,Math.floor(s*n));if(o>=s)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 s=i.geometry.boundingBox;if(s){let n=s.clone().applyMatrix4(i.matrixWorld);t.union(n),r=!0}}}),r?t:new this.THREE.Box3}},He=class{constructor(e,t={}){this.engine=new Pe(e,t)}getEngine(){return this.engine}getName(){return"Three.js"}};return mt(Ct);})();
|
|
163
274
|
//# sourceMappingURL=index.js.map
|