@hology/core 0.0.241 → 0.0.243

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.
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{GpuVfxScheduler as t}from"./gpu-vfx-scheduler.js";import{calculateGpuSpriteOptionalStateLayout as s,GPU_SPRITE_BASE_COMMAND_BYTES as i,GPU_SPRITE_EMITTER_BYTES as r,GPU_SPRITE_TRANSFORM_COMMAND_BYTES as n,GpuSpriteRuntime as a}from"./gpu-sprite-runtime.js";import{GpuSpriteTemplateCache as l,instantiateGpuSpriteTemplate as h}from"./gpu-sprite-template.js";export class GpuSpriteSchedulerRuntime{constructor(t,s,i,r,n,a,l,h,c,u,o){this.maximumInstances=n,this.emittersPerInstance=a,this.instanceDuration=l,this.maximumParticleLife=h,this.emitterCapacities=c,this.emitterPositionOffsets=u,this.inputBindings=o,this.activePages=new Set,this.positionScratch=new e.Vector3,this.activePagesDirty=!1,this.runtime=t,this.scheduler=s,this.compatibility=i,this.reasons=r,this.activeBySlot=new Array(n).fill(null),this.emitterIndexScratch=new Array(a).fill(0),this.instanceParticleCapacity=c.reduce((e,t)=>e+t,0),this.stoppingDeadlines=new Float64Array(n),this.stoppingDeadlines.fill(Number.POSITIVE_INFINITY);for(let e=0;e<t.emitters.length;e++)t.setEmitterActive(e,!1);t.setActivePages([])}static async create(c){const u=Math.max(1,Math.floor(c.maximumInstances)),o=(await(c.templateCache??new l).resolve(c.asset,{assets:c.assets,renderClassCache:c.cache,resolveCustomMaterial:c.resolveCustomMaterial,revision:c.templateRevision})).template;if(null==o)return null;const m=o.particleCapacity,d=Math.max(1,Math.floor(c.particlePageSize??m)),p=Math.ceil(m/d)*d*u,f=m*u,I=u*o.emitters.length,P=o.renderClasses.some(e=>null!=e.meshVertices),g=o.renderClasses.some(e=>!0===e.localSpace&&null==e.trail),S=I*(o.emitters.some(e=>!0===e.localSpace&&null!=o.renderClasses[e.renderClass??0]?.trail)?n:i),y=P||o.emitters.some(e=>1!==e.meshScaleStart.x||1!==e.meshScaleStart.y||1!==e.meshScaleStart.z||1!==e.meshScaleEnd.x||1!==e.meshScaleEnd.y||1!==e.meshScaleEnd.z),v=o.emitters.reduce((e,t)=>{const s=o.renderClasses[t.renderClass??0]?.trail;return e+(null==s?0:t.capacity*(s.historyLength+1))},0)*u,x=s({capacity:p,particleTransforms:y,vortex:o.emitters.some(e=>e.hasVortex),disperse:o.emitters.some(e=>e.hasDisperse),trailHistoryEntries:v}),C=P?16*I*4+o.renderClasses.reduce((e,t)=>e+(t.meshVertices?.byteLength??0),0):0;if(16*p*4+4*f+4*p+4*p*4+I*r+Math.max(i,S)+160+16*o.renderClasses.length*2+C+x.bytes+(g&&!P?16*I*4:0)>(c.maximumStorageBytes??Number.POSITIVE_INFINITY))return null;if(null!=c.device){const e=c.device.limits.maxStorageBufferBindingSize;if([16*p*4,4*f,4*p,4*p*4,I*r,Math.max(i,S),...P||g?[16*I*4]:[],...x.bytes>0?[x.bytes]:[]].some(t=>t>e))return null;if(7+(x.bytes>0?1:0)>c.device.limits.maxStorageBuffersPerShaderStage)return null}const E=new e.Vector3,D=h(o,new Array(u).fill(E)),T=new a(D,o.renderClasses,void 0,{pageSize:d,capacity:p,aliveCountReadback:c.aliveCountReadback});return new GpuSpriteSchedulerRuntime(T,new t({pageSize:d,maximumParticles:p}),o.compatibility,o.reasons,u,o.emitters.length,o.duration,o.emitters.reduce((e,t)=>Math.max(e,t.life),0),o.emitters.map(e=>e.capacity),o.emitters.map(e=>e.position.clone()),o.inputBindings)}spawn(e){const t=this.scheduler.createInstance({particleCapacity:this.instanceParticleCapacity,duration:this.instanceDuration});if(null==t)return null;const s=this.scheduler.arena.get(t).pages;if(0===s.length)return this.scheduler.destroyInstance(t),null;const i={handle:t,pages:s};this.activeBySlot[t.slot]=i;for(const e of s)this.activePages.add(e);this.activePagesDirty=!0;for(let e=0;e<this.emittersPerInstance;e++)this.emitterIndexScratch[e]=t.slot*this.emittersPerInstance+e;this.runtime.mapParticlePages(s,this.emitterIndexScratch,this.emitterCapacities);for(let s=0;s<this.emittersPerInstance;s++){const i=t.slot*this.emittersPerInstance+s;this.positionScratch.copy(this.emitterPositionOffsets[s]),!0!==this.runtime.emitters[i].localSpace&&null==this.runtime.emitters[i].parentEmitter&&this.positionScratch.add(e),this.runtime.queueEmitterState(i,this.positionScratch,!0,!0)}return this.scheduler.play(t),i}destroy(e){if(null==this.scheduler.getInstance(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++){const s=e.handle.slot*this.emittersPerInstance+t;this.runtime.queueEmitterState(s,this.runtime.emitters[s].position,!1)}for(const t of e.pages)this.activePages.delete(t);return this.activePagesDirty=!0,this.activeBySlot[e.handle.slot]=null,this.scheduler.destroyInstance(e.handle)}setPosition(e,t){if(null==this.scheduler.getInstance(e.handle))return!1;for(let s=0;s<this.emittersPerInstance;s++){const i=e.handle.slot*this.emittersPerInstance+s;!0!==this.runtime.emitters[i].localSpace&&null==this.runtime.emitters[i].parentEmitter&&(this.positionScratch.copy(t).add(this.emitterPositionOffsets[s]),this.runtime.queueEmitterState(i,this.positionScratch,!0))}return!0}setTransform(e,t){if(null==this.scheduler.getInstance(e.handle))return!1;for(let s=0;s<this.emittersPerInstance;s++)this.runtime.setEmitterTransform(e.handle.slot*this.emittersPerInstance+s,t);return!0}pause(e){if(!this.scheduler.pause(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++)this.runtime.queueEmitterPaused(e.handle.slot*this.emittersPerInstance+t,!0);return!0}play(e){if(!this.scheduler.play(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++)this.runtime.queueEmitterPaused(e.handle.slot*this.emittersPerInstance+t,!1);return!0}setTimescale(e,t){if(!this.scheduler.setTimescale(e.handle,t))return!1;for(let s=0;s<this.emittersPerInstance;s++)this.runtime.queueEmitterTimescale(e.handle.slot*this.emittersPerInstance+s,t);return!0}setInput(e,t,s){if(null==this.scheduler.getInstance(e.handle))return!1;let i=!1;for(const r of this.inputBindings){if(r.inputId!==t)continue;const n=e.handle.slot*this.emittersPerInstance+r.emitterIndex;i=this.runtime.setEmitterBoundValue(n,r,s)||i}return i&&this.scheduler.setDuration(e.handle,this.calculateInstanceDuration(e.handle.slot)),i}calculateInstanceDuration(e){let t=0;for(let s=0;s<this.emittersPerInstance;s++){const i=this.runtime.emitters[e*this.emittersPerInstance+s],r="continuous"===i.rate.type?i.rate.duration<0?Number.POSITIVE_INFINITY:i.rate.delay+i.rate.duration+i.life:i.rate.delay+i.life;t=Math.max(t,r)}return t}restart(e){if(!this.scheduler.restart(e.handle))return!1;this.stoppingDeadlines[e.handle.slot]=Number.POSITIVE_INFINITY;for(let t=0;t<this.emittersPerInstance;t++){const s=e.handle.slot*this.emittersPerInstance+t;this.runtime.queueEmitterState(s,this.runtime.emitters[s].position,!0,!0)}return!0}stop(e,t){const s=this.scheduler.getInstance(e.handle);if(null==s||!this.scheduler.stop(e.handle))return!1;const i=null==t?this.maximumParticleLife:Math.max(0,t);this.stoppingDeadlines[e.handle.slot]=s.elapsedTime+i;for(let s=0;s<this.emittersPerInstance;s++)this.runtime.queueEmitterStop(e.handle.slot*this.emittersPerInstance+s,t);return!0}update(e){this.scheduler.update(e),this.runtime.update(e);for(const e of this.activeBySlot){if(null==e)continue;const t=this.scheduler.getInstance(e.handle);null!=t&&((!1===t.playing&&t.elapsedTime>=this.instanceDuration||t.stopping&&t.elapsedTime>=this.stoppingDeadlines[e.handle.slot])&&this.destroy(e))}this.flushActivePages()}flushActivePages(){this.activePagesDirty&&(this.runtime.setActivePages(this.activePages),this.activePagesDirty=!1)}getStats(){return{scheduler:this.scheduler.getStats(),particles:this.runtime.getStats()}}dispose(){this.runtime.dispose();for(const e of this.activeBySlot)null!=e&&this.scheduler.destroyInstance(e.handle);this.activeBySlot.fill(null)}}/*
1
+ import*as e from"three";import{GpuVfxScheduler as t}from"./gpu-vfx-scheduler.js";import{calculateGpuSpriteOptionalStateLayout as s,GPU_SPRITE_BASE_COMMAND_BYTES as i,GPU_SPRITE_EMITTER_BYTES as r,GPU_SPRITE_TRANSFORM_COMMAND_BYTES as n,GpuSpriteRuntime as a}from"./gpu-sprite-runtime.js";import{GpuSpriteTemplateCache as l,instantiateGpuSpriteTemplate as h}from"./gpu-sprite-template.js";export class GpuSpriteSchedulerRuntime{constructor(t,s,i,r,n,a,l,h,c,o,u){this.maximumInstances=n,this.emittersPerInstance=a,this.instanceDuration=l,this.maximumParticleLife=h,this.emitterCapacities=c,this.emitterPositionOffsets=o,this.inputBindings=u,this.activePages=new Set,this.positionScratch=new e.Vector3,this.activePagesDirty=!1,this.runtime=t,this.scheduler=s,this.compatibility=i,this.reasons=r,this.activeBySlot=new Array(n).fill(null),this.emitterIndexScratch=new Array(a).fill(0),this.instanceParticleCapacity=c.reduce((e,t)=>e+t,0),this.stoppingDeadlines=new Float64Array(n),this.stoppingDeadlines.fill(Number.POSITIVE_INFINITY);for(let e=0;e<t.emitters.length;e++)t.setEmitterActive(e,!1);t.setActivePages([])}static async create(c){const o=Math.max(1,Math.floor(c.maximumInstances)),u=(await(c.templateCache??new l).resolve(c.asset,{assets:c.assets,renderClassCache:c.cache,resolveCustomMaterial:c.resolveCustomMaterial,revision:c.templateRevision})).template;if(null==u)return null;const m=u.particleCapacity,d=Math.max(1,Math.floor(c.particlePageSize??m)),p=Math.ceil(m/d)*d*o,f=m*o,I=o*u.emitters.length,S=u.renderClasses.some(e=>null!=e.meshVertices),P=u.renderClasses.some(e=>!0===e.localSpace&&null==e.trail),g=I*(u.emitters.some(e=>!0===e.localSpace&&null!=u.renderClasses[e.renderClass??0]?.trail)?n:i),y=S||u.emitters.some(e=>1!==e.meshScaleStart.x||1!==e.meshScaleStart.y||1!==e.meshScaleStart.z||1!==e.meshScaleEnd.x||1!==e.meshScaleEnd.y||1!==e.meshScaleEnd.z),v=u.emitters.reduce((e,t)=>{const s=u.renderClasses[t.renderClass??0]?.trail;return e+(null==s?0:t.capacity*(s.historyLength+1))},0)*o,x=s({capacity:p,particleTransforms:y,vortex:u.emitters.some(e=>e.hasVortex),disperse:u.emitters.some(e=>e.hasDisperse),trailHistoryEntries:v}),E=S?16*I*4+u.renderClasses.reduce((e,t)=>e+(t.meshVertices?.byteLength??0),0):0;if(16*p*4+4*f+4*p+4*p*4+I*r+Math.max(i,g)+160+16*u.renderClasses.length*2+E+x.bytes+(P&&!S?16*I*4:0)>(c.maximumStorageBytes??Number.POSITIVE_INFINITY))return null;if(null!=c.device){const e=c.device.limits.maxStorageBufferBindingSize;if([16*p*4,4*f,4*p,4*p*4,I*r,Math.max(i,g),...S||P?[16*I*4]:[],...x.bytes>0?[x.bytes]:[]].some(t=>t>e))return null;if(7+(x.bytes>0?1:0)>c.device.limits.maxStorageBuffersPerShaderStage)return null}const C=new e.Vector3,D=h(u,new Array(o).fill(C)),T=new a(D,u.renderClasses,void 0,{pageSize:d,capacity:p,aliveCountReadback:c.aliveCountReadback});return new GpuSpriteSchedulerRuntime(T,new t({pageSize:d,maximumParticles:p}),u.compatibility,u.reasons,o,u.emitters.length,u.duration,u.emitters.reduce((e,t)=>Math.max(e,t.life),0),u.emitters.map(e=>e.capacity),u.emitters.map(e=>e.position.clone()),u.inputBindings)}spawn(e){const t=this.scheduler.createInstance({particleCapacity:this.instanceParticleCapacity,duration:this.instanceDuration});if(null==t)return null;const s=this.scheduler.arena.get(t).pages;if(0===s.length)return this.scheduler.destroyInstance(t),null;const i={handle:t,pages:s};this.activeBySlot[t.slot]=i;for(const e of s)this.activePages.add(e);this.activePagesDirty=!0;for(let e=0;e<this.emittersPerInstance;e++)this.emitterIndexScratch[e]=t.slot*this.emittersPerInstance+e;this.runtime.mapParticlePages(s,this.emitterIndexScratch,this.emitterCapacities);for(let s=0;s<this.emittersPerInstance;s++){const i=t.slot*this.emittersPerInstance+s;this.positionScratch.copy(this.emitterPositionOffsets[s]),!0!==this.runtime.emitters[i].localSpace&&null==this.runtime.emitters[i].parentEmitter&&this.positionScratch.add(e),this.runtime.queueEmitterState(i,this.positionScratch,!0,!0)}return this.scheduler.play(t),i}destroy(e){if(null==this.scheduler.getInstance(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++){const s=e.handle.slot*this.emittersPerInstance+t;this.runtime.queueEmitterState(s,this.runtime.emitters[s].position,!1)}for(const t of e.pages)this.activePages.delete(t);return this.activePagesDirty=!0,this.activeBySlot[e.handle.slot]=null,this.scheduler.destroyInstance(e.handle)}setPosition(e,t){if(null==this.scheduler.getInstance(e.handle))return!1;for(let s=0;s<this.emittersPerInstance;s++){const i=e.handle.slot*this.emittersPerInstance+s;!0!==this.runtime.emitters[i].localSpace&&null==this.runtime.emitters[i].parentEmitter&&(this.positionScratch.copy(t).add(this.emitterPositionOffsets[s]),this.runtime.queueEmitterState(i,this.positionScratch,!0))}return!0}setTransform(e,t){if(null==this.scheduler.getInstance(e.handle))return!1;for(let s=0;s<this.emittersPerInstance;s++){const i=e.handle.slot*this.emittersPerInstance+s,r=this.runtime.emitters[i];this.runtime.setEmitterTransform(i,t),!0!==r.localSpace&&null==r.parentEmitter&&(this.positionScratch.copy(this.emitterPositionOffsets[s]).applyMatrix4(t),this.runtime.queueEmitterState(i,this.positionScratch,!0))}return!0}pause(e){if(!this.scheduler.pause(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++)this.runtime.queueEmitterPaused(e.handle.slot*this.emittersPerInstance+t,!0);return!0}play(e){if(!this.scheduler.play(e.handle))return!1;for(let t=0;t<this.emittersPerInstance;t++)this.runtime.queueEmitterPaused(e.handle.slot*this.emittersPerInstance+t,!1);return!0}setTimescale(e,t){if(!this.scheduler.setTimescale(e.handle,t))return!1;for(let s=0;s<this.emittersPerInstance;s++)this.runtime.queueEmitterTimescale(e.handle.slot*this.emittersPerInstance+s,t);return!0}setInput(e,t,s){if(null==this.scheduler.getInstance(e.handle))return!1;let i=!1;for(const r of this.inputBindings){if(r.inputId!==t)continue;const n=e.handle.slot*this.emittersPerInstance+r.emitterIndex;i=this.runtime.setEmitterBoundValue(n,r,s)||i}return i&&this.scheduler.setDuration(e.handle,this.calculateInstanceDuration(e.handle.slot)),i}calculateInstanceDuration(e){let t=0;for(let s=0;s<this.emittersPerInstance;s++){const i=this.runtime.emitters[e*this.emittersPerInstance+s],r="continuous"===i.rate.type?i.rate.duration<0?Number.POSITIVE_INFINITY:i.rate.delay+i.rate.duration+i.life:i.rate.delay+i.life;t=Math.max(t,r)}return t}restart(e){if(!this.scheduler.restart(e.handle))return!1;this.stoppingDeadlines[e.handle.slot]=Number.POSITIVE_INFINITY;for(let t=0;t<this.emittersPerInstance;t++){const s=e.handle.slot*this.emittersPerInstance+t;this.runtime.queueEmitterState(s,this.runtime.emitters[s].position,!0,!0)}return!0}stop(e,t){const s=this.scheduler.getInstance(e.handle);if(null==s||!this.scheduler.stop(e.handle))return!1;const i=null==t?this.maximumParticleLife:Math.max(0,t);this.stoppingDeadlines[e.handle.slot]=s.elapsedTime+i;for(let s=0;s<this.emittersPerInstance;s++)this.runtime.queueEmitterStop(e.handle.slot*this.emittersPerInstance+s,t);return!0}update(e){this.scheduler.update(e),this.runtime.update(e);for(const e of this.activeBySlot){if(null==e)continue;const t=this.scheduler.getInstance(e.handle);null!=t&&((!1===t.playing&&t.elapsedTime>=this.instanceDuration||t.stopping&&t.elapsedTime>=this.stoppingDeadlines[e.handle.slot])&&this.destroy(e))}this.flushActivePages()}flushActivePages(){this.activePagesDirty&&(this.runtime.setActivePages(this.activePages),this.activePagesDirty=!1)}getStats(){return{scheduler:this.scheduler.getStats(),particles:this.runtime.getStats()}}dispose(){this.runtime.dispose();for(const e of this.activeBySlot)null!=e&&this.scheduler.destroyInstance(e.handle);this.activeBySlot.fill(null)}}/*
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*as e from"three";import{calculateGpuSpriteOptionalStateLayout as t,GPU_SPRITE_BASE_COMMAND_BYTES as s,GPU_SPRITE_EMITTER_BYTES as i,GPU_SPRITE_TRANSFORM_COMMAND_BYTES as r,GpuSpriteRuntime as n}from"./gpu-sprite-runtime.js";import{GpuSpriteTemplateCache as l,instantiateGpuSpriteTemplate as a}from"./gpu-sprite-template.js";import{GpuVfxScheduler as o}from"./gpu-vfx-scheduler.js";export class GpuSpriteWorldRuntime{constructor(t,s,i){this.pools=i,this.activeByHandleSlot=[],this.activePages=new Set,this.positionScratch=new e.Vector3,this.activePagesDirty=!1,this.runtime=t,this.scheduler=s,this.templateCount=i.length;for(let e=0;e<t.emitters.length;e++)t.setEmitterActive(e,!1);t.setActivePages([])}static async create(h){if(0===h.templates.length)return null;const c=h.templateCache??new l,u=await Promise.all(h.templates.map(e=>c.resolve(e.asset,{assets:h.assets,renderClassCache:h.renderClassCache,resolveCustomMaterial:h.resolveCustomMaterial,revision:e.revision})));if(u.some(e=>null==e.template))return null;const m=u.map(e=>e.template),p=Math.max(1,Math.floor(h.particlePageSize??256)),d=[],f=new Map,g=[],S=[];let I=0;for(let t=0;t<m.length;t++){const s=m[t],i=h.templates[t],r=Math.max(1,Math.floor(i.maximumInstances)),n=s.renderClasses.map(e=>{let t=f.get(e);return null==t&&(t=d.length,f.set(e,t),d.push(e)),t}),l=g.length,o=new e.Vector3,c=a(s,new Array(r).fill(o));for(const e of c)e.renderClass=n[e.renderClass??0]??0,null!=e.parentEmitter&&(e.parentEmitter+=l),g.push(e);S.push({template:s,baseEmitterIndex:l,maximumInstances:r,freeSlots:Array.from({length:r},(e,t)=>r-t-1),emitterCapacities:s.emitters.map(e=>e.capacity),emitterIndexScratch:new Array(s.emitters.length).fill(0),emitterPositionOffsets:s.emitters.map(e=>e.position.clone()),maximumParticleLife:s.emitters.reduce((e,t)=>Math.max(e,t.life),0)}),I+=Math.ceil(s.particleCapacity/p)*p*r}const y=g.reduce((e,t)=>e+t.capacity,0),v=d.some(e=>null!=e.meshVertices),x=d.some(e=>!0===e.localSpace&&null==e.trail),E=g.some(e=>!0===e.localSpace&&null!=d[e.renderClass??0]?.trail),P=g.length*(E?r:s),C=v||g.some(e=>1!==e.meshScaleStart.x||1!==e.meshScaleStart.y||1!==e.meshScaleStart.z||1!==e.meshScaleEnd.x||1!==e.meshScaleEnd.y||1!==e.meshScaleEnd.z),T=g.reduce((e,t)=>{const s=d[t.renderClass??0]?.trail;return e+(null==s?0:t.capacity*(s.historyLength+1))},0),b=t({capacity:I,particleTransforms:C,vortex:g.some(e=>e.hasVortex),disperse:g.some(e=>e.hasDisperse),collisionEvents:g.some(e=>2===e.childSpawnEvent),trailHistoryEntries:T});if(16*I*4+4*y+4*I+4*I*4+g.length*i+Math.max(s,P)+160+16*d.length*2+d.reduce((e,t)=>e+(t.meshVertices?.byteLength??0),0)+b.bytes+(v||x?16*g.length*4:0)>(h.maximumStorageBytes??Number.POSITIVE_INFINITY))return null;if(null!=h.device){const e=h.device.limits.maxStorageBufferBindingSize;if([16*I*4,4*g.reduce((e,t)=>e+t.capacity,0),4*I,4*I*4,g.length*i,Math.max(s,P),...v||x?[16*g.length*4]:[],...b.bytes>0?[b.bytes]:[]].some(t=>t>e))return null;if(7+(b.bytes>0?1:0)>h.device.limits.maxStorageBuffersPerShaderStage)return null}const B=new n(g,d,void 0,{pageSize:p,capacity:I,aliveCountReadback:h.aliveCountReadback});return new GpuSpriteWorldRuntime(B,new o({pageSize:p,maximumParticles:I}),S)}spawn(e,t){const s=this.pools[e],i=s?.freeSlots.pop();if(null==s||null==i)return null;const r=this.scheduler.createInstance({particleCapacity:s.template.particleCapacity,duration:s.template.duration});if(null==r)return s.freeSlots.push(i),null;const n=this.scheduler.arena.get(r).pages,l={handle:r,templateIndex:e,pages:n,logicalSlot:i,stoppingDeadline:Number.POSITIVE_INFINITY};this.activeByHandleSlot[r.slot]=l;for(const e of n)this.activePages.add(e);this.activePagesDirty=!0;const a=s.template.emitters.length;for(let e=0;e<a;e++){const r=s.baseEmitterIndex+i*a+e;s.emitterIndexScratch[e]=r;const n=this.runtime.emitters[r];this.positionScratch.copy(s.emitterPositionOffsets[e]),!0!==n.localSpace&&null==n.parentEmitter&&this.positionScratch.add(t),this.runtime.queueEmitterState(r,this.positionScratch,!0,!0)}return this.runtime.mapParticlePages(n,s.emitterIndexScratch,s.emitterCapacities),this.scheduler.play(r),l}destroy(e){const t=this.activeByHandleSlot[e.handle.slot];if(null==t||t.handle.generation!==e.handle.generation)return!1;const s=this.pools[t.templateIndex],i=s.template.emitters.length;for(let e=0;e<i;e++){const r=s.baseEmitterIndex+t.logicalSlot*i+e;this.runtime.queueEmitterState(r,this.runtime.emitters[r].position,!1)}for(const e of t.pages)this.activePages.delete(e);return this.activePagesDirty=!0,s.freeSlots.push(t.logicalSlot),this.activeByHandleSlot[e.handle.slot]=null,this.scheduler.destroyInstance(e.handle)}setPosition(e,t){const s=this.resolve(e);if(null==s)return!1;const i=this.pools[s.templateIndex];for(let e=0;e<i.template.emitters.length;e++){const r=this.emitterIndex(s,i,e);!0!==this.runtime.emitters[r].localSpace&&null==this.runtime.emitters[r].parentEmitter&&(this.positionScratch.copy(t).add(i.emitterPositionOffsets[e]),this.runtime.queueEmitterState(r,this.positionScratch,!0))}return!0}setTransform(e,t){const s=this.resolve(e);if(null==s)return!1;const i=this.pools[s.templateIndex];for(let e=0;e<i.template.emitters.length;e++)this.runtime.setEmitterTransform(this.emitterIndex(s,i,e),t);return!0}pause(e){const t=this.resolve(e);return!(null==t||!this.scheduler.pause(t.handle))&&(this.forEachEmitter(t,e=>this.runtime.queueEmitterPaused(e,!0)),!0)}play(e){const t=this.resolve(e);return!(null==t||!this.scheduler.play(t.handle))&&(this.forEachEmitter(t,e=>this.runtime.queueEmitterPaused(e,!1)),!0)}restart(e){const t=this.resolve(e);return!(null==t||!this.scheduler.restart(t.handle))&&(t.stoppingDeadline=Number.POSITIVE_INFINITY,this.forEachEmitter(t,e=>{this.runtime.queueEmitterState(e,this.runtime.emitters[e].position,!0,!0)}),!0)}stop(e,t){const s=this.resolve(e),i=null==s?null:this.scheduler.getInstance(s.handle);if(null==s||null==i||!this.scheduler.stop(s.handle))return!1;const r=this.pools[s.templateIndex];return s.stoppingDeadline=i.elapsedTime+(null==t?r.maximumParticleLife:Math.max(0,t)),this.forEachEmitter(s,e=>this.runtime.queueEmitterStop(e,t)),!0}setTimescale(e,t){const s=this.resolve(e);return!(null==s||!this.scheduler.setTimescale(s.handle,t))&&(this.forEachEmitter(s,e=>this.runtime.queueEmitterTimescale(e,t)),!0)}setInput(e,t,s){const i=this.resolve(e);if(null==i)return!1;const r=this.pools[i.templateIndex];let n=!1;for(const e of r.template.inputBindings)e.inputId===t&&(n=this.runtime.setEmitterBoundValue(this.emitterIndex(i,r,e.emitterIndex),e,s)||n);return n&&this.scheduler.setDuration(i.handle,this.calculateInstanceDuration(i,r)),n}has(e){return null!=this.resolve(e)}update(e){this.scheduler.update(e),this.runtime.update(e);for(const e of this.activeByHandleSlot){if(null==e)continue;const t=this.scheduler.getInstance(e.handle);if(null==t)continue;const s=this.pools[e.templateIndex];(!1===t.playing&&t.elapsedTime>=s.template.duration||t.stopping&&t.elapsedTime>=e.stoppingDeadline)&&this.destroy(e)}this.flushActivePages()}flushActivePages(){this.activePagesDirty&&(this.runtime.setActivePages(this.activePages),this.activePagesDirty=!1)}dispose(){this.runtime.dispose();for(const e of this.activeByHandleSlot)null!=e&&this.scheduler.destroyInstance(e.handle);this.activeByHandleSlot.length=0}resolve(e){const t=this.activeByHandleSlot[e.handle.slot];return null!=t&&t.handle.generation===e.handle.generation&&null!=this.scheduler.getInstance(t.handle)?t:null}emitterIndex(e,t,s){return t.baseEmitterIndex+e.logicalSlot*t.template.emitters.length+s}forEachEmitter(e,t){const s=this.pools[e.templateIndex];for(let i=0;i<s.template.emitters.length;i++)t(this.emitterIndex(e,s,i))}calculateInstanceDuration(e,t){let s=0;for(let i=0;i<t.template.emitters.length;i++){const r=this.runtime.emitters[this.emitterIndex(e,t,i)],n="continuous"===r.rate.type?r.rate.duration<0?Number.POSITIVE_INFINITY:r.rate.delay+r.rate.duration+r.life:r.rate.delay+r.life;s=Math.max(s,n)}return s}}/*
1
+ import*as e from"three";import{calculateGpuSpriteOptionalStateLayout as t,GPU_SPRITE_BASE_COMMAND_BYTES as s,GPU_SPRITE_EMITTER_BYTES as i,GPU_SPRITE_TRANSFORM_COMMAND_BYTES as r,GpuSpriteRuntime as n}from"./gpu-sprite-runtime.js";import{GpuSpriteTemplateCache as l,instantiateGpuSpriteTemplate as a}from"./gpu-sprite-template.js";import{GpuVfxScheduler as o}from"./gpu-vfx-scheduler.js";export class GpuSpriteWorldRuntime{constructor(t,s,i){this.pools=i,this.activeByHandleSlot=[],this.activePages=new Set,this.positionScratch=new e.Vector3,this.activePagesDirty=!1,this.runtime=t,this.scheduler=s,this.templateCount=i.length;for(let e=0;e<t.emitters.length;e++)t.setEmitterActive(e,!1);t.setActivePages([])}static async create(h){if(0===h.templates.length)return null;const c=h.templateCache??new l,m=await Promise.all(h.templates.map(e=>c.resolve(e.asset,{assets:h.assets,renderClassCache:h.renderClassCache,resolveCustomMaterial:h.resolveCustomMaterial,revision:e.revision})));if(m.some(e=>null==e.template))return null;const u=m.map(e=>e.template),p=Math.max(1,Math.floor(h.particlePageSize??256)),d=[],f=new Map,g=[],S=[];let I=0;for(let t=0;t<u.length;t++){const s=u[t],i=h.templates[t],r=Math.max(1,Math.floor(i.maximumInstances)),n=s.renderClasses.map(e=>{let t=f.get(e);return null==t&&(t=d.length,f.set(e,t),d.push(e)),t}),l=g.length,o=new e.Vector3,c=a(s,new Array(r).fill(o));for(const e of c)e.renderClass=n[e.renderClass??0]??0,null!=e.parentEmitter&&(e.parentEmitter+=l),g.push(e);S.push({template:s,baseEmitterIndex:l,maximumInstances:r,freeSlots:Array.from({length:r},(e,t)=>r-t-1),emitterCapacities:s.emitters.map(e=>e.capacity),emitterIndexScratch:new Array(s.emitters.length).fill(0),emitterPositionOffsets:s.emitters.map(e=>e.position.clone()),maximumParticleLife:s.emitters.reduce((e,t)=>Math.max(e,t.life),0)}),I+=Math.ceil(s.particleCapacity/p)*p*r}const y=g.reduce((e,t)=>e+t.capacity,0),v=d.some(e=>null!=e.meshVertices),x=d.some(e=>!0===e.localSpace&&null==e.trail),E=g.some(e=>!0===e.localSpace&&null!=d[e.renderClass??0]?.trail),P=g.length*(E?r:s),C=v||g.some(e=>1!==e.meshScaleStart.x||1!==e.meshScaleStart.y||1!==e.meshScaleStart.z||1!==e.meshScaleEnd.x||1!==e.meshScaleEnd.y||1!==e.meshScaleEnd.z),T=g.reduce((e,t)=>{const s=d[t.renderClass??0]?.trail;return e+(null==s?0:t.capacity*(s.historyLength+1))},0),b=t({capacity:I,particleTransforms:C,vortex:g.some(e=>e.hasVortex),disperse:g.some(e=>e.hasDisperse),collisionEvents:g.some(e=>2===e.childSpawnEvent),trailHistoryEntries:T});if(16*I*4+4*y+4*I+4*I*4+g.length*i+Math.max(s,P)+160+16*d.length*2+d.reduce((e,t)=>e+(t.meshVertices?.byteLength??0),0)+b.bytes+(v||x?16*g.length*4:0)>(h.maximumStorageBytes??Number.POSITIVE_INFINITY))return null;if(null!=h.device){const e=h.device.limits.maxStorageBufferBindingSize;if([16*I*4,4*g.reduce((e,t)=>e+t.capacity,0),4*I,4*I*4,g.length*i,Math.max(s,P),...v||x?[16*g.length*4]:[],...b.bytes>0?[b.bytes]:[]].some(t=>t>e))return null;if(7+(b.bytes>0?1:0)>h.device.limits.maxStorageBuffersPerShaderStage)return null}const B=new n(g,d,void 0,{pageSize:p,capacity:I,aliveCountReadback:h.aliveCountReadback});return new GpuSpriteWorldRuntime(B,new o({pageSize:p,maximumParticles:I}),S)}spawn(e,t){const s=this.pools[e],i=s?.freeSlots.pop();if(null==s||null==i)return null;const r=this.scheduler.createInstance({particleCapacity:s.template.particleCapacity,duration:s.template.duration});if(null==r)return s.freeSlots.push(i),null;const n=this.scheduler.arena.get(r).pages,l={handle:r,templateIndex:e,pages:n,logicalSlot:i,stoppingDeadline:Number.POSITIVE_INFINITY};this.activeByHandleSlot[r.slot]=l;for(const e of n)this.activePages.add(e);this.activePagesDirty=!0;const a=s.template.emitters.length;for(let e=0;e<a;e++){const r=s.baseEmitterIndex+i*a+e;s.emitterIndexScratch[e]=r;const n=this.runtime.emitters[r];this.positionScratch.copy(s.emitterPositionOffsets[e]),!0!==n.localSpace&&null==n.parentEmitter&&this.positionScratch.add(t),this.runtime.queueEmitterState(r,this.positionScratch,!0,!0)}return this.runtime.mapParticlePages(n,s.emitterIndexScratch,s.emitterCapacities),this.scheduler.play(r),l}destroy(e){const t=this.activeByHandleSlot[e.handle.slot];if(null==t||t.handle.generation!==e.handle.generation)return!1;const s=this.pools[t.templateIndex],i=s.template.emitters.length;for(let e=0;e<i;e++){const r=s.baseEmitterIndex+t.logicalSlot*i+e;this.runtime.queueEmitterState(r,this.runtime.emitters[r].position,!1)}for(const e of t.pages)this.activePages.delete(e);return this.activePagesDirty=!0,s.freeSlots.push(t.logicalSlot),this.activeByHandleSlot[e.handle.slot]=null,this.scheduler.destroyInstance(e.handle)}setPosition(e,t){const s=this.resolve(e);if(null==s)return!1;const i=this.pools[s.templateIndex];for(let e=0;e<i.template.emitters.length;e++){const r=this.emitterIndex(s,i,e);!0!==this.runtime.emitters[r].localSpace&&null==this.runtime.emitters[r].parentEmitter&&(this.positionScratch.copy(t).add(i.emitterPositionOffsets[e]),this.runtime.queueEmitterState(r,this.positionScratch,!0))}return!0}setTransform(e,t){const s=this.resolve(e);if(null==s)return!1;const i=this.pools[s.templateIndex];for(let e=0;e<i.template.emitters.length;e++){const r=this.emitterIndex(s,i,e),n=this.runtime.emitters[r];this.runtime.setEmitterTransform(r,t),!0!==n.localSpace&&null==n.parentEmitter&&(this.positionScratch.copy(i.emitterPositionOffsets[e]).applyMatrix4(t),this.runtime.queueEmitterState(r,this.positionScratch,!0))}return!0}pause(e){const t=this.resolve(e);return!(null==t||!this.scheduler.pause(t.handle))&&(this.forEachEmitter(t,e=>this.runtime.queueEmitterPaused(e,!0)),!0)}play(e){const t=this.resolve(e);return!(null==t||!this.scheduler.play(t.handle))&&(this.forEachEmitter(t,e=>this.runtime.queueEmitterPaused(e,!1)),!0)}restart(e){const t=this.resolve(e);return!(null==t||!this.scheduler.restart(t.handle))&&(t.stoppingDeadline=Number.POSITIVE_INFINITY,this.forEachEmitter(t,e=>{this.runtime.queueEmitterState(e,this.runtime.emitters[e].position,!0,!0)}),!0)}stop(e,t){const s=this.resolve(e),i=null==s?null:this.scheduler.getInstance(s.handle);if(null==s||null==i||!this.scheduler.stop(s.handle))return!1;const r=this.pools[s.templateIndex];return s.stoppingDeadline=i.elapsedTime+(null==t?r.maximumParticleLife:Math.max(0,t)),this.forEachEmitter(s,e=>this.runtime.queueEmitterStop(e,t)),!0}setTimescale(e,t){const s=this.resolve(e);return!(null==s||!this.scheduler.setTimescale(s.handle,t))&&(this.forEachEmitter(s,e=>this.runtime.queueEmitterTimescale(e,t)),!0)}setInput(e,t,s){const i=this.resolve(e);if(null==i)return!1;const r=this.pools[i.templateIndex];let n=!1;for(const e of r.template.inputBindings)e.inputId===t&&(n=this.runtime.setEmitterBoundValue(this.emitterIndex(i,r,e.emitterIndex),e,s)||n);return n&&this.scheduler.setDuration(i.handle,this.calculateInstanceDuration(i,r)),n}has(e){return null!=this.resolve(e)}update(e){this.scheduler.update(e),this.runtime.update(e);for(const e of this.activeByHandleSlot){if(null==e)continue;const t=this.scheduler.getInstance(e.handle);if(null==t)continue;const s=this.pools[e.templateIndex];(!1===t.playing&&t.elapsedTime>=s.template.duration||t.stopping&&t.elapsedTime>=e.stoppingDeadline)&&this.destroy(e)}this.flushActivePages()}flushActivePages(){this.activePagesDirty&&(this.runtime.setActivePages(this.activePages),this.activePagesDirty=!1)}dispose(){this.runtime.dispose();for(const e of this.activeByHandleSlot)null!=e&&this.scheduler.destroyInstance(e.handle);this.activeByHandleSlot.length=0}resolve(e){const t=this.activeByHandleSlot[e.handle.slot];return null!=t&&t.handle.generation===e.handle.generation&&null!=this.scheduler.getInstance(t.handle)?t:null}emitterIndex(e,t,s){return t.baseEmitterIndex+e.logicalSlot*t.template.emitters.length+s}forEachEmitter(e,t){const s=this.pools[e.templateIndex];for(let i=0;i<s.template.emitters.length;i++)t(this.emitterIndex(e,s,i))}calculateInstanceDuration(e,t){let s=0;for(let i=0;i<t.template.emitters.length;i++){const r=this.runtime.emitters[this.emitterIndex(e,t,i)],n="continuous"===r.rate.type?r.rate.duration<0?Number.POSITIVE_INFINITY:r.rate.delay+r.rate.duration+r.life:r.rate.delay+r.life;s=Math.max(s,n)}return s}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -5,10 +5,16 @@ export declare class DefaultInitializer extends Initializer {
5
5
  init(emitter: Emitter, particle: Particle): void;
6
6
  initialize(target: Emitter | Particle): void;
7
7
  }
8
- export declare class WorldSpaceEmitterRotationInitializer extends Initializer {
8
+ export declare class WorldSpaceEmitterTransformInitializer extends Initializer {
9
+ private readonly composeParticleRotation;
10
+ constructor(composeParticleRotation: boolean);
9
11
  init(emitter: Emitter, particle: Particle): void;
10
12
  initialize(target: Emitter | Particle): void;
11
13
  }
14
+ /** @deprecated Use WorldSpaceEmitterTransformInitializer. */
15
+ export declare class WorldSpaceEmitterRotationInitializer extends WorldSpaceEmitterTransformInitializer {
16
+ constructor();
17
+ }
12
18
  export declare class Rotation extends Initializer {
13
19
  private rotation;
14
20
  constructor(rotation: Vector3);
@@ -1,4 +1,4 @@
1
- import{Vector3 as t,Quaternion as e,Euler as i,Color as s}from"three";import{Span as o,Initializer as n}from"@hology/nebula";export class DefaultInitializer extends n{init(t,e){e.parent=t}initialize(t){}}export class WorldSpaceEmitterRotationInitializer extends n{init(t,e){"number"!=typeof e.rotation&&(a.setFromEuler(c.set(t.rotation.x,t.rotation.y,t.rotation.z)),r.setFromEuler(c.set(e.rotation.x,e.rotation.y,e.rotation.z)),a.multiply(r),c.setFromQuaternion(a),e.rotation.set(c.x,c.y,c.z))}initialize(t){}}export class Rotation extends n{constructor(t){super(),this.rotation=t}setRotation(t){this.rotation=t.clone()}initialize(t){"number"!=typeof t.rotation&&t.rotation.copy(this.rotation)}}export const randomRotationAxis=["XYZ","X","Y","Z"];export class RandomRotation extends n{constructor(t){super(),this.axis=t}initialize(t){switch(this.axis){case"XYZ":t.rotation.set(this.randomAngle(),this.randomAngle(),this.randomAngle());break;case"X":t.rotation.x=this.randomAngle();break;case"Y":t.rotation.y=this.randomAngle();break;case"Z":t.rotation.z=this.randomAngle()}}randomAngle(){return 2*Math.PI*Math.random()}}export class InitialScale extends n{constructor(t){super(),this.scale=t}setScale(t){this.scale=t}initialize(t){t.scale=this.scale}}export class RandomScale extends n{constructor(t,e){super(),this.min=t,this.max=e}setRange(t,e){this.min=t,this.max=e}initialize(t){t.scale=h(this.min,this.max)}}export class RandomColor extends n{constructor(t,e){super(),this.min=new s,this.max=new s,this.setRange(t,e)}setRange(t,e){this.min.set(t),this.max.set(e)}initialize(t){const e=Math.random();t.color.r=h(this.min.r,this.max.r,e),t.color.g=h(this.min.g,this.max.g,e),t.color.b=h(this.min.b,this.max.b,e),t.useColor=!0}}export class InitialScaleComponents extends n{constructor(t){super(),this.scale=t}setScaleComponents(t){this.scale=t.clone()}initialize(t){t.transform.initialScale=this.scale.clone()}}export class AdditiveVelocity extends n{constructor(t,e){super(),this.min=t,this.max=e}initialize(t){const e=m(this.min),i=null!=this.max?m(this.max):void 0;t.velocity.x+=null!=i?h(e.x,i.x):e.x,t.velocity.y+=null!=i?h(e.y,i.y):e.y,t.velocity.z+=null!=i?h(e.z,i.z):e.z}}export class RandomDirection extends n{constructor(t){super(),this.speed=t}setSpeed(t){this.speed=t}initialize(t){l.set(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).normalize().multiplyScalar(this.speed),t.velocity.x+=l.x,t.velocity.y+=l.y,t.velocity.z+=l.z}}export class RandomVelocity extends n{constructor(t,e){super(),this.min=t,this.max=e,this.x=new o(this.min.x,this.max.x),this.y=new o(this.min.y,this.max.y),this.z=new o(this.min.z,this.max.z)}initialize(t){t.velocity.x+=this.x.getValue(),t.velocity.y+=this.y.getValue(),t.velocity.z+=this.z.getValue()}}export const alignRotationAxes=["+X","-X","+Y","-Y","+Z","-Z"];export const alignRotationModes=["AwayFromCenter","TowardsCenter","AlongVelocity"];export class AlignRotation extends n{constructor(e,i,s=new t,o=new t){super(),this.axis=e,this.mode=i,this.offset=s,this.center=o,this.axisVec=new t(0,1,0),this.setAxis(e)}setAxis(t){switch(t){case"+X":this.axisVec.set(1,0,0);break;case"-X":this.axisVec.set(-1,0,0);break;case"+Y":this.axisVec.set(0,1,0);break;case"-Y":this.axisVec.set(0,-1,0);break;case"+Z":this.axisVec.set(0,0,1);break;case"-Z":this.axisVec.set(0,0,-1)}}initialize(t){if("number"!=typeof t.rotation){switch(this.mode){case"AwayFromCenter":l.copy(t.position).sub(this.center).normalize();break;case"TowardsCenter":l.copy(t.position).sub(this.center).normalize().multiplyScalar(-1);break;case"AlongVelocity":l.copy(t.velocity).normalize()}l.lengthSq()<1e-4&&l.set(0,1,0),a.setFromUnitVectors(this.axisVec,l),this.offset.lengthSq()>0&&(r.setFromEuler(c.set(this.offset.x,this.offset.y,this.offset.z)),a.multiply(r)),c.setFromQuaternion(a),t.rotation.x=c.x,t.rotation.y=c.y,t.rotation.z=c.z}}}const a=new e,r=new e,c=new i,l=new t;function h(t,e,i=Math.random()){return i*(e-t)+t}function m(t){return"function"==typeof t?t():t}/*
1
+ import{Vector3 as t,Quaternion as e,Euler as i,Color as s}from"three";import{Span as o,Initializer as n}from"@hology/nebula";export class DefaultInitializer extends n{init(t,e){e.parent=t}initialize(t){}}export class WorldSpaceEmitterTransformInitializer extends n{constructor(t){super(),this.composeParticleRotation=t}init(t,e){a.setFromEuler(c.set(t.rotation.x,t.rotation.y,t.rotation.z)),e.position.applyQuaternion(a),this.composeParticleRotation&&"number"!=typeof e.rotation&&(r.setFromEuler(c.set(e.rotation.x,e.rotation.y,e.rotation.z)),a.multiply(r),c.setFromQuaternion(a),e.rotation.set(c.x,c.y,c.z))}initialize(t){}}export class WorldSpaceEmitterRotationInitializer extends WorldSpaceEmitterTransformInitializer{constructor(){super(!0)}}export class Rotation extends n{constructor(t){super(),this.rotation=t}setRotation(t){this.rotation=t.clone()}initialize(t){"number"!=typeof t.rotation&&t.rotation.copy(this.rotation)}}export const randomRotationAxis=["XYZ","X","Y","Z"];export class RandomRotation extends n{constructor(t){super(),this.axis=t}initialize(t){switch(this.axis){case"XYZ":t.rotation.set(this.randomAngle(),this.randomAngle(),this.randomAngle());break;case"X":t.rotation.x=this.randomAngle();break;case"Y":t.rotation.y=this.randomAngle();break;case"Z":t.rotation.z=this.randomAngle()}}randomAngle(){return 2*Math.PI*Math.random()}}export class InitialScale extends n{constructor(t){super(),this.scale=t}setScale(t){this.scale=t}initialize(t){t.scale=this.scale}}export class RandomScale extends n{constructor(t,e){super(),this.min=t,this.max=e}setRange(t,e){this.min=t,this.max=e}initialize(t){t.scale=h(this.min,this.max)}}export class RandomColor extends n{constructor(t,e){super(),this.min=new s,this.max=new s,this.setRange(t,e)}setRange(t,e){this.min.set(t),this.max.set(e)}initialize(t){const e=Math.random();t.color.r=h(this.min.r,this.max.r,e),t.color.g=h(this.min.g,this.max.g,e),t.color.b=h(this.min.b,this.max.b,e),t.useColor=!0}}export class InitialScaleComponents extends n{constructor(t){super(),this.scale=t}setScaleComponents(t){this.scale=t.clone()}initialize(t){t.transform.initialScale=this.scale.clone()}}export class AdditiveVelocity extends n{constructor(t,e){super(),this.min=t,this.max=e}initialize(t){const e=m(this.min),i=null!=this.max?m(this.max):void 0;t.velocity.x+=null!=i?h(e.x,i.x):e.x,t.velocity.y+=null!=i?h(e.y,i.y):e.y,t.velocity.z+=null!=i?h(e.z,i.z):e.z}}export class RandomDirection extends n{constructor(t){super(),this.speed=t}setSpeed(t){this.speed=t}initialize(t){l.set(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).normalize().multiplyScalar(this.speed),t.velocity.x+=l.x,t.velocity.y+=l.y,t.velocity.z+=l.z}}export class RandomVelocity extends n{constructor(t,e){super(),this.min=t,this.max=e,this.x=new o(this.min.x,this.max.x),this.y=new o(this.min.y,this.max.y),this.z=new o(this.min.z,this.max.z)}initialize(t){t.velocity.x+=this.x.getValue(),t.velocity.y+=this.y.getValue(),t.velocity.z+=this.z.getValue()}}export const alignRotationAxes=["+X","-X","+Y","-Y","+Z","-Z"];export const alignRotationModes=["AwayFromCenter","TowardsCenter","AlongVelocity"];export class AlignRotation extends n{constructor(e,i,s=new t,o=new t){super(),this.axis=e,this.mode=i,this.offset=s,this.center=o,this.axisVec=new t(0,1,0),this.setAxis(e)}setAxis(t){switch(t){case"+X":this.axisVec.set(1,0,0);break;case"-X":this.axisVec.set(-1,0,0);break;case"+Y":this.axisVec.set(0,1,0);break;case"-Y":this.axisVec.set(0,-1,0);break;case"+Z":this.axisVec.set(0,0,1);break;case"-Z":this.axisVec.set(0,0,-1)}}initialize(t){if("number"!=typeof t.rotation){switch(this.mode){case"AwayFromCenter":l.copy(t.position).sub(this.center).normalize();break;case"TowardsCenter":l.copy(t.position).sub(this.center).normalize().multiplyScalar(-1);break;case"AlongVelocity":l.copy(t.velocity).normalize()}l.lengthSq()<1e-4&&l.set(0,1,0),a.setFromUnitVectors(this.axisVec,l),this.offset.lengthSq()>0&&(r.setFromEuler(c.set(this.offset.x,this.offset.y,this.offset.z)),a.multiply(r)),c.setFromQuaternion(a),t.rotation.x=c.x,t.rotation.y=c.y,t.rotation.z=c.z}}}const a=new e,r=new e,c=new i,l=new t;function h(t,e,i=Math.random()){return i*(e-t)+t}function m(t){return"function"==typeof t?t():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 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 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 G,varyingAttributes as B,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 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,WorldSpaceEmitterRotationInitializer 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";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 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(),d.removeFromParent(),f.dispose()}}}async function we(e,t,r,p,x,S,P,D,F){const L=function(e){let t;switch(e.rate.type){case"continuous":t=new Z(e.rate.delay??0,e.rate.count,e.rate.time,e.rate.duration);break;case"once":t=new $(e.rate.delay??0,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),t=new s(0,1/0)}return t}(e);let O;switch(e.output.type){case"decal":O=new a(await async function(e,t,a,r,s){if("shaderGraph"===be(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,p,P));break;case"sprite":O=new a(await async function(e,t,a,r,s){let n=null;const l=be(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):ge,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=k(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(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 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,Me(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,p,P));break;case"stretchedSprite":O=new a(await async function(e,t){"shaderGraph"===be(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):ge,r=C(a).sample(B.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=N.subtract(H).divide(A(N)),a=w(t,0,1e3);l=l.multiply(T(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),v=R.modelViewMatrix.multiplyVec(V(c,1)),x=R.normalMatrix.multiplyVec(p.xyz),S=E(g(v.xyz,x)).multiplyScalar(y.position.y.multiply(d)),P=x.multiplyScalar(y.position.x.add(.5).multiply(b(1).add(h.divide(M(x)))).multiply(d)),G=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:G,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,Ae(D,e),D}(e.output,t));break;case"shape":O=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=be(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?Ee(await t.getMaterial(e.material)):function(){const e=G(new d("instanceColor")).rgb,t=G(new l("particleData")).x;return new c({color:v({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());Me(h,e);const f=new i.Mesh(u,h);return Ae(f,e),f}(e.output,t,r,p,P));break;case"mesh":O=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=be(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=Ee(await t.getMaterial(e.material))),n?.transparent&&(n.depthWrite=!1),null!=n&&Me(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,p,P));break;case"trail":{const s="shaderGraph"===be(e.output)?await createShaderGraphMaterial(e.output,"trail",r,p,P,{trailBillboard:e.output.billboard??!1}):null;O=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:s instanceof i.ShaderMaterial?s: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 q=new Se(F);q.parent=x,q.setRate(L),q._space=e.output.space;const z=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??{});return he(t,e.params??{},a,D)}));"world"!==e.output.space||"shape"!==e.output.type&&"mesh"!==e.output.type||z.unshift(new Y),z.push(O,new K),q.addInitializers(z);const X=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,p);return ue(t,e.params??{},a,D)}).sort((e,t)=>e instanceof ie?1:0));X.push(new xe);for(const e of X)e instanceof ie&&(e.physics=S);q.addBehaviours(X);for(const a of e.children??[]){const e=await we(a,t,r,p,x,S,P,D,F),s=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=q.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&q.childEmitters.splice(e,1),null!=t.parentParticle&&(n.delete(t.parentParticle.id),t.parentParticle=null),s.release(t)},t}),i=q.eventDispatcher,n=new Map;q.bindEmitterEvent=!0,i.addEventListener("PARTICLE_DEAD",e=>{const t=n.get(e.id);null!=t&&(q.detachChildEmitterFromParticle(t,e),n.delete(e.id))});let l="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":l="PARTICLE_COLLISION";break;case"start":l="PARTICLE_CREATED"}i.addEventListener(l,e=>{const t=s.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),q.childEmitters.push(t),n.set(e.id,t),t.parentParticle=e,t.system=q.system,t.emit()})}return q}const ge=(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}`,Me(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=be(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 ve(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 ve(s.material,r):Ee(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 be(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 ve(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 h=J.color.rgb.multiply(S(new i.Color(n))).multiplyScalar(b(o)),d=J.opacity.multiply(b(l));if(null!=p){const e=C(await t.getTexture(p)).sample(B.uv);h=h.multiply(e.rgb),d=d.multiply(e.a)}null!=u&&(d=d.multiply(C(await t.getTexture(u)).sample(B.uv).r));const m=new c({color:h.rgba(d),opacity:d,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 Me(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 Ee(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: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 xe 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 Se 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?(Ie.copy(t),"local"===a&&"world"===r?Ie.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(Te.copy(this.transformRoot.matrixWorld).invert(),Ie.applyMatrix4(Te)),e.position.copy(Ie)):e.position.copy(t)}clone(){const e=new Se(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 Ie=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}}/*
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 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 G,varyingAttributes as B,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 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";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 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(),d.removeFromParent(),f.dispose()}}}async function we(e,t,r,p,x,S,P,D,F){const L=function(e){let t;switch(e.rate.type){case"continuous":t=new Z(e.rate.delay??0,e.rate.count,e.rate.time,e.rate.duration);break;case"once":t=new $(e.rate.delay??0,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),t=new s(0,1/0)}return t}(e);let O;switch(e.output.type){case"decal":O=new a(await async function(e,t,a,r,s){if("shaderGraph"===be(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,p,P));break;case"sprite":O=new a(await async function(e,t,a,r,s){let n=null;const l=be(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):ge,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=k(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(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 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,Me(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,p,P));break;case"stretchedSprite":O=new a(await async function(e,t){"shaderGraph"===be(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):ge,r=C(a).sample(B.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=N.subtract(H).divide(A(N)),a=w(t,0,1e3);l=l.multiply(T(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),v=R.modelViewMatrix.multiplyVec(V(c,1)),x=R.normalMatrix.multiplyVec(p.xyz),S=E(g(v.xyz,x)).multiplyScalar(y.position.y.multiply(d)),P=x.multiplyScalar(y.position.x.add(.5).multiply(b(1).add(h.divide(M(x)))).multiply(d)),G=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:G,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,Ae(D,e),D}(e.output,t));break;case"shape":O=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=be(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?Ee(await t.getMaterial(e.material)):function(){const e=G(new d("instanceColor")).rgb,t=G(new l("particleData")).x;return new c({color:v({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());Me(h,e);const f=new i.Mesh(u,h);return Ae(f,e),f}(e.output,t,r,p,P));break;case"mesh":O=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=be(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=Ee(await t.getMaterial(e.material))),n?.transparent&&(n.depthWrite=!1),null!=n&&Me(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,p,P));break;case"trail":{const s="shaderGraph"===be(e.output)?await createShaderGraphMaterial(e.output,"trail",r,p,P,{trailBillboard:e.output.billboard??!1}):null;O=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:s instanceof i.ShaderMaterial?s: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 q=new Se(F);q.parent=x,q.setRate(L),q._space=e.output.space;const z=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??{});return he(t,e.params??{},a,D)}));"world"===e.output.space&&z.push(new Y("shape"===e.output.type||"mesh"===e.output.type)),z.push(O,new K),q.addInitializers(z);const X=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,p);return ue(t,e.params??{},a,D)}).sort((e,t)=>e instanceof ie?1:0));X.push(new xe);for(const e of X)e instanceof ie&&(e.physics=S);q.addBehaviours(X);for(const a of e.children??[]){const e=await we(a,t,r,p,x,S,P,D,F),s=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=q.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&q.childEmitters.splice(e,1),null!=t.parentParticle&&(n.delete(t.parentParticle.id),t.parentParticle=null),s.release(t)},t}),i=q.eventDispatcher,n=new Map;q.bindEmitterEvent=!0,i.addEventListener("PARTICLE_DEAD",e=>{const t=n.get(e.id);null!=t&&(q.detachChildEmitterFromParticle(t,e),n.delete(e.id))});let l="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":l="PARTICLE_COLLISION";break;case"start":l="PARTICLE_CREATED"}i.addEventListener(l,e=>{const t=s.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),q.childEmitters.push(t),n.set(e.id,t),t.parentParticle=e,t.system=q.system,t.emit()})}return q}const ge=(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}`,Me(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=be(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 ve(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 ve(s.material,r):Ee(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 be(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 ve(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 h=J.color.rgb.multiply(S(new i.Color(n))).multiplyScalar(b(o)),d=J.opacity.multiply(b(l));if(null!=p){const e=C(await t.getTexture(p)).sample(B.uv);h=h.multiply(e.rgb),d=d.multiply(e.a)}null!=u&&(d=d.multiply(C(await t.getTexture(u)).sample(B.uv).r));const m=new c({color:h.rgba(d),opacity:d,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 Me(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 Ee(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: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 xe 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 Se 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?(Ie.copy(t),"local"===a&&"world"===r?Ie.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(Te.copy(this.transformRoot.matrixWorld).invert(),Ie.applyMatrix4(Te)),e.position.copy(Ie)):e.position.copy(t)}clone(){const e=new Se(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 Ie=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
  */
@@ -126,6 +126,10 @@ export declare abstract class AbstractPhysicsSystem {
126
126
  * Applies an instantaneous force impulse to an actor's physics body
127
127
  */
128
128
  abstract applyImpulse(actor: BaseActor, force: Vector3): void;
129
+ /** Applies an outward impulse to dynamic rigid bodies intersecting a sphere. */
130
+ abstract applyRadialImpulse(position: Vector3, radius: number, impulse: number): number;
131
+ /** Applies an impulse in one direction to dynamic bodies inside a spherical cone. */
132
+ abstract applyDirectionalImpulse(position: Vector3, direction: Vector3, radius: number, halfAngle: number, impulse: number): number;
129
133
  /**
130
134
  * Applies a force at a specific local point on an actor's physics body
131
135
  */
@@ -509,14 +509,10 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
509
509
  * @param localPoint - The local point at which to apply the impulse
510
510
  */
511
511
  applyLocalImpulse(actor: BaseActor, force: Vector3, localPoint?: Vector3): void;
512
- /**
513
- * Apply an impulse on all dynamic physics bodies in the direction away from the given
514
- * position.
515
- * @param position The center of where the impulse should originate.
516
- * @param radius Used to filter which objects should be affected.
517
- * @param forceAmount
518
- */
519
- private applyRadiusImpulse;
512
+ /** Applies an outward, linearly-falling impulse to dynamic bodies in a sphere. */
513
+ applyRadialImpulse(position: Vector3, radius: number, impulse: number): number;
514
+ applyDirectionalImpulse(position: Vector3, direction: Vector3, radius: number, halfAngle: number, impulse: number): number;
515
+ private applyImpulseToBodiesInRadius;
520
516
  /**
521
517
  * Removes an actor from the physics world.
522
518
  * @param actor - The actor to remove
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as p,Group as y,LineSegments as g,Matrix4 as m,Object3D as b,Quaternion as f,Raycaster as w,Scene as x,Vector3 as v}from"three";import*as B from"three/examples/jsm/utils/BufferGeometryUtils.js";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{BoxCollisionShape as R,CapsuleCollisionShape as M,ConeCollisionShape as E,ConvexPolyhedronCollisionShape as T,CylinderCollisionShape as z,PhysicalShapeMesh as P,PlaneCollisionShape as F,SphereCollisionShape as _,toInstancedCollisionShape as I,TrimeshCollisionShape as j}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as W}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as N}from"../../../scene/landscape/landscape.js";import{calculateEffectiveScale as k}from"../../../utils/three/traverse.js";import{ViewController as L}from"../render.js";import{World as V}from"../world.js";import{AbstractPhysicsSystem as O}from"./abstract-physics-system.js";import{NetRole as U}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.hitNormal=new v}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.normal=new v}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new v,K=new v,X=new f,q=new f,H=new f;let Q=class extends O{set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=C(L),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new w,this._reusableResult=new RayTestResult,this._raytestDiff=new v,this._raytestDirection=new v,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,X,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,X,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,X)&&o.push(n)}return o}createDebugMesh(){const t=new g(new p,new d.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new u(t,3);o.setUsage(d.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(s.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(s.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await ct(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!this._isStopped){t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===U.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this._isStopped||(this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents(this.handleCollisionEvent))}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(nt,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,o){null==i&&(i=this._reusableResult);const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==ft&&(ft=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),dt(ft.origin,t),dt(ft.dir,r);const l=this.world.castRayAndGetNormal(ft,a,!1,o?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,o?.collisionFilter,void 0,null!=o?.excludeActor?this.actorBodies.get(o.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit&&(i._internal=l,ut(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==o?.resolveActor)){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}return this.showDebug&&!1!==o?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,o?.debugColor,o?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new h(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())pt(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof P&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof W){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof N?this.addLandscapeGroup(t):(t instanceof y||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof W&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new b;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);this.createStaticBody(c,l)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new b;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>I(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,void 0);const a=e.computedMovement();return ut(yt,a),yt}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(bt)??et,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),ot.set(0,s,0).multiply(r),dt(it,ot),n.setTranslationWrtParent(it),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,o,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(bt)??et,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,o*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(H)??X;ot.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(ot,u,h,s.EXCLUDE_SENSORS,r??void 0,void 0,a,mt)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,void 0);const r=e.computedMovement();return ut(yt,r),yt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(it);s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setNextKinematicTranslation(rt(i)),t.setNextKinematicRotation(at(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setAngvel(it,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setLinvel(it,!0)}getLinearVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(rt(e),!1)}getPosition(t,e=new v){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(at(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new v);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);dt(e,o),t.setTranslation(e,!1),this.world.createCollider(l,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);dt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);gt.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),pt(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),Y(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addTorque(it,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyTorqueImpulse(it,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addForce(it,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyImpulse(it,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);dt(it,e),null==i?s?.addForce(it,!0):(dt(st,i),s?.addForceAtPoint(it,st,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);dt(it,e),null==i?s.applyImpulse(it,!0):(dt(st,i),s.applyImpulseAtPoint(it,st,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=ot;ut(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);it.x=a.x,it.y=a.y,it.z=a.z,o.applyImpulse(it,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof N){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(Y(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,o,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);it.x=i.x,it.y=i.y,it.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,X,it,a,.01,o,!0,r?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){ut(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return ut(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);s?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.sleep(),n.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(bt)??et,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);dt(o.translation,n);const r=(new f).setFromEuler(e.rotation);ht(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof R)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof M){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof j){const i=null!=t.geometry.getIndex()?t.geometry:B.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof T){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=k(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=tt.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),tt.set(o,a),a}if(t instanceof _){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new T(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new v(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof F?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([D(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const J=new v,$=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setTranslation(rt(i),!1),t.setRotation(at(s),!1)}const Z=new v,tt=new Map,et=new v(1,1,1),it=new i.Vector3(0,0,0),st=new i.Vector3(0,0,0),ot=new v,nt=new d.Vector2;function rt(t){return dt(it,t),it}function at(t){return ht(q,t),q}let lt=null;const ct=async()=>(null==lt&&(lt=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),lt);function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function pt(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const yt=new v,gt=new WeakMap,mt=t=>gt.get(t)??!0,bt=new v;let ft,wt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(Q),this.world=C(V)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([A()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as p,Group as y,LineSegments as g,Matrix4 as m,Object3D as b,Quaternion as f,Raycaster as w,Scene as x,Vector3 as v}from"three";import*as B from"three/examples/jsm/utils/BufferGeometryUtils.js";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{BoxCollisionShape as R,CapsuleCollisionShape as M,ConeCollisionShape as E,ConvexPolyhedronCollisionShape as T,CylinderCollisionShape as z,PhysicalShapeMesh as P,PlaneCollisionShape as F,SphereCollisionShape as I,toInstancedCollisionShape as _,TrimeshCollisionShape as N}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as W}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as j}from"../../../scene/landscape/landscape.js";import{calculateEffectiveScale as L}from"../../../utils/three/traverse.js";import{ViewController as k}from"../render.js";import{World as O}from"../world.js";import{AbstractPhysicsSystem as V}from"./abstract-physics-system.js";import{NetRole as U}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.hitNormal=new v}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.normal=new v}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new v,K=new v,X=new f,q=new f,H=new f;let Q=class extends V{set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=C(k),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new w,this._reusableResult=new RayTestResult,this._raytestDiff=new v,this._raytestDirection=new v,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,X,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,X,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,X)&&o.push(n)}return o}createDebugMesh(){const t=new g(new p,new d.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new u(t,3);o.setUsage(d.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(s.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(s.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await pt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!this._isStopped){t=Math.min(.04,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===U.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this._isStopped||(this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents(this.handleCollisionEvent))}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ct,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,o){null==i&&(i=this._reusableResult);const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==Bt&&(Bt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),yt(Bt.origin,t),yt(Bt.dir,r);const l=this.world.castRayAndGetNormal(Bt,a,!1,o?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,o?.collisionFilter,void 0,null!=o?.excludeActor?this.actorBodies.get(o.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit&&(i._internal=l,mt(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==o?.resolveActor)){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}return this.showDebug&&!1!==o?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,o?.debugColor,o?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new h(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())bt(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof P&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof W){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof j?this.addLandscapeGroup(t):(t instanceof y||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof W&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new b;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);this.createStaticBody(c,l)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new b;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>_(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,void 0);const a=e.computedMovement();return mt(ft,a),ft}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(vt)??et,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),ot.set(0,s,0).multiply(r),yt(it,ot),n.setTranslationWrtParent(it),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,o,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(vt)??et,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,o*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(H)??X;ot.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(ot,u,h,s.EXCLUDE_SENSORS,r??void 0,void 0,a,xt)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,void 0);const r=e.computedMovement();return mt(ft,r),ft}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(it);s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setNextKinematicTranslation(dt(i)),t.setNextKinematicRotation(ht(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setAngvel(it,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setLinvel(it,!0)}getLinearVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(dt(e),!1)}getPosition(t,e=new v){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(ht(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new v);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);yt(e,o),t.setTranslation(e,!1),this.world.createCollider(l,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);yt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);wt.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),bt(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),Y(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addTorque(it,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyTorqueImpulse(it,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addForce(it,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyImpulse(it,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);yt(it,e),null==i?s?.addForce(it,!0):(yt(st,i),s?.addForceAtPoint(it,st,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);yt(it,e),null==i?s.applyImpulse(it,!0):(yt(st,i),s.applyImpulseAtPoint(it,st,!0))}applyRadialImpulse(t,e,i){return e<=0||0===i?0:this.applyImpulseToBodiesInRadius(t,e,(t,s,o)=>{o<=1e-6?s.set(0,1,0):s.multiplyScalar(1/o),s.multiplyScalar(i*Math.max(0,1-o/e)),yt(it,s),t.applyImpulse(it,!0)})}applyDirectionalImpulse(t,e,i,s,o){if(i<=0||0===o||e.lengthSq()<=1e-12)return 0;nt.copy(e).normalize();const n=Math.cos(Math.max(0,Math.min(Math.PI,s)));return this.applyImpulseToBodiesInRadius(t,i,(t,e,i)=>{if(i>1e-6&&e.multiplyScalar(1/i).dot(nt)<n)return!1;it.x=nt.x*o,it.y=nt.y*o,it.z=nt.z*o,t.applyImpulse(it,!0)})}applyImpulseToBodiesInRadius(t,e,i){const o=at,n=lt;o.clear(),n.length=0;let r=0;this.world.intersectionsWithShape(t,X,this.getBallShape(e),t=>{const e=t.parent();return null==e||o.has(e.handle)||(o.add(e.handle),n.push(e)),!0},s.ONLY_DYNAMIC|s.EXCLUDE_SENSORS);for(const e of n)mt(rt,e.worldCom()),rt.sub(t),!1!==i(e,rt,rt.length())&&r++;return o.clear(),n.length=0,r}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof j){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(Y(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,o,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);it.x=i.x,it.y=i.y,it.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,X,it,a,.01,o,!0,r?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){mt(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return mt(s.hitPoint,u.witness1),St(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed(),n=this.world.createRigidBody(o);s?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(vt)??et,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);yt(o.translation,n);const r=(new f).setFromEuler(e.rotation);gt(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof R)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof M){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof N){const i=null!=t.geometry.getIndex()?t.geometry:B.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof T){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=L(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=tt.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),tt.set(o,a),a}if(t instanceof I){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new T(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new v(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof F?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([D(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const J=new v,$=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setTranslation(dt(i),!1),t.setRotation(ht(s),!1)}const Z=new v,tt=new Map,et=new v(1,1,1),it=new i.Vector3(0,0,0),st=new i.Vector3(0,0,0),ot=new v,nt=new v,rt=new v,at=new Set,lt=[],ct=new d.Vector2;function dt(t){return yt(it,t),it}function ht(t){return gt(q,t),q}let ut=null;const pt=async()=>(null==ut&&(ut=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ut);function yt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function gt(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function mt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function bt(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const ft=new v,wt=new WeakMap,xt=t=>wt.get(t)??!0,vt=new v;let Bt,Dt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(Q),this.world=C(O)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};Dt=t([A()],Dt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function St(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
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{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as d,mergeCompatibleSkinnedMeshes as p}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as y,firstValueFrom as g}from"rxjs";import{BoxCollisionShape as w,CapsuleCollisionShape as x,CollisionShapeSource as M,CylinderCollisionShape as b,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as S,isCollisionMesh as _}from"./collision/collision-shape-import.js";import*as v from"three";import{iterateMaterials as L}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as R}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as I,EXRLoader as P,FBXLoader as B,GLTFLoader as K,KTX2Loader as k,TGALoader as j,UltraHDRLoader as F}from"three/examples/jsm/Addons.js";import{disposeScene as D}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as z,setAnimationClipRigId as W}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new v.DataTexture(e,1,1,v.RGBAFormat);t.needsUpdate=!0})();const U=new I;U.setDecoderConfig({type:"js"}),U.setDecoderPath("/assets/draco/");const G=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new K(this.loadingManager).setDRACOLoader(U),this.fbxLoader=new B(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new j(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new F(this.loadingManager),this.ktx2Loader=new k(this.loadingManager),this._textureLoader=new v.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new y,this.ready=g(this.makeReady),this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e),this.ktx2Loader.setWorkerLimit(6)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return E.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=q(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(X(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=q(t,e),t.colorSpace=V(X(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof o||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),$(e.fileKey)),null!=e.materialLib&&$(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!G.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r),n=s.scene,o=s.animations;if(!1===t?.clone)return{scene:n,animations:o};const l=this.computeCollisionShapes(e,n);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(n);const c=d(n);c.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const h=new AssetMeshInstance;h.add(c),h.collisionShapes=l,h.animations=o,h.userData.assetId=e.id,h.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const s=e instanceof i?"Mesh":"Group",n=`${t}/${e.name?.trim()?.length>0?e.name:s}[${a}]`;e.userData.secondaryMotionMeshPath=n;for(let t=0;t<e.children.length;t++)r(e.children[t],n,t)}}(h);const u=e.mesh?.animationRigId??e.anim?.rigId;if(h.userData.animationRigId=u,c.userData.animationRigId=u,null!=u&&null!=this.animationRigProvider){const e=await this.animationRigProvider(u);h.userData.animationRig=e,c.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&h.quaternion.copy(z(e))}const m=e.receiveShadow??!1,p=e.castShadow??!1;if(c.traverse(e=>{e.castShadow=p,e.receiveShadow=m}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&h.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(h,t,r,void 0,{textureFlipY:R(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:h,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(W(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):S(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(r=>{if(r instanceof i&&r.geometry instanceof t){const t=removeInvalidFaces(r.geometry);t>0&&console.warn(`Removed ${t} invalid face${1===t?"":"s"} from ${e.name}/${r.name||"unnamed mesh"}`)}r instanceof i&&r.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Q):e.material=Q(t)}(r),_(r)?r.visible=!1:r instanceof i&&r.geometry instanceof t&&(r.geometry.hasAttribute("normal")||r.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{H.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(H);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=Z;Z.length=0,e.traverse(e=>{(e instanceof v.Camera||e instanceof v.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof v.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!_(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}p(e,_);let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof v.SkinnedMesh||e instanceof v.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!_(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r,a=t.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new v.BufferAttribute(r,1)),e})),r=1===t.geometries.length?a[0]:O(a)?C.mergeGeometries(a,!0):null,null!=r)r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material));else for(const r of a)e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new v.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new v.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new v.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>(N(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>D(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const E=new Map;function $(e){E.set(e,(E.get(e)??0)+1)}function O(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const s=Object.keys(e.attributes).sort(),i=Object.keys(e.morphAttributes).sort();if(s.join("|")!==r.join("|"))return!1;if(i.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),s=e.getAttribute(a);if(r.itemSize!==s.itemSize||r.normalized!==s.normalized||r.array.constructor!==s.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],s=e.morphAttributes[r];if(a.length!==s.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==s[e].itemSize||a[e].normalized!==s[e].normalized||a[e].array.constructor!==s[e].array.constructor)return!1}return!0})}function N(e){if(e instanceof i)for(const t of L(e.material))t instanceof v.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(N)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new w((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new x(e.length*a,e.radius*a);break;case"cylinder":t=new b(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=M.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return v.ClampToEdgeWrapping;case"repeat":return v.RepeatWrapping;case"mirror":return v.MirroredRepeatWrapping}return v.RepeatWrapping}function q(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function X(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(J.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?v.LinearSRGBColorSpace:v.SRGBColorSpace}const J=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new v.Matrix4;const Z=[];const H=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,s=Math.floor(a/3),i=[],n=new Uint32Array(s+1),o=new c,l=new c,h=new c;let u=0;for(let e=0;e<s;e++){const a=3*e,s=r?.getX(a)??a,c=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(s)&&Number.isInteger(c)&&Number.isInteger(m)&&s>=0&&c>=0&&m>=0&&s<t.count&&c<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,s),l.fromBufferAttribute(t,c).sub(o),h.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),h.lengthSq(),l.distanceToSquared(h)),r=l.cross(h).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?i.push(s,c,m):u++,n[e+1]=i.length}if(0===u)return 0;if(e.setIndex(i),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(s,Math.floor((r.start+r.count)/3));if(a<=t)continue;const i=n[t],o=n[a]-i;o>0&&e.addGroup(i,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(s,Math.floor((e.drawRange.start+e.drawRange.count)/3)):s,p=Math.min(m,s),f=Math.min(s,Math.max(p,d)),y=n[p];return e.setDrawRange(y,n[f]-y),u}function Q(e){let t=e instanceof v.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof v.MeshLambertMaterial||e instanceof v.MeshPhongMaterial||e instanceof v.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new v.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
1
+ import{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as d,mergeCompatibleSkinnedMeshes as p}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as y,firstValueFrom as g}from"rxjs";import{BoxCollisionShape as w,CapsuleCollisionShape as x,CollisionShapeSource as M,CylinderCollisionShape as b,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as S,isCollisionMesh as _}from"./collision/collision-shape-import.js";import*as v from"three";import{iterateMaterials as L}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as R}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as I,EXRLoader as P,FBXLoader as K,GLTFLoader as B,KTX2Loader as k,TGALoader as F,UltraHDRLoader as j}from"three/examples/jsm/Addons.js";import{disposeScene as D}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as z,setAnimationClipRigId as W}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new v.DataTexture(e,1,1,v.RGBAFormat);t.needsUpdate=!0})();const U=new I;U.setDecoderConfig({type:"js"}),U.setDecoderPath("/assets/draco/");const G=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new B(this.loadingManager).setDRACOLoader(U),this.fbxLoader=new K(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new F(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new j(this.loadingManager),this.ktx2Loader=new k(this.loadingManager),this._textureLoader=new v.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new y,this.ready=g(this.makeReady),this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e),this.ktx2Loader.setWorkerLimit(6)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return E.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=q(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(X(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=q(t,e),t.colorSpace=V(X(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof o||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),$(e.fileKey)),null!=e.materialLib&&$(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!G.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r),n=s.scene,o=s.animations;if(!1===t?.clone)return{scene:n,animations:o};const l=this.computeCollisionShapes(e,n),c=(e.mesh?.secondaryMotion?.regions.length??0)>0;!0!==t?.mergeGeomtries||c||this.optimizeDrawGroups(n);const h=d(n);h.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const u=new AssetMeshInstance;u.add(h),u.collisionShapes=l,u.animations=o,u.userData.assetId=e.id,u.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const s=e instanceof i?"Mesh":"Group",n=`${t}/${e.name?.trim()?.length>0?e.name:s}[${a}]`;e.userData.secondaryMotionMeshPath=n;for(let t=0;t<e.children.length;t++)r(e.children[t],n,t)}}(u);const m=e.mesh?.animationRigId??e.anim?.rigId;if(u.userData.animationRigId=m,h.userData.animationRigId=m,null!=m&&null!=this.animationRigProvider){const e=await this.animationRigProvider(m);u.userData.animationRig=e,h.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&u.quaternion.copy(z(e))}const p=e.receiveShadow??!1,f=e.castShadow??!1;if(h.traverse(e=>{e.castShadow=f,e.receiveShadow=p}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&u.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(u,t,r,void 0,{textureFlipY:R(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:u,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(W(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):S(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(r=>{if(r instanceof i&&r.geometry instanceof t){const t=removeInvalidFaces(r.geometry);t>0&&console.warn(`Removed ${t} invalid face${1===t?"":"s"} from ${e.name}/${r.name||"unnamed mesh"}`)}r instanceof i&&r.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Q):e.material=Q(t)}(r),_(r)?r.visible=!1:r instanceof i&&r.geometry instanceof t&&(r.geometry.hasAttribute("normal")||r.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{H.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(H);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=Z;Z.length=0,e.traverse(e=>{(e instanceof v.Camera||e instanceof v.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof v.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!_(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}p(e,_);let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof v.SkinnedMesh||e instanceof v.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!_(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r,a=t.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new v.BufferAttribute(r,1)),e})),r=1===t.geometries.length?a[0]:O(a)?C.mergeGeometries(a,!0):null,null!=r)r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material));else for(const r of a)e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new v.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new v.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new v.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(t=>{const r=!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")&&1===t.scene.children.length?t.scene.children[0]:t.scene;return r!==t.scene&&t.scene.remove(r),{scene:r,animations:t.animations}});case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>(N(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>D(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const E=new Map;function $(e){E.set(e,(E.get(e)??0)+1)}function O(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const s=Object.keys(e.attributes).sort(),i=Object.keys(e.morphAttributes).sort();if(s.join("|")!==r.join("|"))return!1;if(i.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),s=e.getAttribute(a);if(r.itemSize!==s.itemSize||r.normalized!==s.normalized||r.array.constructor!==s.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],s=e.morphAttributes[r];if(a.length!==s.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==s[e].itemSize||a[e].normalized!==s[e].normalized||a[e].array.constructor!==s[e].array.constructor)return!1}return!0})}function N(e){if(e instanceof i)for(const t of L(e.material))t instanceof v.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(N)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new w((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new x(e.length*a,e.radius*a);break;case"cylinder":t=new b(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=M.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return v.ClampToEdgeWrapping;case"repeat":return v.RepeatWrapping;case"mirror":return v.MirroredRepeatWrapping}return v.RepeatWrapping}function q(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function X(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(J.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?v.LinearSRGBColorSpace:v.SRGBColorSpace}const J=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new v.Matrix4;const Z=[];const H=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,s=Math.floor(a/3),i=[],n=new Uint32Array(s+1),o=new c,l=new c,h=new c;let u=0;for(let e=0;e<s;e++){const a=3*e,s=r?.getX(a)??a,c=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(s)&&Number.isInteger(c)&&Number.isInteger(m)&&s>=0&&c>=0&&m>=0&&s<t.count&&c<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,s),l.fromBufferAttribute(t,c).sub(o),h.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),h.lengthSq(),l.distanceToSquared(h)),r=l.cross(h).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?i.push(s,c,m):u++,n[e+1]=i.length}if(0===u)return 0;if(e.setIndex(i),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(s,Math.floor((r.start+r.count)/3));if(a<=t)continue;const i=n[t],o=n[a]-i;o>0&&e.addGroup(i,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(s,Math.floor((e.drawRange.start+e.drawRange.count)/3)):s,p=Math.min(m,s),f=Math.min(s,Math.max(p,d)),y=n[p];return e.setDrawRange(y,n[f]-y),u}function Q(e){let t=e instanceof v.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof v.MeshLambertMaterial||e instanceof v.MeshPhongMaterial||e instanceof v.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new v.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */