@hology/core 0.0.245 → 0.0.247

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/effects/vfx/gpu-sprite-compiler.js +1 -1
  2. package/dist/effects/vfx/gpu-sprite-runtime.d.ts +18 -1
  3. package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
  4. package/dist/effects/vfx/gpu-sprite-template.d.ts +1 -0
  5. package/dist/effects/vfx/gpu-sprite-template.js +1 -1
  6. package/dist/effects/vfx/gpu-sprite-world-runtime.d.ts +2 -1
  7. package/dist/effects/vfx/gpu-sprite-world-runtime.js +1 -1
  8. package/dist/effects/vfx/gpu-vfx-world-service.d.ts +7 -1
  9. package/dist/effects/vfx/gpu-vfx-world-service.js +1 -1
  10. package/dist/effects/vfx/initializsers.d.ts +15 -0
  11. package/dist/effects/vfx/initializsers.js +1 -1
  12. package/dist/effects/vfx/vfx-actor.d.ts +2 -0
  13. package/dist/effects/vfx/vfx-actor.js +1 -1
  14. package/dist/effects/vfx/vfx-asset.d.ts +7 -3
  15. package/dist/effects/vfx/vfx-asset.js +1 -1
  16. package/dist/effects/vfx/vfx-binding-runtime.d.ts +1 -1
  17. package/dist/effects/vfx/vfx-binding-runtime.js +1 -1
  18. package/dist/effects/vfx/vfx-defs.d.ts +53 -3
  19. package/dist/effects/vfx/vfx-defs.js +1 -1
  20. package/dist/effects/vfx/vfx-input-runtime.d.ts +2 -2
  21. package/dist/effects/vfx/vfx-input-runtime.js +1 -1
  22. package/dist/effects/vfx/vfx-materializer.js +1 -1
  23. package/dist/effects/vfx/vfx-mesh-sampler.d.ts +25 -0
  24. package/dist/effects/vfx/vfx-mesh-sampler.js +4 -0
  25. package/dist/gameplay/actors/builtin/components/index.d.ts +2 -0
  26. package/dist/gameplay/actors/builtin/components/index.js +1 -1
  27. package/dist/gameplay/actors/builtin/components/spline-component.d.ts +65 -0
  28. package/dist/gameplay/actors/builtin/components/spline-component.js +4 -0
  29. package/dist/gameplay/actors/builtin/index.d.ts +6 -0
  30. package/dist/gameplay/actors/builtin/index.js +1 -1
  31. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  32. package/dist/gameplay/actors/builtin/spline-actor.d.ts +6 -0
  33. package/dist/gameplay/actors/builtin/spline-actor.js +4 -0
  34. package/dist/gameplay/actors/builtin/water-spline-volume-actor.d.ts +13 -0
  35. package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +4 -0
  36. package/dist/gameplay/actors/builtin/water-volume-actor.d.ts +8 -0
  37. package/dist/gameplay/actors/builtin/water-volume-actor.js +4 -0
  38. package/dist/gameplay/actors/index.d.ts +4 -0
  39. package/dist/gameplay/actors/index.js +1 -1
  40. package/dist/gameplay/ai/build-tile.d.ts +3 -1
  41. package/dist/gameplay/ai/build-tile.js +1 -1
  42. package/dist/gameplay/ai/dynamic-tiled-navmesh.d.ts +4 -21
  43. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +1 -1
  44. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.d.ts +10 -1
  45. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.js +1 -1
  46. package/dist/gameplay/ai/index.d.ts +1 -0
  47. package/dist/gameplay/ai/index.js +1 -1
  48. package/dist/gameplay/ai/navigation-areas.d.ts +22 -0
  49. package/dist/gameplay/ai/navigation-areas.js +4 -0
  50. package/dist/gameplay/ai/navigation.d.ts +28 -4
  51. package/dist/gameplay/ai/navigation.js +1 -1
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +1 -1
  54. package/dist/scene/materializer.d.ts +3 -0
  55. package/dist/scene/materializer.js +1 -1
  56. package/dist/shader/graph/compiler.js +1 -1
  57. package/dist/shader/graph/model.d.ts +1 -1
  58. package/dist/shader/graph/registry.js +1 -1
  59. package/dist/test/build-tile.test.js +1 -1
  60. package/dist/test/gpu-sprite-compiler.test.js +1 -1
  61. package/dist/test/navmesh-worker-pool.test.js +1 -1
  62. package/dist/test/node-material-webgpu-resolver.test.js +1 -1
  63. package/dist/test/shader-graph.test.js +1 -1
  64. package/dist/test/spline-component.test.d.ts +2 -0
  65. package/dist/test/spline-component.test.js +4 -0
  66. package/dist/test/vfx-mesh-sampler.test.d.ts +2 -0
  67. package/dist/test/vfx-mesh-sampler.test.js +4 -0
  68. package/dist/test/water-spline-volume-actor.test.d.ts +2 -0
  69. package/dist/test/water-spline-volume-actor.test.js +4 -0
  70. package/dist/test/worker-task-executor.test.d.ts +2 -0
  71. package/dist/test/worker-task-executor.test.js +4 -0
  72. package/dist/worker/index.d.ts +11 -2
  73. package/dist/worker/index.js +1 -1
  74. package/dist/worker/task-executor.d.ts +22 -0
  75. package/dist/worker/task-executor.js +4 -0
  76. package/dist/worker/task-worker.d.ts +3 -0
  77. package/dist/worker/task-worker.js +4 -0
  78. package/dist/worker/task.d.ts +39 -0
  79. package/dist/worker/task.js +4 -0
  80. package/package.json +2 -2
  81. package/tsconfig.tsbuildinfo +1 -1
@@ -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,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}}/*
1
+ import e,{Behaviour as t,Body as a,Emitter as r,Rate as s}from"@hology/nebula";import*as i from"three";import{Object3D as n}from"three";import{AttributeVec3Node as l,AttributeVec4Node as o,NodeShaderMaterial as c,RgbNode as p,UniformFloatNode as u,UniformVec3Node as d,Vec3ExpressionNode as h,attributeVec3 as m,attributeVec4 as f,attributes as y,clamp as g,cross as w,float as b,lambertMaterial as v,length as M,log as A,normalize as E,pow as x,rgb as S,rgba as I,smoothstep as T,standardMaterial as P,textureSampler2d as C,uniforms as R,varying as B,varyingAttributes as G,varyingVec3 as k,varyingVec4 as j,vec2 as D,vec3 as F,vec4 as V}from"three-shader-graph";import{prepareClassParameters as L,prepareShaderGraphParameters as O,prepareShapeParameters as W}from"../../scene/materializer.js";import{SerializedParamType as U}from"../../scene/model.js";import{ShapeLibrary as N}from"../../scene/objects/shapes.js";import{fragmentLinearEyeDepth as Q,linearEyeDepth as H}from"../../shader-nodes/depth.js";import{particleEnergyUniformName as q,particleTimeUniformName as z,particleUniforms as J,particleVelcoityUniformName as X}from"../../shader-nodes/particle.js";import{sampleFlipbook as _}from"../../shader-nodes/texture-sequence.js";import{DefaultInitializer as K,WorldSpaceEmitterTransformInitializer as Y}from"./initializsers.js";import{DelayRate as Z,OnceRate as $}from"./rates.js";import{StretchedSprite as ee}from"./stretched-sprite.js";import{ThreeBlendingMode as te}from"./vfx-asset.js";import{VfxBehaviourLibrary as ae,VfxInitializserLibrary as re}from"./vfx-defs.js";import{MultiRenderer as se}from"./vfx-renderers.js";import{WorldCollisionBehaviour as ie}from"./vfx-collision-behaviour.js";import{getSpritePosition as ne,SpriteNodeShader as le,SpriteNodeShaderMaterial as oe}from"../../shader/sprite-shader.js";import{DecalUnlitShader as ce}from"../../shader/builtin/decal-unlit-shader.js";import{DecalStandardShader as pe}from"../../shader/builtin/decal-standard-shader.js";import{createBoundBehaviour as ue,createBoundInitializer as de}from"./vfx-binding-runtime.js";import{buildShaderGraphMaterial as he}from"../../shader/graph/index.js";import{markMaterialUniformValuesNeedUpdate as me,setMaterialUniformValuesAutoUpdate as fe}from"../../rendering/node-material-webgpu-resolver.js";import{applyMeshWorldTransformToGeometry as ye}from"./vfx-mesh-transform.js";export async function materializeVfx(t,a,r,s,l,o,c,p,u){let d=a;for(;null!=d.parent;)d=d.parent;const h=new n;h.name="particle system local",a.add(h);const m=new n;m.name="particle system world";const f=new se(m,h,i,s),y=new e;return(await Promise.all(t.vfx.emitters.slice().sort((e,t)=>(t.output.renderOrder??0)-(e.output.renderOrder??0)).map(async e=>{const t=await we(e,r,c,p,y,l,o,u,a);return t.setParentRecursive(y),t.emit()}))).forEach(e=>y.addEmitter(e)),y.addRenderer(f).emit({onEnd:()=>{}}),{container:m,system:y,dispose:()=>{m.removeFromParent(),h.removeFromParent(),f.dispose()}}}function ge(e,t){let a;const r=function(e,t){const a=Math.max(0,e.rate.delay??0),r=e.rate.delayBinding;if("vfxInput"!==r?.type||null==t)return a;const s=t.getDefinition(r.inputId);return"number"!==s?.type?a:Math.max(0,t.getNumber(r.inputId,a))}(e,t);switch(e.rate.type){case"continuous":a=new Z(r,e.rate.count,e.rate.time,e.rate.duration);break;case"once":a=new $(r,e.rate.count);break;default:console.warn(`Failed to configure rate for emitter: ${JSON.stringify(e)}`),a=new s(0,1/0)}return a}async function we(e,t,r,s,p,x,S,P,D){const F=ge(e,P);let L;switch(e.output.type){case"decal":L=new a(await async function(e,t,a,r,s){if("shaderGraph"===ve(e)){const t=await createShaderGraphMaterial(e,"decal",a,r,s);if(null!=t){const a=new i.Mesh(new i.BoxGeometry(1,1,1),t);return Ee(a,e),a}}const n=!1!==e.unlit?new ce:new pe;n.color=new i.Color(e.color),n instanceof ce?n.intensity=e.intensity??1:n.emissiveIntensity=e.intensity??1;if(e.colorMap){const a=await t.getTexture(e.colorMap);n.colorMap=a}if(e.alphaMap){const a=await t.getTexture(e.alphaMap);n.alphaMap=a}const l=n.build();l.blending=te[e.blendingMode]??i.NormalBlending,l.transparent=!0,l.side=i.BackSide,l.depthTest=!1,null!=l&&!0===e.bloom&&(l.userData.hasBloom=!0);l.defines.IS_PARTICLE="";const o=new i.BoxGeometry(1,1,1),c=new i.Mesh(o,l);return Ee(c,e),c}(e.output,t,r,s,S));break;case"sprite":L=new a(await async function(e,t,a,r,s){let n=null;const l=ve(e);"shaderGraph"===l&&(n=await createShaderGraphMaterial(e,"sprite",a,r,s));null==n&&"shader"===l&&null!=e.shader&&(n=await createShaderMaterial(e,t,s));null==n&&(n=await async function(e,t){const a=null!=e.texture?await t.getTexture(e.texture):be,r=C(a);let s=r.sample(G.uv);e.flipbook?.enabled&&(s=_(r,y.uv,e.flipbook.columns,e.flipbook.rows,J.time,e.flipbook.fps,e.flipbook.mode));const n=new u("rotation",0),l=new d("color").rgb,o=k(new h("instanceColor")).rgb,c=H.subtract(Q).divide(H);let p=J.opacity;switch(e.opacityChannel??"red"){case"none":break;case"red":p=p.multiply(s.r);break;case"alpha":p=p.multiply(s.a)}if("number"==typeof e.softness&&e.softness>0){const t=g(c,0,1e3);p=p.multiply(T(0,.2*e.softness,t))}const m=ne(n,void 0,void 0,!0),f=I(l.multiply(o).multiply(s.rgb).multiplyScalar(e.intensity??1),p);var w=new oe({color:f,emissive:f.rgb.multiplyScalar(p),transparent:!0,position:m,alphaTest:1e-4,uniforms:{color:{value:new i.Color(e.color)}}});w.alphaHash=!0,null!=w&&!0===e.bloom&&(w.userData.hasBloom=!0);return w.blending=te[e.blendingMode]??i.NormalBlending,w}(e,t));n.depthWrite=!1,Ae(n,e);const o=new i.Mesh(new i.PlaneGeometry(1,1),n);return o.name="sprite",Ee(o,e),o}(e.output,t,r,s,S));break;case"stretchedSprite":L=new a(await async function(e,t){"shaderGraph"===ve(e)&&console.warn("Shader graph materials are not supported for stretched sprite VFX outputs yet. Falling back to the default stretched sprite material.");const a=null!=e.texture?await t.getTexture(e.texture):be,r=C(a).sample(G.uv),s=j(new o("particleColor")),n=s.rgb.multiply(r.rgb);let l=s.w;switch(e.opacityChannel??"red"){case"none":break;case"red":l=l.multiply(r.r);break;case"alpha":l=l.multiply(r.a)}if("number"==typeof e.softness&&e.softness>0){const t=H.subtract(Q).divide(A(H)),a=g(t,0,1e3);l=l.multiply(T(0,.2*e.softness,a))}const c=m("offset"),p=f("velocity"),u=m("size"),d=p.w,h=u.x.add(u.y).multiply(.5),v=R.modelViewMatrix.multiplyVec(V(c,1)),x=R.normalMatrix.multiplyVec(p.xyz),S=E(w(v.xyz,x)).multiplyScalar(y.position.y.multiply(h)),P=x.multiplyScalar(y.position.x.add(.5).multiply(b(1).add(d.divide(M(x)))).multiply(h)),B=R.projectionMatrix.multiplyVec(V(v.xyz.add(S).subtract(P),v.w));var k=new oe({color:I(n.multiplyScalar(e.intensity??1),l),alphaTest:.1,transparent:!0,position:B,uniforms:{color:{value:new i.Color(e.color)}}});null!=k&&!0===e.bloom&&(k.userData.hasBloom=!0);k.blending=te[e.blendingMode]??i.NormalBlending;const D=new ee(new i.PlaneGeometry(1,1),k);return D.scaleFactor=e.scale,Ee(D,e),D}(e.output,t));break;case"shape":L=new a(await async function(e,t,a,r,s){if(null==e.shape)return console.log("Shape is null"),new n;const o=N[e.shape];if(null==o)return console.error(`No shape with type ${e.shape}`),new n;const p=W(e.params??{}),u=o.geometry(p);let d=null;const m=ve(e);"shaderGraph"===m&&(d=await createShaderGraphMaterial(e,"surface",a,r,s));null==d&&"shader"===m&&null!=e.shader&&(d=await createShaderMaterial(e,t,s));null==d&&(d="material"===m&&null!=e.material?xe(await t.getMaterial(e.material)):function(){const e=B(new h("instanceColor")).rgb,t=B(new l("particleData")).x;return new c({color:v({color:e}).rgb.rgba(t),opacity:t,transparent:!0})}());Ae(d,e);const f=new i.Mesh(u,d);return Ee(f,e),f}(e.output,t,r,s,S));break;case"mesh":L=new a(await async function(e,t,a,r,s){if(null==e.assetId)return console.warn("Can't use mesh as particle without asset id"),new n;const l=await t.getMesh(e.assetId),o=await t.getAsset(e.assetId),c=ve(e);if("shaderGraph"===c||"shader"===c&&null!=e.shader||"material"===c&&null!=e.material){let n;"shaderGraph"===c?n=await createShaderGraphMaterial(e,"surface",a,r,s):"shader"===c&&null!=e.shader?n=await createShaderMaterial(e,t,s):"material"===c&&null!=e.material&&(n=xe(await t.getMaterial(e.material))),n?.transparent&&(n.depthWrite=!1),null!=n&&Ae(n,e),l.traverse(e=>{e instanceof i.Mesh&&null!=n&&(e.material=n)})}else{const e=[];if(null!=o.materialAssignments)for(const a of o.materialAssignments)null!=a.materialId&&l.traverse(r=>{r instanceof i.Mesh&&r.material instanceof i.Material&&r.material.color instanceof i.Color&&(r.material.name!=a.name&&null!=a.name||"#"+r.material.color.getHexString()!==a.color||e.push(t.getMaterial(a.materialId).then(e=>r.material=e)))});await Promise.all(e)}const p=[];if(l.traverse(e=>{e instanceof i.Mesh&&p.push(e)}),Ee(l,e),1===p.length){const t=p[0];return!0!==e.useLegacyTransform&&function(e){e.geometry=e.geometry.clone(),ye(e,e.geometry),e.position.set(0,0,0),e.quaternion.identity(),e.scale.set(1,1,1),e.updateMatrix(),e.matrixWorld.identity()}(t),t.removeFromParent(),t}return l}(e.output,t,r,s,S));break;case"trail":{const n="shaderGraph"===ve(e.output)?await createShaderGraphMaterial(e.output,"trail",r,s,S,{trailBillboard:e.output.billboard??!1}):null;L=new a({type:"trail",taper:e.output.taper,headGeometry:null,material:n instanceof i.ShaderMaterial?n:void 0,dragTexture:!1,texture:null!=e.output.texture?await t.getTexture(e.output.texture):null,opacityChannel:e.output.opacityChannel,color:e.output.color,colorEnd:e.output.colorEnd,intensity:e.output.intensity??1,intensityEnd:e.output.intensityEnd??1,length:e.output.length,opacityStart:e.output.opacityStart,opacityEnd:e.output.opacityEnd,bloom:e.output.bloom,scrollSpeed:e.output.scrollSpeed,width:e.output.width,billboard:e.output.billboard??!1,renderOrder:e.output.renderOrder});break}default:console.error("Failed to create particly system body: "+JSON.stringify(e))}const O=new Ie(D);O.parent=p,O.setRate(F),O._space=e.output.space;const q=await Promise.all(e.initializers.filter(e=>!1!==e.enabled).filter(e=>null!=re[e.type]).map(async e=>{const t=re[e.type],a=await W(e.params??{},r,s);return de(t,e.params??{},a,P)}));"world"===e.output.space&&q.push(new Y("shape"===e.output.type||"mesh"===e.output.type)),q.push(L,new K),O.addInitializers(q);const z=await Promise.all(e.behaviours.filter(e=>!1!==e.enabled).filter(e=>null!=ae[e.type]).map(async e=>{const t=ae[e.type];for(const[a,r]of Object.entries(e.params))t.parameters&&null!=t.parameters[a]&&"curve"===t.parameters[a].type&&r.type!==U.Curve&&(r.type=U.Curve);const a=await W(e.params??{},r,s);return ue(t,e.params??{},a,P)}).sort((e,t)=>e instanceof ie?1:0));z.push(new Se);for(const e of z)e instanceof ie&&(e.physics=x);O.addBehaviours(z);for(const a of e.children??[]){const e=await we(a,t,r,s,p,x,S,P,D),i=new EmitterPool(()=>{const t=e.clone();return t.onExpired=()=>{const e=O.childEmitters.findIndex(e=>e.id===t.id);-1!=e&&O.childEmitters.splice(e,1),null!=t.parentParticle&&(l.delete(t.parentParticle.id),t.parentParticle=null),i.release(t)},t}),n=O.eventDispatcher,l=new Map;O.bindEmitterEvent=!0,n.addEventListener("PARTICLE_DEAD",e=>{const t=l.get(e.id);null!=t&&(O.detachChildEmitterFromParticle(t,e),l.delete(e.id))});let o="PARTICLE_CREATED";if("spawnEvent"in a)switch(a.spawnEvent){case"collision":o="PARTICLE_COLLISION";break;case"start":o="PARTICLE_CREATED"}n.addEventListener(o,e=>{const t=i.get();t.age=0,t.totalEmitTimes=-1,t.particles.length=0,t.currentEmitTime=0,t.cID=0,t.eventDispatcher.removeAllEventListeners(),O.childEmitters.push(t),l.set(e.id,t),t.parentParticle=e,t.system=O.system,t.emit()})}return O}const be=(new i.TextureLoader).load("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJkSURBVHjaxJeJbusgEEW94S1L//83X18M2MSuLd2pbqc4wZGqRLrKBsyZhQHny7Jk73xVL8xpVhWrcmiB5lX+6GJ5YgQ2owbAm8oIwH1VgKZUmGcRqKGGPgtEQQAzGR8hQ59fAmhJHSAagigJ4E7GPWRXOYC6owAd1JM6wDQPADyMWUqZRMqmAojHp1Vn6EQQEgUNMJLnUjMyJsM49wygBkAPw9dVFwXRkncCIIW3GRgoTQUZn6HxCMAFEFd8TwEQ78X4rHbILoAUmeT+RFG4UhQ6MiIAE4W/UsYFjuVjAIa2nIY4q1R0GFtQWG3E84lqw2GO2QOoCKBVu0BAPgDSU0eUDjjQenNkV/AW/pWChhpMTelo1a64AOKM30vk18GzTHXCNtI/Knz3DFBgsUqBGIjTInXRY1yA9xkVoqW5tVq3pDR9A0hfF5BSARmVnh7RMDCaIdcNgbPBkgzn1Bu+SfIEFSpSBmkxyrMicb0fAEuCZrWnN89veA/4XcakrPcjBWzkTuLjlbfTQPOlBhz+HwkqqPXmPQDdrQItxE1moGof1S74j/8txk8EHhTQrAE8qlwfqS5yukm1x/rAJ9Jiaa6nyATqD78aUVBhFo8b1V4DdTXdCW+IxA1zB4JhiOhZMEWO1HqnvdoHZ4FAMIhV9REF8FiUm0jsYPEJx/Fm/N8OhH90HI9YRHesWbXXZwAShU8qThe7H8YAuJmw5yOd989uRINKRTJAhoF8jbqrHKfeCYdIISZfSq26bk/K+yO3YvfKrVgiwQBHnwt8ynPB25+M8hceTt/ybPhnryJ78+tLgAEAuCFyiQgQB30AAAAASUVORK5CYII=");export async function createShaderMaterial(e,t,a){const r=a.get(e.shader);if(null==r)return console.error("No shader exists with name "+e.shader),new i.Material;const s=new r.type;"sprite"===e.type&&s instanceof le&&(s.instanced=!0);const n=await L(e.shaderParams??{},r.type,t,{getTexture:e=>t.getTexture(e.id),getMaterial:e=>t.getMaterial(e.id),getMesh:e=>t.getMesh(e.id)},void 0,void 0,void 0,void 0,void 0,s);return Object.assign(s,n),s.build()}export async function createShaderGraphMaterial(e,t,a,r,s,i={}){const n=e.shaderGraph;if("asset"!==n?.source||null==n.assetId)return console.warn(`Missing shader graph asset reference for ${e.type} VFX output`),null;const l=await a.getAsset(n.assetId),o=l?.shaderGraph;if(null==o)return console.warn(`Missing shader graph asset "${n.assetId}" for ${e.type} VFX output`),null;if(o.target!==t)return console.warn(`Shader graph "${l.name}" targets "${o.target}" but ${e.type} VFX output expects "${t}"`),null;try{const t=await O(e.shaderGraphParams??{},o,a,r,void 0,s.shaders),l=he(o,{parameters:t,trailBillboard:i.trailBillboard});return l.userData.customShaderName=`shaderGraph:${n.assetId}`,Ae(l,e),l}catch(e){return console.log("Shader graph VFX runtime error: "+e,e),null}}export function createGpuSpriteShaderGraphResolver(e,t,a,r){return async s=>{const n=ve(s);let l=null;if("shaderGraph"===n)l=await createShaderGraphMaterial(s,"sprite"===s.type?"sprite":"decal"===s.type?"decal":"trail"===s.type?"trail":"surface",e,t,a,"trail"===s.type?{trailBillboard:s.billboard??!1}:void 0);else if("shader"===n&&"decal"!==s.type&&null!=r)l=await createShaderMaterial(s,r,a);else if("material"!==n||"mesh"!==s.type&&"shape"!==s.type||null==s.material||null==r){if("default"===n&&"mesh"===s.type&&null!=s.assetId&&null!=r){const e=await r.getAsset(s.assetId),t=e.materialAssignments?.find(e=>null!=e.materialId);null!=t&&(l=await Me(t.materialId,r))}else if("default"===n&&"decal"===s.type&&null!=r){const e=!1!==s.unlit?new ce:new pe;e.color=new i.Color(s.color),e instanceof ce?e.intensity=s.intensity??1:e.emissiveIntensity=s.intensity??1,s.colorMap&&(e.colorMap=await r.getTexture(s.colorMap)),s.alphaMap&&(e.alphaMap=await r.getTexture(s.alphaMap)),l=e.build(),l.transparent=!0}}else l="mesh"===s.type?await Me(s.material,r):xe(await r.getMaterial(s.material));return null==l?null:("mesh"!==s.type&&"shape"!==s.type||!l.transparent||(l.depthWrite=!1),l instanceof c?l:(console.warn(`GPU ${s.type} materials must compile to NodeShaderMaterial; using CPU fallback`),null))}}function ve(e){return null!=e.materialSource?("material"!==e.materialSource||"mesh"!==e.type&&"shape"!==e.type||null!=e.material)&&("shaderGraph"!==e.materialSource||"asset"===e.shaderGraph?.source&&null!=e.shaderGraph.assetId)&&("shader"!==e.materialSource||"shader"in e&&null!=e.shader)?e.materialSource:"default":"asset"===e.shaderGraph?.source?"shaderGraph":"shader"in e&&null!=e.shader?"shader":"mesh"!==e.type&&"shape"!==e.type||null==e.material?"default":"material"}async function Me(e,t){const a=(await t.getAsset(e)).material,r=a?.shaderParams??{},s=a?.params??{},n=r.color?.value??s.color??"#ffffff",l=r.opacity?.value??s.opacity??1,o=r.intensity?.value??s.intensity??1,p=r.map?.value??s.map,u=r.alphaMap?.value??s.alphaMap;let d=J.color.rgb.multiply(S(new i.Color(n))).multiplyScalar(b(o)),h=J.opacity.multiply(b(l));if(null!=p){const e=C(await t.getTexture(p)).sample(G.uv);d=d.multiply(e.rgb),h=h.multiply(e.a)}null!=u&&(h=h.multiply(C(await t.getTexture(u)).sample(G.uv).r));const m=new c({color:d.rgba(h),opacity:h,transparent:!0===a?.transparent||l<1||null!=u});return m.blending=te[a?.blending]??i.NormalBlending,m.alphaTest=a?.alphaTest??0,m.side=a?.side??i.FrontSide,m.transparent&&(m.depthWrite=!1),m}function Ae(e,t){null!=e&&(fe(e,!1),"bloom"in t&&!0===t.bloom&&(e.userData.hasBloom=!0),"sprite"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,!0===t.lockY&&e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.LOCK_Y_AXIS="")):"decal"===t.type?(e.blending=te[t.blendingMode]??i.NormalBlending,e.transparent=!0,e.side=i.BackSide,e.depthTest=!1,e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE="")):"shape"!==t.type&&"mesh"!==t.type||e instanceof i.ShaderMaterial&&(e.defines??(e.defines={}),e.defines.IS_PARTICLE=""))}function Ee(e,t){const a=t.renderOrder;null!=a&&e.traverse(e=>e.renderOrder=a)}function xe(e){const t=B(new h("instanceColor")).rgb;let a,r=B(new l("particleData")).x;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial){let s=t.multiply(S(e.color));null!=e.map&&(s=s.multiply(C(e.map).sample(G.uv).rgb)),null!=e.alphaMap&&(r=r.multiply(C(e.alphaMap).sample(G.uv).r)),e instanceof i.MeshStandardMaterial?a=new c({color:P({color:s,emissive:S(e.emissive),emissiveIntensity:b(e.emissiveIntensity),roughness:e.roughness,metalness:e.metalness}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshLambertMaterial?a=new c({color:v({color:s}).rgb.rgba(r),emissive:S(e.emissive).multiplyScalar(e.emissiveIntensity),transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}):e instanceof i.MeshBasicMaterial&&(a=new c({color:s.rgb.rgba(r),emissive:s.rgb,transparent:e.transparent,opacity:r,alphaTest:e.alphaTest}))}else e instanceof c&&(a=e.clone(),a.defines.IS_PARTICLE="");return null!=a&&(!0===e.userData?.hasBloom&&null!=a&&(a.userData.hasBloom=!0),a.side=e.side,a.transparent=e.transparent),a??e}class Se extends t{initialize(e){e.body instanceof i.Object3D&&e.body.traverse(e=>{if(e instanceof i.Mesh){const t=e.material;t instanceof c&&(null!=t.uniforms[q]||null!=t.uniforms[z]||t.uniforms[X])}})}mutate(e,t,a){this.energize(e,t),e.target instanceof n&&e.target.traverse(t=>{if(t instanceof i.Mesh){const a=t.material;if(a instanceof c){let t=!1;null!=a.uniforms[q]&&(a.uniforms[q].value=this.energy,t=!0),null!=a.uniforms[z]&&(a.uniforms[z].value=e.age,t=!0),null!=a.uniforms[X]&&(a.uniforms[X].value=e.velocity,t=!0),t&&me(a)}}})}}class Ie extends r{constructor(e){super(),this.transformRoot=e,this.childEmitters=[],this.bindEmitterEvent=!1,this.onExpired=()=>{}}clearParticlesRecursive(){let e=this.childEmitters.length;for(;e--;){const t=this.childEmitters[e];t.stopEmit(),t.clearParticlesRecursive(),t.onExpired()}this.childEmitters.length=0;let t=this.particles.length;for(;t--;){const e=this.particles[t];this.system?.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),null!=this.system?this.system.pool.expire(e.reset()):e.reset()}this.particles.length=0}detachChildEmitterFromParticle(e,t){this.copyPositionToChildSpace(e,t.position),e.parentParticle=null,e.stopEmit()}update(e){if(!this.isEmitting&&0===this.particles.length&&0===this.childEmitters.length)return;this.age+=e,(this.dead||this.age>=this.life)&&this.destroy(),this.isEmitting&&this.generate(e),this.integrate(e);let t=this.particles.length;for(;t--;){const e=this.particles[t];e.dead&&(this.system&&this.system.dispatch("PARTICLE_DEAD",e),this.bindEmitterEvent&&this.dispatch("PARTICLE_DEAD",e),this.system.pool.expire(e.reset()),this.particles.splice(t,1))}this.updateEmitterBehaviours(e),this.updateChildren(e),this.isEmitting||0!==this.particles.length||0!==this.childEmitters.length||this.onExpired()}updateChildren(e){for(const t of this.childEmitters)null!=t.parentParticle&&this.copyPositionToChildSpace(t,t.parentParticle.position),t.update(e)}copyPositionToChildSpace(e,t){const a=this._space??"world",r=e._space??"world";a!==r&&null!=this.transformRoot?(Te.copy(t),"local"===a&&"world"===r?Te.applyMatrix4(this.transformRoot.matrixWorld):"world"===a&&"local"===r&&(Pe.copy(this.transformRoot.matrixWorld).invert(),Te.applyMatrix4(Pe)),e.position.copy(Te)):e.position.copy(t)}clone(){const e=new Ie(this.transformRoot);return e.setRate(this.rate.clone()),e.behaviours=this.behaviours,e.initializers=this.initializers,e._space=this._space,e.body=this.body,e.parent=this.parent,e.system=this.system,e}setParentRecursive(e){this.system=e,this.childEmitters.forEach(t=>t.setParentRecursive(e))}}const Te=new i.Vector3,Pe=new i.Matrix4;export class EmitterPool{constructor(e){this.creator=e,this.instances=[]}get(){0==this.instances.length&&this.instances.push(this.creator());return this.instances.pop()}release(e){this.instances.push(e)}dispose(){this.instances.length=0}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,25 @@
1
+ import * as THREE from 'three';
2
+ export type VfxMeshSamplingMode = 'surface' | 'vertices';
3
+ export type VfxMeshAlignmentAxis = '+X' | '-X' | '+Y' | '-Y' | '+Z' | '-Z';
4
+ /** CPU/GPU-ready representation of a static or skinned Object3D mesh hierarchy. */
5
+ export declare class VfxMeshSampler {
6
+ readonly positions: Float32Array;
7
+ readonly normals: Float32Array;
8
+ readonly triangles: Uint32Array;
9
+ readonly triangleAlias: Uint32Array;
10
+ readonly triangleProbability: Float32Array;
11
+ readonly skinIndices: Uint32Array;
12
+ readonly skinWeights: Float32Array;
13
+ readonly boneCount: number;
14
+ private readonly skinPalettes;
15
+ private readonly skinMatrices;
16
+ constructor(root: THREE.Object3D, includeRootTransform?: boolean);
17
+ get valid(): boolean;
18
+ get vertexCount(): number;
19
+ get triangleCount(): number;
20
+ get skinned(): boolean;
21
+ updateSkinMatrices(target?: Float32Array<ArrayBufferLike>, outerTransform?: THREE.Matrix4): Float32Array;
22
+ sample(mode: VfxMeshSamplingMode, position: THREE.Vector3, normal: THREE.Vector3): boolean;
23
+ private readVertex;
24
+ }
25
+ //# sourceMappingURL=vfx-mesh-sampler.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as t from"three";export class VfxMeshSampler{constructor(i,o=!0===i.userData.vfxIncludeRootTransform){const s=[],a=[],l=[],c=[],u=[],h=[];let f=0;i.updateMatrixWorld(!0);const d=(new t.Matrix4).copy(i.matrixWorld).invert(),p=new t.Matrix4,g=new t.Matrix3,m=new t.Vector3,x=new t.Vector3;e(i,t=>{const e=t.geometry;if(null==e||"function"!=typeof e.getAttribute)return;const i=e?.getAttribute("position");if(!n(i)||0===i.count)return;let y=e.getAttribute("normal");if(!n(y)||y.count!==i.count){const t=e.clone();t.computeVertexNormals(),y=t.getAttribute("normal")}const b=!0===t.isSkinnedMesh&&null!=e.getAttribute("skinIndex")&&null!=e.getAttribute("skinWeight");p.copy(t.matrixWorld),o||p.premultiply(d),g.getNormalMatrix(p);const M=t;let V=b?h.find(t=>t.mesh.skeleton===M.skeleton&&r(t.rootTransform,p)&&r(t.mesh.bindMatrix,M.bindMatrix)&&r(t.mesh.bindMatrixInverse,M.bindMatrixInverse)):void 0;b&&null==V&&(V={mesh:M,boneOffset:f,rootTransform:p.clone()},h.push(V),f+=V.mesh.skeleton.bones.length);const w=e.getAttribute("skinIndex"),k=e.getAttribute("skinWeight"),A=s.length/3;for(let t=0;t<i.count;t++){m.fromBufferAttribute(i,t),x.fromBufferAttribute(y,t),b||(m.applyMatrix4(p),x.applyNormalMatrix(g).normalize()),s.push(m.x,m.y,m.z),a.push(x.x,x.y,x.z);for(let e=0;e<4;e++)c.push(null==V?0:V.boneOffset+w.getComponent(t,e)),u.push(null==V?0:k.getComponent(t,e))}const v=e.getIndex();if(null!=v)for(let t=0;t+2<v.count;t+=3)l.push(A+v.getX(t),A+v.getX(t+1),A+v.getX(t+2));else for(let t=0;t+2<i.count;t+=3)l.push(A+t,A+t+1,A+t+2)}),this.positions=new Float32Array(s),this.normals=new Float32Array(a),this.triangles=new Uint32Array(l),this.skinIndices=new Uint32Array(c),this.skinWeights=new Float32Array(u),this.skinPalettes=h,this.boneCount=f,this.skinMatrices=new Float32Array(16*f);const{probability:b,alias:M}=function(e,n){const r=n.length/3,i=new Float32Array(r),o=new Uint32Array(r);if(0===r)return{probability:i,alias:o};const s=new Float64Array(r),a=new t.Vector3,l=new t.Vector3,c=new t.Vector3;let u=0;for(let t=0;t<r;t++)y(e,n[3*t],a),y(e,n[3*t+1],l).sub(a),y(e,n[3*t+2],c).sub(a),s[t]=.5*l.cross(c).length(),u+=s[t];if(!(u>0))return i.fill(1),{probability:i,alias:o};const h=[],f=[];for(let t=0;t<r;t++)s[t]=s[t]*r/u,(s[t]<1?h:f).push(t);for(;h.length&&f.length;){const t=h.pop(),e=f.pop();i[t]=s[t],o[t]=e,s[e]=s[e]+s[t]-1,(s[e]<1?h:f).push(e)}for(const t of[...h,...f])i[t]=1;return{probability:i,alias:o}}(this.positions,this.triangles);this.triangleProbability=b,this.triangleAlias=M}get valid(){return this.positions.length>=3}get vertexCount(){return this.positions.length/3}get triangleCount(){return this.triangles.length/3}get skinned(){return this.boneCount>0}updateSkinMatrices(t=this.skinMatrices,e){for(const n of this.skinPalettes){const r=n.mesh;r.updateWorldMatrix(!0,!0),r.skeleton.update();for(let i=0;i<r.skeleton.bones.length;i++)o.fromArray(r.skeleton.boneMatrices,16*i),s.copy(n.rootTransform),null!=e&&s.premultiply(e),s.multiply(r.bindMatrixInverse).multiply(o).multiply(r.bindMatrix),s.toArray(t,16*(n.boneOffset+i))}return t}sample(t,e,n){if(!this.valid)return!1;if(this.skinned&&this.updateSkinMatrices(),"vertices"===t||0===this.triangleCount){const t=Math.min(this.vertexCount-1,Math.floor(Math.random()*this.vertexCount));return this.readVertex(t,e,n),!0}const r=Math.min(this.triangleCount-1,Math.floor(Math.random()*this.triangleCount)),i=Math.random()<this.triangleProbability[r]?r:this.triangleAlias[r],o=this.triangles[3*i],s=this.triangles[3*i+1],a=this.triangles[3*i+2];let l=Math.random(),c=Math.random();l+c>1&&(l=1-l,c=1-c);const u=1-l-c;return this.readVertex(o,h,p),this.readVertex(s,f,g),this.readVertex(a,d,m),e.copy(h).multiplyScalar(u).addScaledVector(f,l).addScaledVector(d,c),n.copy(p).multiplyScalar(u).addScaledVector(g,l).addScaledVector(m,c).normalize(),!0}readVertex(t,e,n){y(this.positions,t,e),y(this.normals,t,n);const r=4*t,o=this.skinWeights[r]+this.skinWeights[r+1]+this.skinWeights[r+2]+this.skinWeights[r+3];if(o<=0)return void n.normalize();a.copy(e),l.copy(n),e.set(0,0,0),n.set(0,0,0);for(let t=0;t<4;t++){const o=this.skinWeights[r+t];o<=0||(s.fromArray(this.skinMatrices,16*this.skinIndices[r+t]),e.addScaledVector(c.copy(a).applyMatrix4(s),o),n.addScaledVector(i(l,s,u),o))}const h=Math.max(0,1-o);h>0&&(e.addScaledVector(a,h),n.addScaledVector(l,h)),n.normalize()}}function e(t,n){if(!1!==t.userData.vfxMeshSampling){n(t);for(const r of t.children)e(r,n)}}function n(t){const e=t;return null!=e&&Number.isFinite(e.count)&&"function"==typeof e.getX&&"function"==typeof e.getY&&"function"==typeof e.getZ}function r(t,e,n=1e-6){return t.elements.every((t,r)=>Math.abs(t-e.elements[r])<=n)}function i(t,e,n){const r=e.elements;return n.set(r[0]*t.x+r[4]*t.y+r[8]*t.z,r[1]*t.x+r[5]*t.y+r[9]*t.z,r[2]*t.x+r[6]*t.y+r[10]*t.z)}const o=new t.Matrix4,s=new t.Matrix4,a=new t.Vector3,l=new t.Vector3,c=new t.Vector3,u=new t.Vector3,h=new t.Vector3,f=new t.Vector3,d=new t.Vector3,p=new t.Vector3,g=new t.Vector3,m=new t.Vector3;function y(t,e,n){return e*=3,n.set(t[e],t[e+1],t[e+2])}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -8,6 +8,7 @@ import { PositionalAudioComponent } from '../positional-audio-actor.js';
8
8
  import { CameraComponent } from '../../camera/camera-component.js';
9
9
  import { FirstPersonCameraComponent } from '../../camera/first-person-camera-component.js';
10
10
  import { ThirdPersonCameraComponent } from '../../camera/third-person-camera-component.js';
11
+ import { SplineComponent } from './spline-component.js';
11
12
  export declare const builtInComponents: {
12
13
  MeshComponent: typeof MeshComponent;
13
14
  TweenComponent: typeof TweenComponent;
@@ -19,6 +20,7 @@ export declare const builtInComponents: {
19
20
  CameraComponent: typeof CameraComponent;
20
21
  FirstPersonCameraComponent: typeof FirstPersonCameraComponent;
21
22
  ThirdPersonCameraComponent: typeof ThirdPersonCameraComponent;
23
+ SplineComponent: typeof SplineComponent;
22
24
  };
23
25
  export default builtInComponents;
24
26
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
- import{MeshComponent as o}from"./mesh-component.js";import{OldCharacterMovementComponent as r}from"./character/old-character-movement.js";import{CharacterMovementComponent as e}from"./character/character-movement.js";import{CharacterAnimationComponent as m}from"./character/character-animation.js";import{TweenComponent as t}from"./tween-component.js";import{TriggerVolumeComponent as n}from"../trigger-volume.js";import{PositionalAudioComponent as a}from"../positional-audio-actor.js";import{CameraComponent as p}from"../../camera/camera-component.js";import{FirstPersonCameraComponent as c}from"../../camera/first-person-camera-component.js";import{ThirdPersonCameraComponent as i}from"../../camera/third-person-camera-component.js";export const builtInComponents={MeshComponent:o,TweenComponent:t,OldCharacterMovementComponent:r,CharacterMovementComponent:e,CharacterAnimationComponent:m,TriggerVolumeComponent:n,PositionalAudioComponent:a,CameraComponent:p,FirstPersonCameraComponent:c,ThirdPersonCameraComponent:i};export default builtInComponents;/*
1
+ import{MeshComponent as o}from"./mesh-component.js";import{OldCharacterMovementComponent as e}from"./character/old-character-movement.js";import{CharacterMovementComponent as r}from"./character/character-movement.js";import{CharacterAnimationComponent as m}from"./character/character-animation.js";import{TweenComponent as n}from"./tween-component.js";import{TriggerVolumeComponent as t}from"../trigger-volume.js";import{PositionalAudioComponent as a}from"../positional-audio-actor.js";import{CameraComponent as p}from"../../camera/camera-component.js";import{FirstPersonCameraComponent as i}from"../../camera/first-person-camera-component.js";import{ThirdPersonCameraComponent as c}from"../../camera/third-person-camera-component.js";import{SplineComponent as s}from"./spline-component.js";export const builtInComponents={MeshComponent:o,TweenComponent:n,OldCharacterMovementComponent:e,CharacterMovementComponent:r,CharacterAnimationComponent:m,TriggerVolumeComponent:t,PositionalAudioComponent:a,CameraComponent:p,FirstPersonCameraComponent:i,ThirdPersonCameraComponent:c,SplineComponent:s};export default builtInComponents;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,65 @@
1
+ import { Subject } from 'rxjs';
2
+ import { Vector3 } from 'three';
3
+ import { ActorComponent } from '../../component.js';
4
+ export interface SplinePoint {
5
+ /** Actor-local point position. */
6
+ position: Vector3;
7
+ /** Actor-local offset from position to the incoming Bezier handle. */
8
+ inTangent: Vector3;
9
+ /** Actor-local offset from position to the outgoing Bezier handle. */
10
+ outTangent: Vector3;
11
+ }
12
+ export interface ClosestSplinePoint {
13
+ position: Vector3;
14
+ tangent: Vector3;
15
+ t: number;
16
+ distance: number;
17
+ distanceAlongSpline: number;
18
+ }
19
+ /** A generic cubic Bezier spline whose points and tangents are actor-local. */
20
+ export declare class SplineComponent extends ActorComponent {
21
+ /** Compact JSON is intentional: scene files keep the complete spline on one line. */
22
+ splineData: string;
23
+ /** Emits after an in-place authoring/runtime edit. Consumers can update incrementally. */
24
+ readonly changed: Subject<SplineComponent>;
25
+ private _points;
26
+ private _closed;
27
+ private arcLengths;
28
+ private arcTs;
29
+ private _length;
30
+ onInit(): void;
31
+ onEndPlay(): void;
32
+ get points(): readonly SplinePoint[];
33
+ get closed(): boolean;
34
+ get length(): number;
35
+ setData(data: string, emit?: boolean): void;
36
+ setPoints(points: readonly SplinePoint[], closed?: boolean): void;
37
+ updatePoint(index: number, point: SplinePoint): void;
38
+ addPoint(point: SplinePoint, index?: number): void;
39
+ /** Splits a Bezier segment without changing the shape of the spline. */
40
+ insertPointOnSegment(segmentIndex: number, t?: number): number;
41
+ removePoint(index: number): void;
42
+ setClosed(closed: boolean): void;
43
+ applySceneParameters(parameters: {
44
+ splineData?: string;
45
+ }, changed: Set<'splineData'>): boolean;
46
+ /** Samples an actor-local position using normalized t. */
47
+ samplePosition(t: number, target?: Vector3): Vector3;
48
+ sampleTangent(t: number, target?: Vector3): Vector3;
49
+ samplePositionAtDistance(distance: number, target?: Vector3): Vector3;
50
+ sampleTangentAtDistance(distance: number, target?: Vector3): Vector3;
51
+ /** Finds the closest actor-local point to an actor-local query position. */
52
+ closestPoint(point: Vector3, target?: Vector3): ClosestSplinePoint;
53
+ private commitChange;
54
+ private get segmentCount();
55
+ private resolveSegment;
56
+ private rebuildArcLengths;
57
+ private tAtDistance;
58
+ private distanceAtT;
59
+ }
60
+ export declare function packSplineData(points: readonly SplinePoint[], closed: boolean): string;
61
+ export declare function parseSplineData(data: string): {
62
+ points: SplinePoint[];
63
+ closed: boolean;
64
+ };
65
+ //# sourceMappingURL=spline-component.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as t,__metadata as n}from"tslib";import{Subject as s}from"rxjs";import{Vector3 as i}from"three";import{Parameter as e}from"../../../../shader/parameter.js";import{ActorComponent as o,Component as a}from"../../component.js";const h='{"closed":false,"points":[[0,0,0,0,0,0,2,0,0],[5,0,0,-2,0,0,0,0,0]]}';let r=class extends o{constructor(){super(...arguments),this.splineData=h,this.changed=new s,this._points=[],this._closed=!1,this.arcLengths=new Float32Array(0),this.arcTs=new Float32Array(0),this._length=0}onInit(){this.setData(this.splineData,!1)}onEndPlay(){this.changed.complete()}get points(){return this._points}get closed(){return this._closed}get length(){return this._length}setData(t,n=!0){const s=parseSplineData(t);this._closed=s.closed,this._points=s.points,this.splineData=packSplineData(this._points,this._closed),this.rebuildArcLengths(),n&&this.changed.next(this)}setPoints(t,n=this._closed){this._points=t.map(p),this._closed=n,this.commitChange()}updatePoint(t,n){t<0||t>=this._points.length||(this._points[t]=p(n),this.commitChange())}addPoint(t,n=this._points.length){this._points.splice(Math.max(0,Math.min(n,this._points.length)),0,p(t)),this.commitChange()}insertPointOnSegment(t,n=.5){const s=this.segmentCount;if(t<0||t>=s)return-1;const i=(t+1)%this._points.length,e=this._points[t],o=this._points[i],a=e.position,h=e.position.clone().add(e.outTangent),r=o.position.clone().add(o.inTangent),p=o.position,l=a.clone().lerp(h,n),c=h.clone().lerp(r,n),g=r.clone().lerp(p,n),m=l.clone().lerp(c,n),u=c.clone().lerp(g,n),T=m.clone().lerp(u,n);e.outTangent.copy(l).sub(a),o.inTangent.copy(g).sub(p);const d=t+1;return this._points.splice(d,0,{position:T,inTangent:m.sub(T),outTangent:u.sub(T)}),this.commitChange(),d}removePoint(t){t<0||t>=this._points.length||(this._points.splice(t,1),this.commitChange())}setClosed(t){t!==this._closed&&(this._closed=t,this.commitChange())}applySceneParameters(t,n){return!(1!==n.size||!n.has("splineData")||"string"!=typeof t.splineData)&&(this.setData(t.splineData),!0)}samplePosition(t,n=new i){const s=this.resolveSegment(t);return s?function(t,n,s,i){const e=1-s,o=e*e*e,a=3*e*e*s,h=3*e*s*s,r=s*s*s;return i.set(t.position.x*o+(t.position.x+t.outTangent.x)*a+(n.position.x+n.inTangent.x)*h+n.position.x*r,t.position.y*o+(t.position.y+t.outTangent.y)*a+(n.position.y+n.inTangent.y)*h+n.position.y*r,t.position.z*o+(t.position.z+t.outTangent.z)*a+(n.position.z+n.inTangent.z)*h+n.position.z*r)}(s.a,s.b,s.u,n):n.set(0,0,0)}sampleTangent(t,n=new i){const s=this.resolveSegment(t);return s?function(t,n,s,i){const e=1-s;return i.set(3*e*e*t.outTangent.x+6*e*s*(n.position.x+n.inTangent.x-t.position.x-t.outTangent.x)-3*s*s*n.inTangent.x,3*e*e*t.outTangent.y+6*e*s*(n.position.y+n.inTangent.y-t.position.y-t.outTangent.y)-3*s*s*n.inTangent.y,3*e*e*t.outTangent.z+6*e*s*(n.position.z+n.inTangent.z-t.position.z-t.outTangent.z)-3*s*s*n.inTangent.z)}(s.a,s.b,s.u,n).normalize():n.set(0,0,0)}samplePositionAtDistance(t,n=new i){return this.samplePosition(this.tAtDistance(t),n)}sampleTangentAtDistance(t,n=new i){return this.sampleTangent(this.tAtDistance(t),n)}closestPoint(t,n=new i){if(0===this.arcTs.length)return{position:n.set(0,0,0),tangent:new i,t:0,distance:t.length(),distanceAlongSpline:0};let s=0,e=1/0;const o=new i;for(let n=0;n<this.arcTs.length;n++){this.samplePosition(this.arcTs[n],o);const i=o.distanceToSquared(t);i<e&&(e=i,s=this.arcTs[n])}const a=this.arcTs.length>1?1/(this.arcTs.length-1):1;let h=Math.max(0,s-a),r=Math.min(1,s+a);for(let n=0;n<8;n++){const n=h+(r-h)/3,s=r-(r-h)/3;this.samplePosition(n,o);const i=o.distanceToSquared(t);this.samplePosition(s,o),i<o.distanceToSquared(t)?r=s:h=n}return s=.5*(h+r),this.samplePosition(s,n),{position:n,tangent:this.sampleTangent(s),t:s,distance:n.distanceTo(t),distanceAlongSpline:this.distanceAtT(s)}}commitChange(){this.splineData=packSplineData(this._points,this._closed),this.rebuildArcLengths(),this.changed.next(this)}get segmentCount(){return this._points.length<2?0:this._closed?this._points.length:this._points.length-1}resolveSegment(t){const n=this.segmentCount;if(0===n)return this._points[0]?{a:this._points[0],b:this._points[0],u:0}:null;const s=Math.max(0,Math.min(1,t))*n,i=Math.min(Math.floor(s),n-1);return{a:this._points[i],b:this._points[(i+1)%this._points.length],u:s-i}}rebuildArcLengths(){const t=24*this.segmentCount;if(0===t)return this.arcTs=this._points.length?new Float32Array([0]):new Float32Array(0),this.arcLengths=this._points.length?new Float32Array([0]):new Float32Array(0),void(this._length=0);this.arcTs=new Float32Array(t+1),this.arcLengths=new Float32Array(t+1);const n=this.samplePosition(0,new i),s=new i;let e=0;for(let i=1;i<=t;i++){const o=i/t;this.samplePosition(o,s),e+=n.distanceTo(s),this.arcTs[i]=o,this.arcLengths[i]=e,n.copy(s)}this._length=e}tAtDistance(t){if(0===this._length)return 0;const n=Math.max(0,Math.min(this._length,t));let s=0,i=this.arcLengths.length-1;for(;s<i;){const t=s+i>>>1;this.arcLengths[t]<n?s=t+1:i=t}const e=s,o=Math.max(0,e-1),a=this.arcLengths[e]-this.arcLengths[o],h=a>0?(n-this.arcLengths[o])/a:0;return this.arcTs[o]+(this.arcTs[e]-this.arcTs[o])*h}distanceAtT(t){if(this.arcTs.length<2)return 0;const n=Math.max(0,Math.min(1,t))*(this.arcTs.length-1),s=Math.floor(n),i=Math.min(s+1,this.arcLengths.length-1);return this.arcLengths[s]+(this.arcLengths[i]-this.arcLengths[s])*(n-s)}};t([e({label:"Spline Data"}),n("design:type",Object)],r.prototype,"splineData",void 0),r=t([a({inEditor:!0,typeId:"SplineComponent"})],r);export{r as SplineComponent};export function packSplineData(t,n){return JSON.stringify({closed:n,points:t.map(t=>[...t.position.toArray(),...t.inTangent.toArray(),...t.outTangent.toArray()])})}export function parseSplineData(t){let n;try{n=JSON.parse(t)}catch{n=JSON.parse(h)}return{closed:!0===n.closed,points:(n.points??[]).filter(t=>t.length>=9).map(t=>({position:(new i).fromArray(t,0),inTangent:(new i).fromArray(t,3),outTangent:(new i).fromArray(t,6)}))}}function p(t){return{position:t.position.clone(),inTangent:t.inTangent.clone(),outTangent:t.outTangent.clone()}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -7,6 +7,9 @@ import { TriggerVolume } from './trigger-volume.js';
7
7
  import { FogVolume } from '../../../rendering/fog/fog-volume-actor.js';
8
8
  import { SequenceActor } from '../../../effects/sequence/sequence-actor.js';
9
9
  import { LightProbeVolume } from '../../../rendering/light-probes/light-probe-volume-actor.js';
10
+ import { WaterVolume } from './water-volume-actor.js';
11
+ import { SplineActor } from './spline-actor.js';
12
+ import { WaterSplineVolume } from './water-spline-volume-actor.js';
10
13
  export declare const builtInActors: {
11
14
  Camera: typeof CameraActor;
12
15
  SpawnPoint: typeof SpawnPoint;
@@ -17,6 +20,9 @@ export declare const builtInActors: {
17
20
  FogVolume: typeof FogVolume;
18
21
  Sequence: typeof SequenceActor;
19
22
  LightProbeVolume: typeof LightProbeVolume;
23
+ WaterVolume: typeof WaterVolume;
24
+ Spline: typeof SplineActor;
25
+ WaterSplineVolume: typeof WaterSplineVolume;
20
26
  };
21
27
  export default builtInActors;
22
28
  export declare const experimentalActors: string[];
@@ -1,4 +1,4 @@
1
- import{PostProcessVolume as o}from"./post-process-volume-actor.js";import{CameraActor as r}from"./camera-actor.js";import e from"./navmesh-actor.js";import{PositionalAudioActor as t}from"./positional-audio-actor.js";import{SpawnPoint as m}from"./spawn-point.js";import{TriggerVolume as s}from"./trigger-volume.js";import{FogVolume as i}from"../../../rendering/fog/fog-volume-actor.js";import{SequenceActor as p}from"../../../effects/sequence/sequence-actor.js";import{LightProbeVolume as a}from"../../../rendering/light-probes/light-probe-volume-actor.js";export const builtInActors={Camera:r,SpawnPoint:m,TriggerVolume:s,PositionalAudio:t,NavMesh:e,PostProcessVolume:o,FogVolume:i,Sequence:p,LightProbeVolume:a};export default builtInActors;export const experimentalActors=["LightProbeVolume"];/*
1
+ import{PostProcessVolume as o}from"./post-process-volume-actor.js";import{CameraActor as r}from"./camera-actor.js";import e from"./navmesh-actor.js";import{PositionalAudioActor as t}from"./positional-audio-actor.js";import{SpawnPoint as m}from"./spawn-point.js";import{TriggerVolume as i}from"./trigger-volume.js";import{FogVolume as s}from"../../../rendering/fog/fog-volume-actor.js";import{SequenceActor as p}from"../../../effects/sequence/sequence-actor.js";import{LightProbeVolume as a}from"../../../rendering/light-probes/light-probe-volume-actor.js";import{WaterVolume as l}from"./water-volume-actor.js";import{SplineActor as n}from"./spline-actor.js";import{WaterSplineVolume as c}from"./water-spline-volume-actor.js";export const builtInActors={Camera:r,SpawnPoint:m,TriggerVolume:i,PositionalAudio:t,NavMesh:e,PostProcessVolume:o,FogVolume:s,Sequence:p,LightProbeVolume:a,WaterVolume:l,Spline:n,WaterSplineVolume:c};export default builtInActors;export const experimentalActors=["LightProbeVolume"];/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Ball as n,Capsule as s,Cone as o,ConvexPolyhedron as i,Cuboid as r,Cylinder as a,Heightfield as l,ShapeType as c,TriMesh as h}from"@dimforge/rapier3d-simd-compat";import{init as p}from"@recast-navigation/core";import{DebugDrawer as u,getPositionsAndIndices as d}from"@recast-navigation/three";import{BehaviorSubject as m,Subject as f,debounceTime as b,filter as w,firstValueFrom as g,takeUntil as y}from"rxjs";import*as x from"three";import{BufferGeometryUtils as v,ConvexHull as M}from"three/examples/jsm/Addons.js";import{Actor as B,BaseActor as S,Parameter as j,PhysicsSystem as z,ViewController as A,World as k,attach as C,inject as D}from"../../index.js";import{sleepDelay as P}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as F,toSharedFloat32Array as I,toSharedUint32Array as V}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as G,MAX_NAV_MESH_WORKERS as N}from"../../ai/dynamic-tiled-navmesh.js";import{TriggerVolumeMesh as H}from"./components/volume-editor-component.js";var E;!function(e){e[e.none=0]="none",e[e.starting=1]="starting",e[e.started=2]="started"}(E||(E={}));let T=E.none,R=new m(!1);export async function safeRecastInit(){return T===E.none?(T=E.starting,p().then(()=>{R.next(!0),T=E.started})):g(R.pipe(w(e=>e)))}new x.Box3(new x.Vector3(-100,-100,-100),new x.Vector3(100,100,100));const U=Math.max(1,Math.min(N,(navigator.hardwareConcurrency??2)-1));let q=!1,O=class extends S{constructor(){super(...arguments),this.physics=D(z),this.view=D(A),this.world=D(k),this.editorVisualisation=C(H),this.debug=!0,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new x.Box3}async onInit(){q||(await safeRecastInit(),q=!0),setTimeout(()=>{this.init()},10),this.recreateInterval=setInterval(()=>{if("_hology_transform_group"===this.object.parent?.name)return;J.setFromCenterAndSize(this.position,this.object.scale).equals(this.bounds)||(this.disposed.next(!0),this.disposed=new f,this.init())},2e3)}onEndPlay(){clearInterval(this.recreateInterval)}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,!0)}init(){this.bounds.setFromCenterAndSize(this.position,this.object.scale);const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,n=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(n/2))),o=Math.max(this.cellSize,.01),i={tileSize:Math.max(32,Math.floor(s/o)),walkableClimb:this.walkableClimb/o,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/o,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:o,ch:o,maxSimplificationError:1.3,maxEdgeLen:200},r=new G({navMeshBounds:this.bounds,recastConfig:i,maxTiles:1024,workers:U,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const a=this.tileSize*i.cs*2,l=performance.now(),c=new Map,h=new u;h.userData.isDebugDrawer=!0,this.debugDrawer=h;r.navMesh;const p=this.bounds,m=()=>{const e=this.view.getCamera().getWorldPosition(new x.Vector3),t=new x.Box3((new x.Vector3).copy(e).subScalar(a),(new x.Vector3).copy(e).addScalar(a)),n=[],s=this.physics.world.bodies;if(null==s)return[];const o=new x.Box3;for(const e of s.getAll())for(let s=0,i=e.numColliders();s<i;s++){const i=e.collider(s);if(i.isSensor()||null!=i.parent().userData&&!0===i.parent().userData.ignoreForNavMesh)continue;const r=e.handle+","+s,a=c.get(r)?.mesh,l=a??X(i);if($(i,l),null!=l){o.copy(l.geometry.boundingBox),o.min.add(l.position),o.max.add(l.position);const e=o.intersectsBox(t)||!0,s=o.intersectsBox(this.bounds);c.set(r,{pos:i.translation(),mesh:l}),e&&s&&n.push(l)}}return n},f=new x.Box3,w=new Map,g=new Map;let v=!0,M=performance.now(),B=!1;const S=function(e,t){let n=!1;return(async()=>{for(;!n;)await e(),await P(t)})(),()=>{n=!0}}(async()=>{if(B)return;const e=new x.Box3,t=m();for(const n of t){const t=w.get(n);!0!==t?.equals(n.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(n),w.set(n,n.position.clone()))}e.min.subScalar(50),e.max.addScalar(50);const n=r.getTilesForBounds(e);n.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const s=n.slice(0,500);if(0!=s.length){const n=[];for(const s of t)f.setFromObject(s),f.intersectsBox(e)&&n.push(s);let[o,i]=d(n);i=function(e,t,n){const s=new x.Vector3,o=[];for(let i=0;i<t.length;i+=3){let r=!0;for(let o=0;o<3;o++){const a=3*t[i+o];if(s.fromArray(e,a),!n.containsPoint(s)){r=!1;break}}r&&o.push(t[i],t[i+1],t[i+2])}return new Uint32Array(o)}(o,i,p),F&&(o=I(o),i=V(i));const a=v;v=!1,await Promise.all(s.map(e=>(M=performance.now(),r.buildTile(o,i,e,a).then(()=>{const t=e[0]+","+e[1];g.set(t,(g.get(t)??0)+1),this.debug})))).then(()=>{this.debug,B=!1})}else B=!1},this.refreshMs??1e4);this.disposed.subscribe(()=>S()),r.onNavMeshUpdate.pipe(y(this.disposed),b(200)).subscribe(()=>{h.clear(),h.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),h.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(h),this.disposed.subscribe(()=>{r?.destroy(),h.removeFromParent(),h.dispose()});const j=performance.now()-l;j>1e3&&console.warn(`NavMesh update took ${j} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([j(),t("design:type",Boolean)],O.prototype,"debug",void 0),e([j(),t("design:type",Number)],O.prototype,"walkableClimb",void 0),e([j({range:[0,89]}),t("design:type",Number)],O.prototype,"walkableSlopeAngle",void 0),e([j(),t("design:type",Number)],O.prototype,"walkableHeight",void 0),e([j({range:[.01,10]}),t("design:type",Number)],O.prototype,"cellSize",void 0),O=e([B()],O);export default O;const W=new Map,_=new WeakMap;function L(e){if(e.shape instanceof l)return function(e){const t=e.shape;if(t.type!==c.HeightField)throw new Error("The provided collider is not a height field.");let n=!1;const s=t,o=s.heights,i=s.nrows,r=s.ncols,a=s.scale.x,l=s.scale.z,h=s.scale.y,p=i+1,u=new x.PlaneGeometry(l,a,r,i);u.rotateX(-Math.PI/2);const d=u.attributes.position.array;let m=0;for(let e=0;e<p;e++)for(let t=0;t<p;t++)d[m+1]=o[t*p+e]*h,m+=3,0!=d[m+1]&&(n=!0);if(!n){const e=new x.PlaneGeometry(a,l,2,2);return e.rotateX(-Math.PI/2),e}return u}(e);if(e.shape instanceof n)return new x.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new x.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof i){const t=function(e){const t=_.get(e);if(void 0!==t)return t;const n=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<n.length;e++)s=Math.imul(s^n[e],16777619)>>>0;return _.set(e,s),s}(e.shape.vertices);let n=W.get(t);return n||(n=function(e){const t=[];for(let n=0;n<e.length;n+=3)t.push(new x.Vector3(e[n],e[n+1],e[n+2]));const n=(new M).setFromPoints(t),s=[];n.faces.forEach(e=>{const t=e.edge.head().point,n=e.edge.next.head().point,o=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(n.x,n.y,n.z),s.push(o.x,o.y,o.z)});const o=new x.BufferGeometry;return o.setAttribute("position",new x.Float32BufferAttribute(s,3)),o}(e.shape.vertices),W.set(t,n)),n}if(e.shape instanceof h){const t=e.shape.vertices,n=e.shape.indices;let s=new x.BufferGeometry;return s.setAttribute("position",new x.Float32BufferAttribute(t,3)),null!=n?s.setIndex(new x.Uint16BufferAttribute(n,1)):s=v.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof a){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CylinderGeometry(n,n,2*t)}if(e.shape instanceof o){const t=e.shape.halfHeight,n=e.shape.radius;return new x.ConeGeometry(n,2*t)}if(e.shape instanceof s){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CapsuleGeometry(n,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function X(e){const t=L(e);if(null==t)return null;const n=K,s=new x.Mesh(t,n);return s.geometry.computeBoundingBox(),s.geometry.scale(1.01,1.01,1.01),s}function $(e,t){const n=e.translation(),s=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(s.x,s.y,s.z,s.w)}const J=new x.Box3,K=new x.MeshBasicMaterial({wireframe:!1,color:16711680,side:x.FrontSide});/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Ball as n,Capsule as s,Cone as o,ConvexPolyhedron as i,Cuboid as r,Cylinder as a,Heightfield as c,ShapeType as l,TriMesh as h}from"@dimforge/rapier3d-simd-compat";import{init as u}from"@recast-navigation/core";import{DebugDrawer as p,getPositionsAndIndices as d}from"@recast-navigation/three";import{BehaviorSubject as f,Subject as m,debounceTime as w,filter as g,firstValueFrom as b,takeUntil as y}from"rxjs";import*as x from"three";import{BufferGeometryUtils as M,ConvexHull as v}from"three/examples/jsm/Addons.js";import{Actor as B,BaseActor as S,Parameter as z,PhysicsSystem as j,ViewController as k,World as A,attach as C,inject as P}from"../../index.js";import{sleepDelay as V}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as D,toSharedFloat32Array as F,toSharedUint32Array as I}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as N,MAX_NAV_MESH_WORKERS as H}from"../../ai/dynamic-tiled-navmesh.js";import{isNavigationAreaContributor as G}from"../../ai/navigation-areas.js";import{TriggerVolumeMesh as E}from"./components/volume-editor-component.js";var R;!function(e){e[e.none=0]="none",e[e.starting=1]="starting",e[e.started=2]="started"}(R||(R={}));let T=R.none,U=new f(!1);export async function safeRecastInit(){return T===R.none?(T=R.starting,u().then(()=>{U.next(!0),T=R.started})):b(U.pipe(g(e=>e)))}new x.Box3(new x.Vector3(-100,-100,-100),new x.Vector3(100,100,100));const O=Math.max(1,Math.min(H,(navigator.hardwareConcurrency??2)-1));let q=!1,W=class extends S{constructor(){super(...arguments),this.physics=P(j),this.view=P(k),this.world=P(A),this.editorVisualisation=C(E),this.debug=!0,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new x.Box3}async onInit(){q||(await safeRecastInit(),q=!0),setTimeout(()=>{this.init()},10),this.recreateInterval=setInterval(()=>{if("_hology_transform_group"===this.object.parent?.name)return;K.setFromCenterAndSize(this.position,this.object.scale).equals(this.bounds)||(this.disposed.next(!0),this.disposed=new m,this.init())},2e3)}onEndPlay(){clearInterval(this.recreateInterval)}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,!0)}init(){this.bounds.setFromCenterAndSize(this.position,this.object.scale);const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,n=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(n/2))),o=Math.max(this.cellSize,.01),i={tileSize:Math.max(32,Math.floor(s/o)),walkableClimb:this.walkableClimb/o,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/o,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:o,ch:o,maxSimplificationError:1.3,maxEdgeLen:200},r=new N({navMeshBounds:this.bounds,recastConfig:i,maxTiles:1024,workers:O,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const a=this.tileSize*i.cs*2,c=performance.now(),l=new Map,h=new p;h.userData.isDebugDrawer=!0,this.debugDrawer=h;r.navMesh;const u=this.bounds,f=()=>{const e=this.view.getCamera().getWorldPosition(new x.Vector3),t=new x.Box3((new x.Vector3).copy(e).subScalar(a),(new x.Vector3).copy(e).addScalar(a)),n=[],s=this.physics.world.bodies;if(null==s)return[];const o=new x.Box3;for(const e of s.getAll())for(let s=0,i=e.numColliders();s<i;s++){const i=e.collider(s);if(i.isSensor()||null!=i.parent().userData&&!0===i.parent().userData.ignoreForNavMesh)continue;const r=e.handle+","+s,a=l.get(r)?.mesh,c=a??J(i);if($(i,c),null!=c){o.copy(c.geometry.boundingBox),o.min.add(c.position),o.max.add(c.position);const e=o.intersectsBox(t)||!0,s=o.intersectsBox(this.bounds);l.set(r,{pos:i.translation(),mesh:c}),e&&s&&n.push(c)}}return n},m=new x.Box3,g=new Map,b=new Map,M=new Map,v=new Map;let B=!0,S=performance.now(),z=!1;const j=function(e,t){let n=!1;return(async()=>{for(;!n;)await e(),await V(t)})(),()=>{n=!0}}(async()=>{if(z)return;const e=new x.Box3,t=f();for(const n of t){const t=g.get(n);!0!==t?.equals(n.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(n),g.set(n,n.position.clone()))}const n=[],s=new Set;for(const t of this.world.actors){if(!G(t))continue;s.add(t);const o=t.getNavigationAreaModifiers();n.push(...o);const i=Q(o),r=JSON.stringify(o);if(M.get(t)!==r){const n=b.get(t);null!=n&&e.union(n),e.union(i),b.set(t,i),M.set(t,r)}}for(const t of[...b.keys()])s.has(t)||(e.union(b.get(t)),b.delete(t),M.delete(t));const o=e.isEmpty()?[]:r.getTilesForBounds(e.expandByScalar(50));o.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const i=o.slice(0,500);if(0!=i.length){const s=[];for(const n of t)m.setFromObject(n),m.intersectsBox(e)&&s.push(n);let[o,a]=d(s);a=function(e,t,n){const s=new x.Vector3,o=[];for(let i=0;i<t.length;i+=3){let r=!0;for(let o=0;o<3;o++){const a=3*t[i+o];if(s.fromArray(e,a),!n.containsPoint(s)){r=!1;break}}r&&o.push(t[i],t[i+1],t[i+2])}return new Uint32Array(o)}(o,a,u),D&&(o=F(o),a=I(a));const c=B;B=!1,await Promise.all(i.map(e=>{S=performance.now();const t=function(e,t,n){const s=(e.recastConfig.walkableRadius+3)*e.recastConfig.cs,o=new x.Vector3(e.navMeshBoundsMin.x+t[0]*e.tcs-s,e.navMeshBoundsMin.y,e.navMeshBoundsMin.z+t[1]*e.tcs-s),i=new x.Vector3(o.x+e.tcs+2*s,e.navMeshBoundsMax.y,o.z+e.tcs+2*s),r=new x.Box3(o,i);return n.filter(e=>Q([e]).intersectsBox(r))}(r,e,n);return r.buildTile(o,a,e,c,t).then(()=>{const t=e[0]+","+e[1];v.set(t,(v.get(t)??0)+1),this.debug})})).then(()=>{this.debug,z=!1})}else z=!1},this.refreshMs??1e4);this.disposed.subscribe(()=>j()),r.onNavMeshUpdate.pipe(y(this.disposed),w(200)).subscribe(()=>{h.clear(),h.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),h.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(h),this.disposed.subscribe(()=>{r?.destroy(),h.removeFromParent(),h.dispose()});const k=performance.now()-c;k>1e3&&console.warn(`NavMesh update took ${k} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([z(),t("design:type",Boolean)],W.prototype,"debug",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableClimb",void 0),e([z({range:[0,89]}),t("design:type",Number)],W.prototype,"walkableSlopeAngle",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableHeight",void 0),e([z({range:[.01,10]}),t("design:type",Number)],W.prototype,"cellSize",void 0),W=e([B()],W);export default W;const _=new Map,L=new WeakMap;function X(e){if(e.shape instanceof c)return function(e){const t=e.shape;if(t.type!==l.HeightField)throw new Error("The provided collider is not a height field.");let n=!1;const s=t,o=s.heights,i=s.nrows,r=s.ncols,a=s.scale.x,c=s.scale.z,h=s.scale.y,u=i+1,p=new x.PlaneGeometry(c,a,r,i);p.rotateX(-Math.PI/2);const d=p.attributes.position.array;let f=0;for(let e=0;e<u;e++)for(let t=0;t<u;t++)d[f+1]=o[t*u+e]*h,f+=3,0!=d[f+1]&&(n=!0);if(!n){const e=new x.PlaneGeometry(a,c,2,2);return e.rotateX(-Math.PI/2),e}return p}(e);if(e.shape instanceof n)return new x.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new x.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof i){const t=function(e){const t=L.get(e);if(void 0!==t)return t;const n=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<n.length;e++)s=Math.imul(s^n[e],16777619)>>>0;return L.set(e,s),s}(e.shape.vertices);let n=_.get(t);return n||(n=function(e){const t=[];for(let n=0;n<e.length;n+=3)t.push(new x.Vector3(e[n],e[n+1],e[n+2]));const n=(new v).setFromPoints(t),s=[];n.faces.forEach(e=>{const t=e.edge.head().point,n=e.edge.next.head().point,o=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(n.x,n.y,n.z),s.push(o.x,o.y,o.z)});const o=new x.BufferGeometry;return o.setAttribute("position",new x.Float32BufferAttribute(s,3)),o}(e.shape.vertices),_.set(t,n)),n}if(e.shape instanceof h){const t=e.shape.vertices,n=e.shape.indices;let s=new x.BufferGeometry;return s.setAttribute("position",new x.Float32BufferAttribute(t,3)),null!=n?s.setIndex(new x.Uint16BufferAttribute(n,1)):s=M.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof a){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CylinderGeometry(n,n,2*t)}if(e.shape instanceof o){const t=e.shape.halfHeight,n=e.shape.radius;return new x.ConeGeometry(n,2*t)}if(e.shape instanceof s){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CapsuleGeometry(n,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function J(e){const t=X(e);if(null==t)return null;const n=Y,s=new x.Mesh(t,n);return s.geometry.computeBoundingBox(),s.geometry.scale(1.01,1.01,1.01),s}function $(e,t){const n=e.translation(),s=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(s.x,s.y,s.z,s.w)}const K=new x.Box3;function Q(e){const t=new x.Box3;for(const n of e)for(const e of n.vertices)t.expandByPoint(new x.Vector3(e[0],n.minHeight,e[2])),t.expandByPoint(new x.Vector3(e[0],n.maxHeight,e[2]));return t}const Y=new x.MeshBasicMaterial({wireframe:!1,color:16711680,side:x.FrontSide});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,6 @@
1
+ import { BaseActor } from '../actor.js';
2
+ import { SplineComponent } from './components/spline-component.js';
3
+ export declare class SplineActor extends BaseActor {
4
+ readonly spline: SplineComponent;
5
+ }
6
+ //# sourceMappingURL=spline-actor.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as o}from"tslib";import{Actor as t,BaseActor as p}from"../actor.js";import{attach as r}from"../component.js";import{SplineComponent as s}from"./components/spline-component.js";let e=class extends p{constructor(){super(...arguments),this.spline=r(s)}};e=o([t({typeId:"Spline"})],e);export{e as SplineActor};/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,13 @@
1
+ import { type NavigationAreaContributor, type NavigationAreaModifier } from '../../ai/navigation-areas.js';
2
+ import { BaseActor } from '../actor.js';
3
+ import { SplineComponent } from './components/spline-component.js';
4
+ /** A spline-shaped water volume. The spline runs along the center of its surface. */
5
+ export declare class WaterSplineVolume extends BaseActor implements NavigationAreaContributor {
6
+ readonly spline: SplineComponent;
7
+ private readonly editorVisual;
8
+ width: number;
9
+ depth: number;
10
+ applySceneParameters(parameters: Record<string, unknown>, changedParameters: ReadonlySet<string>): boolean;
11
+ getNavigationAreaModifiers(): NavigationAreaModifier[];
12
+ }
13
+ //# sourceMappingURL=water-spline-volume-actor.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as t,__metadata as e}from"tslib";import{BufferGeometry as i,EdgesGeometry as o,Float32BufferAttribute as s,Group as r,LineBasicMaterial as n,LineSegments as l,Mesh as a,MeshBasicMaterial as h,Vector3 as p}from"three";import{takeUntil as d}from"rxjs";import{NavigationArea as m}from"../../ai/navigation-areas.js";import{Parameter as c}from"../../../shader/parameter.js";import{Actor as u,BaseActor as g}from"../actor.js";import{ActorComponent as f,Component as y,attach as w}from"../component.js";import{SplineComponent as b}from"./components/spline-component.js";let M=class extends f{constructor(){super(...arguments),this.visual=new r,this.fillMaterial=new h({color:1477586,transparent:!0,opacity:.18,depthWrite:!1}),this.edgeMaterial=new n({color:3520767}),this.fill=new a(new i,this.fillMaterial),this.edges=new l(new i,this.edgeMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.visual.name="Water Spline Volume Visualization",this.visual.userData.isEditorVisualization=!0,this.fill.frustumCulled=!1,this.edges.frustumCulled=!1,this.visual.add(this.fill,this.edges),this.actor.object.add(this.visual),this.actor.spline.changed.pipe(d(this.disposed)).subscribe(()=>this.rebuild()),this.rebuild()}rebuild(){if(!this.initialized)return;const t=function(t,e,o){const r=new i,n=v(t,e,o);if(n.length<2)return r.setAttribute("position",new s([],3)),r;const l=n.flatMap(t=>[...t.leftTop.toArray(),...t.rightTop.toArray(),...t.leftBottom.toArray(),...t.rightBottom.toArray()]),a=[];for(let t=1;t<n.length;t++){const e=4*(t-1),i=4*t;A(a,e,i,i+1,e+1),A(a,e+2,e+3,i+3,i+2),A(a,e,e+2,i+2,i),A(a,e+1,i+1,i+3,e+3)}if(!t.closed){A(a,0,1,3,2);const t=4*(n.length-1);A(a,t,t+2,t+3,t+1)}return r.setAttribute("position",new s(l,3)),r.setIndex(a),r.computeVertexNormals(),r.computeBoundingBox(),r.computeBoundingSphere(),r}(this.actor.spline,this.actor.width,this.actor.depth),e=0===t.getAttribute("position").count?new i:new o(t,20),r=this.fill.geometry,n=this.edges.geometry;this.fill.geometry=t,this.edges.geometry=e,r.dispose(),n.dispose(),this.visual.updateMatrixWorld(!0)}onEndPlay(){this.fill.geometry.dispose(),this.edges.geometry.dispose(),this.fillMaterial.dispose(),this.edgeMaterial.dispose(),this.visual.removeFromParent()}};M=t([y({inEditor:!0,editorOnly:!0})],M);let x=class extends g{constructor(){super(...arguments),this.spline=w(b),this.editorVisual=w(M),this.width=5,this.depth=2}applySceneParameters(t,e){if(![...e].every(t=>"width"===t||"depth"===t))return!1;const i=e.has("width")?t.width:this.width,o=e.has("depth")?t.depth:this.depth;return!("number"!=typeof i||!Number.isFinite(i)||i<=0)&&(!("number"!=typeof o||!Number.isFinite(o)||o<=0)&&(this.width=i,this.depth=o,this.editorVisual.rebuild(),!0))}getNavigationAreaModifiers(){const t=v(this.spline,this.width,this.depth);if(t.length<2)return[];this.object.updateWorldMatrix(!0,!1);const e=this.object.matrixWorld,i=[];for(let o=1;o<t.length;o++){const s=t[o-1],r=t[o],n=[s.leftTop,s.rightTop,r.rightTop,r.leftTop,s.leftBottom,s.rightBottom,r.rightBottom,r.leftBottom].map(t=>t.clone().applyMatrix4(e));i.push({area:m.Water,vertices:n.slice(0,4).map(t=>t.toArray()),minHeight:Math.min(...n.map(t=>t.y)),maxHeight:Math.max(...n.map(t=>t.y))})}return i}};t([c({range:[.01,1e3]}),e("design:type",Number)],x.prototype,"width",void 0),t([c({range:[.01,1e3]}),e("design:type",Number)],x.prototype,"depth",void 0),x=t([u({typeId:"WaterSplineVolume"})],x);export{x as WaterSplineVolume};function v(t,e,i){if(t.points.length<2||t.length<=0||e<=0||i<=0)return[];const o=Math.min(513,Math.max(2,Math.ceil(t.length/.5)+1)),s=[],r=Array.from({length:o},(e,i)=>t.samplePositionAtDistance(t.length*i/(o-1),new p)),n=Array.from({length:o-1},(e,i)=>{const s=r[i+1].clone().sub(r[i]);return s.y=0,s.lengthSq()<1e-8&&(t.sampleTangentAtDistance(t.length*(i+.5)/(o-1),s),s.y=0),s.lengthSq()<1e-8&&s.set(1,0,0),s.normalize(),new p(-s.z,0,s.x)}),l=.5*e;for(let e=0;e<o;e++){const a=t.closed&&(0===e||e===o-1),h=n[a?n.length-1:Math.max(0,e-1)],p=n[a?0:Math.min(n.length-1,e)],d=h.clone().add(p),m=d.lengthSq()<1e-8?0:d.normalize().dot(p);m<=1e-4?d.copy(p).multiplyScalar(l):d.multiplyScalar(Math.min(l/m,1.5*l));const c=r[e].clone().add(d),u=r[e].clone().sub(d);s.push({leftTop:c,rightTop:u,leftBottom:c.clone().addScaledVector(B,i),rightBottom:u.clone().addScaledVector(B,i)})}return s}function A(t,e,i,o,s){t.push(e,i,o,e,o,s)}const B=new p(0,-1,0);/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,8 @@
1
+ import { BaseActor } from '../../index.js';
2
+ import { type NavigationAreaContributor, type NavigationAreaModifier } from '../../ai/navigation-areas.js';
3
+ /** A semantic box of water. Its top face is the future water surface. */
4
+ export declare class WaterVolume extends BaseActor implements NavigationAreaContributor {
5
+ private editorVisual;
6
+ getNavigationAreaModifiers(): NavigationAreaModifier[];
7
+ }
8
+ //# sourceMappingURL=water-volume-actor.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as t}from"tslib";import{BoxGeometry as e,EdgesGeometry as r,Group as a,LineBasicMaterial as o,LineSegments as i,Mesh as n,MeshBasicMaterial as s,Vector3 as c}from"three";import{Actor as l,BaseActor as p,Component as d,ActorComponent as m,attach as h}from"../../index.js";import{NavigationArea as w}from"../../ai/navigation-areas.js";let u=class extends m{constructor(){super(...arguments),this.visual=new a}onInit(){const t=new e(1,1,1);this.visual.add(new n(t,new s({color:1477586,transparent:!0,opacity:.18,depthWrite:!1})),new i(new r(t),new o({color:3520767}))),this.actor.object.add(this.visual)}};u=t([d({inEditor:!0,editorOnly:!0})],u);let x=class extends p{constructor(){super(...arguments),this.editorVisual=h(u)}getNavigationAreaModifiers(){this.object.updateWorldMatrix(!0,!1);const t=this.object.matrixWorld,e=f.map(e=>e.clone().applyMatrix4(t).toArray());let r=1/0,a=-1/0;for(const e of y){const o=M.copy(e).applyMatrix4(t).y;r=Math.min(r,o),a=Math.max(a,o)}return[{area:w.Water,vertices:e,minHeight:r,maxHeight:a}]}};x=t([l({typeId:"WaterVolume"})],x);export{x as WaterVolume};const f=[new c(-.5,0,-.5),new c(.5,0,-.5),new c(.5,0,.5),new c(-.5,0,.5)],y=[-.5,.5].flatMap(t=>[-.5,.5].flatMap(e=>[-.5,.5].map(r=>new c(t,e,r)))),M=new c;/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -4,7 +4,11 @@ export { FirstPersonCameraComponent } from './camera/first-person-camera-compone
4
4
  export { ThirdPersonCameraComponent, ThirdPartyCameraComponent, type TemporaryThirdPersonCameraControlOptions } from './camera/third-person-camera-component.js';
5
5
  export { SpawnPoint } from './builtin/spawn-point.js';
6
6
  export { TriggerVolume, TriggerVolumeComponent } from './builtin/trigger-volume.js';
7
+ export { WaterVolume } from './builtin/water-volume-actor.js';
7
8
  export { PositionalAudioActor, PositionalAudioComponent } from './builtin/positional-audio-actor.js';
9
+ export { SplineActor } from './builtin/spline-actor.js';
10
+ export { WaterSplineVolume } from './builtin/water-spline-volume-actor.js';
11
+ export * from './builtin/components/spline-component.js';
8
12
  export * from './builtin/components/mesh-component.js';
9
13
  export * from './builtin/components/character/character-movement.js';
10
14
  export * from './builtin/components/character/root-motion-constraint.js';
@@ -1,4 +1,4 @@
1
- export{CameraActor}from"./builtin/camera-actor.js";export{CameraComponent}from"./camera/camera-component.js";export{FirstPersonCameraComponent}from"./camera/first-person-camera-component.js";export{ThirdPersonCameraComponent,ThirdPartyCameraComponent}from"./camera/third-person-camera-component.js";export{SpawnPoint}from"./builtin/spawn-point.js";export{TriggerVolume,TriggerVolumeComponent}from"./builtin/trigger-volume.js";export{PositionalAudioActor,PositionalAudioComponent}from"./builtin/positional-audio-actor.js";export*from"./builtin/components/mesh-component.js";export*from"./builtin/components/character/character-movement.js";export*from"./builtin/components/character/root-motion-constraint.js";export*from"./builtin/components/character/character-movement-policy.js";export*from"./builtin/components/character/old-character-movement.js";export*from"./builtin/components/character/character-movement-like.js";export*from"./builtin/components/character/modes.js";export*from"./builtin/components/character/character-animation.js";export*from"./controller/actor-controller.js";export{builtInComponents}from"./builtin/components/index.js";/*
1
+ export{CameraActor}from"./builtin/camera-actor.js";export{CameraComponent}from"./camera/camera-component.js";export{FirstPersonCameraComponent}from"./camera/first-person-camera-component.js";export{ThirdPersonCameraComponent,ThirdPartyCameraComponent}from"./camera/third-person-camera-component.js";export{SpawnPoint}from"./builtin/spawn-point.js";export{TriggerVolume,TriggerVolumeComponent}from"./builtin/trigger-volume.js";export{WaterVolume}from"./builtin/water-volume-actor.js";export{PositionalAudioActor,PositionalAudioComponent}from"./builtin/positional-audio-actor.js";export{SplineActor}from"./builtin/spline-actor.js";export{WaterSplineVolume}from"./builtin/water-spline-volume-actor.js";export*from"./builtin/components/spline-component.js";export*from"./builtin/components/mesh-component.js";export*from"./builtin/components/character/character-movement.js";export*from"./builtin/components/character/root-motion-constraint.js";export*from"./builtin/components/character/character-movement-policy.js";export*from"./builtin/components/character/old-character-movement.js";export*from"./builtin/components/character/character-movement-like.js";export*from"./builtin/components/character/modes.js";export*from"./builtin/components/character/character-animation.js";export*from"./controller/actor-controller.js";export{builtInComponents}from"./builtin/components/index.js";/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,5 +1,6 @@
1
1
  import type { RecastCompactHeightfield, RecastConfig, RecastContourSet, RecastHeightfield, UnsignedCharArray, Vector3Tuple } from '@recast-navigation/core';
2
2
  import { RecastBuildContext } from '@recast-navigation/core';
3
+ import { type NavigationAreaModifier } from './navigation-areas.js';
3
4
  type BuildConfigProps = {
4
5
  recastConfig: RecastConfig;
5
6
  navMeshBounds: [min: Vector3Tuple, max: Vector3Tuple];
@@ -36,6 +37,7 @@ export type BuildTileMeshProps = {
36
37
  tileBoundsMax: Vector3Tuple;
37
38
  navMeshBounds: [Vector3Tuple, Vector3Tuple];
38
39
  keepIntermediates: boolean;
40
+ areaModifiers?: NavigationAreaModifier[];
39
41
  };
40
42
  export type BuildTileMeshResult = ({
41
43
  success: true;
@@ -47,6 +49,6 @@ export type BuildTileMeshResult = ({
47
49
  tileIntermediates?: TileIntermediates;
48
50
  buildContext: RecastBuildContext;
49
51
  };
50
- export declare const buildTile: ({ positions, indices, navMeshBounds, recastConfig, tileX, tileY, tileBoundsMin, tileBoundsMax, keepIntermediates, }: BuildTileMeshProps) => BuildTileMeshResult;
52
+ export declare const buildTile: ({ positions, indices, navMeshBounds, recastConfig, tileX, tileY, tileBoundsMin, tileBoundsMax, keepIntermediates, areaModifiers, }: BuildTileMeshProps) => BuildTileMeshResult;
51
53
  export {};
52
54
  //# sourceMappingURL=build-tile.d.ts.map
@@ -1,4 +1,4 @@
1
- import{NavMeshCreateParams as e,Raw as t,RecastBuildContext as i,TriangleAreasArray as l,TrianglesArray as o,VerticesArray as r,allocCompactHeightfield as a,allocContourSet as s,allocHeightfield as n,allocPolyMesh as d,allocPolyMeshDetail as c,buildCompactHeightfield as h,buildContours as g,buildDistanceField as m,buildPolyMesh as u,buildPolyMeshDetail as b,buildRegions as f,calcGridSize as S,cloneRcConfig as R,createHeightfield as w,createNavMeshData as p,createRcConfig as C,erodeWalkableArea as M,filterLedgeSpans as _,filterLowHangingWalkableObstacles as x,filterWalkableLowHeightSpans as A,freeCompactHeightfield as y,freeContourSet as k,freeHeightfield as z,markWalkableTriangles as E,rasterizeTriangles as v,vec3 as T}from"@recast-navigation/core";import{dtIlog2 as B,dtNextPow2 as O}from"@recast-navigation/generators";import*as P from"three";export const buildConfig=({recastConfig:e,navMeshBounds:[t,i]})=>{const l=C(e),o=S(t,i,l.cs);l.width=o.width,l.height=o.height,l.minRegionArea=l.minRegionArea*l.minRegionArea,l.mergeRegionArea=l.mergeRegionArea*l.mergeRegionArea,l.tileSize=Math.floor(l.tileSize),l.borderSize=l.walkableRadius+3,l.width=l.tileSize+2*l.borderSize,l.height=l.tileSize+2*l.borderSize,l.detailSampleDist=l.detailSampleDist<.9?0:l.cs*l.detailSampleDist,l.detailSampleMaxError=l.ch*l.detailSampleMaxError;const r=Math.floor(l.tileSize),a=Math.floor((o.width+r-1)/r),s=Math.floor((o.height+r-1)/r),n=l.tileSize*l.cs,d=T.fromArray(t);let c=Math.min(Math.floor(B(O(a*s))),14);c>14&&(c=14);const h=22-c;return{config:l,orig:d,tileBits:c,polyBits:h,maxTiles:1<<c,maxPolysPerTile:1<<h,tcs:n,tileWidth:a,tileHeight:s}};export const buildTile=({positions:S,indices:C,navMeshBounds:T,recastConfig:B,tileX:O,tileY:H,tileBoundsMin:L,tileBoundsMax:G,keepIntermediates:D})=>{const $=new i,F=S,V=S.length/3,W=new r;W.copy(F);const I=C,K=C.length/3;(new o).copy(I);const X={tileX:O,tileY:H},Y=()=>{D||(X.compactHeightfield&&y(X.compactHeightfield),X.heightfield&&z(X.heightfield),X.contourSet&&k(X.contourSet))},N=e=>($.log(t.Module.RC_LOG_ERROR,e),Y(),{success:!1,error:e,tileIntermediates:X,buildContext:$}),{config:U}=buildConfig({recastConfig:B,navMeshBounds:T}),j=R(U),q=[...L],J=[...G];q[0]-=j.borderSize*j.cs,q[2]-=j.borderSize*j.cs,J[0]+=j.borderSize*j.cs,J[2]+=j.borderSize*j.cs,j.set_bmin(0,q[0]),j.set_bmin(1,q[1]),j.set_bmin(2,q[2]),j.set_bmax(0,J[0]),j.set_bmax(1,J[1]),j.set_bmax(2,J[2]),$.resetTimers(),$.startTimer(t.Module.RC_TIMER_TOTAL),$.log(t.Module.RC_LOG_PROGRESS,`Building tile at x: ${O}, y: ${H}`),$.log(t.Module.RC_LOG_PROGRESS,` - ${U.width} x ${U.height} cells`),$.log(t.Module.RC_LOG_PROGRESS,` - ${V/1e3}fK verts, ${K/1e3}K tris`);const Q=n();if(X.heightfield=Q,!w($,Q,j.width,j.height,q,J,j.cs,j.ch))return N("Could not create heightfield");const Z=((e,t,i)=>{const l=[],o=new P.Vector3,r=new P.Vector3,a=new P.Vector3,s=new P.Triangle;for(let n=0;n<t.length;n+=3){const d=t[n],c=t[n+1],h=t[n+2];o.fromArray(e,3*d),r.fromArray(e,3*c),a.fromArray(e,3*h),s.set(o,r,a),s.intersectsBox(i)&&l.push(d,c,h)}return l})(S,C,new P.Box3(new P.Vector3(q[0],q[1],q[2]),new P.Vector3(J[0],J[1],J[2]))),ee=Z.length/3,te=new o;te.copy(Z);const ie=new l;ie.resize(ee),E($,j.walkableSlopeAngle,W,V,te,ee,ie);const le=v($,W,V,te,ie,ee,Q,j.walkableClimb);if(ie.destroy(),!le)return N("Could not rasterize triangles");x($,j.walkableClimb,Q),_($,j.walkableHeight,j.walkableClimb,Q),A($,j.walkableHeight,Q);const oe=a();if(X.compactHeightfield=oe,!h($,j.walkableHeight,j.walkableClimb,Q,oe))return N("Could not build compact heightfield");if(D||(z(X.heightfield),X.heightfield=void 0),!M($,j.walkableRadius,oe))return N("Could not erode walkable area");if(!m($,oe))return N("Failed to build distance field");if(!f($,oe,j.borderSize,j.minRegionArea,j.mergeRegionArea))return N("Failed to build regions");const re=s();if(X.contourSet=re,!g($,oe,j.maxSimplificationError,j.maxEdgeLen,re,t.Module.RC_CONTOUR_TESS_WALL_EDGES))return N("Failed to create contours");const ae=d();if(!u($,re,j.maxVertsPerPoly,ae))return N("Failed to triangulate contours");if(0===ae.npolys())return Y(),{success:!0,tileIntermediates:X,buildContext:$};const se=c();if(!b($,ae,oe,j.detailSampleDist,j.detailSampleMaxError,se))return N("Failed to build detail mesh");D||(y(oe),X.compactHeightfield=void 0,k(re),X.contourSet=void 0);for(let e=0;e<ae.npolys();e++)ae.areas(e)==t.Recast.WALKABLE_AREA&&ae.setAreas(e,0),0==ae.areas(e)&&ae.setFlags(e,1);const ne=new e;ne.setPolyMeshCreateParams(ae),ne.setPolyMeshDetailCreateParams(se),ne.setWalkableHeight(j.walkableHeight),ne.setWalkableRadius(j.walkableRadius),ne.setWalkableClimb(j.walkableClimb),ne.setCellSize(j.cs),ne.setCellHeight(j.ch),ne.setBuildBvTree(!0),ne.setTileX(O),ne.setTileY(H);const de=p(ne);return de.success?($.log(t.Module.RC_LOG_PROGRESS,`>> Polymesh: ${ae.nverts()} vertices ${ae.npolys()} polygons`),Y(),{success:!0,data:de.navMeshData,tileIntermediates:X,buildContext:$}):N("Failed to create Detour navmesh data")};/*
1
+ import{NavMeshCreateParams as e,Raw as t,RecastBuildContext as i,TriangleAreasArray as o,TrianglesArray as r,VerticesArray as l,allocCompactHeightfield as a,allocContourSet as s,allocHeightfield as n,allocPolyMesh as c,allocPolyMeshDetail as d,buildCompactHeightfield as h,buildContours as g,buildDistanceField as m,buildPolyMesh as u,buildPolyMeshDetail as f,buildRegions as b,calcGridSize as S,cloneRcConfig as w,createHeightfield as R,createNavMeshData as p,createRcConfig as C,erodeWalkableArea as M,filterLedgeSpans as _,filterLowHangingWalkableObstacles as x,filterWalkableLowHeightSpans as y,freeCompactHeightfield as A,freeContourSet as k,freeHeightfield as v,FloatArray as z,markConvexPolyArea as E,markWalkableTriangles as T,rasterizeTriangles as B,vec3 as H}from"@recast-navigation/core";import{dtIlog2 as O,dtNextPow2 as P}from"@recast-navigation/generators";import*as G from"three";import{NavigationArea as L,NavigationTraversalFlag as D}from"./navigation-areas.js";export const buildConfig=({recastConfig:e,navMeshBounds:[t,i]})=>{const o=C(e),r=S(t,i,o.cs);o.width=r.width,o.height=r.height,o.minRegionArea=o.minRegionArea*o.minRegionArea,o.mergeRegionArea=o.mergeRegionArea*o.mergeRegionArea,o.tileSize=Math.floor(o.tileSize),o.borderSize=o.walkableRadius+3,o.width=o.tileSize+2*o.borderSize,o.height=o.tileSize+2*o.borderSize,o.detailSampleDist=o.detailSampleDist<.9?0:o.cs*o.detailSampleDist,o.detailSampleMaxError=o.ch*o.detailSampleMaxError;const l=Math.floor(o.tileSize),a=Math.floor((r.width+l-1)/l),s=Math.floor((r.height+l-1)/l),n=o.tileSize*o.cs,c=H.fromArray(t);let d=Math.min(Math.floor(O(P(a*s))),14);d>14&&(d=14);const h=22-d;return{config:o,orig:c,tileBits:d,polyBits:h,maxTiles:1<<d,maxPolysPerTile:1<<h,tcs:n,tileWidth:a,tileHeight:s}};export const buildTile=({positions:S,indices:C,navMeshBounds:H,recastConfig:O,tileX:P,tileY:F,tileBoundsMin:W,tileBoundsMax:$,keepIntermediates:V,areaModifiers:I=[]})=>{const K=new i,X=S,Y=S.length/3,j=new l;j.copy(X);const N=C,U=C.length/3;(new r).copy(N);const q={tileX:P,tileY:F},J=()=>{V||(q.compactHeightfield&&A(q.compactHeightfield),q.heightfield&&v(q.heightfield),q.contourSet&&k(q.contourSet))},Q=e=>(K.log(t.Module.RC_LOG_ERROR,e),J(),{success:!1,error:e,tileIntermediates:q,buildContext:K}),{config:Z}=buildConfig({recastConfig:O,navMeshBounds:H}),ee=w(Z),te=[...W],ie=[...$];te[0]-=ee.borderSize*ee.cs,te[2]-=ee.borderSize*ee.cs,ie[0]+=ee.borderSize*ee.cs,ie[2]+=ee.borderSize*ee.cs,ee.set_bmin(0,te[0]),ee.set_bmin(1,te[1]),ee.set_bmin(2,te[2]),ee.set_bmax(0,ie[0]),ee.set_bmax(1,ie[1]),ee.set_bmax(2,ie[2]),K.resetTimers(),K.startTimer(t.Module.RC_TIMER_TOTAL),K.log(t.Module.RC_LOG_PROGRESS,`Building tile at x: ${P}, y: ${F}`),K.log(t.Module.RC_LOG_PROGRESS,` - ${Z.width} x ${Z.height} cells`),K.log(t.Module.RC_LOG_PROGRESS,` - ${Y/1e3}fK verts, ${U/1e3}K tris`);const oe=n();if(q.heightfield=oe,!R(K,oe,ee.width,ee.height,te,ie,ee.cs,ee.ch))return Q("Could not create heightfield");const re=((e,t,i)=>{const o=[],r=new G.Vector3,l=new G.Vector3,a=new G.Vector3,s=new G.Triangle;for(let n=0;n<t.length;n+=3){const c=t[n],d=t[n+1],h=t[n+2];r.fromArray(e,3*c),l.fromArray(e,3*d),a.fromArray(e,3*h),s.set(r,l,a),s.intersectsBox(i)&&o.push(c,d,h)}return o})(S,C,new G.Box3(new G.Vector3(te[0],te[1],te[2]),new G.Vector3(ie[0],ie[1],ie[2]))),le=re.length/3,ae=new r;ae.copy(re);const se=new o;se.resize(le),T(K,ee.walkableSlopeAngle,j,Y,ae,le,se);const ne=B(K,j,Y,ae,se,le,oe,ee.walkableClimb);if(se.destroy(),!ne)return Q("Could not rasterize triangles");x(K,ee.walkableClimb,oe),_(K,ee.walkableHeight,ee.walkableClimb,oe),y(K,ee.walkableHeight,oe);const ce=a();if(q.compactHeightfield=ce,!h(K,ee.walkableHeight,ee.walkableClimb,oe,ce))return Q("Could not build compact heightfield");if(V||(v(q.heightfield),q.heightfield=void 0),!M(K,ee.walkableRadius,ce))return Q("Could not erode walkable area");for(const e of I){if(e.vertices.length<3)continue;const t=new z;t.copy(e.vertices.flat()),E(K,t,e.vertices.length,e.minHeight,e.maxHeight,e.area,ce),t.destroy()}if(!m(K,ce))return Q("Failed to build distance field");if(!b(K,ce,ee.borderSize,ee.minRegionArea,ee.mergeRegionArea))return Q("Failed to build regions");const de=s();if(q.contourSet=de,!g(K,ce,ee.maxSimplificationError,ee.maxEdgeLen,de,t.Module.RC_CONTOUR_TESS_WALL_EDGES))return Q("Failed to create contours");const he=c();if(!u(K,de,ee.maxVertsPerPoly,he))return Q("Failed to triangulate contours");if(0===he.npolys())return J(),{success:!0,tileIntermediates:q,buildContext:K};const ge=d();if(!f(K,he,ce,ee.detailSampleDist,ee.detailSampleMaxError,ge))return Q("Failed to build detail mesh");V||(A(ce),q.compactHeightfield=void 0,k(de),q.contourSet=void 0);for(let e=0;e<he.npolys();e++){he.areas(e)==t.Recast.WALKABLE_AREA&&he.setAreas(e,0);const i=he.areas(e);i==L.Ground&&he.setFlags(e,D.Walk),i==L.Water&&he.setFlags(e,D.Swim)}const me=new e;me.setPolyMeshCreateParams(he),me.setPolyMeshDetailCreateParams(ge),me.setWalkableHeight(ee.walkableHeight),me.setWalkableRadius(ee.walkableRadius),me.setWalkableClimb(ee.walkableClimb),me.setCellSize(ee.cs),me.setCellHeight(ee.ch),me.setBuildBvTree(!0),me.setTileX(P),me.setTileY(F);const ue=p(me);return ue.success?(K.log(t.Module.RC_LOG_PROGRESS,`>> Polymesh: ${he.nverts()} vertices ${he.npolys()} polygons`),J(),{success:!0,data:ue.navMeshData,tileIntermediates:q,buildContext:K}):Q("Failed to create Detour navmesh data")};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,8 +1,8 @@
1
1
  import type { RecastConfig, Vector3Tuple } from 'recast-navigation';
2
2
  import { NavMesh } from 'recast-navigation';
3
- import type * as THREE from 'three';
4
- import type { BuildTileMeshProps } from './build-tile.js';
3
+ import * as THREE from 'three';
5
4
  import { Subject } from 'rxjs';
5
+ import type { NavigationAreaModifier } from './navigation-areas.js';
6
6
  export type DynamicTiledNavMeshProps = {
7
7
  navMeshBounds: THREE.Box3;
8
8
  recastConfig: Partial<RecastConfig>;
@@ -11,23 +11,6 @@ export type DynamicTiledNavMeshProps = {
11
11
  cacheId: string;
12
12
  };
13
13
  export declare const MAX_NAV_MESH_WORKERS = 4;
14
- type NavMeshWorkerResult = {
15
- tileX: number;
16
- tileY: number;
17
- navMeshData?: Uint8Array;
18
- error?: string;
19
- };
20
- export declare class NavMeshWorkerPool {
21
- private workerFactory;
22
- private slots;
23
- private queue;
24
- private workerLimit;
25
- constructor(workerFactory?: () => Worker);
26
- schedule(owner: object, data: BuildTileMeshProps, transfer: Transferable[] | undefined, onResult: (event: MessageEvent<NavMeshWorkerResult>) => void, requestedWorkers: number): void;
27
- cancel(owner: object): void;
28
- private drain;
29
- private createSlot;
30
- }
31
14
  export declare const getTileBounds: (navMeshBoundsMin: THREE.Vector3, navMeshBoundsMax: THREE.Vector3, tileX: number, tileY: number, tileWorldSize: number) => [min: Vector3Tuple, max: Vector3Tuple];
32
15
  export declare class DynamicTiledNavMesh {
33
16
  navMesh: NavMesh;
@@ -43,13 +26,13 @@ export declare class DynamicTiledNavMesh {
43
26
  recastConfig: RecastConfig;
44
27
  private cacheId;
45
28
  private workerLimit;
29
+ private abortController;
46
30
  constructor(props: DynamicTiledNavMeshProps);
47
31
  private onResult;
48
- buildTile(positions: Float32Array, indices: Uint32Array, [tileX, tileY]: [x: number, y: number], useTileCache?: boolean): Promise<unknown>;
32
+ buildTile(positions: Float32Array, indices: Uint32Array, [tileX, tileY]: [x: number, y: number], useTileCache?: boolean, areaModifiers?: NavigationAreaModifier[]): Promise<unknown>;
49
33
  buildAllTiles(positions: Float32Array, indices: Uint32Array): void;
50
34
  getTileForWorldPosition(worldPosition: THREE.Vector3): [x: number, y: number];
51
35
  getTilesForBounds(bounds: THREE.Box3): [x: number, y: number][];
52
36
  destroy(): void;
53
37
  }
54
- export {};
55
38
  //# sourceMappingURL=dynamic-tiled-navmesh.d.ts.map