@hology/core 0.0.248 → 0.0.250

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/effects/sequence/sequence-data.d.ts +24 -3
  2. package/dist/effects/sequence/sequence-data.js +1 -1
  3. package/dist/effects/sequence/sequence-definitions.d.ts +2 -1
  4. package/dist/effects/sequence/sequence-definitions.js +1 -1
  5. package/dist/effects/sequence/sequence-ops.js +1 -1
  6. package/dist/effects/sequence/sequence-player.d.ts +6 -0
  7. package/dist/effects/sequence/sequence-player.js +1 -1
  8. package/dist/effects/vfx/gpu-sprite-compiler.js +1 -1
  9. package/dist/effects/vfx/seeded-random.d.ts +4 -0
  10. package/dist/effects/vfx/seeded-random.js +4 -0
  11. package/dist/effects/vfx/vfx-actor.d.ts +1 -1
  12. package/dist/effects/vfx/vfx-actor.js +1 -1
  13. package/dist/effects/vfx/vfx-gpu-material.d.ts +9 -0
  14. package/dist/effects/vfx/vfx-gpu-material.js +4 -0
  15. package/dist/effects/vfx/vfx-materializer.js +1 -1
  16. package/dist/gameplay/actors/actor.d.ts +6 -0
  17. package/dist/gameplay/actors/actor.js +1 -1
  18. package/dist/gameplay/actors/builtin/camera-actor.js +1 -1
  19. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  20. package/dist/gameplay/actors/builtin/positional-audio-actor.js +1 -1
  21. package/dist/gameplay/actors/builtin/spawn-point.js +1 -1
  22. package/dist/gameplay/actors/builtin/spline-actor.js +1 -1
  23. package/dist/gameplay/actors/builtin/trigger-volume.js +1 -1
  24. package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +1 -1
  25. package/dist/gameplay/actors/builtin/water-volume-actor.js +1 -1
  26. package/dist/gameplay/actors/component.d.ts +1 -0
  27. package/dist/gameplay/actors/component.js +1 -1
  28. package/dist/gameplay/actors/internal/component-init.d.ts +1 -1
  29. package/dist/gameplay/actors/internal/component-init.js +1 -1
  30. package/dist/gameplay/actors/tabler-icon.d.ts +2 -0
  31. package/dist/gameplay/actors/tabler-icon.js +4 -0
  32. package/dist/gameplay/index.d.ts +1 -1
  33. package/dist/gameplay/index.js +1 -1
  34. package/dist/gameplay/initiate.d.ts +2 -1
  35. package/dist/gameplay/initiate.js +1 -1
  36. package/dist/gameplay/inject.js +1 -1
  37. package/dist/gameplay/net/service/rpc-decorator.js +1 -1
  38. package/dist/gameplay/services/render.d.ts +0 -1
  39. package/dist/gameplay/services/render.js +1 -1
  40. package/dist/gameplay/services/world.js +1 -1
  41. package/dist/rendering/webgpu-experimental-backend.d.ts +2 -0
  42. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  43. package/dist/rendering.d.ts +10 -0
  44. package/dist/rendering.js +1 -1
  45. package/dist/scene/materializer.js +1 -1
  46. package/dist/test/gpu-sprite-compiler.test.js +1 -1
  47. package/dist/test/sequence-light.test.d.ts +2 -0
  48. package/dist/test/sequence-light.test.js +4 -0
  49. package/dist/test/sequence-vfx.test.js +1 -1
  50. package/dist/test/vfx-seeded-random.test.d.ts +2 -0
  51. package/dist/test/vfx-seeded-random.test.js +4 -0
  52. package/package.json +1 -1
  53. package/tsconfig.tsbuildinfo +1 -1
  54. package/dist/gameplay/services/actor-update-registry.d.ts +0 -13
  55. package/dist/gameplay/services/actor-update-registry.js +0 -4
  56. package/dist/test/view-controller-updates.test.d.ts +0 -2
  57. package/dist/test/view-controller-updates.test.js +0 -4
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{applyMeshWorldTransformToGeometry as t}from"./vfx-mesh-transform.js";import{attributes as a,clamp as r,lambertMaterial as s,NodeShaderMaterial as o,rgba as n,smoothstep as i,textureSampler2d as l,varyingAttributes as p}from"three-shader-graph";import{SerializedParamType as c}from"../../scene/model.js";import{particleUniforms as u}from"../../shader-nodes/particle.js";import{sampleFlipbook as m}from"../../shader-nodes/texture-sequence.js";import{fragmentLinearEyeDepth as d,linearEyeDepth as h}from"../../shader-nodes/depth.js";import{ThreeBlendingMode as y}from"./vfx-asset.js";import{getDefaultVfxSpriteTexture as f}from"./vfx-default-sprite-texture.js";import{ShapeLibrary as b}from"../../scene/objects/shapes.js";export class GpuSpriteRenderClassCache{constructor(){this.entries=new Map}resolve(e,t){let a=this.entries.get(e);return null==a&&(a=t().catch(t=>{throw this.entries.delete(e),t}),this.entries.set(e,a)),a}clear(){this.entries.clear()}}export function hasGpuUnsupportedVfxInputBindings(e){const t=new Map((e.vfx.inputs??[]).map(e=>[e.id,e.type])),a=e=>{for(const a of[...e.initializers,...e.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){if("vfxInput"!==s?.binding?.type)continue;const o=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;if(null==o||t.get(s.binding.inputId)!==o)return!0;if("lifetime"===a.type&&"duration"===r&&"continuous"===e.rate.type)return!0}return(e.children??[]).some(a)};return e.vfx.emitters.some(a)}export function selectVfxBackend(e,t="auto"){if("cpu"===t)return{backend:"cpu",reasons:["CPU backend explicitly requested"]};const a=e.issues.filter(e=>"error"===e.severity).map(e=>e.message);return a.length>0&&"gpu"!==t?{backend:"cpu",reasons:a}:a.length>0?{backend:"gpu",reasons:["GPU backend explicitly forced despite incompatibilities",...a]}:{backend:"gpu",reasons:e.issues.filter(e=>"warning"===e.severity).map(e=>e.message)}}export function compileGpuSpriteEmitters(t,a,r="emitter-major"){const s=[],o=[],n=new Map,i=[],l=[],p=new Map((t.vfx.inputs??[]).map(e=>[e.id,e.type])),u=new Map((t.vfx.inputs??[]).filter(e=>"number"===e.type).map(e=>[e.id,"number"==typeof e.defaultValue?e.defaultValue:0]));hasGpuUnsupportedVfxInputBindings(t)&&i.push({severity:"error",code:"vfx-input-binding",emitter:"effect",message:"this VFX input binding target is not supported on GPU yet"});const m=t.vfx.emitters.slice().sort((e,t)=>(e.output.renderOrder??0)-(t.output.renderOrder??0)),d=(t,r,m)=>{const h="vfxInput"===t.rate.delayBinding?.type?u.get(t.rate.delayBinding.inputId):void 0,y=null==h?t:{...t,rate:{...t.rate,delay:Math.max(0,h)}};if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"stretchedSprite"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type)return void w(i,t,"error","output-type","this output type is not supported by the GPU sprite backend");if("mesh"===t.output.type&&null==t.output.assetId)return;if(t.rate.count<=0)return;const f="trail"===(b=t.output).type?JSON.stringify(b):"mesh"===b.type?JSON.stringify({type:b.type,assetId:b.assetId,renderOrder:b.renderOrder??0,useLegacyTransform:!0===b.useLegacyTransform,materialSource:b.materialSource??null,material:b.material??null,shader:b.shader??null,shaderParams:b.shaderParams??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"decal"===b.type?JSON.stringify({type:b.type,colorMap:b.colorMap,alphaMap:b.alphaMap,color:b.color,unlit:b.unlit,intensity:b.intensity,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"shape"===b.type?JSON.stringify({type:b.type,shape:b.shape,params:b.params,material:b.material,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):JSON.stringify({type:b.type,texture:b.texture,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,softness:b.softness,renderOrder:b.renderOrder??0,bloom:b.bloom,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space,lockY:"sprite"===b.type&&!0===b.lockY,stretchScale:"stretchedSprite"===b.type?b.scale:null});var b;let x=n.get(f);null==x&&(x=o.length,n.set(f,x),o.push({key:f,output:t.output}));const v=[];for(let o=0;o<a.length;o++){const n=g(y,null==r?a[o]:new e.Vector3,x,i);if(null!=n){if(null!=r){const e=s[r]?.instances[o];if(null==e)continue;const a=n.capacity,l=e.capacity*a;if(l>25e4){w(i,t,"error","child-particle-capacity",`child emitter expansion requires ${l} particles, exceeding the GPU per-emitter limit`);continue}n.capacity=l,n.parentEmitter=r,n.childParticlesPerParent=a,n.childSpawnEvent="collision"===t.spawnEvent?2:1,n.childLevel=m,!0===n.localSpace&&!0!==e.localSpace&&w(i,t,"error","child-emitter-local-space","GPU child emitters do not yet support a world-space parent with local-space child output"),"trail"===t.output.type&&w(i,t,"error","child-emitter-trail","GPU child emitters do not yet support trail output")}v.push(n)}}if(v.length>0){const e=s.length;s.push({instances:v,parentSource:r});for(const a of[...t.initializers,...t.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){const o=s?.binding;if("vfxInput"!==o?.type)continue;const n=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;null!=n&&p.get(o.inputId)===n&&("mesh"!==n&&("lifetime"===a.type&&"duration"===r&&"continuous"===t.rate.type||l.push({inputId:o.inputId,emitterIndex:e,target:`${t.initializers.includes(a)?"initializer":"behaviour"}:${a.type}:${r}`,authoredScalar:"number"==typeof s.value?s.value:void 0,baseScaleStart:[...v[0].scaleStart],baseScaleEnd:[...v[0].scaleEnd]})))}for(const a of t.children??[])d(a,e,m+1)}};for(const e of m)d(e,null,0);const h="instance-major"===r?a.flatMap((e,t)=>s.flatMap(e=>null==e.instances[t]?[]:[e.instances[t]])):s.flatMap(e=>e.instances);for(let e=0;e<s.length;e++){const t=s[e];if(null!=t.parentSource)for(let e=0;e<t.instances.length;e++)t.instances[e].parentEmitter="instance-major"===r?e*s.length+t.parentSource:t.parentSource*a.length+e}const y=o.map((e,t)=>({renderClass:e,oldIndex:t})).sort((e,t)=>(e.renderClass.output.renderOrder??0)-(t.renderClass.output.renderOrder??0)),f=new Array(o.length);for(let e=0;e<y.length;e++)f[y[e].oldIndex]=e;for(const e of h)e.renderClass=f[e.renderClass??0]??0;const b={compatible:!i.some(e=>"error"===e.severity),issues:i};return{emitters:h,inputBindings:l,renderClasses:y.map(e=>e.renderClass),compatibility:b,unsupported:[...new Set(i.map(e=>`${e.emitter}: ${e.message}`))]}}export async function materializeGpuSpriteRenderClasses(c,g,w,x){const v=async c=>{const x=c.output;if("trail"===x.type){const t=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default"),a="default"===t?null:await(w?.(x))??null;if(null==a&&"default"!==t)throw new Error(`${t} trail material requires a compatible GPU material resolver`);return{texture:null!=x.texture?await g.getTexture(x.texture):f(),material:a??void 0,localSpace:"local"===x.space,trail:{historyLength:Math.max(2,Math.round(x.length)+1),width:x.width??1,taper:x.taper,colorStart:new e.Color(x.color).multiplyScalar(x.intensity),colorEnd:new e.Color(x.colorEnd).multiplyScalar(x.intensityEnd),opacityStart:x.opacityStart,opacityEnd:x.opacityEnd,scrollSpeed:x.scrollSpeed??0,opacityChannel:x.opacityChannel??"red",blendingMode:x.blendingMode??"normal",billboard:x.billboard??!1}}}if("mesh"===x.type){if(null==g.getMesh)throw new Error("GPU mesh particles require a mesh asset provider");const a=await g.getMesh(x.assetId);a.updateWorldMatrix(!0,!0);const r=[];if(a.traverse(t=>{t instanceof e.Mesh&&r.push(t)}),1!==r.length)throw new Error(`GPU mesh particles require exactly one mesh geometry; asset ${x.assetId} resolved to ${r.length}`);const s=null==r[0].geometry.index?r[0].geometry.clone():r[0].geometry.toNonIndexed();!0!==x.useLegacyTransform&&t(r[0],s);const n=s.getAttribute("position");if(null==n)throw new Error(`GPU mesh particle asset ${x.assetId} has no position attribute`);const i=s.getAttribute("normal"),l=s.getAttribute("uv"),p=new Float32Array(8*n.count);for(let e=0;e<n.count;e++){const t=8*e;p[t]=n.getX(e),p[t+1]=n.getY(e),p[t+2]=n.getZ(e),p[t+3]=i?.getX(e)??0,p[t+4]=i?.getY(e)??1,p[t+5]=i?.getZ(e)??0,p[t+6]=l?.getX(e)??0,p[t+7]=l?.getY(e)??0}s.dispose();const c=Array.isArray(r[0].material)?r[0].material[0]:r[0].material,m="material"===x.materialSource&&null==x.material||"shaderGraph"===x.materialSource&&("asset"!==x.shaderGraph?.source||null==x.shaderGraph.assetId)||"shader"===x.materialSource&&null==x.shader?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),d="default"===m?await(w?.(x))??function(){const e=u.opacity;return new o({color:u.color.rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??null;if(null==d&&"default"!==m)throw new Error(`${m} mesh material requires a compatible GPU material resolver`);const h=null!=c&&"color"in c&&c.color instanceof e.Color?c.color.clone():new e.Color(16777215);return{texture:f(),meshVertices:p,meshColor:h,meshOpacity:c?.opacity??1,localSpace:"local"===x.space,material:d??void 0}}if("decal"===x.type){const t=await(w?.(x))??null;if(null==t)throw new Error("GPU decal output requires a compatible GPU decal material resolver");const a=new e.BoxGeometry(1,1,1).toNonIndexed(),r=a.getAttribute("position"),s=a.getAttribute("normal"),o=a.getAttribute("uv"),n=new Float32Array(8*r.count);for(let e=0;e<r.count;e++){const t=8*e;n[t]=r.getX(e),n[t+1]=r.getY(e),n[t+2]=r.getZ(e),n[t+3]=s.getX(e),n[t+4]=s.getY(e),n[t+5]=s.getZ(e),n[t+6]=o.getX(e),n[t+7]=o.getY(e)}return a.dispose(),{texture:f(),meshVertices:n,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:t}}if("shape"===x.type){const t=b[x.shape];if(null==t)throw new Error(`GPU shape output has unknown shape ${x.shape}`);const a=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),r="default"===a?function(){const e=u.opacity;return new o({color:s({color:u.color.rgb}).rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??null;if(null==r&&"default"!==a)throw new Error(`${a} shape material requires a compatible GPU material resolver`);const n=Object.fromEntries(Object.entries(x.params??{}).map(([e,t])=>[e,t.value])),i=t.geometry(n),l=null==i.index?i:i.toNonIndexed(),p=l.getAttribute("position"),c=l.getAttribute("normal"),m=l.getAttribute("uv"),d=new Float32Array(8*p.count);for(let e=0;e<p.count;e++){const t=8*e;d[t]=p.getX(e),d[t+1]=p.getY(e),d[t+2]=p.getZ(e),d[t+3]=c?.getX(e)??0,d[t+4]=c?.getY(e)??1,d[t+5]=c?.getZ(e)??0,d[t+6]=m?.getX(e)??0,d[t+7]=m?.getY(e)??0}return l!==i&&l.dispose(),i.dispose(),{texture:f(),meshVertices:d,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:r??void 0}}const v=null!=x.texture?await g.getTexture(x.texture):f(),S="stretchedSprite"===x.type?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default");let M="default"===S?null:await(w?.(x))??null;if(null==M&&"default"!==S)throw new Error(`${S} material requires a compatible GPU material resolver`);return M??(M=function(t,s){const c=l(s),f="sprite"===t.type&&!0===t.flipbook?.enabled?m(c,a.uv,t.flipbook.columns,t.flipbook.rows,u.time,t.flipbook.fps,t.flipbook.mode):c.sample(p.uv);let b=u.opacity;"red"===(t.opacityChannel??"red")?b=b.multiply(f.r):"alpha"===t.opacityChannel&&(b=b.multiply(f.a));if(t.softness>0){const e=h.subtract(d).divide(h);b=b.multiply(i(0,.2*t.softness,r(e,0,1e3)))}const g=new o({color:n(u.color.multiply(f.rgb),b),transparent:!0,lights:!1,fog:!1,alphaTest:1e-4});return g.blending=y[t.blendingMode]??e.NormalBlending,g.depthWrite=!1,g}(x,v)),M.transparent&&(M.depthWrite=!1),{texture:v,material:M,lockY:"sprite"===x.type&&!0===x.lockY,localSpace:"local"===x.space,stretchScale:"stretchedSprite"===x.type?0===x.scale?.001:x.scale:void 0}};return{renderClasses:await Promise.all(c.map(e=>x?.resolve(e.key,()=>v(e))??v(e))),unsupported:[]}}function g(t,a,r,s){if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type&&"stretchedSprite"!==t.output.type)return null;const o="mesh"===t.output.type||"decal"===t.output.type||"shape"===t.output.type;let n=99999,i=99999,l=0,p=0;const c=new e.Vector4,u=new e.Vector4,m=new e.Vector3,d=new e.Vector3,h=new e.Vector3;let y=0,f=1;const b=new e.Vector3;let g=0,k=0,G=!1,V=0,C=!1;const I=new e.Vector3;let P,O=0,E=!1,U=!1,A=0,R=0,N=0,B=!1,T=[1,1],z=1,$=1,j=new e.Color("sprite"===t.output.type||"stretchedSprite"===t.output.type?t.output.color:"#ffffff"),F=j.clone(),Y=!1,X=1,Z=1,D=0,q=0;const L=new e.Quaternion,Q=new e.Vector3,J=new e.Vector3;let W=0;const H=new e.Vector3(0,1,0);let K=0,_=0,ee=!1;const te=new e.Vector3;let ae=0,re=0,se=!1;const oe=new e.Vector3(0,1,0);let ne=0;const ie=new e.Vector3,le=new e.Vector3,pe=new e.Vector3(0,1,0);let ce=0,ue=!1,me=0,de=0,he=0,ye=!1;const fe=new e.Vector4(0,0,0,0),be=new e.Vector3(1,1,1),ge=new e.Vector3(1,1,1),we=new e.Vector3(1,1,1);let xe,ve,Se,Me,ke,Ge="surface";for(const a of t.initializers.filter(e=>!1!==e.enabled))switch(a.type){case"lifetime":i=n=x(a.params.duration,1);break;case"randomLifetime":{const e=x(a.params.minDuration,1),t=x(a.params.maxDuration,2);i=Math.min(e,t),n=Math.max(e,t);break}case"velocity":{const e=S(a.params.velocity);m.copy(e),d.copy(e);break}case"randomVelocity":m.copy(S(a.params.min)),d.copy(S(a.params.max));break;case"randomDirection":{const e=x(a.params.speed,1);m.setScalar(-e),d.setScalar(e);break}case"radialVelocity":H.copy(S(a.params.direction)).normalize(),K=x(a.params.speed,1),_=e.MathUtils.degToRad(x(a.params.spread,0)),ee=!0;break;case"mass":f=Math.max(1e-6,x(a.params.min,1));break;case"positionPoint":c.copy(new e.Vector4(...S(a.params.position).toArray(),0));break;case"positionSphere":{l=x(a.params.radius,1);const e=S(a.params.position);p=1,c.set(e.x,e.y,e.z,!0===a.params.surface?.value?1:0);break}case"positionBox":{const e=S(a.params.position),t=S(a.params.dimensions);p=2,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionLine":{const e=S(a.params.a),t=S(a.params.b);p=3,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionCircle":case"positionRing":{const t=S(a.params.position),r=S(a.params.rotation).multiplyScalar(Math.PI/180);l=x(a.params.radius,1);const s="positionRing"===a.type?Math.max(x(a.params.thickness,.2),1e-4):0;p=4,c.set(t.x,t.y,t.z,s),u.set(r.x,r.y,r.z,e.MathUtils.degToRad(Math.max(0,Math.min(360,x(a.params.angle,360)))));break}case"positionMesh":{const r=a.params.mesh?.value,o=a.params.mesh?.binding;if("vfxInput"===o?.type&&(ve=o.inputId),("string"!=typeof r||0===r.length)&&null==ve){w(s,t,"error","mesh-sampler-source","GPU mesh sampling requires a selected fallback mesh asset");break}if(xe="string"==typeof r&&r.length>0?r:void 0,Ge="vertices"===a.params.sampling?.value?"vertices":"surface",Se=(new e.Matrix4).compose(S(a.params.position),(new e.Quaternion).setFromEuler((new e.Euler).setFromVector3(S(a.params.rotation).multiplyScalar(Math.PI/180))),null==a.params.scale?new e.Vector3(1,1,1):S(a.params.scale)),!0===a.params.alignNormal?.value){const t=a.params.alignmentAxis?.value;Me="+X"===t?new e.Vector3(1,0,0):"-X"===t?new e.Vector3(-1,0,0):"-Y"===t?new e.Vector3(0,-1,0):"+Z"===t?new e.Vector3(0,0,1):"-Z"===t?new e.Vector3(0,0,-1):new e.Vector3(0,1,0)}!0===a.params.normalVelocity?.value&&(ke=new e.Vector4(x(a.params.normalVelocityMin,1),x(a.params.normalVelocityMax,1),e.MathUtils.degToRad(e.MathUtils.clamp(x(a.params.normalVelocitySpread,0),0,180)),1)),p=5;break}case"scale":{const e=x(a.params.scale,1);T=[e,e];break}case"scaleComponents":be.copy(S(a.params.scale));break;case"randomScale":T=[x(a.params.min,1),x(a.params.max,1)];break;case"randomColor":j=M(a.params.a,j),F=M(a.params.b,j),Y=!0;break;case"rotation":{const t=S(a.params.rotation);D=q=e.MathUtils.degToRad(t.z),Q.set(e.MathUtils.degToRad(t.x),e.MathUtils.degToRad(t.y),e.MathUtils.degToRad(t.z)),L.setFromEuler(new e.Euler(Q.x,Q.y,Q.z));break}case"randomRotation":{if(o){const e=a.params.axis?.value;W="X"===e?2:"Y"===e?3:"Z"===e?4:1;break}const e=a.params.axis?.value;"XYZ"!==e&&"Z"!==e&&null!=e||(q=2*Math.PI);break}case"alignRotation":{if(!o)break;const e=a.params.axis?.value;"+X"===e?oe.set(1,0,0):"-X"===e?oe.set(-1,0,0):"-Y"===e?oe.set(0,-1,0):"+Z"===e?oe.set(0,0,1):"-Z"===e?oe.set(0,0,-1):oe.set(0,1,0);const t=a.params.mode?.value;ne="TowardsCenter"===t?2:"AlongVelocity"===t?3:1,ie.copy(S(a.params.center)),le.copy(S(a.params.offset)).multiplyScalar(Math.PI/180);break}default:w(s,t,"error",`initializer:${a.type}`,`initializer ${a.type} is not supported on GPU`)}for(const e of t.behaviours.filter(e=>!1!==e.enabled))switch(e.type){case"force":h.add(S(e.params.force));break;case"gravity":h.y-=x(e.params.gravity,8);break;case"linearDamping":y+=x(e.params.factor,.1);break;case"randomDrift":b.copy(S(e.params.drift)),g=Math.max(0,x(e.params.delay,0)),k=v(e.params.ease?.value),G=!0;break;case"followParent":V=x(e.params.speed,0),C=!0;break;case"moveTo":I.copy(S(e.params.target)),O=v(e.params.ease?.value),E=!0;break;case"attraction":case"repulsion":if(se){w(s,t,"error","multiple-attraction-behaviours","multiple attraction or repulsion behaviours are not supported in one GPU emitter");break}te.copy(S(e.params.target)),ae=x(e.params.force,1)*("repulsion"===e.type?-1:1),re=Math.max(0,x(e.params.radius,1)),se=!0;break;case"vortex":if(ue){w(s,t,"error","multiple-vortex-behaviours","multiple vortex behaviours are not supported in one GPU emitter");break}pe.copy(S(e.params.axis)),ce=x(e.params.amount,1),ue=!0;break;case"disperse":{if(ye){w(s,t,"error","multiple-disperse-behaviours","multiple disperse behaviours are not supported in one GPU emitter");break}me=x(e.params.distance,1);const a=e.params.axis?.value;de="XY"===a?1:"XZ"===a?2:"YZ"===a?3:0,he=v(e.params.ease?.value),ye=!0;break}case"worldCollision":U=!0,A=Math.max(0,x(e.params.bounce,0)),R=Math.max(0,Math.min(1,x(e.params.friction,0))),N=Math.max(0,x(e.params.lifeLoss,0)),B=!0===e.params.debug?.value;break;case"scale":z=x(e.params.a,1),$=x(e.params.b,1),fe.x=v(e.params.ease?.value);break;case"scaleComponents":ge.copy(be).multiply(S(e.params.a)),we.copy(be).multiply(S(e.params.b)),fe.w=v(e.params.ease?.value);break;case"changeColor":j=M(e.params.a,j),F=M(e.params.b,F),fe.y=v(e.params.ease?.value),Y=!1;break;case"changeOpacity":X=x(e.params.a,1),Z=x(e.params.b,0),fe.z=v(e.params.ease?.value);break;case"rotate":case"rotateAdd":{const t=S(e.params.rotation);t.multiplyScalar(Math.PI/180*Math.PI/180),o?J.add(t):P=(P??0)+t.z;break}default:w(s,t,"error",`behaviour:${e.type}`,`behaviour ${e.type} is not supported on GPU`)}const Ve=Math.max(0,Math.floor(t.rate.count)),Ce="sprite"!==t.output.type&&"stretchedSprite"!==t.output.type||!Number.isFinite(t.output.intensity)?1:t.output.intensity;j.multiplyScalar(Ce),F.multiplyScalar(Ce);const Ie="once"===t.rate.type?Ve:Math.max(Ve,Math.ceil(n/Math.max(t.rate.time,1e-4))*Ve),Pe=Math.min(25e4,Ie);return Pe!==Ie&&w(s,t,"warning","particle-capacity-clamped",`particle capacity ${Ie} exceeds the current GPU per-emitter limit of ${Pe}`),t.behaviours.some(e=>!1!==e.enabled&&"scaleComponents"===e.type)||(ge.copy(be),we.copy(be)),U&&"local"===t.output.space&&w(s,t,"error","world-collision-local-space","GPU screen-space world collision currently requires world-space output"),{position:(new e.Vector3).fromArray(t.position).add("local"===t.output.space?new e.Vector3:a),localSpace:"local"===t.output.space,capacity:Pe,rate:"once"===t.rate.type?{type:"once",count:Ve,delay:Math.max(0,t.rate.delay??0)}:{type:"continuous",count:Ve,interval:Math.max(t.rate.time,1e-4),delay:Math.max(0,t.rate.delay??0),duration:(t.rate.duration??0)>0?t.rate.duration:-1},life:n,lifeMin:i,positionRadius:l,spawnZoneType:p,spawnZoneA:c,spawnZoneB:u,meshSamplerAssetId:xe,meshSamplerInputId:ve,meshSamplerMode:Ge,meshSamplerTransform:Se,meshSamplerAlignAxis:Me,meshNormalVelocity:ke,velocityMin:m,velocityMax:d,force:h,damping:y,mass:f,randomDrift:b,randomDriftDelay:g,randomDriftEasing:k,hasRandomDrift:G,followParentSpeed:V,hasFollowParent:C,moveToTarget:I,moveToEasing:O,hasMoveTo:E,hasWorldCollision:U,collisionBounce:A,collisionFriction:R,collisionLifeLoss:N,collisionDebug:B,orientAlongVelocity:!1,scaleStart:[T[0]*z,T[1]*z],scaleEnd:[T[0]*$,T[1]*$],colorStart:j,colorEnd:F,randomColor:Y,alphaStart:X,alphaEnd:Z,rotationMin:D,rotationMax:q,spriteRotationStep:P,meshRotation:L,meshRotationEuler:Q,meshRotationStep:J,randomMeshRotationAxis:W,radialVelocityDirection:H,radialVelocitySpeed:K,radialVelocitySpread:_,hasRadialVelocity:ee,attractionTarget:te,attractionForce:ae,attractionRadius:re,hasAttraction:se,alignRotationAxis:oe,alignRotationMode:ne,alignRotationCenter:ie,alignRotationOffset:le,vortexAxis:pe,vortexAmount:ce,hasVortex:ue,disperseDistance:me,dispersePlane:de,disperseEasing:he,hasDisperse:ye,curveEasing:fe,meshScaleStart:ge,meshScaleEnd:we,renderClass:r}}function w(e,t,a,r,s){e.some(e=>e.emitter===t.name&&e.code===r)||e.push({severity:a,code:r,emitter:t.name||t.id,message:s})}function x(e,t){const a=e?.value;if("number"==typeof a)return Number.isFinite(a)?a:t;if("string"==typeof a&&""!==a.trim()){const e=Number(a);if(Number.isFinite(e))return e}return t}function v(e){switch(e){case"InQuad":return 1;case"OutQuad":return 2;case"InOutQuad":return 3;case"InCubic":return 4;case"OutCubic":return 5;case"InOutCubic":return 6;case"InQuart":return 7;case"OutQuart":return 8;case"InOutQuart":return 9;case"InSine":return 10;case"OutSine":return 11;case"InOutSine":return 12;case"InExpo":return 13;case"OutExpo":return 14;case"InOutExpo":return 15;case"InCirc":return 16;case"InBack":return 17;case"OutBack":return 18;case"Bump":return 19;case"BumpSharp":return 20;case"BumpFlat":return 21;case"SpikeFade":return 22;case"OutCirc":return 23;case"InOutCirc":return 24;case"InOutBack":return 25;case"BumpFade":return 26;case"BumpFall":return 27;default:return 0}}function S(t){const a=t?.value;return Array.isArray(a)?new e.Vector3(Number(a[0]),Number(a[1]),Number(a[2])):new e.Vector3}function M(t,a){const r=t?.value;if("string"==typeof r){const t=/^#([A-Fa-f0-9]{6})$/.exec(r);if(null!=t){const a=Number.parseInt(t[1],16);return(new e.Color).setRGB((a>>16&255)/255,(a>>8&255)/255,(255&a)/255)}const a=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);if(null!=a)return(new e.Color).setRGB(Math.min(255,Number.parseInt(a[1],10))/255,Math.min(255,Number.parseInt(a[2],10))/255,Math.min(255,Number.parseInt(a[3],10))/255)}if("number"==typeof r&&Number.isFinite(r)){const t=Math.floor(r);return(new e.Color).setRGB((t>>16&255)/255,(t>>8&255)/255,(255&t)/255)}if(null!=r&&"object"==typeof r&&"r"in r&&"g"in r&&"b"in r){const t=r;return(new e.Color).setRGB(t.r,t.g,t.b)}return a.clone()}/*
1
+ import*as e from"three";import{applyMeshWorldTransformToGeometry as t}from"./vfx-mesh-transform.js";import{attributes as a,clamp as r,lambertMaterial as s,NodeShaderMaterial as o,rgba as n,smoothstep as i,textureSampler2d as l,varyingAttributes as p}from"three-shader-graph";import{SerializedParamType as c}from"../../scene/model.js";import{particleUniforms as u}from"../../shader-nodes/particle.js";import{sampleFlipbook as m}from"../../shader-nodes/texture-sequence.js";import{fragmentLinearEyeDepth as d,linearEyeDepth as h}from"../../shader-nodes/depth.js";import{ThreeBlendingMode as y}from"./vfx-asset.js";import{getDefaultVfxSpriteTexture as f}from"./vfx-default-sprite-texture.js";import{ShapeLibrary as b}from"../../scene/objects/shapes.js";export class GpuSpriteRenderClassCache{constructor(){this.entries=new Map}resolve(e,t){let a=this.entries.get(e);return null==a&&(a=t().catch(t=>{throw this.entries.delete(e),t}),this.entries.set(e,a)),a}clear(){this.entries.clear()}}export function hasGpuUnsupportedVfxInputBindings(e){const t=new Map((e.vfx.inputs??[]).map(e=>[e.id,e.type])),a=e=>{for(const a of[...e.initializers,...e.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){if("vfxInput"!==s?.binding?.type)continue;const o=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;if(null==o||t.get(s.binding.inputId)!==o)return!0;if("lifetime"===a.type&&"duration"===r&&"continuous"===e.rate.type)return!0}return(e.children??[]).some(a)};return e.vfx.emitters.some(a)}export function selectVfxBackend(e,t="auto"){if("cpu"===t)return{backend:"cpu",reasons:["CPU backend explicitly requested"]};const a=e.issues.filter(e=>"error"===e.severity).map(e=>e.message);return a.length>0&&"gpu"!==t?{backend:"cpu",reasons:a}:a.length>0?{backend:"gpu",reasons:["GPU backend explicitly forced despite incompatibilities",...a]}:{backend:"gpu",reasons:e.issues.filter(e=>"warning"===e.severity).map(e=>e.message)}}export function compileGpuSpriteEmitters(t,a,r="emitter-major"){const s=[],o=[],n=new Map,i=[],l=[],p=new Map((t.vfx.inputs??[]).map(e=>[e.id,e.type])),u=new Map((t.vfx.inputs??[]).filter(e=>"number"===e.type).map(e=>[e.id,"number"==typeof e.defaultValue?e.defaultValue:0]));hasGpuUnsupportedVfxInputBindings(t)&&i.push({severity:"error",code:"vfx-input-binding",emitter:"effect",message:"this VFX input binding target is not supported on GPU yet"});const m=t.vfx.emitters.slice().sort((e,t)=>(e.output.renderOrder??0)-(t.output.renderOrder??0)),d=(t,r,m)=>{const h="vfxInput"===t.rate.delayBinding?.type?u.get(t.rate.delayBinding.inputId):void 0,y=null==h?t:{...t,rate:{...t.rate,delay:Math.max(0,h)}};if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"stretchedSprite"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type)return void w(i,t,"error","output-type","this output type is not supported by the GPU sprite backend");if("mesh"===t.output.type&&null==t.output.assetId)return;if(t.rate.count<=0)return;const f="trail"===(b=t.output).type?JSON.stringify(b):"mesh"===b.type?JSON.stringify({type:b.type,assetId:b.assetId,renderOrder:b.renderOrder??0,useLegacyTransform:!0===b.useLegacyTransform,materialSource:b.materialSource??null,material:b.material??null,shader:b.shader??null,shaderParams:b.shaderParams??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"decal"===b.type?JSON.stringify({type:b.type,colorMap:b.colorMap,alphaMap:b.alphaMap,color:b.color,unlit:b.unlit,intensity:b.intensity,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):"shape"===b.type?JSON.stringify({type:b.type,shape:b.shape,params:b.params,material:b.material,renderOrder:b.renderOrder??0,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space}):JSON.stringify({type:b.type,texture:b.texture,opacityChannel:b.opacityChannel??"red",blendingMode:b.blendingMode,softness:b.softness,renderOrder:b.renderOrder??0,bloom:b.bloom,materialSource:b.materialSource??null,shader:b.shader??null,shaderGraph:b.shaderGraph??null,shaderGraphParams:b.shaderGraphParams??null,space:b.space,lockY:"sprite"===b.type&&!0===b.lockY,stretchScale:"stretchedSprite"===b.type?b.scale:null});var b;let x=n.get(f);null==x&&(x=o.length,n.set(f,x),o.push({key:f,output:t.output}));const v=[];for(let o=0;o<a.length;o++){const n=g(y,null==r?a[o]:new e.Vector3,x,i);if(null!=n){if(null!=r){const e=s[r]?.instances[o];if(null==e)continue;const a=n.capacity,l=e.capacity*a;if(l>25e4){w(i,t,"error","child-particle-capacity",`child emitter expansion requires ${l} particles, exceeding the GPU per-emitter limit`);continue}n.capacity=l,n.parentEmitter=r,n.childParticlesPerParent=a,n.childSpawnEvent="collision"===t.spawnEvent?2:1,n.childLevel=m,!0===n.localSpace&&!0!==e.localSpace&&w(i,t,"error","child-emitter-local-space","GPU child emitters do not yet support a world-space parent with local-space child output"),"trail"===t.output.type&&w(i,t,"error","child-emitter-trail","GPU child emitters do not yet support trail output")}v.push(n)}}if(v.length>0){const e=s.length;s.push({instances:v,parentSource:r});for(const a of[...t.initializers,...t.behaviours])if(!1!==a.enabled)for(const[r,s]of Object.entries(a.params)){const o=s?.binding;if("vfxInput"!==o?.type)continue;const n=s.type===c.Number?"number":s.type===c.Vector3?"vec3":s.type===c.Color?"color":s.type===c.Object3D?"mesh":void 0;null!=n&&p.get(o.inputId)===n&&("mesh"!==n&&("lifetime"===a.type&&"duration"===r&&"continuous"===t.rate.type||l.push({inputId:o.inputId,emitterIndex:e,target:`${t.initializers.includes(a)?"initializer":"behaviour"}:${a.type}:${r}`,authoredScalar:"number"==typeof s.value?s.value:void 0,baseScaleStart:[...v[0].scaleStart],baseScaleEnd:[...v[0].scaleEnd]})))}for(const a of t.children??[])d(a,e,m+1)}};for(const e of m)d(e,null,0);const h="instance-major"===r?a.flatMap((e,t)=>s.flatMap(e=>null==e.instances[t]?[]:[e.instances[t]])):s.flatMap(e=>e.instances);for(let e=0;e<s.length;e++){const t=s[e];if(null!=t.parentSource)for(let e=0;e<t.instances.length;e++)t.instances[e].parentEmitter="instance-major"===r?e*s.length+t.parentSource:t.parentSource*a.length+e}const y=o.map((e,t)=>({renderClass:e,oldIndex:t})).sort((e,t)=>(e.renderClass.output.renderOrder??0)-(t.renderClass.output.renderOrder??0)),f=new Array(o.length);for(let e=0;e<y.length;e++)f[y[e].oldIndex]=e;for(const e of h)e.renderClass=f[e.renderClass??0]??0;const b={compatible:!i.some(e=>"error"===e.severity),issues:i};return{emitters:h,inputBindings:l,renderClasses:y.map(e=>e.renderClass),compatibility:b,unsupported:[...new Set(i.map(e=>`${e.emitter}: ${e.message}`))]}}export async function materializeGpuSpriteRenderClasses(c,g,w,x){const v=async c=>{const x=c.output;if("trail"===x.type){const t=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default"),a="default"===t?null:await(w?.(x))??null;if(null==a&&"default"!==t)throw new Error(`${t} trail material requires a compatible GPU material resolver`);return{texture:null!=x.texture?await g.getTexture(x.texture):f(),material:a??void 0,localSpace:"local"===x.space,trail:{historyLength:Math.max(2,Math.round(x.length)+1),width:x.width??1,taper:x.taper,colorStart:new e.Color(x.color).multiplyScalar(x.intensity),colorEnd:new e.Color(x.colorEnd).multiplyScalar(x.intensityEnd),opacityStart:x.opacityStart,opacityEnd:x.opacityEnd,scrollSpeed:x.scrollSpeed??0,opacityChannel:x.opacityChannel??"red",blendingMode:x.blendingMode??"normal",billboard:x.billboard??!1}}}if("mesh"===x.type){if(null==g.getMesh)throw new Error("GPU mesh particles require a mesh asset provider");const a=await g.getMesh(x.assetId);a.updateWorldMatrix(!0,!0);const r=[];if(a.traverse(t=>{t instanceof e.Mesh&&r.push(t)}),1!==r.length)throw new Error(`GPU mesh particles require exactly one mesh geometry; asset ${x.assetId} resolved to ${r.length}`);const s=null==r[0].geometry.index?r[0].geometry.clone():r[0].geometry.toNonIndexed();!0!==x.useLegacyTransform&&t(r[0],s);const n=s.getAttribute("position");if(null==n)throw new Error(`GPU mesh particle asset ${x.assetId} has no position attribute`);const i=s.getAttribute("normal"),l=s.getAttribute("uv"),p=new Float32Array(8*n.count);for(let e=0;e<n.count;e++){const t=8*e;p[t]=n.getX(e),p[t+1]=n.getY(e),p[t+2]=n.getZ(e),p[t+3]=i?.getX(e)??0,p[t+4]=i?.getY(e)??1,p[t+5]=i?.getZ(e)??0,p[t+6]=l?.getX(e)??0,p[t+7]=l?.getY(e)??0}s.dispose();const c=Array.isArray(r[0].material)?r[0].material[0]:r[0].material,m="material"===x.materialSource&&null==x.material||"shaderGraph"===x.materialSource&&("asset"!==x.shaderGraph?.source||null==x.shaderGraph.assetId)||"shader"===x.materialSource&&null==x.shader?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),d="default"===m?await(w?.(x))??function(){const e=u.opacity;return new o({color:u.color.rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??null;if(null==d&&"default"!==m)throw new Error(`${m} mesh material requires a compatible GPU material resolver`);const h=null!=c&&"color"in c&&c.color instanceof e.Color?c.color.clone():new e.Color(16777215);return{texture:f(),meshVertices:p,meshColor:h,meshOpacity:c?.opacity??1,localSpace:"local"===x.space,material:d??void 0}}if("decal"===x.type){const t=await(w?.(x))??null;if(null==t)throw new Error("GPU decal output requires a compatible GPU decal material resolver");const a=new e.BoxGeometry(1,1,1).toNonIndexed(),r=a.getAttribute("position"),s=a.getAttribute("normal"),o=a.getAttribute("uv"),n=new Float32Array(8*r.count);for(let e=0;e<r.count;e++){const t=8*e;n[t]=r.getX(e),n[t+1]=r.getY(e),n[t+2]=r.getZ(e),n[t+3]=s.getX(e),n[t+4]=s.getY(e),n[t+5]=s.getZ(e),n[t+6]=o.getX(e),n[t+7]=o.getY(e)}return a.dispose(),{texture:f(),meshVertices:n,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:t}}if("shape"===x.type){const t=b[x.shape];if(null==t)throw new Error(`GPU shape output has unknown shape ${x.shape}`);const a=x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":null!=x.shader?"shader":null!=x.material?"material":"default"),r="default"===a?function(){const e=u.opacity;return new o({color:s({color:u.color.rgb}).rgb.rgba(e),opacity:e,transparent:!0})}():await(w?.(x))??null;if(null==r&&"default"!==a)throw new Error(`${a} shape material requires a compatible GPU material resolver`);const n=Object.fromEntries(Object.entries(x.params??{}).map(([e,t])=>[e,t.value])),i=t.geometry(n),l=null==i.index?i:i.toNonIndexed(),p=l.getAttribute("position"),c=l.getAttribute("normal"),m=l.getAttribute("uv"),d=new Float32Array(8*p.count);for(let e=0;e<p.count;e++){const t=8*e;d[t]=p.getX(e),d[t+1]=p.getY(e),d[t+2]=p.getZ(e),d[t+3]=c?.getX(e)??0,d[t+4]=c?.getY(e)??1,d[t+5]=c?.getZ(e)??0,d[t+6]=m?.getX(e)??0,d[t+7]=m?.getY(e)??0}return l!==i&&l.dispose(),i.dispose(),{texture:f(),meshVertices:d,meshColor:new e.Color(16777215),meshOpacity:1,localSpace:"local"===x.space,material:r??void 0}}const v=null!=x.texture?await g.getTexture(x.texture):f(),S="stretchedSprite"===x.type?"default":x.materialSource??("asset"===x.shaderGraph?.source?"shaderGraph":"default");let M="default"===S?null:await(w?.(x))??null;if(null==M&&"default"!==S)throw new Error(`${S} material requires a compatible GPU material resolver`);return M??(M=function(t,s){const c=l(s),f="sprite"===t.type&&!0===t.flipbook?.enabled?m(c,a.uv,t.flipbook.columns,t.flipbook.rows,u.time,t.flipbook.fps,t.flipbook.mode):c.sample(p.uv);let b=u.opacity;"red"===(t.opacityChannel??"red")?b=b.multiply(f.r):"alpha"===t.opacityChannel&&(b=b.multiply(f.a));if(t.softness>0){const e=h.subtract(d).divide(h);b=b.multiply(i(0,.2*t.softness,r(e,0,1e3)))}const g=new o({color:n(u.color.multiply(f.rgb),b),transparent:!0,lights:!1,fog:!1,alphaTest:1e-4});return g.blending=y[t.blendingMode]??e.NormalBlending,g.depthWrite=!1,g}(x,v)),M.transparent&&(M.depthWrite=!1),{texture:v,material:M,lockY:"sprite"===x.type&&!0===x.lockY,localSpace:"local"===x.space,stretchScale:"stretchedSprite"===x.type?0===x.scale?.001:x.scale:void 0}};return{renderClasses:await Promise.all(c.map(e=>x?.resolve(e.key,()=>v(e))??v(e))),unsupported:[]}}function g(t,a,r,s){if("sprite"!==t.output.type&&"mesh"!==t.output.type&&"decal"!==t.output.type&&"shape"!==t.output.type&&"trail"!==t.output.type&&"stretchedSprite"!==t.output.type)return null;const o="mesh"===t.output.type||"decal"===t.output.type||"shape"===t.output.type;let n=99999,i=99999,l=0,p=0;const c=new e.Vector4,u=new e.Vector4,m=new e.Vector3,d=new e.Vector3,h=new e.Vector3;let y=0,f=1;const b=new e.Vector3;let g=0,k=0,G=!1,V=0,C=!1;const I=new e.Vector3;let P,O=0,E=!1,U=!1,A=0,R=0,N=0,B=!1,T=[1,1],z=1,$=1,j=new e.Color("sprite"===t.output.type||"stretchedSprite"===t.output.type?t.output.color:"#ffffff"),F=j.clone(),Y=!1,X=1,Z=1,D=0,q=0;const L=new e.Quaternion,Q=new e.Vector3,J=new e.Vector3;let W=0;const H=new e.Vector3(0,1,0);let K=0,_=0,ee=!1;const te=new e.Vector3;let ae=0,re=0,se=!1;const oe=new e.Vector3(0,1,0);let ne=0;const ie=new e.Vector3,le=new e.Vector3,pe=new e.Vector3(0,1,0);let ce=0,ue=!1,me=0,de=0,he=0,ye=!1;const fe=new e.Vector4(0,0,0,0),be=new e.Vector3(1,1,1),ge=new e.Vector3(1,1,1),we=new e.Vector3(1,1,1);let xe,ve,Se,Me,ke,Ge="surface";for(const a of t.initializers.filter(e=>!1!==e.enabled))switch(a.type){case"lifetime":i=n=x(a.params.duration,1);break;case"randomLifetime":{const e=x(a.params.minDuration,1),t=x(a.params.maxDuration,2);i=Math.min(e,t),n=Math.max(e,t);break}case"velocity":{const e=S(a.params.velocity);m.copy(e),d.copy(e);break}case"randomVelocity":m.copy(S(a.params.min)),d.copy(S(a.params.max));break;case"randomDirection":{const e=x(a.params.speed,1);m.setScalar(-e),d.setScalar(e);break}case"radialVelocity":H.copy(S(a.params.direction)).normalize(),K=x(a.params.speed,1),_=e.MathUtils.degToRad(x(a.params.spread,0)),ee=!0;break;case"mass":f=Math.max(1e-6,x(a.params.min,1));break;case"positionPoint":c.copy(new e.Vector4(...S(a.params.position).toArray(),0));break;case"positionSphere":{l=x(a.params.radius,1);const e=S(a.params.position);p=1,c.set(e.x,e.y,e.z,!0===a.params.surface?.value?1:0);break}case"positionBox":{const e=S(a.params.position),t=S(a.params.dimensions);p=2,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionLine":{const e=S(a.params.a),t=S(a.params.b);p=3,c.set(e.x,e.y,e.z,0),u.set(t.x,t.y,t.z,0);break}case"positionCircle":case"positionRing":{const t=S(a.params.position),r=S(a.params.rotation).multiplyScalar(Math.PI/180);l=x(a.params.radius,1);const s="positionRing"===a.type?Math.max(x(a.params.thickness,.2),1e-4):0;p=4,c.set(t.x,t.y,t.z,s),u.set(r.x,r.y,r.z,e.MathUtils.degToRad(Math.max(0,Math.min(360,x(a.params.angle,360)))));break}case"positionMesh":{const r=a.params.mesh?.value,o=a.params.mesh?.binding;if("vfxInput"===o?.type&&(ve=o.inputId),("string"!=typeof r||0===r.length)&&null==ve){w(s,t,"error","mesh-sampler-source","GPU mesh sampling requires a selected fallback mesh asset");break}if(xe="string"==typeof r&&r.length>0?r:void 0,Ge="vertices"===a.params.sampling?.value?"vertices":"surface",Se=(new e.Matrix4).compose(S(a.params.position),(new e.Quaternion).setFromEuler((new e.Euler).setFromVector3(S(a.params.rotation).multiplyScalar(Math.PI/180))),null==a.params.scale?new e.Vector3(1,1,1):S(a.params.scale)),!0===a.params.alignNormal?.value){const t=a.params.alignmentAxis?.value;Me="+X"===t?new e.Vector3(1,0,0):"-X"===t?new e.Vector3(-1,0,0):"-Y"===t?new e.Vector3(0,-1,0):"+Z"===t?new e.Vector3(0,0,1):"-Z"===t?new e.Vector3(0,0,-1):new e.Vector3(0,1,0)}!0===a.params.normalVelocity?.value&&(ke=new e.Vector4(x(a.params.normalVelocityMin,1),x(a.params.normalVelocityMax,1),e.MathUtils.degToRad(e.MathUtils.clamp(x(a.params.normalVelocitySpread,0),0,180)),1)),p=5;break}case"scale":{const e=x(a.params.scale,1);T=[e,e];break}case"scaleComponents":be.copy(S(a.params.scale));break;case"randomScale":T=[x(a.params.min,1),x(a.params.max,1)];break;case"randomColor":j=M(a.params.a,j),F=M(a.params.b,j),Y=!0;break;case"rotation":{const t=S(a.params.rotation);D=q=e.MathUtils.degToRad(t.z),Q.set(e.MathUtils.degToRad(t.x),e.MathUtils.degToRad(t.y),e.MathUtils.degToRad(t.z)),L.setFromEuler(new e.Euler(Q.x,Q.y,Q.z));break}case"randomRotation":{if(o){const e=a.params.axis?.value;W="X"===e?2:"Y"===e?3:"Z"===e?4:1;break}const e=a.params.axis?.value;"XYZ"!==e&&"Z"!==e&&null!=e||(q=2*Math.PI);break}case"alignRotation":{if(!o)break;const e=a.params.axis?.value;"+X"===e?oe.set(1,0,0):"-X"===e?oe.set(-1,0,0):"-Y"===e?oe.set(0,-1,0):"+Z"===e?oe.set(0,0,1):"-Z"===e?oe.set(0,0,-1):oe.set(0,1,0);const t=a.params.mode?.value;ne="TowardsCenter"===t?2:"AlongVelocity"===t?3:1,ie.copy(S(a.params.center)),le.copy(S(a.params.offset)).multiplyScalar(Math.PI/180);break}default:w(s,t,"error",`initializer:${a.type}`,`initializer ${a.type} is not supported on GPU`)}for(const e of t.behaviours.filter(e=>!1!==e.enabled))switch(e.type){case"force":h.add(S(e.params.force));break;case"gravity":h.y-=x(e.params.gravity,8);break;case"linearDamping":y+=x(e.params.factor,.1);break;case"randomDrift":b.copy(S(e.params.drift)),g=Math.max(0,x(e.params.delay,0)),k=v(e.params.ease?.value),G=!0;break;case"followParent":V=x(e.params.speed,0),C=!0;break;case"moveTo":I.copy(S(e.params.target)),O=v(e.params.ease?.value),E=!0;break;case"attraction":case"repulsion":if(se){w(s,t,"error","multiple-attraction-behaviours","multiple attraction or repulsion behaviours are not supported in one GPU emitter");break}te.copy(S(e.params.target)),ae=x(e.params.force,1)*("repulsion"===e.type?-1:1),re=Math.max(0,x(e.params.radius,1)),se=!0;break;case"vortex":if(ue){w(s,t,"error","multiple-vortex-behaviours","multiple vortex behaviours are not supported in one GPU emitter");break}pe.copy(S(e.params.axis)),ce=x(e.params.amount,1),ue=!0;break;case"disperse":{if(ye){w(s,t,"error","multiple-disperse-behaviours","multiple disperse behaviours are not supported in one GPU emitter");break}me=x(e.params.distance,1);const a=e.params.axis?.value;de="XY"===a?1:"XZ"===a?2:"YZ"===a?3:0,he=v(e.params.ease?.value),ye=!0;break}case"worldCollision":U=!0,A=Math.max(0,x(e.params.bounce,0)),R=Math.max(0,Math.min(1,x(e.params.friction,0))),N=Math.max(0,x(e.params.lifeLoss,0)),B=!0===e.params.debug?.value;break;case"scale":z=x(e.params.a,1),$=x(e.params.b,1),fe.x=v(e.params.ease?.value);break;case"scaleComponents":ge.copy(be).multiply(S(e.params.a)),we.copy(be).multiply(S(e.params.b)),fe.w=v(e.params.ease?.value);break;case"changeColor":j=M(e.params.a,j),F=M(e.params.b,F),fe.y=v(e.params.ease?.value),Y=!1;break;case"changeOpacity":X=x(e.params.a,1),Z=x(e.params.b,0),fe.z=v(e.params.ease?.value);break;case"rotate":case"rotateAdd":{const t=S(e.params.rotation);t.multiplyScalar(Math.PI/180*Math.PI/180),o?J.add(t):P=(P??0)+t.z;break}default:w(s,t,"error",`behaviour:${e.type}`,`behaviour ${e.type} is not supported on GPU`)}const Ve=Math.max(0,Math.floor(t.rate.count)),Ce="sprite"!==t.output.type&&"stretchedSprite"!==t.output.type||!Number.isFinite(t.output.intensity)?1:t.output.intensity;j.multiplyScalar(Ce),F.multiplyScalar(Ce);const Ie="once"===t.rate.type?Ve:Math.max(Ve,Math.ceil(n/Math.max(t.rate.time,1e-4))*Ve),Pe=Math.min(25e4,Ie);return Pe!==Ie&&w(s,t,"warning","particle-capacity-clamped",`particle capacity ${Ie} exceeds the current GPU per-emitter limit of ${Pe}`),t.behaviours.some(e=>!1!==e.enabled&&"scaleComponents"===e.type)||(ge.copy(be),we.copy(be)),U&&"local"===t.output.space&&w(s,t,"error","world-collision-local-space","GPU screen-space world collision currently requires world-space output"),{position:(new e.Vector3).fromArray(t.position).add("local"===t.output.space?new e.Vector3:a),localSpace:"local"===t.output.space,capacity:Pe,rate:"once"===t.rate.type?{type:"once",count:Ve,delay:Math.max(0,t.rate.delay??0)}:{type:"continuous",count:Ve,interval:Math.max(t.rate.time,1e-4),delay:Math.max(0,t.rate.delay??0),duration:(t.rate.duration??0)>0?t.rate.duration:-1},life:n,lifeMin:i,positionRadius:l,spawnZoneType:p,spawnZoneA:c,spawnZoneB:u,meshSamplerAssetId:xe,meshSamplerInputId:ve,meshSamplerMode:Ge,meshSamplerTransform:Se,meshSamplerAlignAxis:Me,meshNormalVelocity:ke,velocityMin:m,velocityMax:d,force:h,damping:y,mass:f,randomDrift:b,randomDriftDelay:g,randomDriftEasing:k,hasRandomDrift:G,followParentSpeed:V,hasFollowParent:C,moveToTarget:I,moveToEasing:O,hasMoveTo:E,hasWorldCollision:U,collisionBounce:A,collisionFriction:R,collisionLifeLoss:N,collisionDebug:B,orientAlongVelocity:!1,scaleStart:[T[0]*z,T[1]*z],scaleEnd:[T[0]*$,T[1]*$],colorStart:j,colorEnd:F,randomColor:Y,alphaStart:X,alphaEnd:Z,rotationMin:D,rotationMax:q,spriteRotationStep:P,meshRotation:L,meshRotationEuler:Q,meshRotationStep:J,randomMeshRotationAxis:W,radialVelocityDirection:H,radialVelocitySpeed:K,radialVelocitySpread:_,hasRadialVelocity:ee,attractionTarget:te,attractionForce:ae,attractionRadius:re,hasAttraction:se,alignRotationAxis:oe,alignRotationMode:ne,alignRotationCenter:ie,alignRotationOffset:le,vortexAxis:pe,vortexAmount:ce,hasVortex:ue,disperseDistance:me,dispersePlane:de,disperseEasing:he,hasDisperse:ye,curveEasing:fe,meshScaleStart:ge,meshScaleEnd:we,renderClass:r}}function w(e,t,a,r,s){e.some(e=>e.emitter===t.name&&e.code===r)||e.push({severity:a,code:r,emitter:t.name||t.id,message:s})}function x(e,t){const a=e?.value;if("number"==typeof a)return Number.isFinite(a)?a:t;if("string"==typeof a&&""!==a.trim()){const e=Number(a);if(Number.isFinite(e))return e}return t}function v(e){switch(e){case"InQuad":return 1;case"OutQuad":return 2;case"InOutQuad":return 3;case"InCubic":return 4;case"OutCubic":return 5;case"InOutCubic":return 6;case"InQuart":return 7;case"OutQuart":return 8;case"InOutQuart":return 9;case"InSine":return 10;case"OutSine":return 11;case"InOutSine":return 12;case"InExpo":return 13;case"OutExpo":return 14;case"InOutExpo":return 15;case"InCirc":return 16;case"InBack":return 17;case"OutBack":return 18;case"Bump":return 19;case"BumpSharp":return 20;case"BumpFlat":return 21;case"SpikeFade":return 22;case"OutCirc":return 23;case"InOutCirc":return 24;case"InOutBack":return 25;case"BumpFade":return 26;case"BumpFall":return 27;default:return 0}}function S(t){const a=t?.value;return Array.isArray(a)?new e.Vector3(Number(a[0]),Number(a[1]),Number(a[2])):new e.Vector3}function M(t,a){const r=t?.value;if("string"==typeof r){if(null!=/^#([A-Fa-f0-9]{6})$/.exec(r))return new e.Color(r);const t=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);if(null!=t)return(new e.Color).setRGB(Math.min(255,Number.parseInt(t[1],10))/255,Math.min(255,Number.parseInt(t[2],10))/255,Math.min(255,Number.parseInt(t[3],10))/255,e.SRGBColorSpace)}if("number"==typeof r&&Number.isFinite(r))return new e.Color(Math.floor(r));if(null!=r&&"object"==typeof r&&"r"in r&&"g"in r&&"b"in r){const t=r;return(new e.Color).setRGB(t.r,t.g,t.b)}return a.clone()}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,4 @@
1
+ /** Run synchronous CPU particle simulation with a repeatable random stream. */
2
+ export declare function withSeededRandom<T>(seed: number, callback: () => T): T;
3
+ export declare function hashVfxPreviewSeed(value: string): number;
4
+ //# sourceMappingURL=seeded-random.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function withSeededRandom(t,e){const r=Math.random;let n=t>>>0;Math.random=()=>{n=n+1831565813|0;let t=n;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296};try{return e()}finally{Math.random=r}}export function hashVfxPreviewSeed(t){let e=2166136261;for(let r=0;r<t.length;r++)e=Math.imul(e^t.charCodeAt(r),16777619);return e>>>0}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -49,7 +49,7 @@ export declare class VfxActor extends BaseActor {
49
49
  * simulation on subsequent frames. This is intended for editor scrubbing;
50
50
  * gameplay continues to use play() and onUpdate().
51
51
  */
52
- previewAt(time: number, emissionDuration: number, endBehavior?: VfxClipEndBehavior, expireWithinSeconds?: number): void;
52
+ previewAt(time: number, emissionDuration: number, endBehavior?: VfxClipEndBehavior, expireWithinSeconds?: number, seed?: number): void;
53
53
  /** Clear an editor preview before the corresponding sequence clip begins. */
54
54
  clearPreview(): void;
55
55
  stop(): void;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as s from"three";import{Rate as i}from"@hology/nebula";import{Actor as r,BaseActor as a}from"../../gameplay/actors/actor.js";import{inject as n}from"../../gameplay/inject.js";import{AssetLoader as o}from"../../gameplay/services/asset-loader.js";import{ViewController as l}from"../../gameplay/services/render.js";import{World as p}from"../../gameplay/services/world.js";import{DelayRate as h}from"./rates.js";import{materializeVfx as u}from"./vfx-materializer.js";import{PhysicsSystem as m}from"../../gameplay/services/physics/physics-system.js";import{ShaderProvider as d}from"../../gameplay/services/shader-provider.js";import{AssetResourceLoader as c}from"../../scene/asset-resource-loader.js";import{AssetsProvider as f}from"../../scene/assets-provider.js";import{VfxInputRuntime as g}from"./vfx-input-runtime.js";import{Subject as y}from"rxjs";import{EventGraphCallable as v}from"../../gameplay/event-graph/decorators.js";import{EVENT_GRAPH_VOID_TYPE as b}from"../../gameplay/event-graph/types.js";import{VFX_ACTOR_TYPE_ID as w}from"../../gameplay/event-graph/asset-actor-types.js";import{GpuVfxWorldService as P}from"./gpu-vfx-world-service.js";import{compileGpuSpriteEmitters as S}from"./gpu-sprite-compiler.js";let j=class extends a{constructor(){super(...arguments),this.onComplete=new y,this._timescale=1,this.paused=!0,this.runtimeBackend="cpu",this.backendFallbackReasons=[],this.profilingEnabled=!1,this.simulationCpuMs=0,this.system=null,this.disposeSystem=null,this.assetLoader=n(o),this.assetManagerService=n(c),this.assetService=n(f),this.world=n(p),this.view=n(l),this.gpuWorld=n(P),this.particleSystemContainer=null,this.gpuPrepared=null,this.gpuHandle=null,this.physics=n(m),this.shaderProvider=n(d),this.inputRuntime=new g,this.inputOverrides=new Map,this.finishRequested=!1,this.completionEmitted=!1,this.inputsMaterialized=!1,this._worldPos=new s.Vector3,this._worldRot=new s.Quaternion,this._worldEul=new s.Euler,this._worldScale=new s.Vector3,this.previewStepSeconds=1/60,this.maxPreviewSteps=240,this.max=0}get timescale(){return this._timescale}set timescale(t){this._timescale=Math.max(0,t),this.gpuHandle?.setTimescale(this._timescale)}async fromAsset(t,e,i,r){if("vfx"!==t.type)throw"Asset must be a VFX asset but is "+t.type;null!=this.system&&(this.system.destroy(),this.system.emitters.forEach(t=>t.reset())),this.gpuHandle?.release(),this.gpuPrepared?.release(),this.gpuHandle=null,this.gpuPrepared=null,this.runtimeBackend="cpu",this.backendFallbackReasons=[],this.simulationCpuMs=0,this.sourceAsset=t,this.finishRequested=!1,this.completionEmitted=!1,this.inputsMaterialized=!1,this.disposeSystem&&this.disposeSystem(),null==this.object.parent&&this.world.scene.add(this.object),this.inputRuntime.setDefinitions(this.sourceAsset.vfx.inputs??[]);for(const t of this.inputRuntime.getDefinitions()){if("mesh"!==t.type||"string"!=typeof t.defaultValue||0===t.defaultValue.length)continue;const e=await this.assetService.getAsset(t.defaultValue);if(null==e)continue;const s=await this.assetManagerService.getMesh(e,{applyMaterials:!0,rescale:!0});this.inputRuntime.setInput(t.id,s.scene)}for(const[t,e]of this.inputOverrides)this.inputRuntime.setInput(t,e);null!=e&&this.setInputs(e);const a=i??this.view.vfxBackendPreference;if("cpu"===a&&(this.backendFallbackReasons=["GPU VFX was not requested; the selected VFX backend preference is CPU."]),"cpu"!==a){const t=new Map;for(const e of this.inputRuntime.getDefinitions()){if("mesh"!==e.type)continue;const s=this.inputRuntime.getMesh(e.id);null!=s&&t.set(e.id,s)}if(this.gpuPrepared=await this.gpuWorld.prepare(this.sourceAsset,r,t),null!=this.gpuPrepared)return this.runtimeBackend="gpu",this.system=null,this.disposeSystem=null,this.particleSystemContainer=null,this.object.visible=!1,this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,void(this.inputsMaterialized=!0);if(this.backendFallbackReasons=this.gpuWorld.getFallbackReasons(this.sourceAsset,r),"gpu"===a){const t=S(this.sourceAsset,[new s.Vector3]).compatibility;this.backendFallbackReasons=t.issues.filter(t=>"error"===t.severity).map(t=>`${t.emitter}: ${t.message}`),0===this.backendFallbackReasons.length&&(this.backendFallbackReasons=["GPU template or material preparation failed; inspect earlier shader diagnostics."])}}const{system:n,dispose:o,container:l}=await u(this.sourceAsset,this.object,{getAsset:t=>this.assetLoader.getAsset(t),getMaterial:t=>this.assetLoader.getMaterialByAssetId(t),getTexture:t=>this.assetLoader.getTextureByAssetId(t),getMesh:async t=>(await this.assetManagerService.getMesh(await this.assetService.getAsset(t),{applyMaterials:!0,rescale:!0})).scene},this.view,this.physics,this.shaderProvider,this.assetService,this.assetManagerService,this.inputRuntime);this.system=n,this.disposeSystem=o,this.particleSystemContainer=l,this.inputsMaterialized=!0,this.object.visible=!1,this.object.matrixAutoUpdate=!1,this.object.matrixWorldAutoUpdate=!1,this.particleSystemContainer.matrixAutoUpdate=!1,this.particleSystemContainer.matrixWorldAutoUpdate=!1}setInput(t,e){const i=this.inputRuntime.getDefinition(t);if(this.inputsMaterialized&&"mesh"===i?.type)return void console.warn(`VFX mesh input "${i.name}" is creation-time only; recreate the VFX to replace it.`);this.inputOverrides.set(t,function(t){if(t instanceof s.Vector3||t instanceof s.Color)return t.clone();if(Array.isArray(t))return[...t];return t}(e)),this.inputRuntime.setInput(t,e);const r=this.inputRuntime.getDefinition(t);null!=r&&this.gpuHandle?.setInput(r.id,this.inputRuntime.getValue(r.id))}setInputs(t){for(const[e,s]of Object.entries(t))this.setInput(e,s)}play(){if(this.prepareForPlayback(),this.paused=!1,null!=this.gpuPrepared){if(this.object.getWorldPosition(this._worldPos),null!=this.gpuHandle&&this.gpuHandle.active)this.gpuHandle.play();else{this.gpuHandle=this.gpuPrepared.spawn(this._worldPos),this.gpuHandle?.setTransform(this.object.matrixWorld),this.gpuHandle?.setTimescale(this._timescale);for(const t of this.inputRuntime.getDefinitions())this.gpuHandle?.setInput(t.id,this.inputRuntime.getValue(t.id))}return}this.system.emitters.every(t=>t.dead)&&this.restart()}pause(){this.paused=!0,this.gpuHandle?.pause()}previewAt(t,e,s,i){if(null==this.system)return;this.prepareForPlayback(),this.restart(),this.paused=!0;const r=Math.max(0,t),a=Math.min(r,Math.max(0,e)),n=r-a,o=Number(a>0)+Number(n>0),l=Math.max(o,Math.min(this.maxPreviewSteps,Math.max(1,Math.ceil(r/this.previewStepSeconds)))),p=a<=0?0:n<=0?l:Math.min(l-1,Math.max(1,Math.round(l*a/r)));this.simulatePreview(a,p),n>0&&(this.applyClipEndBehavior(s,i),this.simulatePreview(n,l-p))}clearPreview(){this.restart(),this.pause(),this.object.visible=!1,null!=this.particleSystemContainer&&(this.particleSystemContainer.visible=!1)}stop(){this.finishRequested=!0,null==this.gpuPrepared?null!=this.system?.emitters&&this.system.emitters.forEach(t=>{this.stopEmitterEmission(t)}):this.gpuHandle?.stop()}applyClipEndBehavior(t,e){const s=t??"finish";if("finish"!==s){if(null!=this.gpuPrepared)return this.finishRequested=!0,void("kill"===s?this.gpuHandle?.kill():this.gpuHandle?.expire(Math.max(0,e??0)));if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters)this.applyEmitterClipEndBehavior(t,s,e)}else this.stop()}restart(){if(null==this.gpuPrepared){if(null!=this.system&&null!=this.system.emitters){this.finishRequested=!1,this.completionEmitted=!1;for(const t of this.system.emitters)this.restartEmitter(t)}}else if(this.finishRequested=!1,this.completionEmitted=!1,null!=this.gpuHandle){if(!this.gpuHandle.active&&!this.paused)return void this.play();this.gpuHandle.restart()}}restartEmitter(t){const e=t.rate;e instanceof h?e.restart():e instanceof i&&(e.nextTime=0),null==t.clearParticlesRecursive?this.removeEmitterParticlesRecursive(t):t.clearParticlesRecursive()}removeEmitterParticlesRecursive(t){const e=t.childEmitters??[];for(const t of e)this.removeEmitterParticlesRecursive(t);t.removeAllParticles?.()}onUpdate(t){if(this.paused)null!=this.gpuHandle&&(this.object.getWorldPosition(this._worldPos),this.gpuHandle.setPosition(this._worldPos),this.gpuHandle.setTransform(this.object.matrixWorld));else{if(null!=this.gpuPrepared)return this.object.getWorldPosition(this._worldPos),this.gpuHandle?.setPosition(this._worldPos),this.gpuHandle?.setTransform(this.object.matrixWorld),void this.updateCompletionState();this.updateWorldSpaceEmitterTransforms(),this.updateSystem(t*this.timescale),this.updateCompletionState()}}prepareForPlayback(){null==this.gpuPrepared?(null!=this.particleSystemContainer&&null==this.particleSystemContainer.parent&&this.world.scene.add(this.particleSystemContainer),this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,null!=this.particleSystemContainer&&(this.particleSystemContainer.matrixAutoUpdate=!0,this.particleSystemContainer.matrixWorldAutoUpdate=!0),this.object.visible=!0,null!=this.particleSystemContainer&&(this.particleSystemContainer.visible=!0)):this.object.visible=!0}simulatePreview(t,e){if(t<=0)return;const s=t/e;for(let t=0;t<e;t++)this.updateWorldSpaceEmitterTransforms(),this.updateSystem(s)}updateWorldSpaceEmitterTransforms(){this.object.getWorldPosition(this._worldPos),this.object.getWorldQuaternion(this._worldRot),this.object.getWorldScale(this._worldScale),this._worldEul.setFromQuaternion(this._worldRot),this.system?.emitters.forEach(t=>{if("world"===t._space){t.setPosition(this._worldPos),t.setRotation(this._worldEul);(t._worldScale??(t._worldScale=new s.Vector3)).copy(this._worldScale)}})}getParticleCount(){return null!=this.gpuPrepared?0:this.system?.getCount()??0}getProfilingStats(){let t=0,e=0;return this.particleSystemContainer?.traverse(i=>{const r=i,a=r.geometry;if(null==a||!1===r.visible)return;const n=r instanceof s.InstancedMesh?r.count:1,o=a.index?.count??a.getAttribute("position")?.count??0;n<=0||o<=0||(t++,e+=Math.floor(o/3)*n)}),{particles:this.system?.getCount()??0,drawCalls:t,triangles:e,cpuTimeMs:this.simulationCpuMs}}onEndPlay(){this.stop(),null!=this.disposeSystem&&this.disposeSystem(),this.gpuHandle?.release(),this.gpuPrepared?.release(),this.gpuHandle=null,this.gpuPrepared=null,this.onComplete.complete()}updateCompletionState(){if(null!=this.gpuPrepared){if(this.completionEmitted||!1!==this.gpuHandle?.active)return;return this.completionEmitted=!0,void this.onComplete.next()}if(this.completionEmitted||null==this.system||!this.onComplete.observed)return;const t=this.system.emitters.every(t=>t.dead),e=this.finishRequested&&0===this.system.getCount();(t||e)&&(this.completionEmitted=!0,this.onComplete.next())}updateSystem(t){if(null==this.system)return;if(!this.profilingEnabled)return void this.system.update(t);const e=performance.now();this.system.update(t),this.simulationCpuMs=performance.now()-e}applyEmitterClipEndBehavior(t,e,s,i=!1){this.stopEmitterEmission(t,i);const r=t.particles??[];if("kill"===e)t.removeAllParticles?.();else{const t=Math.max(0,s??0);for(const e of r)e.life=Math.min(e.life,e.age+t)}const a=t.childEmitters??[];for(const t of a)this.applyEmitterClipEndBehavior(t,e,s,!0)}stopEmitterEmission(t,e=!1){const s=t.rate;s instanceof i&&(s.nextTime=1/0),e&&t.stopEmit?.()}};t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],j.prototype,"play",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],j.prototype,"pause",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],j.prototype,"stop",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],j.prototype,"restart",null),j=t([r({typeId:w})],j);export{j as VfxActor};/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as s from"three";import{Rate as i}from"@hology/nebula";import{Actor as r,BaseActor as a}from"../../gameplay/actors/actor.js";import{inject as n}from"../../gameplay/inject.js";import{AssetLoader as o}from"../../gameplay/services/asset-loader.js";import{ViewController as l}from"../../gameplay/services/render.js";import{World as p}from"../../gameplay/services/world.js";import{DelayRate as h}from"./rates.js";import{materializeVfx as u}from"./vfx-materializer.js";import{PhysicsSystem as m}from"../../gameplay/services/physics/physics-system.js";import{ShaderProvider as d}from"../../gameplay/services/shader-provider.js";import{AssetResourceLoader as c}from"../../scene/asset-resource-loader.js";import{AssetsProvider as f}from"../../scene/assets-provider.js";import{VfxInputRuntime as g}from"./vfx-input-runtime.js";import{Subject as y}from"rxjs";import{EventGraphCallable as v}from"../../gameplay/event-graph/decorators.js";import{EVENT_GRAPH_VOID_TYPE as b}from"../../gameplay/event-graph/types.js";import{VFX_ACTOR_TYPE_ID as w}from"../../gameplay/event-graph/asset-actor-types.js";import{GpuVfxWorldService as P}from"./gpu-vfx-world-service.js";import{compileGpuSpriteEmitters as S}from"./gpu-sprite-compiler.js";import{withSeededRandom as j}from"./seeded-random.js";let E=class extends a{constructor(){super(...arguments),this.onComplete=new y,this._timescale=1,this.paused=!0,this.runtimeBackend="cpu",this.backendFallbackReasons=[],this.profilingEnabled=!1,this.simulationCpuMs=0,this.system=null,this.disposeSystem=null,this.assetLoader=n(o),this.assetManagerService=n(c),this.assetService=n(f),this.world=n(p),this.view=n(l),this.gpuWorld=n(P),this.particleSystemContainer=null,this.gpuPrepared=null,this.gpuHandle=null,this.physics=n(m),this.shaderProvider=n(d),this.inputRuntime=new g,this.inputOverrides=new Map,this.finishRequested=!1,this.completionEmitted=!1,this.inputsMaterialized=!1,this._worldPos=new s.Vector3,this._worldRot=new s.Quaternion,this._worldEul=new s.Euler,this._worldScale=new s.Vector3,this.previewStepSeconds=1/60,this.maxPreviewSteps=240,this.max=0}get timescale(){return this._timescale}set timescale(t){this._timescale=Math.max(0,t),this.gpuHandle?.setTimescale(this._timescale)}async fromAsset(t,e,i,r){if("vfx"!==t.type)throw"Asset must be a VFX asset but is "+t.type;null!=this.system&&(this.system.destroy(),this.system.emitters.forEach(t=>t.reset())),this.gpuHandle?.release(),this.gpuPrepared?.release(),this.gpuHandle=null,this.gpuPrepared=null,this.runtimeBackend="cpu",this.backendFallbackReasons=[],this.simulationCpuMs=0,this.sourceAsset=t,this.finishRequested=!1,this.completionEmitted=!1,this.inputsMaterialized=!1,this.disposeSystem&&this.disposeSystem(),null==this.object.parent&&this.world.scene.add(this.object),this.inputRuntime.setDefinitions(this.sourceAsset.vfx.inputs??[]);for(const t of this.inputRuntime.getDefinitions()){if("mesh"!==t.type||"string"!=typeof t.defaultValue||0===t.defaultValue.length)continue;const e=await this.assetService.getAsset(t.defaultValue);if(null==e)continue;const s=await this.assetManagerService.getMesh(e,{applyMaterials:!0,rescale:!0});this.inputRuntime.setInput(t.id,s.scene)}for(const[t,e]of this.inputOverrides)this.inputRuntime.setInput(t,e);null!=e&&this.setInputs(e);const a=i??this.view.vfxBackendPreference;if("cpu"===a&&(this.backendFallbackReasons=["GPU VFX was not requested; the selected VFX backend preference is CPU."]),"cpu"!==a){const t=new Map;for(const e of this.inputRuntime.getDefinitions()){if("mesh"!==e.type)continue;const s=this.inputRuntime.getMesh(e.id);null!=s&&t.set(e.id,s)}if(this.gpuPrepared=await this.gpuWorld.prepare(this.sourceAsset,r,t),null!=this.gpuPrepared)return this.runtimeBackend="gpu",this.system=null,this.disposeSystem=null,this.particleSystemContainer=null,this.object.visible=!1,this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,void(this.inputsMaterialized=!0);if(this.backendFallbackReasons=this.gpuWorld.getFallbackReasons(this.sourceAsset,r),"gpu"===a){const t=S(this.sourceAsset,[new s.Vector3]).compatibility;this.backendFallbackReasons=t.issues.filter(t=>"error"===t.severity).map(t=>`${t.emitter}: ${t.message}`),0===this.backendFallbackReasons.length&&(this.backendFallbackReasons=["GPU template or material preparation failed; inspect earlier shader diagnostics."])}}const{system:n,dispose:o,container:l}=await u(this.sourceAsset,this.object,{getAsset:t=>this.assetLoader.getAsset(t),getMaterial:t=>this.assetLoader.getMaterialByAssetId(t),getTexture:t=>this.assetLoader.getTextureByAssetId(t),getMesh:async t=>(await this.assetManagerService.getMesh(await this.assetService.getAsset(t),{applyMaterials:!0,rescale:!0})).scene},this.view,this.physics,this.shaderProvider,this.assetService,this.assetManagerService,this.inputRuntime);this.system=n,this.disposeSystem=o,this.particleSystemContainer=l,this.inputsMaterialized=!0,this.object.visible=!1,this.object.matrixAutoUpdate=!1,this.object.matrixWorldAutoUpdate=!1,this.particleSystemContainer.matrixAutoUpdate=!1,this.particleSystemContainer.matrixWorldAutoUpdate=!1}setInput(t,e){const i=this.inputRuntime.getDefinition(t);if(this.inputsMaterialized&&"mesh"===i?.type)return void console.warn(`VFX mesh input "${i.name}" is creation-time only; recreate the VFX to replace it.`);this.inputOverrides.set(t,function(t){if(t instanceof s.Vector3||t instanceof s.Color)return t.clone();if(Array.isArray(t))return[...t];return t}(e)),this.inputRuntime.setInput(t,e);const r=this.inputRuntime.getDefinition(t);null!=r&&this.gpuHandle?.setInput(r.id,this.inputRuntime.getValue(r.id))}setInputs(t){for(const[e,s]of Object.entries(t))this.setInput(e,s)}play(){if(this.prepareForPlayback(),this.paused=!1,null!=this.gpuPrepared){if(this.object.getWorldPosition(this._worldPos),null!=this.gpuHandle&&this.gpuHandle.active)this.gpuHandle.play();else{this.gpuHandle=this.gpuPrepared.spawn(this._worldPos),this.gpuHandle?.setTransform(this.object.matrixWorld),this.gpuHandle?.setTimescale(this._timescale);for(const t of this.inputRuntime.getDefinitions())this.gpuHandle?.setInput(t.id,this.inputRuntime.getValue(t.id))}return}this.system.emitters.every(t=>t.dead)&&this.restart()}pause(){this.paused=!0,this.gpuHandle?.pause()}previewAt(t,e,s,i,r=0){null!=this.system&&(this.prepareForPlayback(),j(r,()=>{this.restart(),this.paused=!0;const r=Math.max(0,t),a=Math.min(r,Math.max(0,e)),n=r-a,o=Number(a>0)+Number(n>0),l=Math.max(o,Math.min(this.maxPreviewSteps,Math.max(1,Math.ceil(r/this.previewStepSeconds)))),p=a<=0?0:n<=0?l:Math.min(l-1,Math.max(1,Math.round(l*a/r)));this.simulatePreview(a,p),n>0&&(this.applyClipEndBehavior(s,i),this.simulatePreview(n,l-p))}))}clearPreview(){this.restart(),this.pause(),this.object.visible=!1,null!=this.particleSystemContainer&&(this.particleSystemContainer.visible=!1)}stop(){this.finishRequested=!0,null==this.gpuPrepared?null!=this.system?.emitters&&this.system.emitters.forEach(t=>{this.stopEmitterEmission(t)}):this.gpuHandle?.stop()}applyClipEndBehavior(t,e){const s=t??"finish";if("finish"!==s){if(null!=this.gpuPrepared)return this.finishRequested=!0,void("kill"===s?this.gpuHandle?.kill():this.gpuHandle?.expire(Math.max(0,e??0)));if(null!=this.system&&null!=this.system.emitters)for(const t of this.system.emitters)this.applyEmitterClipEndBehavior(t,s,e)}else this.stop()}restart(){if(null==this.gpuPrepared){if(null!=this.system&&null!=this.system.emitters){this.finishRequested=!1,this.completionEmitted=!1;for(const t of this.system.emitters)this.restartEmitter(t)}}else if(this.finishRequested=!1,this.completionEmitted=!1,null!=this.gpuHandle){if(!this.gpuHandle.active&&!this.paused)return void this.play();this.gpuHandle.restart()}}restartEmitter(t){const e=t.rate;e instanceof h?e.restart():e instanceof i&&(e.nextTime=0),null==t.clearParticlesRecursive?this.removeEmitterParticlesRecursive(t):t.clearParticlesRecursive()}removeEmitterParticlesRecursive(t){const e=t.childEmitters??[];for(const t of e)this.removeEmitterParticlesRecursive(t);t.removeAllParticles?.()}onUpdate(t){if(this.paused)null!=this.gpuHandle&&(this.object.getWorldPosition(this._worldPos),this.gpuHandle.setPosition(this._worldPos),this.gpuHandle.setTransform(this.object.matrixWorld));else{if(null!=this.gpuPrepared)return this.object.getWorldPosition(this._worldPos),this.gpuHandle?.setPosition(this._worldPos),this.gpuHandle?.setTransform(this.object.matrixWorld),void this.updateCompletionState();this.updateWorldSpaceEmitterTransforms(),this.updateSystem(t*this.timescale),this.updateCompletionState()}}prepareForPlayback(){null==this.gpuPrepared?(null!=this.particleSystemContainer&&null==this.particleSystemContainer.parent&&this.world.scene.add(this.particleSystemContainer),this.object.matrixAutoUpdate=!0,this.object.matrixWorldAutoUpdate=!0,null!=this.particleSystemContainer&&(this.particleSystemContainer.matrixAutoUpdate=!0,this.particleSystemContainer.matrixWorldAutoUpdate=!0),this.object.visible=!0,null!=this.particleSystemContainer&&(this.particleSystemContainer.visible=!0)):this.object.visible=!0}simulatePreview(t,e){if(t<=0)return;const s=t/e;for(let t=0;t<e;t++)this.updateWorldSpaceEmitterTransforms(),this.updateSystem(s)}updateWorldSpaceEmitterTransforms(){this.object.getWorldPosition(this._worldPos),this.object.getWorldQuaternion(this._worldRot),this.object.getWorldScale(this._worldScale),this._worldEul.setFromQuaternion(this._worldRot),this.system?.emitters.forEach(t=>{if("world"===t._space){t.setPosition(this._worldPos),t.setRotation(this._worldEul);(t._worldScale??(t._worldScale=new s.Vector3)).copy(this._worldScale)}})}getParticleCount(){return null!=this.gpuPrepared?0:this.system?.getCount()??0}getProfilingStats(){let t=0,e=0;return this.particleSystemContainer?.traverse(i=>{const r=i,a=r.geometry;if(null==a||!1===r.visible)return;const n=r instanceof s.InstancedMesh?r.count:1,o=a.index?.count??a.getAttribute("position")?.count??0;n<=0||o<=0||(t++,e+=Math.floor(o/3)*n)}),{particles:this.system?.getCount()??0,drawCalls:t,triangles:e,cpuTimeMs:this.simulationCpuMs}}onEndPlay(){this.stop(),null!=this.disposeSystem&&this.disposeSystem(),this.gpuHandle?.release(),this.gpuPrepared?.release(),this.gpuHandle=null,this.gpuPrepared=null,this.onComplete.complete()}updateCompletionState(){if(null!=this.gpuPrepared){if(this.completionEmitted||!1!==this.gpuHandle?.active)return;return this.completionEmitted=!0,void this.onComplete.next()}if(this.completionEmitted||null==this.system||!this.onComplete.observed)return;const t=this.system.emitters.every(t=>t.dead),e=this.finishRequested&&0===this.system.getCount();(t||e)&&(this.completionEmitted=!0,this.onComplete.next())}updateSystem(t){if(null==this.system)return;if(!this.profilingEnabled)return void this.system.update(t);const e=performance.now();this.system.update(t),this.simulationCpuMs=performance.now()-e}applyEmitterClipEndBehavior(t,e,s,i=!1){this.stopEmitterEmission(t,i);const r=t.particles??[];if("kill"===e)t.removeAllParticles?.();else{const t=Math.max(0,s??0);for(const e of r)e.life=Math.min(e.life,e.age+t)}const a=t.childEmitters??[];for(const t of a)this.applyEmitterClipEndBehavior(t,e,s,!0)}stopEmitterEmission(t,e=!1){const s=t.rate;s instanceof i&&(s.nextTime=1/0),e&&t.stopEmit?.()}};t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],E.prototype,"play",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],E.prototype,"pause",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],E.prototype,"stop",null),t([v({parameters:[],returns:b}),e("design:type",Function),e("design:paramtypes",[]),e("design:returntype",void 0)],E.prototype,"restart",null),E=t([r({typeId:w})],E);export{E as VfxActor};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,9 @@
1
+ import { NodeShaderMaterial } from 'three-shader-graph';
2
+ import type { VfxAssetProvider } from './vfx-materializer.js';
3
+ /**
4
+ * Adds particle tint and opacity at the source material's named uniform reads.
5
+ * This retains the complete graph (including all maps and physical features)
6
+ * and applies tint to the albedo before lighting rather than to the final BRDF.
7
+ */
8
+ export declare function createGpuMeshAssetMaterial(materialId: string, assetProvider: VfxAssetProvider): Promise<NodeShaderMaterial>;
9
+ //# sourceMappingURL=vfx-gpu-material.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as r from"three";import{NodeShaderMaterial as e,deriveNodeShaderMaterial as o,float as t,getNodeMaterialDefinition as a,rgb as i,uniformFloat as s,uniformVec3 as n}from"three-shader-graph";import{particleColorUniformName as l,particleOpacityUniformName as m}from"../../shader-nodes/particle.js";export async function createGpuMeshAssetMaterial(u,p){const c=await p.getMaterial(u);if(!(c instanceof e))throw new Error(`GPU mesh material ${u} did not resolve to a NodeShaderMaterial`);const f=a(c).graph,h=c.uniforms.color?.value,d=c.uniforms.opacity?.value,y=h instanceof r.Color?h:new r.Color(16777215),w="number"==typeof d?d:1,M=n(l),g=s(m),v=o(c,{uniformNodes:{...f.uniformNodes,color:M.multiply(i(y)),opacity:g.multiply(t(w))}});return v.userData={...c.userData},v}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import e,{Behaviour as t,Body as a,Emitter as r,Rate as s}from"@hology/nebula";import*as i from"three";import{Object3D as n}from"three";import{AttributeVec3Node as l,AttributeVec4Node as o,NodeShaderMaterial as c,RgbNode as p,UniformFloatNode as u,UniformVec3Node as d,Vec3ExpressionNode as h,attributeVec3 as m,attributeVec4 as f,attributes as y,clamp as g,cross as w,float as b,lambertMaterial as v,length as M,log as A,normalize as E,pow as x,rgb as S,rgba as I,smoothstep as T,standardMaterial as P,textureSampler2d as C,uniforms as R,varying as B,varyingAttributes as G,varyingVec3 as k,varyingVec4 as j,vec2 as D,vec3 as F,vec4 as V}from"three-shader-graph";import{prepareClassParameters as L,prepareShaderGraphParameters as O,prepareShapeParameters as W}from"../../scene/materializer.js";import{SerializedParamType as U}from"../../scene/model.js";import{ShapeLibrary as N}from"../../scene/objects/shapes.js";import{fragmentLinearEyeDepth as Q,linearEyeDepth as H}from"../../shader-nodes/depth.js";import{particleEnergyUniformName as q,particleTimeUniformName as z,particleUniforms as J,particleVelcoityUniformName as X}from"../../shader-nodes/particle.js";import{sampleFlipbook as _}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as K,WorldSpaceEmitterTransformInitializer as Y}from"./initializsers.js";import{DelayRate as Z,OnceRate as $}from"./rates.js";import{StretchedSprite as ee}from"./stretched-sprite.js";import{ThreeBlendingMode as te}from"./vfx-asset.js";import{VfxBehaviourLibrary as ae,VfxInitializserLibrary as re}from"./vfx-defs.js";import{MultiRenderer as se}from"./vfx-renderers.js";import{WorldCollisionBehaviour as ie}from"./vfx-collision-behaviour.js";import{getSpritePosition as ne,SpriteNodeShader as le,SpriteNodeShaderMaterial as oe}from"../../shader/sprite-shader.js";import{DecalUnlitShader as ce}from"../../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as pe}from"../../shader/builtin/decal-standard-shader.js";import{createBoundBehaviour as ue,createBoundInitializer as de}from"./vfx-binding-runtime.js";import{buildShaderGraphMaterial as he}from"../../shader/graph/index.js";import{markMaterialUniformValuesNeedUpdate as me,setMaterialUniformValuesAutoUpdate as fe}from"../../rendering/node-material-webgpu-resolver.js";import{applyMeshWorldTransformToGeometry as ye}from"./vfx-mesh-transform.js";export async function materializeVfx(t,a,r,s,l,o,c,p,u){let d=a;for(;null!=d.parent;)d=d.parent;const h=new n;h.name="particle system local",a.add(h);const m=new n;m.name="particle system world";const f=new se(m,h,i,s),y=new e;return(await Promise.all(t.vfx.emitters.slice().sort((e,t)=>(t.output.renderOrder??0)-(e.output.renderOrder??0)).map(async e=>{const t=await we(e,r,c,p,y,l,o,u,a);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:m,system:y,dispose:()=>{m.removeFromParent(),h.removeFromParent(),f.dispose()}}}function ge(e,t){let a;const r=function(e,t){const a=Math.max(0,e.rate.delay??0),r=e.rate.delayBinding;if("vfxInput"!==r?.type||null==t)return a;const s=t.getDefinition(r.inputId);return"number"!==s?.type?a:Math.max(0,t.getNumber(r.inputId,a))}(e,t);switch(e.rate.type){case"continuous":a=new Z(r,e.rate.count,e.rate.time,e.rate.duration);break;case"once":a=new $(r,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),a=new s(0,1/0)}return a}async function we(e,t,r,s,p,x,S,P,D){const F=ge(e,P);let L;switch(e.output.type){case"decal":L=new a(await async function(e,t,a,r,s){if("shaderGraph"===ve(e)){const t=await createShaderGraphMaterial(e,"decal",a,r,s);if(null!=t){const a=new i.Mesh(new i.BoxGeometry(1,1,1),t);return Ee(a,e),a}}const n=!1!==e.unlit?new ce:new pe;n.color=new i.Color(e.color),n instanceof ce?n.intensity=e.intensity??1:n.emissiveIntensity=e.intensity??1;if(e.colorMap){const a=await t.getTexture(e.colorMap);n.colorMap=a}if(e.alphaMap){const a=await t.getTexture(e.alphaMap);n.alphaMap=a}const l=n.build();l.blending=te[e.blendingMode]??i.NormalBlending,l.transparent=!0,l.side=i.BackSide,l.depthTest=!1,null!=l&&!0===e.bloom&&(l.userData.hasBloom=!0);l.defines.IS_PARTICLE="";const o=new i.BoxGeometry(1,1,1),c=new i.Mesh(o,l);return Ee(c,e),c}(e.output,t,r,s,S));break;case"sprite":L=new a(await async function(e,t,a,r,s){let n=null;const l=ve(e);"shaderGraph"===l&&(n=await createShaderGraphMaterial(e,"sprite",a,r,s));null==n&&"shader"===l&&null!=e.shader&&(n=await createShaderMaterial(e,t,s));null==n&&(n=await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):be,r=C(a);let s=r.sample(G.uv);e.flipbook?.enabled&&(s=_(r,y.uv,e.flipbook.columns,e.flipbook.rows,J.time,e.flipbook.fps,e.flipbook.mode));const n=new u("rotation",0),l=new d("color").rgb,o=k(new h("instanceColor")).rgb,c=H.subtract(Q).divide(H);let p=J.opacity;switch(e.opacityChannel??"red"){case"none":break;case"red":p=p.multiply(s.r);break;case"alpha":p=p.multiply(s.a)}if("number"==typeof e.softness&&e.softness>0){const t=g(c,0,1e3);p=p.multiply(T(0,.2*e.softness,t))}const m=ne(n,void 0,void 0,!0),f=I(l.multiply(o).multiply(s.rgb).multiplyScalar(e.intensity??1),p);var w=new oe({color:f,emissive:f.rgb.multiplyScalar(p),transparent:!0,position:m,alphaTest:1e-4,uniforms:{color:{value:new i.Color(e.color)}}});w.alphaHash=!0,null!=w&&!0===e.bloom&&(w.userData.hasBloom=!0);return w.blending=te[e.blendingMode]??i.NormalBlending,w}(e,t));n.depthWrite=!1,Ae(n,e);const o=new i.Mesh(new i.PlaneGeometry(1,1),n);return o.name="sprite",Ee(o,e),o}(e.output,t,r,s,S));break;case"stretchedSprite":L=new a(await async function(e,t){"shaderGraph"===ve(e)&&console.warn("Shader graph materials are not supported for stretched sprite VFX outputs yet. Falling back to the default stretched sprite material.");const a=null!=e.texture?await t.getTexture(e.texture):be,r=C(a).sample(G.uv),s=j(new o("particleColor")),n=s.rgb.multiply(r.rgb);let l=s.w;switch(e.opacityChannel??"red"){case"none":break;case"red":l=l.multiply(r.r);break;case"alpha":l=l.multiply(r.a)}if("number"==typeof e.softness&&e.softness>0){const t=H.subtract(Q).divide(A(H)),a=g(t,0,1e3);l=l.multiply(T(0,.2*e.softness,a))}const c=m("offset"),p=f("velocity"),u=m("size"),d=p.w,h=u.x.add(u.y).multiply(.5),v=R.modelViewMatrix.multiplyVec(V(c,1)),x=R.normalMatrix.multiplyVec(p.xyz),S=E(w(v.xyz,x)).multiplyScalar(y.position.y.multiply(h)),P=x.multiplyScalar(y.position.x.add(.5).multiply(b(1).add(d.divide(M(x)))).multiply(h)),B=R.projectionMatrix.multiplyVec(V(v.xyz.add(S).subtract(P),v.w));var k=new oe({color:I(n.multiplyScalar(e.intensity??1),l),alphaTest:.1,transparent:!0,position:B,uniforms:{color:{value:new i.Color(e.color)}}});null!=k&&!0===e.bloom&&(k.userData.hasBloom=!0);k.blending=te[e.blendingMode]??i.NormalBlending;const D=new ee(new i.PlaneGeometry(1,1),k);return D.scaleFactor=e.scale,Ee(D,e),D}(e.output,t));break;case"shape":L=new a(await async function(e,t,a,r,s){if(null==e.shape)return console.log("Shape is null"),new n;const o=N[e.shape];if(null==o)return console.error(`No shape with type ${e.shape}`),new n;const p=W(e.params??{}),u=o.geometry(p);let d=null;const m=ve(e);"shaderGraph"===m&&(d=await createShaderGraphMaterial(e,"surface",a,r,s));null==d&&"shader"===m&&null!=e.shader&&(d=await createShaderMaterial(e,t,s));null==d&&(d="material"===m&&null!=e.material?xe(await t.getMaterial(e.material)):function(){const e=B(new h("instanceColor")).rgb,t=B(new l("particleData")).x;return new c({color:v({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());Ae(d,e);const f=new i.Mesh(u,d);return Ee(f,e),f}(e.output,t,r,s,S));break;case"mesh":L=new a(await async function(e,t,a,r,s){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new n;const l=await t.getMesh(e.assetId),o=await t.getAsset(e.assetId),c=ve(e);if("shaderGraph"===c||"shader"===c&&null!=e.shader||"material"===c&&null!=e.material){let n;"shaderGraph"===c?n=await createShaderGraphMaterial(e,"surface",a,r,s):"shader"===c&&null!=e.shader?n=await createShaderMaterial(e,t,s):"material"===c&&null!=e.material&&(n=xe(await t.getMaterial(e.material))),n?.transparent&&(n.depthWrite=!1),null!=n&&Ae(n,e),l.traverse(e=>{e instanceof i.Mesh&&null!=n&&(e.material=n)})}else{const e=[];if(null!=o.materialAssignments)for(const a of o.materialAssignments)null!=a.materialId&&l.traverse(r=>{r instanceof i.Mesh&&r.material instanceof i.Material&&r.material.color instanceof i.Color&&(r.material.name!=a.name&&null!=a.name||"#"+r.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>r.material=e)))});await Promise.all(e)}const p=[];if(l.traverse(e=>{e instanceof i.Mesh&&p.push(e)}),Ee(l,e),1===p.length){const t=p[0];return!0!==e.useLegacyTransform&&function(e){e.geometry=e.geometry.clone(),ye(e,e.geometry),e.position.set(0,0,0),e.quaternion.identity(),e.scale.set(1,1,1),e.updateMatrix(),e.matrixWorld.identity()}(t),t.removeFromParent(),t}return l}(e.output,t,r,s,S));break;case"trail":{const n="shaderGraph"===ve(e.output)?await createShaderGraphMaterial(e.output,"trail",r,s,S,{trailBillboard:e.output.billboard??!1}):null;L=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:n instanceof i.ShaderMaterial?n:void 0,dragTexture:!1,texture:null!=e.output.texture?await t.getTexture(e.output.texture):null,opacityChannel:e.output.opacityChannel,color:e.output.color,colorEnd:e.output.colorEnd,intensity:e.output.intensity??1,intensityEnd:e.output.intensityEnd??1,length:e.output.length,opacityStart:e.output.opacityStart,opacityEnd:e.output.opacityEnd,bloom:e.output.bloom,scrollSpeed:e.output.scrollSpeed,width:e.output.width,billboard:e.output.billboard??!1,renderOrder:e.output.renderOrder});break}default:console.error("Failed to create particly system body: "+JSON.stringify(e))}const O=new Ie(D);O.parent=p,O.setRate(F),O._space=e.output.space;const q=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=re[e.type]).map(async e=>{const t=re[e.type],a=await W(e.params??{},r,s);return de(t,e.params??{},a,P)}));"world"===e.output.space&&q.push(new Y("shape"===e.output.type||"mesh"===e.output.type)),q.push(L,new K),O.addInitializers(q);const z=await Promise.all(e.behaviours.filter(e=>!1!==e.enabled).filter(e=>null!=ae[e.type]).map(async e=>{const t=ae[e.type];for(const[a,r]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&r.type!==U.Curve&&(r.type=U.Curve);const a=await W(e.params??{},r,s);return ue(t,e.params??{},a,P)}).sort((e,t)=>e instanceof ie?1:0));z.push(new Se);for(const e of z)e instanceof ie&&(e.physics=x);O.addBehaviours(z);for(const a of e.children??[]){const e=await we(a,t,r,s,p,x,S,P,D),i=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=O.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&O.childEmitters.splice(e,1),null!=t.parentParticle&&(l.delete(t.parentParticle.id),t.parentParticle=null),i.release(t)},t}),n=O.eventDispatcher,l=new Map;O.bindEmitterEvent=!0,n.addEventListener("PARTICLE_DEAD",e=>{const t=l.get(e.id);null!=t&&(O.detachChildEmitterFromParticle(t,e),l.delete(e.id))});let o="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":o="PARTICLE_COLLISION";break;case"start":o="PARTICLE_CREATED"}n.addEventListener(o,e=>{const t=i.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),O.childEmitters.push(t),l.set(e.id,t),t.parentParticle=e,t.system=O.system,t.emit()})}return O}const be=(new i.TextureLoader).load("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJkSURBVHjaxJeJbusgEEW94S1L//83X18M2MSuLd2pbqc4wZGqRLrKBsyZhQHny7Jk73xVL8xpVhWrcmiB5lX+6GJ5YgQ2owbAm8oIwH1VgKZUmGcRqKGGPgtEQQAzGR8hQ59fAmhJHSAagigJ4E7GPWRXOYC6owAd1JM6wDQPADyMWUqZRMqmAojHp1Vn6EQQEgUNMJLnUjMyJsM49wygBkAPw9dVFwXRkncCIIW3GRgoTQUZn6HxCMAFEFd8TwEQ78X4rHbILoAUmeT+RFG4UhQ6MiIAE4W/UsYFjuVjAIa2nIY4q1R0GFtQWG3E84lqw2GO2QOoCKBVu0BAPgDSU0eUDjjQenNkV/AW/pWChhpMTelo1a64AOKM30vk18GzTHXCNtI/Knz3DFBgsUqBGIjTInXRY1yA9xkVoqW5tVq3pDR9A0hfF5BSARmVnh7RMDCaIdcNgbPBkgzn1Bu+SfIEFSpSBmkxyrMicb0fAEuCZrWnN89veA/4XcakrPcjBWzkTuLjlbfTQPOlBhz+HwkqqPXmPQDdrQItxE1moGof1S74j/8txk8EHhTQrAE8qlwfqS5yukm1x/rAJ9Jiaa6nyATqD78aUVBhFo8b1V4DdTXdCW+IxA1zB4JhiOhZMEWO1HqnvdoHZ4FAMIhV9REF8FiUm0jsYPEJx/Fm/N8OhH90HI9YRHesWbXXZwAShU8qThe7H8YAuJmw5yOd989uRINKRTJAhoF8jbqrHKfeCYdIISZfSq26bk/K+yO3YvfKrVgiwQBHnwt8ynPB25+M8hceTt/ybPhnryJ78+tLgAEAuCFyiQgQB30AAAAASUVORK5CYII=");export async function createShaderMaterial(e,t,a){const r=a.get(e.shader);if(null==r)return console.error("No shader exists with name "+e.shader),new i.Material;const s=new r.type;"sprite"===e.type&&s instanceof le&&(s.instanced=!0);const n=await L(e.shaderParams??{},r.type,t,{getTexture:e=>t.getTexture(e.id),getMaterial:e=>t.getMaterial(e.id),getMesh:e=>t.getMesh(e.id)},void 0,void 0,void 0,void 0,void 0,s);return Object.assign(s,n),s.build()}export async function createShaderGraphMaterial(e,t,a,r,s,i={}){const n=e.shaderGraph;if("asset"!==n?.source||null==n.assetId)return console.warn(`Missing shader graph asset reference for ${e.type} VFX output`),null;const l=await a.getAsset(n.assetId),o=l?.shaderGraph;if(null==o)return console.warn(`Missing shader graph asset "${n.assetId}" for ${e.type} VFX output`),null;if(o.target!==t)return console.warn(`Shader graph "${l.name}" targets "${o.target}" but ${e.type} VFX output expects "${t}"`),null;try{const t=await O(e.shaderGraphParams??{},o,a,r,void 0,s.shaders),l=he(o,{parameters:t,trailBillboard:i.trailBillboard});return l.userData.customShaderName=`shaderGraph:${n.assetId}`,Ae(l,e),l}catch(e){return console.log("Shader graph VFX runtime error: "+e,e),null}}export function createGpuSpriteShaderGraphResolver(e,t,a,r){return async s=>{const n=ve(s);let l=null;if("shaderGraph"===n)l=await createShaderGraphMaterial(s,"sprite"===s.type?"sprite":"decal"===s.type?"decal":"trail"===s.type?"trail":"surface",e,t,a,"trail"===s.type?{trailBillboard:s.billboard??!1}:void 0);else if("shader"===n&&"decal"!==s.type&&null!=r)l=await createShaderMaterial(s,r,a);else if("material"!==n||"mesh"!==s.type&&"shape"!==s.type||null==s.material||null==r){if("default"===n&&"mesh"===s.type&&null!=s.assetId&&null!=r){const e=await r.getAsset(s.assetId),t=e.materialAssignments?.find(e=>null!=e.materialId);null!=t&&(l=await Me(t.materialId,r))}else if("default"===n&&"decal"===s.type&&null!=r){const e=!1!==s.unlit?new ce:new pe;e.color=new i.Color(s.color),e instanceof ce?e.intensity=s.intensity??1:e.emissiveIntensity=s.intensity??1,s.colorMap&&(e.colorMap=await r.getTexture(s.colorMap)),s.alphaMap&&(e.alphaMap=await r.getTexture(s.alphaMap)),l=e.build(),l.transparent=!0}}else l="mesh"===s.type?await Me(s.material,r):xe(await r.getMaterial(s.material));return null==l?null:("mesh"!==s.type&&"shape"!==s.type||!l.transparent||(l.depthWrite=!1),l instanceof c?l:(console.warn(`GPU ${s.type} materials must compile to NodeShaderMaterial; using CPU fallback`),null))}}function ve(e){return null!=e.materialSource?("material"!==e.materialSource||"mesh"!==e.type&&"shape"!==e.type||null!=e.material)&&("shaderGraph"!==e.materialSource||"asset"===e.shaderGraph?.source&&null!=e.shaderGraph.assetId)&&("shader"!==e.materialSource||"shader"in e&&null!=e.shader)?e.materialSource:"default":"asset"===e.shaderGraph?.source?"shaderGraph":"shader"in e&&null!=e.shader?"shader":"mesh"!==e.type&&"shape"!==e.type||null==e.material?"default":"material"}async function Me(e,t){const a=(await t.getAsset(e)).material,r=a?.shaderParams??{},s=a?.params??{},n=r.color?.value??s.color??"#ffffff",l=r.opacity?.value??s.opacity??1,o=r.intensity?.value??s.intensity??1,p=r.map?.value??s.map,u=r.alphaMap?.value??s.alphaMap;let d=J.color.rgb.multiply(S(new i.Color(n))).multiplyScalar(b(o)),h=J.opacity.multiply(b(l));if(null!=p){const e=C(await t.getTexture(p)).sample(G.uv);d=d.multiply(e.rgb),h=h.multiply(e.a)}null!=u&&(h=h.multiply(C(await t.getTexture(u)).sample(G.uv).r));const m=new c({color:d.rgba(h),opacity:h,transparent:!0===a?.transparent||l<1||null!=u});return m.blending=te[a?.blending]??i.NormalBlending,m.alphaTest=a?.alphaTest??0,m.side=a?.side??i.FrontSide,m.transparent&&(m.depthWrite=!1),m}function Ae(e,t){null!=e&&(fe(e,!1),"bloom"in t&&!0===t.bloom&&(e.userData.hasBloom=!0),"sprite"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,!0===t.lockY&&e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.LOCK_Y_AXIS="")):"decal"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,e.transparent=!0,e.side=i.BackSide,e.depthTest=!1,e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE="")):"shape"!==t.type&&"mesh"!==t.type||e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE=""))}function Ee(e,t){const a=t.renderOrder;null!=a&&e.traverse(e=>e.renderOrder=a)}function xe(e){const t=B(new h("instanceColor")).rgb;let a,r=B(new l("particleData")).x;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial){let s=t.multiply(S(e.color));null!=e.map&&(s=s.multiply(C(e.map).sample(G.uv).rgb)),null!=e.alphaMap&&(r=r.multiply(C(e.alphaMap).sample(G.uv).r)),e instanceof i.MeshStandardMaterial?a=new c({color:P({color:s,emissive:S(e.emissive),emissiveIntensity:b(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshLambertMaterial?a=new c({color:v({color:s}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshBasicMaterial&&(a=new c({color:s.rgb.rgba(r),emissive:s.rgb,transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}))}else e instanceof c&&(a=e.clone(),a.defines.IS_PARTICLE="");return null!=a&&(!0===e.userData?.hasBloom&&null!=a&&(a.userData.hasBloom=!0),a.side=e.side,a.transparent=e.transparent),a??e}class Se extends t{initialize(e){e.body instanceof i.Object3D&&e.body.traverse(e=>{if(e instanceof i.Mesh){const t=e.material;t instanceof c&&(null!=t.uniforms[q]||null!=t.uniforms[z]||t.uniforms[X])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof n&&e.target.traverse(t=>{if(t instanceof i.Mesh){const a=t.material;if(a instanceof c){let t=!1;null!=a.uniforms[q]&&(a.uniforms[q].value=this.energy,t=!0),null!=a.uniforms[z]&&(a.uniforms[z].value=e.age,t=!0),null!=a.uniforms[X]&&(a.uniforms[X].value=e.velocity,t=!0),t&&me(a)}}})}}class Ie extends r{constructor(e){super(),this.transformRoot=e,this.childEmitters=[],this.bindEmitterEvent=!1,this.onExpired=()=>{}}clearParticlesRecursive(){let e=this.childEmitters.length;for(;e--;){const t=this.childEmitters[e];t.stopEmit(),t.clearParticlesRecursive(),t.onExpired()}this.childEmitters.length=0;let t=this.particles.length;for(;t--;){const e=this.particles[t];this.system?.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),null!=this.system?this.system.pool.expire(e.reset()):e.reset()}this.particles.length=0}detachChildEmitterFromParticle(e,t){this.copyPositionToChildSpace(e,t.position),e.parentParticle=null,e.stopEmit()}update(e){if(!this.isEmitting&&0===this.particles.length&&0===this.childEmitters.length)return;this.age+=e,(this.dead||this.age>=this.life)&&this.destroy(),this.isEmitting&&this.generate(e),this.integrate(e);let t=this.particles.length;for(;t--;){const e=this.particles[t];e.dead&&(this.system&&this.system.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),this.system.pool.expire(e.reset()),this.particles.splice(t,1))}this.updateEmitterBehaviours(e),this.updateChildren(e),this.isEmitting||0!==this.particles.length||0!==this.childEmitters.length||this.onExpired()}updateChildren(e){for(const t of this.childEmitters)null!=t.parentParticle&&this.copyPositionToChildSpace(t,t.parentParticle.position),t.update(e)}copyPositionToChildSpace(e,t){const a=this._space??"world",r=e._space??"world";a!==r&&null!=this.transformRoot?(Te.copy(t),"local"===a&&"world"===r?Te.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(Pe.copy(this.transformRoot.matrixWorld).invert(),Te.applyMatrix4(Pe)),e.position.copy(Te)):e.position.copy(t)}clone(){const e=new Ie(this.transformRoot);return e.setRate(this.rate.clone()),e.behaviours=this.behaviours,e.initializers=this.initializers,e._space=this._space,e.body=this.body,e.parent=this.parent,e.system=this.system,e}setParentRecursive(e){this.system=e,this.childEmitters.forEach(t=>t.setParentRecursive(e))}}const Te=new i.Vector3,Pe=new i.Matrix4;export class EmitterPool{constructor(e){this.creator=e,this.instances=[]}get(){0==this.instances.length&&this.instances.push(this.creator());return this.instances.pop()}release(e){this.instances.push(e)}dispose(){this.instances.length=0}}/*
1
+ import e,{Behaviour as t,Body as a,Emitter as r,Rate as s}from"@hology/nebula";import*as i from"three";import{Object3D as n}from"three";import{AttributeVec3Node as l,AttributeVec4Node as o,NodeShaderMaterial as c,RgbNode as p,UniformFloatNode as u,UniformVec3Node as h,Vec3ExpressionNode as d,attributeVec3 as m,attributeVec4 as f,attributes as y,clamp as w,cross as g,float as b,lambertMaterial as M,length as v,log as E,normalize as A,pow as x,rgb as S,rgba as I,smoothstep as P,standardMaterial as T,textureSampler2d as C,uniforms as R,varying as G,varyingAttributes as B,varyingVec3 as j,varyingVec4 as k,vec2 as D,vec3 as F,vec4 as V}from"three-shader-graph";import{prepareClassParameters as L,prepareShaderGraphParameters as O,prepareShapeParameters as W}from"../../scene/materializer.js";import{SerializedParamType as U}from"../../scene/model.js";import{ShapeLibrary as Q}from"../../scene/objects/shapes.js";import{fragmentLinearEyeDepth as H,linearEyeDepth as N}from"../../shader-nodes/depth.js";import{particleEnergyUniformName as q,particleTimeUniformName as z,particleUniforms as J,particleVelcoityUniformName as X}from"../../shader-nodes/particle.js";import{sampleFlipbook as _}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as K,WorldSpaceEmitterTransformInitializer as Y}from"./initializsers.js";import{DelayRate as Z,OnceRate as $}from"./rates.js";import{StretchedSprite as ee}from"./stretched-sprite.js";import{ThreeBlendingMode as te}from"./vfx-asset.js";import{VfxBehaviourLibrary as ae,VfxInitializserLibrary as re}from"./vfx-defs.js";import{MultiRenderer as se}from"./vfx-renderers.js";import{WorldCollisionBehaviour as ie}from"./vfx-collision-behaviour.js";import{getSpritePosition as ne,SpriteNodeShader as le,SpriteNodeShaderMaterial as oe}from"../../shader/sprite-shader.js";import{DecalUnlitShader as ce}from"../../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as pe}from"../../shader/builtin/decal-standard-shader.js";import{createBoundBehaviour as ue,createBoundInitializer as he}from"./vfx-binding-runtime.js";import{buildShaderGraphMaterial as de}from"../../shader/graph/index.js";import{markMaterialUniformValuesNeedUpdate as me,setMaterialUniformValuesAutoUpdate as fe}from"../../rendering/node-material-webgpu-resolver.js";import{applyMeshWorldTransformToGeometry as ye}from"./vfx-mesh-transform.js";import{createGpuMeshAssetMaterial as we}from"./vfx-gpu-material.js";export async function materializeVfx(t,a,r,s,l,o,c,p,u){let h=a;for(;null!=h.parent;)h=h.parent;const d=new n;d.name="particle system local",a.add(d);const m=new n;m.name="particle system world";const f=new se(m,d,i,s),y=new e;return(await Promise.all(t.vfx.emitters.slice().sort((e,t)=>(t.output.renderOrder??0)-(e.output.renderOrder??0)).map(async e=>{const t=await be(e,r,c,p,y,l,o,u,a);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:m,system:y,dispose:()=>{m.removeFromParent(),d.removeFromParent(),f.dispose()}}}function ge(e,t){let a;const r=function(e,t){const a=Math.max(0,e.rate.delay??0),r=e.rate.delayBinding;if("vfxInput"!==r?.type||null==t)return a;const s=t.getDefinition(r.inputId);return"number"!==s?.type?a:Math.max(0,t.getNumber(r.inputId,a))}(e,t);switch(e.rate.type){case"continuous":a=new Z(r,e.rate.count,e.rate.time,e.rate.duration);break;case"once":a=new $(r,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),a=new s(0,1/0)}return a}async function be(e,t,r,s,p,x,S,T,D){const F=ge(e,T);let L;switch(e.output.type){case"decal":L=new a(await async function(e,t,a,r,s){if("shaderGraph"===ve(e)){const t=await createShaderGraphMaterial(e,"decal",a,r,s);if(null!=t){const a=new i.Mesh(new i.BoxGeometry(1,1,1),t);return Ae(a,e),a}}const n=!1!==e.unlit?new ce:new pe;n.color=new i.Color(e.color),n instanceof ce?n.intensity=e.intensity??1:n.emissiveIntensity=e.intensity??1;if(e.colorMap){const a=await t.getTexture(e.colorMap);n.colorMap=a}if(e.alphaMap){const a=await t.getTexture(e.alphaMap);n.alphaMap=a}const l=n.build();l.blending=te[e.blendingMode]??i.NormalBlending,l.transparent=!0,l.side=i.BackSide,l.depthTest=!1,null!=l&&!0===e.bloom&&(l.userData.hasBloom=!0);l.defines.IS_PARTICLE="";const o=new i.BoxGeometry(1,1,1),c=new i.Mesh(o,l);return Ae(c,e),c}(e.output,t,r,s,S));break;case"sprite":L=new a(await async function(e,t,a,r,s){let n=null;const l=ve(e);"shaderGraph"===l&&(n=await createShaderGraphMaterial(e,"sprite",a,r,s));null==n&&"shader"===l&&null!=e.shader&&(n=await createShaderMaterial(e,t,s));null==n&&(n=await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):Me,r=C(a);let s=r.sample(B.uv);e.flipbook?.enabled&&(s=_(r,y.uv,e.flipbook.columns,e.flipbook.rows,J.time,e.flipbook.fps,e.flipbook.mode));const n=new u("rotation",0),l=new h("color").rgb,o=j(new d("instanceColor")).rgb,c=N.subtract(H).divide(N);let p=J.opacity;switch(e.opacityChannel??"red"){case"none":break;case"red":p=p.multiply(s.r);break;case"alpha":p=p.multiply(s.a)}if("number"==typeof e.softness&&e.softness>0){const t=w(c,0,1e3);p=p.multiply(P(0,.2*e.softness,t))}const m=ne(n,void 0,void 0,!0),f=I(l.multiply(o).multiply(s.rgb).multiplyScalar(e.intensity??1),p);var g=new oe({color:f,emissive:f.rgb.multiplyScalar(p),transparent:!0,position:m,alphaTest:1e-4,uniforms:{color:{value:new i.Color(e.color)}}});g.alphaHash=!0,null!=g&&!0===e.bloom&&(g.userData.hasBloom=!0);return g.blending=te[e.blendingMode]??i.NormalBlending,g}(e,t));n.depthWrite=!1,Ee(n,e);const o=new i.Mesh(new i.PlaneGeometry(1,1),n);return o.name="sprite",Ae(o,e),o}(e.output,t,r,s,S));break;case"stretchedSprite":L=new a(await async function(e,t){"shaderGraph"===ve(e)&&console.warn("Shader graph materials are not supported for stretched sprite VFX outputs yet. Falling back to the default stretched sprite material.");const a=null!=e.texture?await t.getTexture(e.texture):Me,r=C(a).sample(B.uv),s=k(new o("particleColor")),n=s.rgb.multiply(r.rgb);let l=s.w;switch(e.opacityChannel??"red"){case"none":break;case"red":l=l.multiply(r.r);break;case"alpha":l=l.multiply(r.a)}if("number"==typeof e.softness&&e.softness>0){const t=N.subtract(H).divide(E(N)),a=w(t,0,1e3);l=l.multiply(P(0,.2*e.softness,a))}const c=m("offset"),p=f("velocity"),u=m("size"),h=p.w,d=u.x.add(u.y).multiply(.5),M=R.modelViewMatrix.multiplyVec(V(c,1)),x=R.normalMatrix.multiplyVec(p.xyz),S=A(g(M.xyz,x)).multiplyScalar(y.position.y.multiply(d)),T=x.multiplyScalar(y.position.x.add(.5).multiply(b(1).add(h.divide(v(x)))).multiply(d)),G=R.projectionMatrix.multiplyVec(V(M.xyz.add(S).subtract(T),M.w));var j=new oe({color:I(n.multiplyScalar(e.intensity??1),l),alphaTest:.1,transparent:!0,position:G,uniforms:{color:{value:new i.Color(e.color)}}});null!=j&&!0===e.bloom&&(j.userData.hasBloom=!0);j.blending=te[e.blendingMode]??i.NormalBlending;const D=new ee(new i.PlaneGeometry(1,1),j);return D.scaleFactor=e.scale,Ae(D,e),D}(e.output,t));break;case"shape":L=new a(await async function(e,t,a,r,s){if(null==e.shape)return console.log("Shape is null"),new n;const o=Q[e.shape];if(null==o)return console.error(`No shape with type ${e.shape}`),new n;const p=W(e.params??{}),u=o.geometry(p);let h=null;const m=ve(e);"shaderGraph"===m&&(h=await createShaderGraphMaterial(e,"surface",a,r,s));null==h&&"shader"===m&&null!=e.shader&&(h=await createShaderMaterial(e,t,s));null==h&&(h="material"===m&&null!=e.material?xe(await t.getMaterial(e.material)):function(){const e=G(new d("instanceColor")).rgb,t=G(new l("particleData")).x;return new c({color:M({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());Ee(h,e);const f=new i.Mesh(u,h);return Ae(f,e),f}(e.output,t,r,s,S));break;case"mesh":L=new a(await async function(e,t,a,r,s){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new n;const l=await t.getMesh(e.assetId),o=await t.getAsset(e.assetId),c=ve(e);if("shaderGraph"===c||"shader"===c&&null!=e.shader||"material"===c&&null!=e.material){let n;"shaderGraph"===c?n=await createShaderGraphMaterial(e,"surface",a,r,s):"shader"===c&&null!=e.shader?n=await createShaderMaterial(e,t,s):"material"===c&&null!=e.material&&(n=xe(await t.getMaterial(e.material))),n?.transparent&&(n.depthWrite=!1),null!=n&&Ee(n,e),l.traverse(e=>{e instanceof i.Mesh&&null!=n&&(e.material=n)})}else{const e=[];if(null!=o.materialAssignments)for(const a of o.materialAssignments)null!=a.materialId&&l.traverse(r=>{r instanceof i.Mesh&&r.material instanceof i.Material&&r.material.color instanceof i.Color&&(r.material.name!=a.name&&null!=a.name||"#"+r.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>r.material=e)))});await Promise.all(e)}const p=[];if(l.traverse(e=>{e instanceof i.Mesh&&p.push(e)}),Ae(l,e),1===p.length){const t=p[0];return!0!==e.useLegacyTransform&&function(e){e.geometry=e.geometry.clone(),ye(e,e.geometry),e.position.set(0,0,0),e.quaternion.identity(),e.scale.set(1,1,1),e.updateMatrix(),e.matrixWorld.identity()}(t),t.removeFromParent(),t}return l}(e.output,t,r,s,S));break;case"trail":{const n="shaderGraph"===ve(e.output)?await createShaderGraphMaterial(e.output,"trail",r,s,S,{trailBillboard:e.output.billboard??!1}):null;L=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:n instanceof i.ShaderMaterial?n:void 0,dragTexture:!1,texture:null!=e.output.texture?await t.getTexture(e.output.texture):null,opacityChannel:e.output.opacityChannel,color:e.output.color,colorEnd:e.output.colorEnd,intensity:e.output.intensity??1,intensityEnd:e.output.intensityEnd??1,length:e.output.length,opacityStart:e.output.opacityStart,opacityEnd:e.output.opacityEnd,bloom:e.output.bloom,scrollSpeed:e.output.scrollSpeed,width:e.output.width,billboard:e.output.billboard??!1,renderOrder:e.output.renderOrder});break}default:console.error("Failed to create particly system body: "+JSON.stringify(e))}const O=new Ie(D);O.parent=p,O.setRate(F),O._space=e.output.space;const q=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=re[e.type]).map(async e=>{const t=re[e.type],a=await W(e.params??{},r,s);return he(t,e.params??{},a,T)}));"world"===e.output.space&&q.push(new Y("shape"===e.output.type||"mesh"===e.output.type)),q.push(L,new K),O.addInitializers(q);const z=await Promise.all(e.behaviours.filter(e=>!1!==e.enabled).filter(e=>null!=ae[e.type]).map(async e=>{const t=ae[e.type];for(const[a,r]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&r.type!==U.Curve&&(r.type=U.Curve);const a=await W(e.params??{},r,s);return ue(t,e.params??{},a,T)}).sort((e,t)=>e instanceof ie?1:0));z.push(new Se);for(const e of z)e instanceof ie&&(e.physics=x);O.addBehaviours(z);for(const a of e.children??[]){const e=await be(a,t,r,s,p,x,S,T,D),i=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=O.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&O.childEmitters.splice(e,1),null!=t.parentParticle&&(l.delete(t.parentParticle.id),t.parentParticle=null),i.release(t)},t}),n=O.eventDispatcher,l=new Map;O.bindEmitterEvent=!0,n.addEventListener("PARTICLE_DEAD",e=>{const t=l.get(e.id);null!=t&&(O.detachChildEmitterFromParticle(t,e),l.delete(e.id))});let o="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":o="PARTICLE_COLLISION";break;case"start":o="PARTICLE_CREATED"}n.addEventListener(o,e=>{const t=i.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),O.childEmitters.push(t),l.set(e.id,t),t.parentParticle=e,t.system=O.system,t.emit()})}return O}const Me=(new i.TextureLoader).load("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJkSURBVHjaxJeJbusgEEW94S1L//83X18M2MSuLd2pbqc4wZGqRLrKBsyZhQHny7Jk73xVL8xpVhWrcmiB5lX+6GJ5YgQ2owbAm8oIwH1VgKZUmGcRqKGGPgtEQQAzGR8hQ59fAmhJHSAagigJ4E7GPWRXOYC6owAd1JM6wDQPADyMWUqZRMqmAojHp1Vn6EQQEgUNMJLnUjMyJsM49wygBkAPw9dVFwXRkncCIIW3GRgoTQUZn6HxCMAFEFd8TwEQ78X4rHbILoAUmeT+RFG4UhQ6MiIAE4W/UsYFjuVjAIa2nIY4q1R0GFtQWG3E84lqw2GO2QOoCKBVu0BAPgDSU0eUDjjQenNkV/AW/pWChhpMTelo1a64AOKM30vk18GzTHXCNtI/Knz3DFBgsUqBGIjTInXRY1yA9xkVoqW5tVq3pDR9A0hfF5BSARmVnh7RMDCaIdcNgbPBkgzn1Bu+SfIEFSpSBmkxyrMicb0fAEuCZrWnN89veA/4XcakrPcjBWzkTuLjlbfTQPOlBhz+HwkqqPXmPQDdrQItxE1moGof1S74j/8txk8EHhTQrAE8qlwfqS5yukm1x/rAJ9Jiaa6nyATqD78aUVBhFo8b1V4DdTXdCW+IxA1zB4JhiOhZMEWO1HqnvdoHZ4FAMIhV9REF8FiUm0jsYPEJx/Fm/N8OhH90HI9YRHesWbXXZwAShU8qThe7H8YAuJmw5yOd989uRINKRTJAhoF8jbqrHKfeCYdIISZfSq26bk/K+yO3YvfKrVgiwQBHnwt8ynPB25+M8hceTt/ybPhnryJ78+tLgAEAuCFyiQgQB30AAAAASUVORK5CYII=");export async function createShaderMaterial(e,t,a){const r=a.get(e.shader);if(null==r)return console.error("No shader exists with name "+e.shader),new i.Material;const s=new r.type;"sprite"===e.type&&s instanceof le&&(s.instanced=!0);const n=await L(e.shaderParams??{},r.type,t,{getTexture:e=>t.getTexture(e.id),getMaterial:e=>t.getMaterial(e.id),getMesh:e=>t.getMesh(e.id)},void 0,void 0,void 0,void 0,void 0,s);return Object.assign(s,n),s.build()}export async function createShaderGraphMaterial(e,t,a,r,s,i={}){const n=e.shaderGraph;if("asset"!==n?.source||null==n.assetId)return console.warn(`Missing shader graph asset reference for ${e.type} VFX output`),null;const l=await a.getAsset(n.assetId),o=l?.shaderGraph;if(null==o)return console.warn(`Missing shader graph asset "${n.assetId}" for ${e.type} VFX output`),null;if(o.target!==t)return console.warn(`Shader graph "${l.name}" targets "${o.target}" but ${e.type} VFX output expects "${t}"`),null;try{const t=await O(e.shaderGraphParams??{},o,a,r,void 0,s.shaders),l=de(o,{parameters:t,trailBillboard:i.trailBillboard});return l.userData.customShaderName=`shaderGraph:${n.assetId}`,Ee(l,e),l}catch(e){return console.log("Shader graph VFX runtime error: "+e,e),null}}export function createGpuSpriteShaderGraphResolver(e,t,a,r){return async s=>{const n=ve(s);let l=null;if("shaderGraph"===n)l=await createShaderGraphMaterial(s,"sprite"===s.type?"sprite":"decal"===s.type?"decal":"trail"===s.type?"trail":"surface",e,t,a,"trail"===s.type?{trailBillboard:s.billboard??!1}:void 0);else if("shader"===n&&"decal"!==s.type&&null!=r)l=await createShaderMaterial(s,r,a);else if("material"!==n||"mesh"!==s.type&&"shape"!==s.type||null==s.material||null==r){if("default"===n&&"mesh"===s.type&&null!=s.assetId&&null!=r){const e=await r.getAsset(s.assetId),t=e.materialAssignments?.find(e=>null!=e.materialId);null!=t&&(l=await we(t.materialId,r))}else if("default"===n&&"decal"===s.type&&null!=r){const e=!1!==s.unlit?new ce:new pe;e.color=new i.Color(s.color),e instanceof ce?e.intensity=s.intensity??1:e.emissiveIntensity=s.intensity??1,s.colorMap&&(e.colorMap=await r.getTexture(s.colorMap)),s.alphaMap&&(e.alphaMap=await r.getTexture(s.alphaMap)),l=e.build(),l.transparent=!0}}else l="mesh"===s.type?await we(s.material,r):xe(await r.getMaterial(s.material));return null==l?null:("mesh"!==s.type&&"shape"!==s.type||!l.transparent||(l.depthWrite=!1),l instanceof c?l:(console.warn(`GPU ${s.type} materials must compile to NodeShaderMaterial; using CPU fallback`),null))}}function ve(e){return null!=e.materialSource?("material"!==e.materialSource||"mesh"!==e.type&&"shape"!==e.type||null!=e.material)&&("shaderGraph"!==e.materialSource||"asset"===e.shaderGraph?.source&&null!=e.shaderGraph.assetId)&&("shader"!==e.materialSource||"shader"in e&&null!=e.shader)?e.materialSource:"default":"asset"===e.shaderGraph?.source?"shaderGraph":"shader"in e&&null!=e.shader?"shader":"mesh"!==e.type&&"shape"!==e.type||null==e.material?"default":"material"}function Ee(e,t){null!=e&&(fe(e,!1),"bloom"in t&&!0===t.bloom&&(e.userData.hasBloom=!0),"sprite"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,!0===t.lockY&&e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.LOCK_Y_AXIS="")):"decal"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,e.transparent=!0,e.side=i.BackSide,e.depthTest=!1,e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE="")):"shape"!==t.type&&"mesh"!==t.type||e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE=""))}function Ae(e,t){const a=t.renderOrder;null!=a&&e.traverse(e=>e.renderOrder=a)}function xe(e){const t=G(new d("instanceColor")).rgb;let a,r=G(new l("particleData")).x;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial){let s=t.multiply(S(e.color));null!=e.map&&(s=s.multiply(C(e.map).sample(B.uv).rgb)),null!=e.alphaMap&&(r=r.multiply(C(e.alphaMap).sample(B.uv).r)),e instanceof i.MeshStandardMaterial?a=new c({color:T({color:s,emissive:S(e.emissive),emissiveIntensity:b(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshLambertMaterial?a=new c({color:M({color:s}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshBasicMaterial&&(a=new c({color:s.rgb.rgba(r),emissive:s.rgb,transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}))}else e instanceof c&&(a=e.clone(),a.defines.IS_PARTICLE="");return null!=a&&(!0===e.userData?.hasBloom&&null!=a&&(a.userData.hasBloom=!0),a.side=e.side,a.transparent=e.transparent),a??e}class Se extends t{initialize(e){e.body instanceof i.Object3D&&e.body.traverse(e=>{if(e instanceof i.Mesh){const t=e.material;t instanceof c&&(null!=t.uniforms[q]||null!=t.uniforms[z]||t.uniforms[X])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof n&&e.target.traverse(t=>{if(t instanceof i.Mesh){const a=t.material;if(a instanceof c){let t=!1;null!=a.uniforms[q]&&(a.uniforms[q].value=this.energy,t=!0),null!=a.uniforms[z]&&(a.uniforms[z].value=e.age,t=!0),null!=a.uniforms[X]&&(a.uniforms[X].value=e.velocity,t=!0),t&&me(a)}}})}}class Ie extends r{constructor(e){super(),this.transformRoot=e,this.childEmitters=[],this.bindEmitterEvent=!1,this.onExpired=()=>{}}clearParticlesRecursive(){let e=this.childEmitters.length;for(;e--;){const t=this.childEmitters[e];t.stopEmit(),t.clearParticlesRecursive(),t.onExpired()}this.childEmitters.length=0;let t=this.particles.length;for(;t--;){const e=this.particles[t];this.system?.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),null!=this.system?this.system.pool.expire(e.reset()):e.reset()}this.particles.length=0}detachChildEmitterFromParticle(e,t){this.copyPositionToChildSpace(e,t.position),e.parentParticle=null,e.stopEmit()}update(e){if(!this.isEmitting&&0===this.particles.length&&0===this.childEmitters.length)return;this.age+=e,(this.dead||this.age>=this.life)&&this.destroy(),this.isEmitting&&this.generate(e),this.integrate(e);let t=this.particles.length;for(;t--;){const e=this.particles[t];e.dead&&(this.system&&this.system.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),this.system.pool.expire(e.reset()),this.particles.splice(t,1))}this.updateEmitterBehaviours(e),this.updateChildren(e),this.isEmitting||0!==this.particles.length||0!==this.childEmitters.length||this.onExpired()}updateChildren(e){for(const t of this.childEmitters)null!=t.parentParticle&&this.copyPositionToChildSpace(t,t.parentParticle.position),t.update(e)}copyPositionToChildSpace(e,t){const a=this._space??"world",r=e._space??"world";a!==r&&null!=this.transformRoot?(Pe.copy(t),"local"===a&&"world"===r?Pe.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(Te.copy(this.transformRoot.matrixWorld).invert(),Pe.applyMatrix4(Te)),e.position.copy(Pe)):e.position.copy(t)}clone(){const e=new Ie(this.transformRoot);return e.setRate(this.rate.clone()),e.behaviours=this.behaviours,e.initializers=this.initializers,e._space=this._space,e.body=this.body,e.parent=this.parent,e.system=this.system,e}setParentRecursive(e){this.system=e,this.childEmitters.forEach(t=>t.setParentRecursive(e))}}const Pe=new i.Vector3,Te=new i.Matrix4;export class EmitterPool{constructor(e){this.creator=e,this.instances=[]}get(){0==this.instances.length&&this.instances.push(this.creator());return this.instances.pop()}release(e){this.instances.push(e)}dispose(){this.instances.length=0}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -3,15 +3,21 @@ import { Object3D } from "three";
3
3
  import { Constructable } from "typedi";
4
4
  import { ActorComponent, ComponentAttachProps } from './component.js';
5
5
  import { NetRole } from "../net/service/net-actor-role.js";
6
+ import type { TablerIcon } from './tabler-icon.js';
7
+ export type { TablerIcon } from './tabler-icon.js';
6
8
  export { getActorClassById, getActorClassId, getRegisteredActorClasses, } from './type-registry.js';
7
9
  export type ActorOptions = {
8
10
  /** Stable serialized identity. Defaults to the class name for backwards compatibility. */
9
11
  typeId?: string;
12
+ /** Tabler icon name used by editor UI, for example `flag` or `camera`. */
13
+ icon?: TablerIcon;
10
14
  replicate: boolean;
11
15
  relevancy?: {
12
16
  ownerOnly?: boolean;
13
17
  };
14
18
  };
19
+ /** Returns the metadata supplied to an actor class' `@Actor()` decorator. */
20
+ export declare function getActorOptions(type: Function): Readonly<Partial<ActorOptions>>;
15
21
  export declare function Actor(options?: Partial<ActorOptions>): (targetConstructor: any) => void;
16
22
  export type ActorId = number;
17
23
  /**
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import o,{ignore as r}from"@plumier/reflect";import{Subject as i}from"rxjs";import{Group as s}from"three";import n,{Service as a}from"typedi";import{ActorComponent as p}from"./component.js";import{initComponentsSync as c}from"./internal/component-init.js";import{activeContainerInstance as d,containerRefMap as m}from"./internal/container-map.js";import{randomString as l}from"../../utils/math.js";import{inject as h}from"../inject.js";import{ViewController as f}from"../services/render.js";import{actorConstructContext as u}from"./factory.js";import{NetRole as y}from"../net/service/net-actor-role.js";import{registerActorClass as g}from"./type-registry.js";export{getActorClassById,getActorClassId,getRegisteredActorClasses}from"./type-registry.js";export const $actorOptions=Symbol("actor-options");const j={replicate:!1};export function Actor(t=j){const e=a({transient:!0});return function(r){const i=arguments[1],s=t.typeId??i?.name??r.name,n=g(s,r);null!=n&&n!==r&&console.warn(`Duplicate actor class name ${s}`),r.__actorId=s,r.__isActor=!0,e(r),o.noop()(r),o.parameterProperties()(r),r[$actorOptions]=t}}let U=0;export class BaseActor{get position(){return this.object?.position}get quaternion(){return this.object?.quaternion}get rotation(){return this.object?.rotation}onInit(){}onBeginPlay(){}onEndPlay(){}applySceneParameters(t,e){return!1}onUpdate(t){}onLateUpdate(t){}constructor(){this.id=++U,this.netRole=y.authority,this.__isInitialised=!1,this.object=new s,this.disposed=new i,this.attachedComponents=[],u.actor=this,this.onUpdate!==BaseActor.prototype.onUpdate&&h(f).registerActorUpdate(this,t=>{this.__isInitialised&&this.onUpdate(t)}),this.onLateUpdate!==BaseActor.prototype.onLateUpdate&&h(f).registerActorUpdate(this,t=>{this.__isInitialised&&this.onLateUpdate(t)},!0)}attach(t,e){const o=d.value,r=m.get(this)??d.value??n.of("default");d.value=r;const i=l();r.set({id:i,type:t,transient:!0});const s=r.get(i);if(d.value=o,null!=e)for(const t of Object.keys(e))s[t]=e[t];return this.__isInitialised&&(s.actor=this,s.onInit(),c(s,this)),this.attachedComponents.push(s),s}getComponent(t){for(const e of Object.values(this))if(e instanceof t)return e;for(const e of this.attachedComponents)if(e instanceof t)return e}}t([r(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"position",null),t([r(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"quaternion",null),t([r(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"rotation",null);export function _setupActorUpdateEventHandlers(){this.onUpdate!==p.prototype.onUpdate&&h(f).registerActorUpdate(this.actor,t=>{this.actor?.__isInitialised&&this.onUpdate(t)}),this.onLateUpdate!==p.prototype.onLateUpdate&&h(f).registerActorUpdate(this.actor,t=>{this.actor?.__isInitialised&&this.onLateUpdate(t)},!0)}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import o,{ignore as i}from"@plumier/reflect";import{Subject as s,skipWhile as r}from"rxjs";import{Group as n}from"three";import a,{Service as p}from"typedi";import{ActorComponent as c}from"./component.js";import{initComponentsSync as d}from"./internal/component-init.js";import{activeContainerInstance as m,containerRefMap as l}from"./internal/container-map.js";import{randomString as h}from"../../utils/math.js";import{inject as u}from"../inject.js";import{ViewController as f}from"../services/render.js";import{actorConstructContext as y}from"./factory.js";import{NetRole as j}from"../net/service/net-actor-role.js";import{registerActorClass as g}from"./type-registry.js";export{getActorClassById,getActorClassId,getRegisteredActorClasses}from"./type-registry.js";export const $actorOptions=Symbol("actor-options");export function getActorOptions(t){return t[$actorOptions]??b}const b={replicate:!1};export function Actor(t=b){const e=p({transient:!0});return function(i){const s=arguments[1],r=t.typeId??s?.name??i.name,n=g(r,i);null!=n&&n!==i&&console.warn(`Duplicate actor class name ${r}`),i.__actorId=r,i.__isActor=!0,e(i),o.noop()(i),o.parameterProperties()(i),i[$actorOptions]=t}}let U=0;export class BaseActor{get position(){return this.object?.position}get quaternion(){return this.object?.quaternion}get rotation(){return this.object?.rotation}onInit(){}onBeginPlay(){}onEndPlay(){}applySceneParameters(t,e){return!1}onUpdate(t){}onLateUpdate(t){}constructor(){this.id=++U,this.netRole=j.authority,this.__isInitialised=!1,this.object=new n,this.disposed=new s,this.attachedComponents=[],y.actor=this,this.onUpdate!==BaseActor.prototype.onUpdate&&u(f).onUpdate(this).pipe(r(()=>!this.__isInitialised)).subscribe(t=>this.onUpdate(t)),this.onLateUpdate!==BaseActor.prototype.onLateUpdate&&u(f).onLateUpdate(this).pipe(r(()=>!this.__isInitialised)).subscribe(t=>this.onLateUpdate(t))}attach(t,e){const o=m.value,i=l.get(this)??m.value??a.of("default");m.value=i;const s=h();i.set({id:s,type:t,transient:!0});const r=i.get(s);if(m.value=o,null!=e)for(const t of Object.keys(e))r[t]=e[t];return this.__isInitialised&&(r.actor=this,r.onInit(),d(r,this)),this.attachedComponents.push(r),r}getComponent(t){for(const e of Object.values(this))if(e instanceof t)return e;for(const e of this.attachedComponents)if(e instanceof t)return e}}t([i(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"position",null),t([i(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"quaternion",null),t([i(),e("design:type",Object),e("design:paramtypes",[])],BaseActor.prototype,"rotation",null);export function _setupActorUpdateEventHandlers(){this.onUpdate!==c.prototype.onUpdate&&u(f).onUpdate(this.actor).pipe(r(()=>!this.actor?.__isInitialised)).subscribe(t=>this.onUpdate(t)),this.onLateUpdate!==c.prototype.onLateUpdate&&u(f).onLateUpdate(this.actor).pipe(r(()=>!this.actor?.__isInitialised)).subscribe(t=>this.onLateUpdate(t))}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as o}from"tslib";import{Actor as r,BaseActor as t}from"../actor.js";import{CameraComponent as m}from"../camera/camera-component.js";import{attach as e}from"../component.js";let s=class extends t{constructor(){super(...arguments),this.camera=e(m)}};s=o([r()],s);export{s as CameraActor};/*
1
+ import{__decorate as o}from"tslib";import{Actor as r,BaseActor as m}from"../actor.js";import{CameraComponent as t}from"../camera/camera-component.js";import{attach as c}from"../component.js";let e=class extends m{constructor(){super(...arguments),this.camera=c(t)}};e=o([r({icon:"camera"})],e);export{e as CameraActor};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Ball as n,Capsule as s,Cone as o,ConvexPolyhedron as i,Cuboid as r,Cylinder as a,Heightfield as c,ShapeType as l,TriMesh as h}from"@dimforge/rapier3d-simd-compat";import{init as u}from"@recast-navigation/core";import{DebugDrawer as p,getPositionsAndIndices as d}from"@recast-navigation/three";import{BehaviorSubject as f,Subject as m,debounceTime as w,filter as g,firstValueFrom as b,takeUntil as y}from"rxjs";import*as x from"three";import{BufferGeometryUtils as M,ConvexHull as v}from"three/examples/jsm/Addons.js";import{Actor as B,BaseActor as S,Parameter as z,PhysicsSystem as j,ViewController as k,World as A,attach as C,inject as P}from"../../index.js";import{sleepDelay as V}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as D,toSharedFloat32Array as F,toSharedUint32Array as I}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as N,MAX_NAV_MESH_WORKERS as H}from"../../ai/dynamic-tiled-navmesh.js";import{isNavigationAreaContributor as G}from"../../ai/navigation-areas.js";import{TriggerVolumeMesh as E}from"./components/volume-editor-component.js";var R;!function(e){e[e.none=0]="none",e[e.starting=1]="starting",e[e.started=2]="started"}(R||(R={}));let T=R.none,U=new f(!1);export async function safeRecastInit(){return T===R.none?(T=R.starting,u().then(()=>{U.next(!0),T=R.started})):b(U.pipe(g(e=>e)))}new x.Box3(new x.Vector3(-100,-100,-100),new x.Vector3(100,100,100));const O=Math.max(1,Math.min(H,(navigator.hardwareConcurrency??2)-1));let q=!1,W=class extends S{constructor(){super(...arguments),this.physics=P(j),this.view=P(k),this.world=P(A),this.editorVisualisation=C(E),this.debug=!0,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new x.Box3}async onInit(){q||(await safeRecastInit(),q=!0),setTimeout(()=>{this.init()},10),this.recreateInterval=setInterval(()=>{if("_hology_transform_group"===this.object.parent?.name)return;K.setFromCenterAndSize(this.position,this.object.scale).equals(this.bounds)||(this.disposed.next(!0),this.disposed=new m,this.init())},2e3)}onEndPlay(){clearInterval(this.recreateInterval)}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,!0)}init(){this.bounds.setFromCenterAndSize(this.position,this.object.scale);const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,n=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(n/2))),o=Math.max(this.cellSize,.01),i={tileSize:Math.max(32,Math.floor(s/o)),walkableClimb:this.walkableClimb/o,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/o,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:o,ch:o,maxSimplificationError:1.3,maxEdgeLen:200},r=new N({navMeshBounds:this.bounds,recastConfig:i,maxTiles:1024,workers:O,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const a=this.tileSize*i.cs*2,c=performance.now(),l=new Map,h=new p;h.userData.isDebugDrawer=!0,this.debugDrawer=h;r.navMesh;const u=this.bounds,f=()=>{const e=this.view.getCamera().getWorldPosition(new x.Vector3),t=new x.Box3((new x.Vector3).copy(e).subScalar(a),(new x.Vector3).copy(e).addScalar(a)),n=[],s=this.physics.world.bodies;if(null==s)return[];const o=new x.Box3;for(const e of s.getAll())for(let s=0,i=e.numColliders();s<i;s++){const i=e.collider(s);if(i.isSensor()||null!=i.parent().userData&&!0===i.parent().userData.ignoreForNavMesh)continue;const r=e.handle+","+s,a=l.get(r)?.mesh,c=a??J(i);if($(i,c),null!=c){o.copy(c.geometry.boundingBox),o.min.add(c.position),o.max.add(c.position);const e=o.intersectsBox(t)||!0,s=o.intersectsBox(this.bounds);l.set(r,{pos:i.translation(),mesh:c}),e&&s&&n.push(c)}}return n},m=new x.Box3,g=new Map,b=new Map,M=new Map,v=new Map;let B=!0,S=performance.now(),z=!1;const j=function(e,t){let n=!1;return(async()=>{for(;!n;)await e(),await V(t)})(),()=>{n=!0}}(async()=>{if(z)return;const e=new x.Box3,t=f();for(const n of t){const t=g.get(n);!0!==t?.equals(n.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(n),g.set(n,n.position.clone()))}const n=[],s=new Set;for(const t of this.world.actors){if(!G(t))continue;s.add(t);const o=t.getNavigationAreaModifiers();n.push(...o);const i=Q(o),r=JSON.stringify(o);if(M.get(t)!==r){const n=b.get(t);null!=n&&e.union(n),e.union(i),b.set(t,i),M.set(t,r)}}for(const t of[...b.keys()])s.has(t)||(e.union(b.get(t)),b.delete(t),M.delete(t));const o=e.isEmpty()?[]:r.getTilesForBounds(e.expandByScalar(50));o.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const i=o.slice(0,500);if(0!=i.length){const s=[];for(const n of t)m.setFromObject(n),m.intersectsBox(e)&&s.push(n);let[o,a]=d(s);a=function(e,t,n){const s=new x.Vector3,o=[];for(let i=0;i<t.length;i+=3){let r=!0;for(let o=0;o<3;o++){const a=3*t[i+o];if(s.fromArray(e,a),!n.containsPoint(s)){r=!1;break}}r&&o.push(t[i],t[i+1],t[i+2])}return new Uint32Array(o)}(o,a,u),D&&(o=F(o),a=I(a));const c=B;B=!1,await Promise.all(i.map(e=>{S=performance.now();const t=function(e,t,n){const s=(e.recastConfig.walkableRadius+3)*e.recastConfig.cs,o=new x.Vector3(e.navMeshBoundsMin.x+t[0]*e.tcs-s,e.navMeshBoundsMin.y,e.navMeshBoundsMin.z+t[1]*e.tcs-s),i=new x.Vector3(o.x+e.tcs+2*s,e.navMeshBoundsMax.y,o.z+e.tcs+2*s),r=new x.Box3(o,i);return n.filter(e=>Q([e]).intersectsBox(r))}(r,e,n);return r.buildTile(o,a,e,c,t).then(()=>{const t=e[0]+","+e[1];v.set(t,(v.get(t)??0)+1),this.debug})})).then(()=>{this.debug,z=!1})}else z=!1},this.refreshMs??1e4);this.disposed.subscribe(()=>j()),r.onNavMeshUpdate.pipe(y(this.disposed),w(200)).subscribe(()=>{h.clear(),h.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),h.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(h),this.disposed.subscribe(()=>{r?.destroy(),h.removeFromParent(),h.dispose()});const k=performance.now()-c;k>1e3&&console.warn(`NavMesh update took ${k} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([z(),t("design:type",Boolean)],W.prototype,"debug",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableClimb",void 0),e([z({range:[0,89]}),t("design:type",Number)],W.prototype,"walkableSlopeAngle",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableHeight",void 0),e([z({range:[.01,10]}),t("design:type",Number)],W.prototype,"cellSize",void 0),W=e([B()],W);export default W;const _=new Map,L=new WeakMap;function X(e){if(e.shape instanceof c)return function(e){const t=e.shape;if(t.type!==l.HeightField)throw new Error("The provided collider is not a height field.");let n=!1;const s=t,o=s.heights,i=s.nrows,r=s.ncols,a=s.scale.x,c=s.scale.z,h=s.scale.y,u=i+1,p=new x.PlaneGeometry(c,a,r,i);p.rotateX(-Math.PI/2);const d=p.attributes.position.array;let f=0;for(let e=0;e<u;e++)for(let t=0;t<u;t++)d[f+1]=o[t*u+e]*h,f+=3,0!=d[f+1]&&(n=!0);if(!n){const e=new x.PlaneGeometry(a,c,2,2);return e.rotateX(-Math.PI/2),e}return p}(e);if(e.shape instanceof n)return new x.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new x.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof i){const t=function(e){const t=L.get(e);if(void 0!==t)return t;const n=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<n.length;e++)s=Math.imul(s^n[e],16777619)>>>0;return L.set(e,s),s}(e.shape.vertices);let n=_.get(t);return n||(n=function(e){const t=[];for(let n=0;n<e.length;n+=3)t.push(new x.Vector3(e[n],e[n+1],e[n+2]));const n=(new v).setFromPoints(t),s=[];n.faces.forEach(e=>{const t=e.edge.head().point,n=e.edge.next.head().point,o=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(n.x,n.y,n.z),s.push(o.x,o.y,o.z)});const o=new x.BufferGeometry;return o.setAttribute("position",new x.Float32BufferAttribute(s,3)),o}(e.shape.vertices),_.set(t,n)),n}if(e.shape instanceof h){const t=e.shape.vertices,n=e.shape.indices;let s=new x.BufferGeometry;return s.setAttribute("position",new x.Float32BufferAttribute(t,3)),null!=n?s.setIndex(new x.Uint16BufferAttribute(n,1)):s=M.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof a){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CylinderGeometry(n,n,2*t)}if(e.shape instanceof o){const t=e.shape.halfHeight,n=e.shape.radius;return new x.ConeGeometry(n,2*t)}if(e.shape instanceof s){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CapsuleGeometry(n,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function J(e){const t=X(e);if(null==t)return null;const n=Y,s=new x.Mesh(t,n);return s.geometry.computeBoundingBox(),s.geometry.scale(1.01,1.01,1.01),s}function $(e,t){const n=e.translation(),s=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(s.x,s.y,s.z,s.w)}const K=new x.Box3;function Q(e){const t=new x.Box3;for(const n of e)for(const e of n.vertices)t.expandByPoint(new x.Vector3(e[0],n.minHeight,e[2])),t.expandByPoint(new x.Vector3(e[0],n.maxHeight,e[2]));return t}const Y=new x.MeshBasicMaterial({wireframe:!1,color:16711680,side:x.FrontSide});/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Ball as n,Capsule as s,Cone as o,ConvexPolyhedron as i,Cuboid as r,Cylinder as a,Heightfield as c,ShapeType as l,TriMesh as h}from"@dimforge/rapier3d-simd-compat";import{init as u}from"@recast-navigation/core";import{DebugDrawer as p,getPositionsAndIndices as d}from"@recast-navigation/three";import{BehaviorSubject as f,Subject as m,debounceTime as w,filter as g,firstValueFrom as b,takeUntil as y}from"rxjs";import*as x from"three";import{BufferGeometryUtils as M,ConvexHull as v}from"three/examples/jsm/Addons.js";import{Actor as B,BaseActor as S,Parameter as z,PhysicsSystem as j,ViewController as k,World as A,attach as C,inject as P}from"../../index.js";import{sleepDelay as V}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as D,toSharedFloat32Array as F,toSharedUint32Array as I}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as N,MAX_NAV_MESH_WORKERS as H}from"../../ai/dynamic-tiled-navmesh.js";import{isNavigationAreaContributor as G}from"../../ai/navigation-areas.js";import{TriggerVolumeMesh as E}from"./components/volume-editor-component.js";var R;!function(e){e[e.none=0]="none",e[e.starting=1]="starting",e[e.started=2]="started"}(R||(R={}));let T=R.none,U=new f(!1);export async function safeRecastInit(){return T===R.none?(T=R.starting,u().then(()=>{U.next(!0),T=R.started})):b(U.pipe(g(e=>e)))}new x.Box3(new x.Vector3(-100,-100,-100),new x.Vector3(100,100,100));const O=Math.max(1,Math.min(H,(navigator.hardwareConcurrency??2)-1));let q=!1,W=class extends S{constructor(){super(...arguments),this.physics=P(j),this.view=P(k),this.world=P(A),this.editorVisualisation=C(E),this.debug=!0,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new x.Box3}async onInit(){q||(await safeRecastInit(),q=!0),setTimeout(()=>{this.init()},10),this.recreateInterval=setInterval(()=>{if("_hology_transform_group"===this.object.parent?.name)return;K.setFromCenterAndSize(this.position,this.object.scale).equals(this.bounds)||(this.disposed.next(!0),this.disposed=new m,this.init())},2e3)}onEndPlay(){clearInterval(this.recreateInterval)}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,!0)}init(){this.bounds.setFromCenterAndSize(this.position,this.object.scale);const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,n=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(n/2))),o=Math.max(this.cellSize,.01),i={tileSize:Math.max(32,Math.floor(s/o)),walkableClimb:this.walkableClimb/o,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/o,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:o,ch:o,maxSimplificationError:1.3,maxEdgeLen:200},r=new N({navMeshBounds:this.bounds,recastConfig:i,maxTiles:1024,workers:O,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const a=this.tileSize*i.cs*2,c=performance.now(),l=new Map,h=new p;h.userData.isDebugDrawer=!0,this.debugDrawer=h;r.navMesh;const u=this.bounds,f=()=>{const e=this.view.getCamera().getWorldPosition(new x.Vector3),t=new x.Box3((new x.Vector3).copy(e).subScalar(a),(new x.Vector3).copy(e).addScalar(a)),n=[],s=this.physics.world.bodies;if(null==s)return[];const o=new x.Box3;for(const e of s.getAll())for(let s=0,i=e.numColliders();s<i;s++){const i=e.collider(s);if(i.isSensor()||null!=i.parent().userData&&!0===i.parent().userData.ignoreForNavMesh)continue;const r=e.handle+","+s,a=l.get(r)?.mesh,c=a??J(i);if($(i,c),null!=c){o.copy(c.geometry.boundingBox),o.min.add(c.position),o.max.add(c.position);const e=o.intersectsBox(t)||!0,s=o.intersectsBox(this.bounds);l.set(r,{pos:i.translation(),mesh:c}),e&&s&&n.push(c)}}return n},m=new x.Box3,g=new Map,b=new Map,M=new Map,v=new Map;let B=!0,S=performance.now(),z=!1;const j=function(e,t){let n=!1;return(async()=>{for(;!n;)await e(),await V(t)})(),()=>{n=!0}}(async()=>{if(z)return;const e=new x.Box3,t=f();for(const n of t){const t=g.get(n);!0!==t?.equals(n.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(n),g.set(n,n.position.clone()))}const n=[],s=new Set;for(const t of this.world.actors){if(!G(t))continue;s.add(t);const o=t.getNavigationAreaModifiers();n.push(...o);const i=Q(o),r=JSON.stringify(o);if(M.get(t)!==r){const n=b.get(t);null!=n&&e.union(n),e.union(i),b.set(t,i),M.set(t,r)}}for(const t of[...b.keys()])s.has(t)||(e.union(b.get(t)),b.delete(t),M.delete(t));const o=e.isEmpty()?[]:r.getTilesForBounds(e.expandByScalar(50));o.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const i=o.slice(0,500);if(0!=i.length){const s=[];for(const n of t)m.setFromObject(n),m.intersectsBox(e)&&s.push(n);let[o,a]=d(s);a=function(e,t,n){const s=new x.Vector3,o=[];for(let i=0;i<t.length;i+=3){let r=!0;for(let o=0;o<3;o++){const a=3*t[i+o];if(s.fromArray(e,a),!n.containsPoint(s)){r=!1;break}}r&&o.push(t[i],t[i+1],t[i+2])}return new Uint32Array(o)}(o,a,u),D&&(o=F(o),a=I(a));const c=B;B=!1,await Promise.all(i.map(e=>{S=performance.now();const t=function(e,t,n){const s=(e.recastConfig.walkableRadius+3)*e.recastConfig.cs,o=new x.Vector3(e.navMeshBoundsMin.x+t[0]*e.tcs-s,e.navMeshBoundsMin.y,e.navMeshBoundsMin.z+t[1]*e.tcs-s),i=new x.Vector3(o.x+e.tcs+2*s,e.navMeshBoundsMax.y,o.z+e.tcs+2*s),r=new x.Box3(o,i);return n.filter(e=>Q([e]).intersectsBox(r))}(r,e,n);return r.buildTile(o,a,e,c,t).then(()=>{const t=e[0]+","+e[1];v.set(t,(v.get(t)??0)+1),this.debug})})).then(()=>{this.debug,z=!1})}else z=!1},this.refreshMs??1e4);this.disposed.subscribe(()=>j()),r.onNavMeshUpdate.pipe(y(this.disposed),w(200)).subscribe(()=>{h.clear(),h.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),h.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(h),this.disposed.subscribe(()=>{r?.destroy(),h.removeFromParent(),h.dispose()});const k=performance.now()-c;k>1e3&&console.warn(`NavMesh update took ${k} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([z(),t("design:type",Boolean)],W.prototype,"debug",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableClimb",void 0),e([z({range:[0,89]}),t("design:type",Number)],W.prototype,"walkableSlopeAngle",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableHeight",void 0),e([z({range:[.01,10]}),t("design:type",Number)],W.prototype,"cellSize",void 0),W=e([B({icon:"route"})],W);export default W;const _=new Map,L=new WeakMap;function X(e){if(e.shape instanceof c)return function(e){const t=e.shape;if(t.type!==l.HeightField)throw new Error("The provided collider is not a height field.");let n=!1;const s=t,o=s.heights,i=s.nrows,r=s.ncols,a=s.scale.x,c=s.scale.z,h=s.scale.y,u=i+1,p=new x.PlaneGeometry(c,a,r,i);p.rotateX(-Math.PI/2);const d=p.attributes.position.array;let f=0;for(let e=0;e<u;e++)for(let t=0;t<u;t++)d[f+1]=o[t*u+e]*h,f+=3,0!=d[f+1]&&(n=!0);if(!n){const e=new x.PlaneGeometry(a,c,2,2);return e.rotateX(-Math.PI/2),e}return p}(e);if(e.shape instanceof n)return new x.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new x.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof i){const t=function(e){const t=L.get(e);if(void 0!==t)return t;const n=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<n.length;e++)s=Math.imul(s^n[e],16777619)>>>0;return L.set(e,s),s}(e.shape.vertices);let n=_.get(t);return n||(n=function(e){const t=[];for(let n=0;n<e.length;n+=3)t.push(new x.Vector3(e[n],e[n+1],e[n+2]));const n=(new v).setFromPoints(t),s=[];n.faces.forEach(e=>{const t=e.edge.head().point,n=e.edge.next.head().point,o=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(n.x,n.y,n.z),s.push(o.x,o.y,o.z)});const o=new x.BufferGeometry;return o.setAttribute("position",new x.Float32BufferAttribute(s,3)),o}(e.shape.vertices),_.set(t,n)),n}if(e.shape instanceof h){const t=e.shape.vertices,n=e.shape.indices;let s=new x.BufferGeometry;return s.setAttribute("position",new x.Float32BufferAttribute(t,3)),null!=n?s.setIndex(new x.Uint16BufferAttribute(n,1)):s=M.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof a){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CylinderGeometry(n,n,2*t)}if(e.shape instanceof o){const t=e.shape.halfHeight,n=e.shape.radius;return new x.ConeGeometry(n,2*t)}if(e.shape instanceof s){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CapsuleGeometry(n,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function J(e){const t=X(e);if(null==t)return null;const n=Y,s=new x.Mesh(t,n);return s.geometry.computeBoundingBox(),s.geometry.scale(1.01,1.01,1.01),s}function $(e,t){const n=e.translation(),s=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(s.x,s.y,s.z,s.w)}const K=new x.Box3;function Q(e){const t=new x.Box3;for(const n of e)for(const e of n.vertices)t.expandByPoint(new x.Vector3(e[0],n.minHeight,e[2])),t.expandByPoint(new x.Vector3(e[0],n.maxHeight,e[2]));return t}const Y=new x.MeshBasicMaterial({wireframe:!1,color:16711680,side:x.FrontSide});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as o,__metadata as t}from"tslib";import*as s from"three";import{Actor as i,BaseActor as e}from"../actor.js";import{ActorComponent as n,Component as r,attach as a}from"../component.js";import{Parameter as d}from"../../../shader/index.js";import{ViewController as u}from"../../services/render.js";import{inject as l}from"../../inject.js";import{PositionalAudioHelper as p}from"../../../utils/three/positional-audio-helper.js";let h=class extends e{constructor(){super(...arguments),this.audio=a(c)}};h=o([i()],h);export{h as PositionalAudioActor};let m=class extends n{onInit(){const o=(new s.TextureLoader).load("assets/audio.png"),t=new s.SpriteMaterial({map:o}),i=new s.Sprite(t);this.actor.object.add(i),this.helper=new p(this.positionalAudio)}};m=o([r({inEditor:!0,editorOnly:!0})],m);let c=class extends n{constructor(){super(...arguments),this.volume=1,this.loop=!1,this.autoPlay=!0,this.view=l(u),this.sound=new s.PositionalAudio(this.view.audioListener),this.visualisation=a(m,{positionalAudio:this.sound})}onInit(){this.sound.setBuffer(this.audioBuffer),null!=this.refDistance&&this.sound.setRefDistance(Math.max(this.refDistance,0)),null!=this.rollofFactor&&this.sound.setRolloffFactor(this.rollofFactor),null!=this.maxDistance&&this.sound.setMaxDistance(this.maxDistance),null!=this.volume?this.sound.setVolume(Math.max(this.volume,0)):this.sound.setVolume(0),this.sound.loop=this.loop??!1,this.visualisation?.helper?.update(),this.actor.object.add(this.sound),this.autoPlay&&this.sound?.play(),this.disposed.subscribe(()=>{this.sound.isPlaying&&(this.sound?.stop(),console.log(this.sound.getVolume(),this.volume)),this.sound.removeFromParent()}),console.log(this.sound)}onEndPlay(){this.sound.isPlaying&&(this.sound?.stop(),this.sound.loop=!1),this.sound.removeFromParent()}};o([d(),t("design:type",AudioBuffer)],c.prototype,"audioBuffer",void 0),o([d({range:[0,1]}),t("design:type",Number)],c.prototype,"volume",void 0),o([d(),t("design:type",Boolean)],c.prototype,"loop",void 0),o([d(),t("design:type",Boolean)],c.prototype,"autoPlay",void 0),o([d({range:[0,1e3]}),t("design:type",Number)],c.prototype,"refDistance",void 0),o([d(),t("design:type",Number)],c.prototype,"rollofFactor",void 0),o([d(),t("design:type",Number)],c.prototype,"maxDistance",void 0),c=o([r({inEditor:!0})],c);export{c as PositionalAudioComponent};/*
1
+ import{__decorate as o,__metadata as t}from"tslib";import*as s from"three";import{Actor as i,BaseActor as e}from"../actor.js";import{ActorComponent as n,Component as r,attach as a}from"../component.js";import{Parameter as u}from"../../../shader/index.js";import{ViewController as d}from"../../services/render.js";import{inject as l}from"../../inject.js";import{PositionalAudioHelper as p}from"../../../utils/three/positional-audio-helper.js";let h=class extends e{constructor(){super(...arguments),this.audio=a(c)}};h=o([i({icon:"volume"})],h);export{h as PositionalAudioActor};let m=class extends n{onInit(){const o=(new s.TextureLoader).load("assets/audio.png"),t=new s.SpriteMaterial({map:o}),i=new s.Sprite(t);this.actor.object.add(i),this.helper=new p(this.positionalAudio)}};m=o([r({inEditor:!0,editorOnly:!0})],m);let c=class extends n{constructor(){super(...arguments),this.volume=1,this.loop=!1,this.autoPlay=!0,this.view=l(d),this.sound=new s.PositionalAudio(this.view.audioListener),this.visualisation=a(m,{positionalAudio:this.sound})}onInit(){this.sound.setBuffer(this.audioBuffer),null!=this.refDistance&&this.sound.setRefDistance(Math.max(this.refDistance,0)),null!=this.rollofFactor&&this.sound.setRolloffFactor(this.rollofFactor),null!=this.maxDistance&&this.sound.setMaxDistance(this.maxDistance),null!=this.volume?this.sound.setVolume(Math.max(this.volume,0)):this.sound.setVolume(0),this.sound.loop=this.loop??!1,this.visualisation?.helper?.update(),this.actor.object.add(this.sound),this.autoPlay&&this.sound?.play(),this.disposed.subscribe(()=>{this.sound.isPlaying&&(this.sound?.stop(),console.log(this.sound.getVolume(),this.volume)),this.sound.removeFromParent()}),console.log(this.sound)}onEndPlay(){this.sound.isPlaying&&(this.sound?.stop(),this.sound.loop=!1),this.sound.removeFromParent()}};o([u(),t("design:type",AudioBuffer)],c.prototype,"audioBuffer",void 0),o([u({range:[0,1]}),t("design:type",Number)],c.prototype,"volume",void 0),o([u(),t("design:type",Boolean)],c.prototype,"loop",void 0),o([u(),t("design:type",Boolean)],c.prototype,"autoPlay",void 0),o([u({range:[0,1e3]}),t("design:type",Number)],c.prototype,"refDistance",void 0),o([u(),t("design:type",Number)],c.prototype,"rollofFactor",void 0),o([u(),t("design:type",Number)],c.prototype,"maxDistance",void 0),c=o([r({inEditor:!0})],c);export{c as PositionalAudioComponent};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import{ArrowHelper as o,Vector3 as r,Euler as e}from"three";import{Actor as s,BaseActor as i}from"../actor.js";import{Component as n,ActorComponent as m,attach as p}from"../component.js";import{World as c}from"../../../gameplay/services/world.js";import{inject as a}from"../../../gameplay/inject.js";import{createLineSphere as l}from"../../../utils/three/line-sphere.js";let d=class extends m{onInit(){const t=l(1);this.actor.object.add(t);const e=new o(new r(0,0,1),new r,1,1268122,.3,.3);this.actor.object.add(e)}};d=t([n({inEditor:!0,editorOnly:!0})],d);export{d as SpawnPointMesh};let h=class extends i{constructor(){super(...arguments),this.mesh=p(d),this.world=a(c)}spawnActor(t){return this.world.spawnActor(t,this.position,new e(0,this.rotation.y,0,"XYZ"))}};h=t([s()],h);export{h as SpawnPoint};/*
1
+ import{__decorate as t}from"tslib";import{ArrowHelper as o,Vector3 as r,Euler as e}from"three";import{Actor as s,BaseActor as i}from"../actor.js";import{Component as n,ActorComponent as m,attach as c}from"../component.js";import{World as p}from"../../../gameplay/services/world.js";import{inject as a}from"../../../gameplay/inject.js";import{createLineSphere as l}from"../../../utils/three/line-sphere.js";let d=class extends m{onInit(){const t=l(1);this.actor.object.add(t);const e=new o(new r(0,0,1),new r,1,1268122,.3,.3);this.actor.object.add(e)}};d=t([n({inEditor:!0,editorOnly:!0})],d);export{d as SpawnPointMesh};let h=class extends i{constructor(){super(...arguments),this.mesh=c(d),this.world=a(p)}spawnActor(t){return this.world.spawnActor(t,this.position,new e(0,this.rotation.y,0,"XYZ"))}};h=t([s({icon:"arrow-big-left-line"})],h);export{h as SpawnPoint};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as o}from"tslib";import{Actor as t,BaseActor as p}from"../actor.js";import{attach as r}from"../component.js";import{SplineComponent as s}from"./components/spline-component.js";let e=class extends p{constructor(){super(...arguments),this.spline=r(s)}};e=o([t({typeId:"Spline"})],e);export{e as SplineActor};/*
1
+ import{__decorate as o}from"tslib";import{Actor as t,BaseActor as e}from"../actor.js";import{attach as p}from"../component.js";import{SplineComponent as r}from"./components/spline-component.js";let s=class extends e{constructor(){super(...arguments),this.spline=p(r)}};s=o([t({typeId:"Spline",icon:"vector-spline"})],s);export{s as SplineActor};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- var e,t;import{__decorate as r,__metadata as i}from"tslib";import{EdgesGeometry as n,LineSegments as o,LineBasicMaterial as s,Vector3 as p,BoxGeometry as a,Mesh as c,MeshBasicMaterial as l,Group as y,Color as h}from"three";import{Actor as d,BaseActor as m}from"../actor.js";import{Component as g,ActorComponent as O,attach as u}from"../component.js";import{PhysicsSystem as v}from"../../services/physics/physics-system.js";import{BoxCollisionShape as f}from"../../../scene/collision/collision-shape.js";import{Parameter as b}from"../../../shader/parameter.js";import{firstValueFrom as j,Observable as W}from"rxjs";import{inject as w}from"../../../gameplay/inject.js";import{EventGraphEventSource as E,EventGraphProperty as B}from"../../event-graph/decorators.js";import{EVENT_GRAPH_ACTOR_CLASS_TYPE as T,EVENT_GRAPH_ACTOR_TYPE as S}from"../../event-graph/types.js";let x=class extends O{constructor(){super(...arguments),this.color=new h(16777215),this.dimensions=new p(1,1,1)}onInit(){const e=new a(this.dimensions.x,this.dimensions.y,this.dimensions.z),t=new n(e),r=new o(t,new s({color:this.color})),i=(new c(e,new l({color:this.color,transparent:!0,opacity:.3,visible:!1})),new y);i.add(r),this.actor.object.add(i)}};r([b(),i("design:type",h)],x.prototype,"color",void 0),r([b(),i("design:type",p)],x.prototype,"dimensions",void 0),x=r([g({inEditor:!0,editorOnly:!0})],x);export{x as TriggerVolumeMesh};let F=class extends O{constructor(){super(...arguments),this.dimensions=new p(1,1,1),this.offset=new p(0,0,0),this.editorMesh=u(x),this.physicsSystem=w(v)}onInit(){this.physicsSystem.addActor(this.actor,[new f(this.dimensions).withOffset(this.offset)],{isTrigger:!0}),j(this.disposed).then(()=>{this.physicsSystem.removeActor(this.actor)})}onBeginOverlap(){return this.physicsSystem.onBeginOverlap(this.actor)}onEndOverlap(){return this.physicsSystem.onEndOverlap(this.actor)}onBeginOverlapWithActor(e){return this.physicsSystem.onBeginOverlapWithActor(this.actor,e)}onEndOverlapWithActor(e){return this.physicsSystem.onEndOverlapWithActor(this.actor,e)}onBeginOverlapWithActorType(e){return this.physicsSystem.onBeginOverlapWithActorType(this.actor,e)}onEndOverlapWithActorType(e){return this.physicsSystem.onEndOverlapWithActorType(this.actor,e)}};r([E({label:"On Begin Overlap",emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[]),i("design:returntype",W)],F.prototype,"onBeginOverlap",null),r([E({label:"On End Overlap",emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[]),i("design:returntype",W)],F.prototype,"onEndOverlap",null),r([E({label:"On Begin Overlap With Actor",parameters:[{name:"actor",type:S}],emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",["function"==typeof(e="undefined"!=typeof A&&A)?e:Object]),i("design:returntype",W)],F.prototype,"onBeginOverlapWithActor",null),r([E({label:"On End Overlap With Actor",parameters:[{name:"actor",type:S}],emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",["function"==typeof(t="undefined"!=typeof A&&A)?t:Object]),i("design:returntype",W)],F.prototype,"onEndOverlapWithActor",null),r([E({label:"On Begin Overlap With Actor Type",parameters:[{name:"actorType",type:T}],emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[Object]),i("design:returntype",W)],F.prototype,"onBeginOverlapWithActorType",null),r([E({label:"On End Overlap With Actor Type",parameters:[{name:"actorType",type:T}],emits:S,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[Object]),i("design:returntype",W)],F.prototype,"onEndOverlapWithActorType",null),F=r([g({inEditor:!0,editorOnly:!1})],F);export{F as TriggerVolumeComponent};let L=class extends m{constructor(){super(...arguments),this.trigger=u(F)}};r([B({type:F,writable:!1}),i("design:type",Object)],L.prototype,"trigger",void 0),L=r([d({typeId:"TriggerVolume"})],L);export{L as TriggerVolume};/*
1
+ var e,t;import{__decorate as r,__metadata as i}from"tslib";import{EdgesGeometry as n,LineSegments as o,LineBasicMaterial as s,Vector3 as p,BoxGeometry as a,Mesh as c,MeshBasicMaterial as l,Group as y,Color as h}from"three";import{Actor as d,BaseActor as m}from"../actor.js";import{Component as g,ActorComponent as O,attach as u}from"../component.js";import{PhysicsSystem as v}from"../../services/physics/physics-system.js";import{BoxCollisionShape as f}from"../../../scene/collision/collision-shape.js";import{Parameter as b}from"../../../shader/parameter.js";import{firstValueFrom as j,Observable as W}from"rxjs";import{inject as w}from"../../../gameplay/inject.js";import{EventGraphEventSource as E,EventGraphProperty as B}from"../../event-graph/decorators.js";import{EVENT_GRAPH_ACTOR_CLASS_TYPE as T,EVENT_GRAPH_ACTOR_TYPE as x}from"../../event-graph/types.js";let S=class extends O{constructor(){super(...arguments),this.color=new h(16777215),this.dimensions=new p(1,1,1)}onInit(){const e=new a(this.dimensions.x,this.dimensions.y,this.dimensions.z),t=new n(e),r=new o(t,new s({color:this.color})),i=(new c(e,new l({color:this.color,transparent:!0,opacity:.3,visible:!1})),new y);i.add(r),this.actor.object.add(i)}};r([b(),i("design:type",h)],S.prototype,"color",void 0),r([b(),i("design:type",p)],S.prototype,"dimensions",void 0),S=r([g({inEditor:!0,editorOnly:!0})],S);export{S as TriggerVolumeMesh};let F=class extends O{constructor(){super(...arguments),this.dimensions=new p(1,1,1),this.offset=new p(0,0,0),this.editorMesh=u(S),this.physicsSystem=w(v)}onInit(){this.physicsSystem.addActor(this.actor,[new f(this.dimensions).withOffset(this.offset)],{isTrigger:!0}),j(this.disposed).then(()=>{this.physicsSystem.removeActor(this.actor)})}onBeginOverlap(){return this.physicsSystem.onBeginOverlap(this.actor)}onEndOverlap(){return this.physicsSystem.onEndOverlap(this.actor)}onBeginOverlapWithActor(e){return this.physicsSystem.onBeginOverlapWithActor(this.actor,e)}onEndOverlapWithActor(e){return this.physicsSystem.onEndOverlapWithActor(this.actor,e)}onBeginOverlapWithActorType(e){return this.physicsSystem.onBeginOverlapWithActorType(this.actor,e)}onEndOverlapWithActorType(e){return this.physicsSystem.onEndOverlapWithActorType(this.actor,e)}};r([E({label:"On Begin Overlap",emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[]),i("design:returntype",W)],F.prototype,"onBeginOverlap",null),r([E({label:"On End Overlap",emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[]),i("design:returntype",W)],F.prototype,"onEndOverlap",null),r([E({label:"On Begin Overlap With Actor",parameters:[{name:"actor",type:x}],emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",["function"==typeof(e="undefined"!=typeof A&&A)?e:Object]),i("design:returntype",W)],F.prototype,"onBeginOverlapWithActor",null),r([E({label:"On End Overlap With Actor",parameters:[{name:"actor",type:x}],emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",["function"==typeof(t="undefined"!=typeof A&&A)?t:Object]),i("design:returntype",W)],F.prototype,"onEndOverlapWithActor",null),r([E({label:"On Begin Overlap With Actor Type",parameters:[{name:"actorType",type:T}],emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[Object]),i("design:returntype",W)],F.prototype,"onBeginOverlapWithActorType",null),r([E({label:"On End Overlap With Actor Type",parameters:[{name:"actorType",type:T}],emits:x,valueLabel:"Other Actor"}),i("design:type",Function),i("design:paramtypes",[Object]),i("design:returntype",W)],F.prototype,"onEndOverlapWithActorType",null),F=r([g({inEditor:!0,editorOnly:!1})],F);export{F as TriggerVolumeComponent};let L=class extends m{constructor(){super(...arguments),this.trigger=u(F)}};r([B({type:F,writable:!1}),i("design:type",Object)],L.prototype,"trigger",void 0),L=r([d({typeId:"TriggerVolume",icon:"box-multiple"})],L);export{L as TriggerVolume};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{BufferGeometry as i,EdgesGeometry as s,Float32BufferAttribute as r,Group as o,DoubleSide as a,LineBasicMaterial as n,LineSegments as l,Mesh as h,MeshBasicMaterial as c,Material as u,Matrix4 as p,Vector3 as d}from"three";import{takeUntil as f}from"rxjs";import{NavigationArea as m}from"../../ai/navigation-areas.js";import{Parameter as g}from"../../../shader/parameter.js";import{Actor as w,BaseActor as y}from"../actor.js";import{ActorComponent as b,Component as S,attach as x}from"../component.js";import{SplineComponent as M}from"./components/spline-component.js";import{WaterPostProcessSettings as z}from"./components/water-post-process-settings.js";const v=1477586;let A=class extends b{constructor(){super(...arguments),this.fallbackMaterial=new c({color:v,transparent:!0,opacity:.65,side:a}),this.surface=new h(new i,this.fallbackMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.surface.name="Water Surface",this.actor.object.add(this.surface),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.setMaterial(this.actor.surfaceMaterial),this.rebuild()}setMaterial(t){this.surface.material=t??this.fallbackMaterial}rebuild(){if(!this.initialized)return;const t=this.surface.geometry;this.surface.geometry=F(this.actor.spline,this.actor.width,this.actor.surfaceSampleDistance,this.actor.surfaceWidthSubdivisions),this.surface.visible=this.actor.showSurface,t.dispose()}onEndPlay(){this.surface.geometry.dispose(),this.fallbackMaterial.dispose(),this.surface.removeFromParent()}};A=t([S({inEditor:!0})],A);let T=class extends b{constructor(){super(...arguments),this.visual=new o,this.fillMaterial=new c({color:v,transparent:!0,opacity:.18,depthWrite:!1}),this.edgeMaterial=new n({color:3520767}),this.fill=new h(new i,this.fillMaterial),this.edges=new l(new i,this.edgeMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.visual.name="Water Spline Volume Visualization",this.visual.userData.isEditorVisualization=!0,this.fill.frustumCulled=!1,this.edges.frustumCulled=!1,this.visual.add(this.fill,this.edges),this.actor.object.add(this.visual),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.rebuild()}rebuild(){if(!this.initialized)return;const t=function(t,e,s,o=!1,a=.5){const n=new i,l=D(t,e,s,a);if(l.length<2)return n.setAttribute("position",new r([],3)),n;const h=l.flatMap(t=>[...t.leftTop.toArray(),...t.rightTop.toArray(),...t.leftBottom.toArray(),...t.rightBottom.toArray()]),c=[];for(let t=1;t<l.length;t++){const e=4*(t-1),i=4*t;o||k(c,e,i,i+1,e+1),k(c,e+2,e+3,i+3,i+2),k(c,e,e+2,i+2,i),k(c,e+1,i+1,i+3,e+3)}if(!t.closed){k(c,0,1,3,2);const t=4*(l.length-1);k(c,t,t+2,t+3,t+1)}return n.setAttribute("position",new r(h,3)),n.setIndex(c),n.computeVertexNormals(),n.computeBoundingBox(),n.computeBoundingSphere(),n}(this.actor.spline,this.actor.width,this.actor.depth,this.actor.showSurface,this.actor.surfaceSampleDistance),e=0===t.getAttribute("position").count?new i:new s(t,20),o=this.fill.geometry,a=this.edges.geometry;this.fill.geometry=t,this.edges.geometry=e,o.dispose(),a.dispose(),this.visual.updateMatrixWorld(!0)}onEndPlay(){this.fill.geometry.dispose(),this.edges.geometry.dispose(),this.fillMaterial.dispose(),this.edgeMaterial.dispose(),this.visual.removeFromParent()}};T=t([S({inEditor:!0,editorOnly:!0})],T);let W=class extends y{constructor(){super(...arguments),this.spline=x(M),this.surface=x(A),this.editorVisual=x(T),this.underwater=x(z),this.width=5,this.depth=2,this.showSurface=!0,this.surfaceSampleDistance=1,this.surfaceWidthSubdivisions=1}applySceneParameters(t,e){if(![...e].every(t=>["width","depth","showSurface","surfaceMaterial","surfaceSampleDistance","surfaceWidthSubdivisions"].includes(t)))return!1;const i=e.has("width")?t.width:this.width,s=e.has("depth")?t.depth:this.depth;if("number"!=typeof i||!Number.isFinite(i)||i<=0)return!1;if("number"!=typeof s||!Number.isFinite(s)||s<=0)return!1;if(e.has("showSurface")&&"boolean"!=typeof t.showSurface)return!1;if(e.has("surfaceMaterial")&&null!=t.surfaceMaterial&&!(t.surfaceMaterial instanceof u))return!1;const r=e.has("surfaceSampleDistance")?t.surfaceSampleDistance:this.surfaceSampleDistance,o=e.has("surfaceWidthSubdivisions")?t.surfaceWidthSubdivisions:this.surfaceWidthSubdivisions;return!("number"!=typeof r||!Number.isFinite(r)||r<=0)&&(!("number"!=typeof o||!Number.isFinite(o)||o<1)&&(this.width=i,this.depth=s,e.has("showSurface")&&(this.showSurface=t.showSurface),e.has("surfaceMaterial")&&(this.surfaceMaterial=t.surfaceMaterial,this.surface.setMaterial(this.surfaceMaterial)),this.surfaceSampleDistance=r,this.surfaceWidthSubdivisions=Math.round(o),this.editorVisual.rebuild(),this.surface.rebuild(),!0))}containsWaterPoint(t){this.object.updateWorldMatrix(!0,!1);const e=E.copy(t).applyMatrix4(q.copy(this.object.matrixWorld).invert()),i=D(this.spline,this.width,this.depth,this.surfaceSampleDistance);for(let t=1;t<i.length;t++){const s=i[t-1],r=i[t];if(C(e,s.leftTop,s.rightTop,r.rightTop,r.leftTop,this.depth))return!0}return!1}getNavigationAreaModifiers(){const t=D(this.spline,this.width,this.depth);if(t.length<2)return[];this.object.updateWorldMatrix(!0,!1);const e=this.object.matrixWorld,i=[];for(let s=1;s<t.length;s++){const r=t[s-1],o=t[s],a=[r.leftTop,r.rightTop,o.rightTop,o.leftTop,r.leftBottom,r.rightBottom,o.rightBottom,o.leftBottom].map(t=>t.clone().applyMatrix4(e));i.push({area:m.Water,vertices:a.slice(0,4).map(t=>t.toArray()),minHeight:Math.min(...a.map(t=>t.y)),maxHeight:Math.max(...a.map(t=>t.y))})}return i}};t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"width",void 0),t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"depth",void 0),t([g({group:"Surface"}),e("design:type",Boolean)],W.prototype,"showSurface",void 0),t([g({type:u,group:"Surface",requires:{showSurface:!0},help:"Optional. Uses a translucent debug material when unset."}),e("design:type",u)],W.prototype,"surfaceMaterial",void 0),t([g({range:[.1,100],group:"Surface",requires:{showSurface:!0},help:"Target spacing in world units between sections along the spline."}),e("design:type",Number)],W.prototype,"surfaceSampleDistance",void 0),t([g({range:[1,64],stepSize:1,group:"Surface",requires:{showSurface:!0},help:"Subdivisions across the water. Increase for vertex displacement and detailed bank effects."}),e("design:type",Number)],W.prototype,"surfaceWidthSubdivisions",void 0),W=t([w({typeId:"WaterSplineVolume"})],W);export{W as WaterSplineVolume};function D(t,e,i,s=.5){if(t.points.length<2||t.length<=0||e<=0||i<0)return[];const r=Math.min(513,Math.max(2,Math.ceil(t.length/Math.max(.01,s))+1)),o=[],a=Array.from({length:r},(e,i)=>t.samplePositionAtDistance(t.length*i/(r-1),new d)),n=Math.min(.5*e,.25*t.length),l=Array.from({length:r},(e,i)=>{const s=t.length*i/(r-1),o=V(t,s-n,new d),a=V(t,s+n,new d).sub(o).setY(0);return a.lengthSq()<1e-8&&t.sampleTangentAtDistance(s,a).setY(0),a.lengthSq()<1e-8&&a.set(1,0,0),a.normalize(),new d(-a.z,0,a.x)}),h=.5*e,c=Array(r).fill(h),u=Array(r).fill(h);for(let e=0;e<r;e++){if(!t.closed&&(0===e||e===r-1))continue;const i=a[0===e?r-2:e-1],s=a[e],o=a[e===r-1?1:e+1],n=Math.min(h,.6*P(i,s,o)),l=N(i,s,o);l>1e-8?c[e]=n:l<-1e-8&&(u[e]=n)}j(c,a),j(u,a);for(let e=0;e<r;e++){const s=l[e],n=a[e].clone().addScaledVector(s,c[e]),h=a[e].clone().addScaledVector(s,-u[e]);o.push({leftTop:n,rightTop:h,leftBottom:n.clone().addScaledVector(I,i),rightBottom:h.clone().addScaledVector(I,i),flowDirection:t.sampleTangentAtDistance(t.length*e/(r-1),new d).normalize(),distanceAlongSpline:t.length*e/(r-1),surfaceWidth:c[e]+u[e]})}return function(t,e,i){B(t.map(t=>t.leftTop),e),B(t.map(t=>t.rightTop),e);for(const e of t)e.leftBottom.copy(e.leftTop).addScaledVector(I,i),e.rightBottom.copy(e.rightTop).addScaledVector(I,i),e.surfaceWidth=e.leftTop.distanceTo(e.rightTop)}(o,t.closed,i),o}function B(t,e){const i=e?t.length-1:t.length;if(!(i<3))for(let s=0;s<2;s++){const s=t.map(t=>t.clone()),r=e?i:i-1;for(let o=e?0:1;o<r;o++){const e=s[(o-1+i)%i],r=s[(o+1)%i];t[o].lerpVectors(e,r,.5).lerp(s[o],.5)}e&&t[t.length-1].copy(t[0])}}function V(t,e,i){if(!t.closed)return t.samplePositionAtDistance(e,i);const s=(e%t.length+t.length)%t.length;return t.samplePositionAtDistance(s,i)}function j(t,e){for(let i=1;i<t.length;i++)t[i]=Math.min(t[i],t[i-1]+.5*e[i].distanceTo(e[i-1]));for(let i=t.length-2;i>=0;i--)t[i]=Math.min(t[i],t[i+1]+.5*e[i].distanceTo(e[i+1]))}function N(t,e,i){return(e.x-t.x)*(i.z-e.z)-(e.z-t.z)*(i.x-e.x)}function P(t,e,i){const s=Math.hypot(e.x-t.x,e.z-t.z),r=Math.hypot(i.x-e.x,i.z-e.z),o=Math.hypot(i.x-t.x,i.z-t.z),a=Math.abs((e.x-t.x)*(i.z-t.z)-(e.z-t.z)*(i.x-t.x));return s<1e-6||r<1e-6||o<1e-6||a<1e-8?1/0:s*r*o/(2*a)}export function createWaterSplineSurfaceGeometry(t,e,i,s){return F(t,e,i,s)}function F(t,e,s,o){const a=new i,n=D(t,e,0,s),l=Math.max(1,Math.round(o))+1;if(n.length<2)return a.setAttribute("position",new r([],3)),a;const h=[],c=[],u=[],p=[],d=[];for(const e of n)for(let i=0;i<l;i++){const s=i/(l-1);h.push(...e.leftTop.clone().lerp(e.rightTop,s).toArray()),c.push(s,t.length>0?e.distanceAlongSpline/t.length:0),u.push(...e.flowDirection.toArray()),p.push(Math.min(s,1-s)*e.surfaceWidth),d.push(e.distanceAlongSpline)}const f=[];for(let t=1;t<n.length;t++)for(let e=1;e<l;e++){const i=(t-1)*l+e-1,s=t*l+e-1;k(f,i,s,s+1,i+1)}return a.setAttribute("position",new r(h,3)),a.setAttribute("uv",new r(c,2)),a.setAttribute("waterFlowDirection",new r(u,3)),a.setAttribute("waterDistanceFromBank",new r(p,1)),a.setAttribute("waterDistanceAlongSpline",new r(d,1)),a.setIndex(f),a.computeVertexNormals(),a.computeBoundingBox(),a.computeBoundingSphere(),a}function k(t,e,i,s,r){t.push(e,i,s,e,s,r)}const I=new d(0,-1,0),q=new p,E=new d;function C(t,e,i,s,r,o){const a=H(t,e,i,s)??H(t,e,s,r);return null!=a&&t.y<=a&&t.y>=a-o}function H(t,e,i,s){const r=(i.z-s.z)*(e.x-s.x)+(s.x-i.x)*(e.z-s.z);if(Math.abs(r)<1e-8)return null;const o=((i.z-s.z)*(t.x-s.x)+(s.x-i.x)*(t.z-s.z))/r,a=((s.z-e.z)*(t.x-s.x)+(e.x-s.x)*(t.z-s.z))/r,n=1-o-a;return o>=0&&a>=0&&n>=0?o*e.y+a*i.y+n*s.y:null}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import{BufferGeometry as i,EdgesGeometry as s,Float32BufferAttribute as r,Group as o,DoubleSide as a,LineBasicMaterial as n,LineSegments as l,Mesh as h,MeshBasicMaterial as c,Material as u,Matrix4 as p,Vector3 as d}from"three";import{takeUntil as f}from"rxjs";import{NavigationArea as m}from"../../ai/navigation-areas.js";import{Parameter as g}from"../../../shader/parameter.js";import{Actor as w,BaseActor as y}from"../actor.js";import{ActorComponent as b,Component as S,attach as x}from"../component.js";import{SplineComponent as M}from"./components/spline-component.js";import{WaterPostProcessSettings as z}from"./components/water-post-process-settings.js";const v=1477586;let A=class extends b{constructor(){super(...arguments),this.fallbackMaterial=new c({color:v,transparent:!0,opacity:.65,side:a}),this.surface=new h(new i,this.fallbackMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.surface.name="Water Surface",this.actor.object.add(this.surface),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.setMaterial(this.actor.surfaceMaterial),this.rebuild()}setMaterial(t){this.surface.material=t??this.fallbackMaterial}rebuild(){if(!this.initialized)return;const t=this.surface.geometry;this.surface.geometry=F(this.actor.spline,this.actor.width,this.actor.surfaceSampleDistance,this.actor.surfaceWidthSubdivisions),this.surface.visible=this.actor.showSurface,t.dispose()}onEndPlay(){this.surface.geometry.dispose(),this.fallbackMaterial.dispose(),this.surface.removeFromParent()}};A=t([S({inEditor:!0})],A);let T=class extends b{constructor(){super(...arguments),this.visual=new o,this.fillMaterial=new c({color:v,transparent:!0,opacity:.18,depthWrite:!1}),this.edgeMaterial=new n({color:3520767}),this.fill=new h(new i,this.fillMaterial),this.edges=new l(new i,this.edgeMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.visual.name="Water Spline Volume Visualization",this.visual.userData.isEditorVisualization=!0,this.fill.frustumCulled=!1,this.edges.frustumCulled=!1,this.visual.add(this.fill,this.edges),this.actor.object.add(this.visual),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.rebuild()}rebuild(){if(!this.initialized)return;const t=function(t,e,s,o=!1,a=.5){const n=new i,l=D(t,e,s,a);if(l.length<2)return n.setAttribute("position",new r([],3)),n;const h=l.flatMap(t=>[...t.leftTop.toArray(),...t.rightTop.toArray(),...t.leftBottom.toArray(),...t.rightBottom.toArray()]),c=[];for(let t=1;t<l.length;t++){const e=4*(t-1),i=4*t;o||k(c,e,i,i+1,e+1),k(c,e+2,e+3,i+3,i+2),k(c,e,e+2,i+2,i),k(c,e+1,i+1,i+3,e+3)}if(!t.closed){k(c,0,1,3,2);const t=4*(l.length-1);k(c,t,t+2,t+3,t+1)}return n.setAttribute("position",new r(h,3)),n.setIndex(c),n.computeVertexNormals(),n.computeBoundingBox(),n.computeBoundingSphere(),n}(this.actor.spline,this.actor.width,this.actor.depth,this.actor.showSurface,this.actor.surfaceSampleDistance),e=0===t.getAttribute("position").count?new i:new s(t,20),o=this.fill.geometry,a=this.edges.geometry;this.fill.geometry=t,this.edges.geometry=e,o.dispose(),a.dispose(),this.visual.updateMatrixWorld(!0)}onEndPlay(){this.fill.geometry.dispose(),this.edges.geometry.dispose(),this.fillMaterial.dispose(),this.edgeMaterial.dispose(),this.visual.removeFromParent()}};T=t([S({inEditor:!0,editorOnly:!0})],T);let W=class extends y{constructor(){super(...arguments),this.spline=x(M),this.surface=x(A),this.editorVisual=x(T),this.underwater=x(z),this.width=5,this.depth=2,this.showSurface=!0,this.surfaceSampleDistance=1,this.surfaceWidthSubdivisions=1}applySceneParameters(t,e){if(![...e].every(t=>["width","depth","showSurface","surfaceMaterial","surfaceSampleDistance","surfaceWidthSubdivisions"].includes(t)))return!1;const i=e.has("width")?t.width:this.width,s=e.has("depth")?t.depth:this.depth;if("number"!=typeof i||!Number.isFinite(i)||i<=0)return!1;if("number"!=typeof s||!Number.isFinite(s)||s<=0)return!1;if(e.has("showSurface")&&"boolean"!=typeof t.showSurface)return!1;if(e.has("surfaceMaterial")&&null!=t.surfaceMaterial&&!(t.surfaceMaterial instanceof u))return!1;const r=e.has("surfaceSampleDistance")?t.surfaceSampleDistance:this.surfaceSampleDistance,o=e.has("surfaceWidthSubdivisions")?t.surfaceWidthSubdivisions:this.surfaceWidthSubdivisions;return!("number"!=typeof r||!Number.isFinite(r)||r<=0)&&(!("number"!=typeof o||!Number.isFinite(o)||o<1)&&(this.width=i,this.depth=s,e.has("showSurface")&&(this.showSurface=t.showSurface),e.has("surfaceMaterial")&&(this.surfaceMaterial=t.surfaceMaterial,this.surface.setMaterial(this.surfaceMaterial)),this.surfaceSampleDistance=r,this.surfaceWidthSubdivisions=Math.round(o),this.editorVisual.rebuild(),this.surface.rebuild(),!0))}containsWaterPoint(t){this.object.updateWorldMatrix(!0,!1);const e=E.copy(t).applyMatrix4(q.copy(this.object.matrixWorld).invert()),i=D(this.spline,this.width,this.depth,this.surfaceSampleDistance);for(let t=1;t<i.length;t++){const s=i[t-1],r=i[t];if(C(e,s.leftTop,s.rightTop,r.rightTop,r.leftTop,this.depth))return!0}return!1}getNavigationAreaModifiers(){const t=D(this.spline,this.width,this.depth);if(t.length<2)return[];this.object.updateWorldMatrix(!0,!1);const e=this.object.matrixWorld,i=[];for(let s=1;s<t.length;s++){const r=t[s-1],o=t[s],a=[r.leftTop,r.rightTop,o.rightTop,o.leftTop,r.leftBottom,r.rightBottom,o.rightBottom,o.leftBottom].map(t=>t.clone().applyMatrix4(e));i.push({area:m.Water,vertices:a.slice(0,4).map(t=>t.toArray()),minHeight:Math.min(...a.map(t=>t.y)),maxHeight:Math.max(...a.map(t=>t.y))})}return i}};t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"width",void 0),t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"depth",void 0),t([g({group:"Surface"}),e("design:type",Boolean)],W.prototype,"showSurface",void 0),t([g({type:u,group:"Surface",requires:{showSurface:!0},help:"Optional. Uses a translucent debug material when unset."}),e("design:type",u)],W.prototype,"surfaceMaterial",void 0),t([g({range:[.1,100],group:"Surface",requires:{showSurface:!0},help:"Target spacing in world units between sections along the spline."}),e("design:type",Number)],W.prototype,"surfaceSampleDistance",void 0),t([g({range:[1,64],stepSize:1,group:"Surface",requires:{showSurface:!0},help:"Subdivisions across the water. Increase for vertex displacement and detailed bank effects."}),e("design:type",Number)],W.prototype,"surfaceWidthSubdivisions",void 0),W=t([w({typeId:"WaterSplineVolume",icon:"ripple"})],W);export{W as WaterSplineVolume};function D(t,e,i,s=.5){if(t.points.length<2||t.length<=0||e<=0||i<0)return[];const r=Math.min(513,Math.max(2,Math.ceil(t.length/Math.max(.01,s))+1)),o=[],a=Array.from({length:r},(e,i)=>t.samplePositionAtDistance(t.length*i/(r-1),new d)),n=Math.min(.5*e,.25*t.length),l=Array.from({length:r},(e,i)=>{const s=t.length*i/(r-1),o=V(t,s-n,new d),a=V(t,s+n,new d).sub(o).setY(0);return a.lengthSq()<1e-8&&t.sampleTangentAtDistance(s,a).setY(0),a.lengthSq()<1e-8&&a.set(1,0,0),a.normalize(),new d(-a.z,0,a.x)}),h=.5*e,c=Array(r).fill(h),u=Array(r).fill(h);for(let e=0;e<r;e++){if(!t.closed&&(0===e||e===r-1))continue;const i=a[0===e?r-2:e-1],s=a[e],o=a[e===r-1?1:e+1],n=Math.min(h,.6*P(i,s,o)),l=N(i,s,o);l>1e-8?c[e]=n:l<-1e-8&&(u[e]=n)}j(c,a),j(u,a);for(let e=0;e<r;e++){const s=l[e],n=a[e].clone().addScaledVector(s,c[e]),h=a[e].clone().addScaledVector(s,-u[e]);o.push({leftTop:n,rightTop:h,leftBottom:n.clone().addScaledVector(I,i),rightBottom:h.clone().addScaledVector(I,i),flowDirection:t.sampleTangentAtDistance(t.length*e/(r-1),new d).normalize(),distanceAlongSpline:t.length*e/(r-1),surfaceWidth:c[e]+u[e]})}return function(t,e,i){B(t.map(t=>t.leftTop),e),B(t.map(t=>t.rightTop),e);for(const e of t)e.leftBottom.copy(e.leftTop).addScaledVector(I,i),e.rightBottom.copy(e.rightTop).addScaledVector(I,i),e.surfaceWidth=e.leftTop.distanceTo(e.rightTop)}(o,t.closed,i),o}function B(t,e){const i=e?t.length-1:t.length;if(!(i<3))for(let s=0;s<2;s++){const s=t.map(t=>t.clone()),r=e?i:i-1;for(let o=e?0:1;o<r;o++){const e=s[(o-1+i)%i],r=s[(o+1)%i];t[o].lerpVectors(e,r,.5).lerp(s[o],.5)}e&&t[t.length-1].copy(t[0])}}function V(t,e,i){if(!t.closed)return t.samplePositionAtDistance(e,i);const s=(e%t.length+t.length)%t.length;return t.samplePositionAtDistance(s,i)}function j(t,e){for(let i=1;i<t.length;i++)t[i]=Math.min(t[i],t[i-1]+.5*e[i].distanceTo(e[i-1]));for(let i=t.length-2;i>=0;i--)t[i]=Math.min(t[i],t[i+1]+.5*e[i].distanceTo(e[i+1]))}function N(t,e,i){return(e.x-t.x)*(i.z-e.z)-(e.z-t.z)*(i.x-e.x)}function P(t,e,i){const s=Math.hypot(e.x-t.x,e.z-t.z),r=Math.hypot(i.x-e.x,i.z-e.z),o=Math.hypot(i.x-t.x,i.z-t.z),a=Math.abs((e.x-t.x)*(i.z-t.z)-(e.z-t.z)*(i.x-t.x));return s<1e-6||r<1e-6||o<1e-6||a<1e-8?1/0:s*r*o/(2*a)}export function createWaterSplineSurfaceGeometry(t,e,i,s){return F(t,e,i,s)}function F(t,e,s,o){const a=new i,n=D(t,e,0,s),l=Math.max(1,Math.round(o))+1;if(n.length<2)return a.setAttribute("position",new r([],3)),a;const h=[],c=[],u=[],p=[],d=[];for(const e of n)for(let i=0;i<l;i++){const s=i/(l-1);h.push(...e.leftTop.clone().lerp(e.rightTop,s).toArray()),c.push(s,t.length>0?e.distanceAlongSpline/t.length:0),u.push(...e.flowDirection.toArray()),p.push(Math.min(s,1-s)*e.surfaceWidth),d.push(e.distanceAlongSpline)}const f=[];for(let t=1;t<n.length;t++)for(let e=1;e<l;e++){const i=(t-1)*l+e-1,s=t*l+e-1;k(f,i,s,s+1,i+1)}return a.setAttribute("position",new r(h,3)),a.setAttribute("uv",new r(c,2)),a.setAttribute("waterFlowDirection",new r(u,3)),a.setAttribute("waterDistanceFromBank",new r(p,1)),a.setAttribute("waterDistanceAlongSpline",new r(d,1)),a.setIndex(f),a.computeVertexNormals(),a.computeBoundingBox(),a.computeBoundingSphere(),a}function k(t,e,i,s,r){t.push(e,i,s,e,s,r)}const I=new d(0,-1,0),q=new p,E=new d;function C(t,e,i,s,r,o){const a=H(t,e,i,s)??H(t,e,s,r);return null!=a&&t.y<=a&&t.y>=a-o}function H(t,e,i,s){const r=(i.z-s.z)*(e.x-s.x)+(s.x-i.x)*(e.z-s.z);if(Math.abs(r)<1e-8)return null;const o=((i.z-s.z)*(t.x-s.x)+(s.x-i.x)*(t.z-s.z))/r,a=((s.z-e.z)*(t.x-s.x)+(e.x-s.x)*(t.z-s.z))/r,n=1-o-a;return o>=0&&a>=0&&n>=0?o*e.y+a*i.y+n*s.y:null}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */