@hology/core 0.0.199 → 0.0.201

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/effects/sequence/sequence-action.d.ts +1 -0
  2. package/dist/effects/sequence/sequence-actor.d.ts +5 -0
  3. package/dist/effects/sequence/sequence-actor.js +1 -1
  4. package/dist/effects/sequence/sequence-player.d.ts +6 -0
  5. package/dist/effects/sequence/sequence-player.js +1 -1
  6. package/dist/effects/vfx/trail-renderer.js +1 -1
  7. package/dist/effects/vfx/vfx-asset.d.ts +17 -6
  8. package/dist/effects/vfx/vfx-materializer.js +1 -1
  9. package/dist/effects/vfx/vfx-renderers.js +1 -1
  10. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  11. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +8 -1
  12. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  13. package/dist/gameplay/services/physics/physics-system.js +1 -1
  14. package/dist/scene/custom-param-runtime-types.d.ts +35 -0
  15. package/dist/scene/custom-param-runtime-types.js +4 -0
  16. package/dist/scene/landscape/landscape.js +1 -1
  17. package/dist/scene/materializer.d.ts +19 -3
  18. package/dist/scene/materializer.js +1 -1
  19. package/dist/scene/model.d.ts +13 -5
  20. package/dist/scene/sky.js +1 -1
  21. package/dist/scene/storage/storage.js +1 -1
  22. package/dist/shader/graph/compiler.d.ts +81 -0
  23. package/dist/shader/graph/compiler.js +4 -0
  24. package/dist/shader/graph/index.d.ts +5 -0
  25. package/dist/shader/graph/index.js +4 -0
  26. package/dist/shader/graph/model.d.ts +81 -0
  27. package/dist/shader/graph/model.js +4 -0
  28. package/dist/shader/graph/parameters.d.ts +7 -0
  29. package/dist/shader/graph/parameters.js +4 -0
  30. package/dist/shader/graph/registry.d.ts +22 -0
  31. package/dist/shader/graph/registry.js +4 -0
  32. package/dist/shader/index.d.ts +1 -0
  33. package/dist/shader/index.js +1 -1
  34. package/dist/shader-nodes/bulge.js +1 -1
  35. package/dist/shader-nodes/depth.d.ts +2 -0
  36. package/dist/shader-nodes/depth.js +1 -1
  37. package/dist/shader-nodes/effects.d.ts +5 -0
  38. package/dist/shader-nodes/effects.js +1 -1
  39. package/dist/shader-nodes/gradient-sample.d.ts +16 -0
  40. package/dist/shader-nodes/gradient-sample.js +4 -0
  41. package/dist/shader-nodes/index.d.ts +1 -0
  42. package/dist/shader-nodes/index.js +1 -1
  43. package/dist/shader-nodes/layers.d.ts +6 -3
  44. package/dist/shader-nodes/layers.js +1 -1
  45. package/dist/shader-nodes/math.d.ts +4 -0
  46. package/dist/shader-nodes/math.js +1 -1
  47. package/dist/shader-nodes/particle.d.ts +10 -2
  48. package/dist/shader-nodes/particle.js +1 -1
  49. package/dist/shader-nodes/texture-sequence.d.ts +2 -1
  50. package/dist/shader-nodes/texture-sequence.js +1 -1
  51. package/dist/test/runtime-param-type-inference.test.d.ts +2 -0
  52. package/dist/test/runtime-param-type-inference.test.js +4 -0
  53. package/dist/test/shader-graph.test.d.ts +2 -0
  54. package/dist/test/shader-graph.test.js +4 -0
  55. package/dist/test/storage-case-collision.test.js +1 -1
  56. package/package.json +6 -2
  57. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{CustomRenderer as e,MeshRenderer as t,PUID as r}from"@hology/nebula";import*as a from"three";import{InstancedBufferAttribute as i,Object3D as o}from"three";import{NodeShaderMaterial as n}from"three-shader-graph";import{StretchedSprite as s}from"./stretched-sprite.js";import{Trail as l}from"./trail-renderer.js";import{SpriteNodeShaderMaterial as c}from"../../shader/sprite-shader";var d;!function(e){e[e.mesh=0]="mesh",e[e.instanced=1]="instanced",e[e.sprite=2]="sprite",e[e.stretchedBillboard=3]="stretchedBillboard",e[e.trail=4]="trail"}(d||(d={}));export class MultiRenderer extends e{constructor(e,t,r,a){super(),this.worldContainer=e,this.localContainer=t,this.three=r,this.view=a,this.localRenderers=[],this.worldRenderers=[]}onSystemUpdate(){for(const e of this.worldRenderers)e?.onSystemUpdate();for(const e of this.localRenderers)e?.onSystemUpdate()}onParticleCreated(e){e.target=null,this.getRenderer(e)?.onParticleCreated(e)}onParticleUpdate(e){this.getRenderer(e)?.onParticleUpdate(e)}onParticleDead(e){this.getRenderer(e)?.onParticleDead(e),e._renderer=null}getRenderer(e){if(e._renderer)return e._renderer;const t=(null!=e?.parent?e?.parent._space:null)??"world",r="world"===t?this.worldContainer:this.localContainer,i="world"===t?this.worldRenderers:this.localRenderers;return"trail"===e.body.type?(null==i[d.trail]&&(i[d.trail]=new TrailRenderer(r,this.three)),e._renderer=i[d.trail]):e.body instanceof s?(null==i[d.stretchedBillboard]&&(i[d.stretchedBillboard]=new StretchedSpriteInstancedRenderer(r,this.three,this.view)),e._renderer=i[d.stretchedBillboard]):e.body instanceof a.Sprite||e.body instanceof a.Mesh&&"sprite"===e.body.name?(null==i[d.sprite]&&(i[d.sprite]=new CombinedRenderer(r,this.three)),e._renderer=i[d.sprite]):e.body instanceof a.Mesh&&0==e.body.children.length&&e.body.material instanceof n?(null==i[d.instanced]&&(i[d.instanced]=new InstancedRenderer(r,this.three,this.view)),e._renderer=i[d.instanced]):e.body instanceof a.Object3D?(null==i[d.mesh]&&(i[d.mesh]=new CombinedRenderer(r,this.three)),e._renderer=i[d.mesh]):void 0}dispose(){this.localRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()}),this.worldRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()})}}export class TrailRenderer extends t{constructor(){super(...arguments),this.trails=[]}dispose(){}onSystemUpdate(){for(const e of this.trails)e.update()}onParticleCreated(e){const t=e.body,r=new l(this.container,!1),i=new o;this.container.add(i),i.updateMatrixWorld(),i.updateWorldMatrix(!0,!0);const n=l.createBaseMaterial(t.texture,t.scrollSpeed,t.opacityChannel,t.billboard??!1);n.uniforms.taper.value=t.taper??!1;const s=new a.Color(t.color??0).multiplyScalar(t.intensity),c=new a.Color(t.colorEnd??0).multiplyScalar(t.intensityEnd??t.intensity??1);n.uniforms.headColor&&n.uniforms.tailColor&&(n.uniforms.headColor.value=new a.Vector4(s.r,s.g,s.b,t.opacityStart??1),n.uniforms.tailColor.value=new a.Vector4(c.r,c.g,c.b,t.opacityEnd??1)),t.bloom&&(n.userData.hasBloom=!0),r.initialize(n,Math.round(t.length??10),!1,t.width,null,i,t.billboard??!1);const d=e.rotation;i.rotation.set(d.x,d.y,d.z);e.scale;r.activate(),this.trails.push(r),e.target=i}onParticleUpdate(e){const t=e.target;t.position.copy(e.position);const r=e.body;let a=w;e.old&&e.old.position?a.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize():a.copy(e.velocity).normalize();const i=x;i.setFromUnitVectors(a,y),t.rotation.set(0,0,0),t.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),t.applyQuaternion(i);const o=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=o){const t=this.trails[o];if(e.useAlpha&&t.material.uniforms.headColor&&t.material.uniforms.tailColor){t.material.uniforms.headColor.value.setW(r.opacityStart*e.alpha);t.material.uniforms.tailColor.value.setW(r.opacityEnd*e.alpha)}}}onParticleDead(e){const t=e.target,r=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=r){const e=this.trails[r];e.removeFromParent(),e.mesh.removeFromParent(),e.targetObject.removeFromParent(),t.removeFromParent(),this.trails.splice(r,1)}}}export class CombinedRenderer extends t{dispose(){}scale(e){const t=e.transform.initialScale;e.target instanceof a.Sprite?null!=t?e.target.scale.set(t.x*e.scale*e.radius,t.y*e.scale*e.radius,1):e.target.scale.set(e.scale*e.radius,e.scale*e.radius,1):null!=t?e.target.scale.set(t.x*e.scale,t.y*e.scale,t.z*e.scale):super.scale(e)}rotate(e){e.target.material.rotation=e.rotation.z}onParticleCreated(e){e.target||(e.target=this._targetPool.get(e.body),(e.useAlpha||e.useColor)&&(e.target instanceof a.Mesh||e.target instanceof a.Sprite&&e.target.material instanceof a.Material)&&(e.target.material.__puid=r.id(e.body.material),e.target.material=this._materialPool.get(e.target.material))),e.target&&e.target instanceof o&&(e.target.position.set(e.position.x,e.position.y,e.position.z),this.container.add(e.target))}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:i,rotation:n}=e;if(t){if(t.position.copy(e.position),this.isThreeSprite(e)||(t instanceof a.Mesh&&t.material instanceof c?e.target.material.rotation=e.rotation.z:t.rotation.set(n.x,n.y,n.z)),this.scale(e),e.transform&&e.transform.orientAlongVelocity&&t instanceof o){const r=m.set(e.velocity.x,e.velocity.y,e.velocity.z).normalize(),a=t.getWorldDirection(u);a.applyAxisAngle(p,Math.PI/-2),h.setFromUnitVectors(a,r),t.quaternion.copy(h)}t.material instanceof a.Material&&(r&&(t.material instanceof c&&null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha,t.material.uniformsNeedUpdate=!0),t.material.opacity=e.alpha,t.material.transparent=!0),i&&(null!=t.material.color?t.material.color.copy(e.color):t.material instanceof a.ShaderMaterial&&null!=t.material.uniforms.color&&(t.material.uniforms.color.value=e.color,t.material.uniformsNeedUpdate=!0)))}}onParticleDead(e){e.target&&(e.target.material&&(e.useAlpha||e.useColor)&&this._materialPool.expire(e.target.material),this._targetPool.expire(e.target),this.container.remove(e.target),e.target=null)}}export class StretchedSpriteInstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.geometry.dispose())}onSystemUpdate(){for(const e of this.meshes){const t=e.mesh.geometry.getAttribute("offset"),r=e.mesh.geometry.getAttribute("size"),i=e.mesh.geometry.getAttribute("velocity"),o=e.mesh.geometry.getAttribute("rotation"),n=e.mesh.geometry.getAttribute("color");let s=0;for(const l of e.particles){if(null==l||l.dead)continue;if(l.useColor||l.color instanceof a.Color){const e=C.copy(l.color).getRGB(M);n.setXYZW(s,e.r,e.g,e.b,1),n.needsUpdate=!0}l.useAlpha&&(n.setW(s,l.alpha),n.needsUpdate=!0),"number"==typeof l.rotation?o.setX(s,l.rotation):o.setX(s,l.rotation.x);const e=l.position;if(t.setXYZ(s,e.x,e.y,e.z),"number"!=typeof l.scale)throw new Error("Particle scale is not a number");r.setXYZ(s,l.scale,l.scale,l.scale);let c=l.body.scaleFactor;0===c&&(c=.001);const d=1,m=l.velocity;i.setXYZW(s,m.x*c,m.y*c,m.z*c,d),s++}s>0&&(t.clearUpdateRanges(),t.addUpdateRange(0,3*s),t.needsUpdate=!0,r.clearUpdateRanges(),r.addUpdateRange(0,3*s),r.needsUpdate=!0,n.clearUpdateRanges(),n.addUpdateRange(0,4*s),n.needsUpdate=!0,i.clearUpdateRanges(),i.addUpdateRange(0,4*s),i.needsUpdate=!0,o.clearUpdateRanges(),o.addUpdateRange(0,s),o.needsUpdate=!0)}}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof s&&null==e.target){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(null==r){const o=this.calcMaxCount(e),n=new a.InstancedBufferGeometry;n.setIndex(t.geometry.getIndex()),n.setAttribute("position",t.geometry.getAttribute("position")),t.geometry.hasAttribute("normal")&&n.setAttribute("normal",t.geometry.getAttribute("normal")),n.setAttribute("uv",t.geometry.getAttribute("uv"));const s=new i(new Float32Array(3*o),3);s.setUsage(a.DynamicDrawUsage),n.setAttribute("offset",s);const l=new i(new Float32Array(4*o),4);if(l.setUsage(a.DynamicDrawUsage),n.setAttribute("color",l),t.material instanceof c){const e=new a.Color(t.material.color);for(let t=0;t<l.count;t++)l.setXYZW(t,e.r,e.g,e.b,1)}const d=new i(new Float32Array(3*o),3);d.setUsage(a.DynamicDrawUsage),n.setAttribute("size",d);const m=new i(new Float32Array(4*o),4);m.setUsage(a.DynamicDrawUsage),n.setAttribute("velocity",m);const u=new i(new Float32Array(4*o),1);u.setUsage(a.DynamicDrawUsage),n.setAttribute("rotation",u),r={mesh:new a.Mesh(n,t.material),indices:new Float32Array(o),particles:[]},this.meshes.push(r),this.container.add(r.mesh)}let o=r.indices.findIndex(e=>0===e);o<0&&(o=function(e){let t=e[0],r=0;for(let a=1;a<e.length;a++)e[a]<t&&(t=e[a],r=a);return r}(r.indices)),r.indices[o]=performance.now(),e.target=o,r.particles[o]=e}}onParticleUpdate(e){}onParticleDead(e){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(r){const t=r.mesh.geometry.getAttribute("size");t.setXYZ(e.target,0,0,0),t.needsUpdate=!0,r.particles[e.target]=null,r.indices[e.target]=0}e.target=null}}const m=new a.Vector3,u=new a.Vector3,h=new a.Quaternion,p=new a.Vector3(1,0,0);export class InstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.dispose())}onSystemUpdate(){for(const e of this.meshes);}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof a.Sprite)return;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r){const i=this.calcMaxCount(e);r={mesh:new a.InstancedMesh(t.geometry,t.material,i),indices:new Array(i).fill(null),particles:[]},r.mesh.renderOrder=t.renderOrder,r.mesh.setColorAt(0,C.setScalar(1)),r.mesh.instanceColor.needsUpdate=!0,r.mesh.material.defines.USE_INSTANCING="";const o=new Float32Array(3*i);b.makeScale(0,0,0);for(let e=0;e<i;e++)o[3*e+0]=1,o[3*e+1]=1,r.mesh.setMatrixAt(e,b);r.mesh.instanceMatrix.needsUpdate=!0,r.mesh.geometry.setAttribute("particleData",new a.InstancedBufferAttribute(o,3)),this.meshes.push(r),this.container.add(r.mesh)}let i=r.indices.findIndex(e=>null==e);if(i<0&&(i=r.indices.indexOf(Math.min(...r.indices))),r.indices[i]=performance.now(),e.target=i,r.particles[i]=e,"number"==typeof e.target){e.transform.initialScale;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);f(e,r.mesh),e.useAlpha&&(r.mesh.material.transparent=!0)}}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:a,rotation:i}=e;if(null==t)return;const o=e.body,n=this.meshes.find(e=>e.mesh.geometry.uuid===o.geometry.uuid&&e.mesh.material.uuid===o.material.uuid);if(null==n)return;n.mesh.frustumCulled=!1,f(e,n.mesh),a&&(n.mesh.setColorAt(e.target,C.copy(e.color)),n.mesh.instanceColor.needsUpdate=!0);const s=n.mesh.geometry.getAttribute("particleData");r&&s.setX(e.target,e.alpha),s.setY(e.target,e.energy),s.needsUpdate=!0}onParticleDead(e){if(null!=e.target){const t=e.body,r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r)return;r.indices[e.target]=null,e.scale=0,f(e,r.mesh),r.mesh.instanceMatrix.needsUpdate=!0,e.target=null}}}const g=new o;function f(e,t){if(w.set(e.position.x,e.position.y,e.position.z),e.transform&&e.transform.orientAlongVelocity){const r=m.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize();t.getMatrixAt(e.target,g.matrix);const a=g.getWorldDirection(A);a.applyAxisAngle(p,Math.PI/-2),x.setFromUnitVectors(a,r)}else U.set(e.rotation.x,e.rotation.y,e.rotation.z),x.setFromEuler(U);const r=e.transform.initialScale;null!=r?A.set(r.x*e.scale,r.y*e.scale,r.z*e.scale):A.set(e.scale,e.scale,e.scale),b.compose(w,x,A),t.setMatrixAt(e.target,b),t.instanceMatrix.needsUpdate=!0}const y=new a.Vector3(0,0,-1),b=new a.Matrix4,x=new a.Quaternion,w=new a.Vector3,A=new a.Vector3,U=new a.Euler,C=new a.Color(0),M={r:0,g:0,b:0};function P(e,t){const r=e.mesh,i=r.count,o=[],n=r.geometry.getAttribute("particleData"),s=new a.Vector3;for(let l=0;l<i;l++){const i=new a.Matrix4,c=new a.Color;r.getMatrixAt(l,i),r.getColorAt(l,c);const d=n.getX(l);s.setFromMatrixPosition(i);const m=s.distanceTo(t.position);o.push({index:l,distance:m,matrix:i,particle:e.particles[l],color:c,pdx:d})}o.sort((e,t)=>t.distance-e.distance);for(let e=0;e<i;e++){const t=o[e].matrix;null==o[e].particle&&t.makeScale(0,0,0),r.setMatrixAt(e,t),r.setColorAt(e,o[e].color),n.setX(e,o[e].pdx)}r.instanceMatrix.needsUpdate=!0}export{P as sortInstancedMeshByDistance};/*
1
+ import{CustomRenderer as e,MeshRenderer as t,PUID as r}from"@hology/nebula";import*as a from"three";import{InstancedBufferAttribute as o,Object3D as i}from"three";import{NodeShaderMaterial as n}from"three-shader-graph";import{StretchedSprite as s}from"./stretched-sprite.js";import{Trail as l}from"./trail-renderer.js";import{SpriteNodeShaderMaterial as c}from"../../shader/sprite-shader";import{particleEnergyUniformName as d}from"../../shader-nodes/particle";var m;!function(e){e[e.mesh=0]="mesh",e[e.instanced=1]="instanced",e[e.sprite=2]="sprite",e[e.stretchedBillboard=3]="stretchedBillboard",e[e.trail=4]="trail"}(m||(m={}));export class MultiRenderer extends e{constructor(e,t,r,a){super(),this.worldContainer=e,this.localContainer=t,this.three=r,this.view=a,this.localRenderers=[],this.worldRenderers=[]}onSystemUpdate(){for(const e of this.worldRenderers)e?.onSystemUpdate();for(const e of this.localRenderers)e?.onSystemUpdate()}onParticleCreated(e){e.target=null,this.getRenderer(e)?.onParticleCreated(e)}onParticleUpdate(e){this.getRenderer(e)?.onParticleUpdate(e)}onParticleDead(e){this.getRenderer(e)?.onParticleDead(e),e._renderer=null}getRenderer(e){if(e._renderer)return e._renderer;const t=(null!=e?.parent?e?.parent._space:null)??"world",r="world"===t?this.worldContainer:this.localContainer,o="world"===t?this.worldRenderers:this.localRenderers;return"trail"===e.body.type?(null==o[m.trail]&&(o[m.trail]=new TrailRenderer(r,this.three)),e._renderer=o[m.trail]):e.body instanceof s?(null==o[m.stretchedBillboard]&&(o[m.stretchedBillboard]=new StretchedSpriteInstancedRenderer(r,this.three,this.view)),e._renderer=o[m.stretchedBillboard]):e.body instanceof a.Sprite||e.body instanceof a.Mesh&&"sprite"===e.body.name?(null==o[m.sprite]&&(o[m.sprite]=new CombinedRenderer(r,this.three)),e._renderer=o[m.sprite]):e.body instanceof a.Mesh&&0==e.body.children.length&&e.body.material instanceof n?(null==o[m.instanced]&&(o[m.instanced]=new InstancedRenderer(r,this.three,this.view)),e._renderer=o[m.instanced]):e.body instanceof a.Object3D?(null==o[m.mesh]&&(o[m.mesh]=new CombinedRenderer(r,this.three)),e._renderer=o[m.mesh]):void 0}dispose(){this.localRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()}),this.worldRenderers.forEach(e=>{e instanceof InstancedRenderer&&e.dispose()})}}export class TrailRenderer extends t{constructor(){super(...arguments),this.trails=[]}dispose(){}onSystemUpdate(){for(const e of this.trails)e.update()}onParticleCreated(e){const t=e.body,r=new l(this.container,!1),o=new i;this.container.add(o),o.updateMatrixWorld(),o.updateWorldMatrix(!0,!0);const n=t.material?.clone()??l.createBaseMaterial(t.texture,t.scrollSpeed,t.opacityChannel,t.billboard??!1);n.uniforms.taper&&(n.uniforms.taper.value=t.taper??!1);const s=new a.Color(t.color??0).multiplyScalar(t.intensity),c=new a.Color(t.colorEnd??0).multiplyScalar(t.intensityEnd??t.intensity??1);n.uniforms.headColor&&n.uniforms.tailColor&&(n.uniforms.headColor.value=new a.Vector4(s.r,s.g,s.b,t.opacityStart??1),n.uniforms.tailColor.value=new a.Vector4(c.r,c.g,c.b,t.opacityEnd??1)),n.uniforms.color&&null==n.uniforms.headColor&&(n.uniforms.color.value=s),n.uniforms.opacity&&null==n.uniforms.headColor&&(n.uniforms.opacity.value=t.opacityStart??1),t.bloom&&(n.userData.hasBloom=!0),r.initialize(n,Math.round(t.length??10),!1,t.width,null,o,t.billboard??!1);const d=e.rotation;o.rotation.set(d.x,d.y,d.z);e.scale;r.activate(),this.trails.push(r),e.target=o}onParticleUpdate(e){const t=e.target;t.position.copy(e.position);const r=e.body;let a=A;e.old&&e.old.position?a.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize():a.copy(e.velocity).normalize();const o=w;o.setFromUnitVectors(a,b),t.rotation.set(0,0,0),t.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),t.applyQuaternion(o);const i=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=i){const t=this.trails[i];if(e.useAlpha){if(t.material.uniforms.headColor&&t.material.uniforms.tailColor){t.material.uniforms.headColor.value.setW(r.opacityStart*e.alpha);t.material.uniforms.tailColor.value.setW(r.opacityEnd*e.alpha)}null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha)}e.useColor&&null!=t.material.uniforms.color&&t.material.uniforms.color.value.copy(e.color),null!=t.material.uniforms[d]&&(t.material.uniforms[d].value=e.energy)}}onParticleDead(e){const t=e.target,r=this.trails.findIndex(e=>e.targetObject.id===t.id);if(-1!=r){const e=this.trails[r];e.removeFromParent(),e.mesh.removeFromParent(),e.targetObject.removeFromParent(),t.removeFromParent(),this.trails.splice(r,1)}}}export class CombinedRenderer extends t{dispose(){}scale(e){const t=e.transform.initialScale;e.target instanceof a.Sprite?null!=t?e.target.scale.set(t.x*e.scale*e.radius,t.y*e.scale*e.radius,1):e.target.scale.set(e.scale*e.radius,e.scale*e.radius,1):null!=t?e.target.scale.set(t.x*e.scale,t.y*e.scale,t.z*e.scale):super.scale(e)}rotate(e){e.target.material.rotation=e.rotation.z}onParticleCreated(e){e.target||(e.target=this._targetPool.get(e.body),(e.useAlpha||e.useColor)&&(e.target instanceof a.Mesh||e.target instanceof a.Sprite&&e.target.material instanceof a.Material)&&(e.target.material.__puid=r.id(e.body.material),e.target.material=this._materialPool.get(e.target.material))),e.target&&e.target instanceof i&&(e.target.position.set(e.position.x,e.position.y,e.position.z),this.container.add(e.target))}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:o,rotation:n}=e;if(t){if(t.position.copy(e.position),this.isThreeSprite(e)||(t instanceof a.Mesh&&t.material instanceof c?e.target.material.rotation=e.rotation.z:t.rotation.set(n.x,n.y,n.z)),this.scale(e),e.transform&&e.transform.orientAlongVelocity&&t instanceof i){const r=u.set(e.velocity.x,e.velocity.y,e.velocity.z).normalize(),a=t.getWorldDirection(p);a.applyAxisAngle(f,Math.PI/-2),h.setFromUnitVectors(a,r),t.quaternion.copy(h)}t.material instanceof a.Material&&(r&&(t.material instanceof c&&null!=t.material.uniforms.opacity&&(t.material.uniforms.opacity.value=e.alpha,t.material.uniformsNeedUpdate=!0),t.material.opacity=e.alpha,t.material.transparent=!0),o&&(null!=t.material.color?t.material.color.copy(e.color):t.material instanceof a.ShaderMaterial&&null!=t.material.uniforms.color&&(t.material.uniforms.color.value=e.color,t.material.uniformsNeedUpdate=!0)))}}onParticleDead(e){e.target&&(e.target.material&&(e.useAlpha||e.useColor)&&this._materialPool.expire(e.target.material),this._targetPool.expire(e.target),this.container.remove(e.target),e.target=null)}}export class StretchedSpriteInstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.geometry.dispose())}onSystemUpdate(){for(const e of this.meshes){const t=e.mesh.geometry.getAttribute("offset"),r=e.mesh.geometry.getAttribute("size"),o=e.mesh.geometry.getAttribute("velocity"),i=e.mesh.geometry.getAttribute("rotation"),n=e.mesh.geometry.getAttribute("color");let s=0;for(const l of e.particles){if(null==l||l.dead)continue;if(l.useColor||l.color instanceof a.Color){const e=M.copy(l.color).getRGB(P);n.setXYZW(s,e.r,e.g,e.b,1),n.needsUpdate=!0}l.useAlpha&&(n.setW(s,l.alpha),n.needsUpdate=!0),"number"==typeof l.rotation?i.setX(s,l.rotation):i.setX(s,l.rotation.x);const e=l.position;if(t.setXYZ(s,e.x,e.y,e.z),"number"!=typeof l.scale)throw new Error("Particle scale is not a number");r.setXYZ(s,l.scale,l.scale,l.scale);let c=l.body.scaleFactor;0===c&&(c=.001);const d=1,m=l.velocity;o.setXYZW(s,m.x*c,m.y*c,m.z*c,d),s++}s>0&&(t.clearUpdateRanges(),t.addUpdateRange(0,3*s),t.needsUpdate=!0,r.clearUpdateRanges(),r.addUpdateRange(0,3*s),r.needsUpdate=!0,n.clearUpdateRanges(),n.addUpdateRange(0,4*s),n.needsUpdate=!0,o.clearUpdateRanges(),o.addUpdateRange(0,4*s),o.needsUpdate=!0,i.clearUpdateRanges(),i.addUpdateRange(0,s),i.needsUpdate=!0)}}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof s&&null==e.target){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(null==r){const i=this.calcMaxCount(e),n=new a.InstancedBufferGeometry;n.setIndex(t.geometry.getIndex()),n.setAttribute("position",t.geometry.getAttribute("position")),t.geometry.hasAttribute("normal")&&n.setAttribute("normal",t.geometry.getAttribute("normal")),n.setAttribute("uv",t.geometry.getAttribute("uv"));const s=new o(new Float32Array(3*i),3);s.setUsage(a.DynamicDrawUsage),n.setAttribute("offset",s);const l=new o(new Float32Array(4*i),4);if(l.setUsage(a.DynamicDrawUsage),n.setAttribute("color",l),t.material instanceof c){const e=new a.Color(t.material.color);for(let t=0;t<l.count;t++)l.setXYZW(t,e.r,e.g,e.b,1)}const d=new o(new Float32Array(3*i),3);d.setUsage(a.DynamicDrawUsage),n.setAttribute("size",d);const m=new o(new Float32Array(4*i),4);m.setUsage(a.DynamicDrawUsage),n.setAttribute("velocity",m);const u=new o(new Float32Array(4*i),1);u.setUsage(a.DynamicDrawUsage),n.setAttribute("rotation",u),r={mesh:new a.Mesh(n,t.material),indices:new Float32Array(i),particles:[]},this.meshes.push(r),this.container.add(r.mesh)}let i=r.indices.findIndex(e=>0===e);i<0&&(i=function(e){let t=e[0],r=0;for(let a=1;a<e.length;a++)e[a]<t&&(t=e[a],r=a);return r}(r.indices)),r.indices[i]=performance.now(),e.target=i,r.particles[i]=e}}onParticleUpdate(e){}onParticleDead(e){const t=e.body;let r=this.meshes.find(e=>e.mesh.material.uuid===t.material.uuid);if(r){const t=r.mesh.geometry.getAttribute("size");t.setXYZ(e.target,0,0,0),t.needsUpdate=!0,r.particles[e.target]=null,r.indices[e.target]=0}e.target=null}}const u=new a.Vector3,p=new a.Vector3,h=new a.Quaternion,f=new a.Vector3(1,0,0);export class InstancedRenderer extends t{constructor(e,t,r){super(e,t),this.view=r,this.meshes=[]}dispose(){this.meshes.forEach(e=>e.mesh.dispose())}onSystemUpdate(){for(const e of this.meshes);}calcMaxCount(e){if(null==e)return 1;const t=e.parent.rate,r=t.timePan.a;if(!Number.isFinite(r)||r<=0)return t.numPan.b*this.calcMaxCount(e.parent.parentParticle);return Math.min(t.numPan.b*Math.ceil(e.life/Math.min(Math.max(t.timePan.a,.01),1)),1e5)*this.calcMaxCount(e.parent.parentParticle)}onParticleCreated(e){if(e.body instanceof a.Sprite)return;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r){const o=this.calcMaxCount(e);r={mesh:new a.InstancedMesh(t.geometry,t.material,o),indices:new Array(o).fill(null),particles:[]},r.mesh.renderOrder=t.renderOrder,r.mesh.setColorAt(0,M.setScalar(1)),r.mesh.instanceColor.needsUpdate=!0,r.mesh.material.defines.USE_INSTANCING="";const i=new Float32Array(3*o);x.makeScale(0,0,0);for(let e=0;e<o;e++)i[3*e+0]=1,i[3*e+1]=1,r.mesh.setMatrixAt(e,x);r.mesh.instanceMatrix.needsUpdate=!0,r.mesh.geometry.setAttribute("particleData",new a.InstancedBufferAttribute(i,3)),this.meshes.push(r),this.container.add(r.mesh)}let o=r.indices.findIndex(e=>null==e);if(o<0&&(o=r.indices.indexOf(Math.min(...r.indices))),r.indices[o]=performance.now(),e.target=o,r.particles[o]=e,"number"==typeof e.target){e.transform.initialScale;const t=e.body;let r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);y(e,r.mesh),e.useAlpha&&(r.mesh.material.transparent=!0)}}onParticleUpdate(e){const{target:t,useAlpha:r,useColor:a,rotation:o}=e;if(null==t)return;const i=e.body,n=this.meshes.find(e=>e.mesh.geometry.uuid===i.geometry.uuid&&e.mesh.material.uuid===i.material.uuid);if(null==n)return;n.mesh.frustumCulled=!1,y(e,n.mesh),a&&(n.mesh.setColorAt(e.target,M.copy(e.color)),n.mesh.instanceColor.needsUpdate=!0);const s=n.mesh.geometry.getAttribute("particleData");r&&s.setX(e.target,e.alpha),s.setY(e.target,e.energy),s.needsUpdate=!0}onParticleDead(e){if(null!=e.target){const t=e.body,r=this.meshes.find(e=>e.mesh.geometry.uuid===t.geometry.uuid&&e.mesh.material.uuid===t.material.uuid);if(null==r)return;r.indices[e.target]=null,e.scale=0,y(e,r.mesh),r.mesh.instanceMatrix.needsUpdate=!0,e.target=null}}}const g=new i;function y(e,t){if(A.set(e.position.x,e.position.y,e.position.z),e.transform&&e.transform.orientAlongVelocity){const r=u.set(e.position.x-e.old.position.x,e.position.y-e.old.position.y,e.position.z-e.old.position.z).normalize();t.getMatrixAt(e.target,g.matrix);const a=g.getWorldDirection(U);a.applyAxisAngle(f,Math.PI/-2),w.setFromUnitVectors(a,r)}else C.set(e.rotation.x,e.rotation.y,e.rotation.z),w.setFromEuler(C);const r=e.transform.initialScale;null!=r?U.set(r.x*e.scale,r.y*e.scale,r.z*e.scale):U.set(e.scale,e.scale,e.scale),x.compose(A,w,U),t.setMatrixAt(e.target,x),t.instanceMatrix.needsUpdate=!0}const b=new a.Vector3(0,0,-1),x=new a.Matrix4,w=new a.Quaternion,A=new a.Vector3,U=new a.Vector3,C=new a.Euler,M=new a.Color(0),P={r:0,g:0,b:0};function R(e,t){const r=e.mesh,o=r.count,i=[],n=r.geometry.getAttribute("particleData"),s=new a.Vector3;for(let l=0;l<o;l++){const o=new a.Matrix4,c=new a.Color;r.getMatrixAt(l,o),r.getColorAt(l,c);const d=n.getX(l);s.setFromMatrixPosition(o);const m=s.distanceTo(t.position);i.push({index:l,distance:m,matrix:o,particle:e.particles[l],color:c,pdx:d})}i.sort((e,t)=>t.distance-e.distance);for(let e=0;e<o;e++){const t=i[e].matrix;null==i[e].particle&&t.makeScale(0,0,0),r.setMatrixAt(e,t),r.setColorAt(e,i[e].color),n.setX(e,i[e].pdx)}r.instanceMatrix.needsUpdate=!0}export{R as sortInstancedMeshByDistance};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as d,SkinnedMesh as p,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";const I=new d(0,-1,0),B=new d(0,1,0),x=new d(1,1,1),D=new f,F=new d,P=new d,R=new d,A=new d,M=new d,T=new f,W=new f,O=new f,V=new f,C=new g,q=new g,H=new d(1,0,0),E=new d(0,1,0),z=new d(0,0,1);function N(){return{point:new d,normal:new d,hasNormal:!1}}const U=["mixamorigHips","Hips","hips","Pelvis","pelvis"],j={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},Q={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},G=["left","right"];let _=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new d,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:N(),toe:N(),heel:N(),side:N()},this.footIkAxesScratch={up:new d,forward:new d,right:new d},this.footIkSampleAxesScratch={forward:new d,right:new d},this.footIkScratch={footWorldPos:new d,centerRayStart:new d,toeRayStart:new d,heelRayStart:new d,sideRayStart:new d,desiredTargetPos:new d,desiredNormal:new d,desiredForward:new d,debugRayEndA:new d,debugRayEndB:new d,debugRayEndC:new d,debugRayEndD:new d,debugRayEndE:new d,debugRayEndF:new d},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=J(t=>t.uuid,t=>K(this.fullBodyMask,t)),this.getUpperBodyClip=J(t=>t.uuid,t=>K(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,I),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(I,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(Z(t,e)||Z(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof p||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=Y(e),this.fullBodyMask=function(t,e){const o=new Set(Y(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(X(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t),this.updateFootIk(t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,j),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,Q);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??X(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),d=i.getBoneByName("_IKTargetRightFoot"),p=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),p=!0),null==d&&(d=new l,d.name="_IKTargetRightFoot",h.add(d),p=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(F)),this.setBoneWorldPosition(d,r.foot.getWorldPosition(F)),p||i.bones.indexOf(c)<0||i.bones.indexOf(d)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(d)<0&&(t.push(d),e.push((new g).copy(d.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:d};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(d),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof p||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...U]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(F),o=t.lower.getWorldPosition(P),i=t.foot.getWorldPosition(R),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(F.copy(e))),t.quaternion.copy(D),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),d=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,d),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:d}}createDebugArrow(t){const e=new m(B,new d,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){F.subVectors(o,e);const i=F.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(F.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of G){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(F);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of G){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(F),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(P),r=R.copy(s).addScaledVector(B,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(P),h=R.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(T)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=C.copy(t.boneInverses[i]).invert(),n=q.copy(r).multiply(s),d=F.setFromMatrixPosition(n),p=A.copy(d).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,p.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(F),i=t.foot.getWorldPosition(P),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=A.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(B),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),d=r.centerRayStart.copy(l).addScaledVector(B,this.footIkRayStartHeight),p=r.toeRayStart.copy(d).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(d).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(d).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(d,n.center),m=this.getFirstGroundHit(p,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,I=this.footIkWeightOutSpeed;const x=null!=g||null!=m||null!=k;let D=l.y;null!=g?D=g.point.y:null!=m&&null!=k?D=.5*(m.point.y+k.point.y):null!=m?D=m.point.y:null!=k&&(D=k.point.y);const F=this.ikBoneRefs?.[t],P=this.ikLegLengths?.[t],R=null!=F&&null!=P?this.computeLegExtensionRatio(F,P):1,A=Math.max(0,l.y-D,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,x,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,I=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-I*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:d,toeRayStart:p,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),d=this.computeFootVerticalSpeed(s,c,n),p=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,p,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(B,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),I=l.desiredNormal.set(0,1,0),x=l.desiredForward.copy(u.forward);let D=0,F=0,P=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,d,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,I)){this.computeDesiredFootForward(u.forward,u.right,I,w,b,x),D=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(D))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),F=1,P=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,I,null,null,x),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-P*n);s.targetPosition.lerp(v,O),s.normal.lerp(I,O).normalize(),s.forward.lerp(x,O).normalize(),s.pitch=y.lerp(s.pitch,D,O),s.weight=y.lerp(s.weight,F,V),s.planted=W&&F>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:I,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(I,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(I,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(I,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(I,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new d,right:new d},n=this.actor.object.getWorldDirection(A);n.addScaledVector(B,-n.dot(B)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(B,-s.forward.dot(B)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=M.crossVectors(B,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,A);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=P.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=R.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(B),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(B)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(A)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=A.copy(this.actor.object.getWorldDirection(A));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=P.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=T.copy(e.quaternion),l=W.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=O.setFromAxisAngle(t.rightLocal,.15);return R.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=P.subVectors(i,o),r=s.dot(B),n=R.copy(s).addScaledVector(B,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(B,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(F).clone(),c=P.subVectors(i,h),d=c.length(),p=.995*e.total;d>p&&d>1e-6&&i.copy(h).addScaledVector(c,p/d)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(F).clone(),s=e.lower.getWorldPosition(P).clone(),r=e.foot.getWorldPosition(R).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new d).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,p=n+l-1e-4,u=y.clamp(h,c,p),f=a.multiplyScalar(1/h),g=(new d).subVectors(s,i).normalize(),m=(new d).subVectors(r,s).normalize(),k=(new d).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(F).cross(B)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new d).copy(i).addScaledVector(f,S);let v=(new d).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new d).crossVectors(f,B),v.lengthSq()<1e-8&&(v=new d(1,0,0))),v.normalize();const I=(new d).copy(L).addScaledVector(v,b),x=(new d).copy(L).addScaledVector(v,-b),D=(new d).subVectors(s,L).dot(v)>=0?I:x;this.rotateBoneToward(e.upper,i,s,D),e.upper.updateMatrixWorld(!0);const A=e.lower.getWorldPosition(P),M=e.foot.getWorldPosition(R);this.rotateBoneToward(e.lower,A,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,D,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new d).subVectors(o,e),r=(new d).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(T),a=W.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(O),c=V.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(T),o=this.actor.object.getWorldDirection(F);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:E.clone(),world:E.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)}];i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:E.clone().multiplyScalar(-1),world:E.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(B);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new d,forward:new d,right:new d},r=e.getWorldQuaternion(T);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(B),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(B,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){T.copy(t.quaternion),t.quaternion.copy(e).slerp(T,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=F.copy(o.normal).normalize(),n=P.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=R.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(A.crossVectors(l,r)).normalize(),C.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),T.setFromRotationMatrix(C),q.makeBasis(l,r,n),W.setFromRotationMatrix(q);const a=O.copy(W).multiply(V.copy(T).invert()),h=e.parent.getWorldQuaternion(V),c=W.copy(h).invert().multiply(a),d=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(d,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyTimer=0}beginExternalAnimationControl(t,e={}){$(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){$(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){if(null!=t&&t.getClip().uuid===e.uuid)return t;const i=o?.fadeTime??this.fadeTime;if(t){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.fadeIn(i),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};_=t([o({inEditor:!0})],_);export{_ as CharacterAnimationComponent};function K(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function Y(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function $(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function J(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function X(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function Z(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
1
+ import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as d,SkinnedMesh as p,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";const B=new d(0,-1,0),I=new d(0,1,0),x=new d(1,1,1),D=new f,F=new d,P=new d,R=new d,A=new d,M=new d,T=new f,W=new f,O=new f,V=new f,C=new g,E=new g,q=new d(1,0,0),H=new d(0,1,0),z=new d(0,0,1);function N(){return{point:new d,normal:new d,hasNormal:!1}}const U=["mixamorigHips","Hips","hips","Pelvis","pelvis"],j={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},Q={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},G=["left","right"];let _=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new d,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:N(),toe:N(),heel:N(),side:N()},this.footIkAxesScratch={up:new d,forward:new d,right:new d},this.footIkSampleAxesScratch={forward:new d,right:new d},this.footIkScratch={footWorldPos:new d,centerRayStart:new d,toeRayStart:new d,heelRayStart:new d,sideRayStart:new d,desiredTargetPos:new d,desiredNormal:new d,desiredForward:new d,debugRayEndA:new d,debugRayEndB:new d,debugRayEndC:new d,debugRayEndD:new d,debugRayEndE:new d,debugRayEndF:new d},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=J(t=>t.uuid,t=>K(this.fullBodyMask,t)),this.getUpperBodyClip=J(t=>t.uuid,t=>K(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,B),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(B,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(Z(t,e)||Z(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof p||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=Y(e),this.fullBodyMask=function(t,e){const o=new Set(Y(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(X(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t),this.updateFootIk(t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,j),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,Q);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??X(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),d=i.getBoneByName("_IKTargetRightFoot"),p=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),p=!0),null==d&&(d=new l,d.name="_IKTargetRightFoot",h.add(d),p=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(F)),this.setBoneWorldPosition(d,r.foot.getWorldPosition(F)),p||i.bones.indexOf(c)<0||i.bones.indexOf(d)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(d)<0&&(t.push(d),e.push((new g).copy(d.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:d};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(d),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof p||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...U]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(F),o=t.lower.getWorldPosition(P),i=t.foot.getWorldPosition(R),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(F.copy(e))),t.quaternion.copy(D),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),d=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,d),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:d}}createDebugArrow(t){const e=new m(I,new d,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){F.subVectors(o,e);const i=F.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(F.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of G){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(F);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of G){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(F),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(P),r=R.copy(s).addScaledVector(I,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(P),h=R.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(T)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=C.copy(t.boneInverses[i]).invert(),n=E.copy(r).multiply(s),d=F.setFromMatrixPosition(n),p=A.copy(d).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,p.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(F),i=t.foot.getWorldPosition(P),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=A.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(I),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),d=r.centerRayStart.copy(l).addScaledVector(I,this.footIkRayStartHeight),p=r.toeRayStart.copy(d).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(d).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(d).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(d,n.center),m=this.getFirstGroundHit(p,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,B=this.footIkWeightOutSpeed;const x=null!=g||null!=m||null!=k;let D=l.y;null!=g?D=g.point.y:null!=m&&null!=k?D=.5*(m.point.y+k.point.y):null!=m?D=m.point.y:null!=k&&(D=k.point.y);const F=this.ikBoneRefs?.[t],P=this.ikLegLengths?.[t],R=null!=F&&null!=P?this.computeLegExtensionRatio(F,P):1,A=Math.max(0,l.y-D,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,x,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,B=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-B*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:d,toeRayStart:p,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),d=this.computeFootVerticalSpeed(s,c,n),p=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,p,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(I,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),B=l.desiredNormal.set(0,1,0),x=l.desiredForward.copy(u.forward);let D=0,F=0,P=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,d,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,B)){this.computeDesiredFootForward(u.forward,u.right,B,w,b,x),D=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(D))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),F=1,P=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,B,null,null,x),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-P*n);s.targetPosition.lerp(v,O),s.normal.lerp(B,O).normalize(),s.forward.lerp(x,O).normalize(),s.pitch=y.lerp(s.pitch,D,O),s.weight=y.lerp(s.weight,F,V),s.planted=W&&F>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:B,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(B,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(B,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(B,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(B,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new d,right:new d},n=this.actor.object.getWorldDirection(A);n.addScaledVector(I,-n.dot(I)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(I,-s.forward.dot(I)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=M.crossVectors(I,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,A);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=P.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=R.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(I),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(I)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(A)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=A.copy(this.actor.object.getWorldDirection(A));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=P.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=T.copy(e.quaternion),l=W.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=O.setFromAxisAngle(t.rightLocal,.15);return R.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=P.subVectors(i,o),r=s.dot(I),n=R.copy(s).addScaledVector(I,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(I,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(F).clone(),c=P.subVectors(i,h),d=c.length(),p=.995*e.total;d>p&&d>1e-6&&i.copy(h).addScaledVector(c,p/d)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(F).clone(),s=e.lower.getWorldPosition(P).clone(),r=e.foot.getWorldPosition(R).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new d).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,p=n+l-1e-4,u=y.clamp(h,c,p),f=a.multiplyScalar(1/h),g=(new d).subVectors(s,i).normalize(),m=(new d).subVectors(r,s).normalize(),k=(new d).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(F).cross(I)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new d).copy(i).addScaledVector(f,S);let v=(new d).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new d).crossVectors(f,I),v.lengthSq()<1e-8&&(v=new d(1,0,0))),v.normalize();const B=(new d).copy(L).addScaledVector(v,b),x=(new d).copy(L).addScaledVector(v,-b),D=(new d).subVectors(s,L).dot(v)>=0?B:x;this.rotateBoneToward(e.upper,i,s,D),e.upper.updateMatrixWorld(!0);const A=e.lower.getWorldPosition(P),M=e.foot.getWorldPosition(R);this.rotateBoneToward(e.lower,A,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,D,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new d).subVectors(o,e),r=(new d).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(T),a=W.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(O),c=V.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(T),o=this.actor.object.getWorldDirection(F);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:q.clone(),world:q.clone().applyQuaternion(e)},{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)}];i.push({local:q.clone().multiplyScalar(-1),world:q.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(I);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new d,forward:new d,right:new d},r=e.getWorldQuaternion(T);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(I),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(I,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){T.copy(t.quaternion),t.quaternion.copy(e).slerp(T,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=F.copy(o.normal).normalize(),n=P.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=R.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(A.crossVectors(l,r)).normalize(),C.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),T.setFromRotationMatrix(C),E.makeBasis(l,r,n),W.setFromRotationMatrix(E);const a=O.copy(W).multiply(V.copy(T).invert()),h=e.parent.getWorldQuaternion(V),c=W.copy(h).invert().multiply(a),d=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(d,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,null==this.fullBodyAction||this.fullBodyAction.isRunning()||(this.fullBodyAction=null),null==this.upperBodyAction||this.upperBodyAction.isRunning()||(this.upperBodyAction=null),this.fullBodyTimer=0}cancelRootMotionAction(t){null!=t&&this.fullBodyAction!==t||(this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyAction?.stop(),this.fullBodyAction=null,this.fullBodyTimer=0)}beginExternalAnimationControl(t,e={}){$(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){$(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){const i=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return t.isRunning()||(t.reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play(),!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0)),t;if(t&&t.isRunning()){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};_=t([o({inEditor:!0})],_);export{_ as CharacterAnimationComponent};function K(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function Y(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function $(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function J(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function X(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function Z(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -27,6 +27,7 @@ export declare class CharacterMovementComponent extends ActorComponent {
27
27
  normalizedDirection: boolean;
28
28
  /** Collide with other characters */
29
29
  characterCollision: boolean;
30
+ allowRootMotionJumpCancel: boolean;
30
31
  get autoStepMinWidth(): number;
31
32
  set autoStepMinWidth(minWidth: number);
32
33
  get autoStepDynamicObjects(): boolean;
@@ -56,6 +57,7 @@ export declare class CharacterMovementComponent extends ActorComponent {
56
57
  private resetRootMotion;
57
58
  private rootMotionInterpolant;
58
59
  private rootMotionRootBone;
60
+ private rootMotionOptions;
59
61
  /**
60
62
  * Makes the character rotate to the direction of movement input instead
61
63
  * of strafing or walking backwards
@@ -79,7 +81,8 @@ export declare class CharacterMovementComponent extends ActorComponent {
79
81
  applyImpulse(impulse: Vector3): void;
80
82
  private debugDirection;
81
83
  private rootMotionAction;
82
- setRootMotionAction(action: AnimationAction): void;
84
+ setRootMotionAction(action: AnimationAction, options?: RootMotionActionOptions): void;
85
+ private clearRootMotionAction;
83
86
  private getWallDirection;
84
87
  private moveTo;
85
88
  getEffectiveGravity(): number;
@@ -90,4 +93,8 @@ export declare class CharacterMovementComponent extends ActorComponent {
90
93
  private performMovement;
91
94
  private arrowHelper;
92
95
  }
96
+ export type RootMotionActionOptions = {
97
+ cancelWithJump?: boolean;
98
+ onJumpCancel?: () => void;
99
+ };
93
100
  //# sourceMappingURL=character-movement.d.ts.map
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Vector3 as a}from"three";import{RootMotionClip as c}from"../../../../../gameplay/animation/root-motion.js";import{ActionInput as h,AxisInput as l,RotationInput as p}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as m,RayTestResult as u}from"../../../../../gameplay/services/physics/physics-system.js";import{CapsuleCollisionShape as d}from"../../../../../scene/collision/collision-shape.js";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{ActorComponent as g,Component as f}from"../../../component.js";import{CharacterMovementMode as S}from"./modes.js";import{inject as M}from"../../../../../gameplay/inject.js";const w=new a,v=new a,x=1/30,b=131070;let I=class extends g{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}constructor(){super(),this.directionInput=new l,this.jumpInput=new h,this.sprintInput=new h,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.enabled=!0,this.velocity=new a,this.mode=S.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new u,this.physicsSystem=M(m),this.resetRootMotion=!1,this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulse=new a,this.impulseDamping=2;const t=this.cc=this.physicsSystem.getCharacterController(.1);t.enableSnapToGround(.1),t.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation);let e=this.rotationInput.rotation.y;const i=new a,n=new a,h=new a,l=new a,p=new a,m=new a,u=new a;let d=0,g=null;const f=new a,M=new a,I=new a,A=new a,R=new a,z=new a,C=new a,k=this.characterCollision?null:b;let E=this.rotateToMovementDirection;this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(o=>{if(this.checkGrounded(o),!this.enabled)return;if(M.set(0,0,0),null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof c){const t=this.rootMotionInterpolant;this.resetRootMotion&&(f.fromArray(t.evaluate(0)),this.resetRootMotion=!1),z.fromArray(t.evaluate(this.rootMotionAction.time)),M.subVectors(z,f),f.copy(z);(this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(R),M.multiply(R)}}o>x&&(o=x);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled,b=y&&0!==M.lengthSq();this.pressedJump=!y&&this.jumpInput.activated,this.isSprinting=!y&&this.sprintInput.activated;const B=E!==this.rotateToMovementDirection;let H=r.euclideanModulo(this.rotationInput.rotation.y-e+Math.PI,2*Math.PI)-Math.PI;B&&(this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)),E?this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)):(H=0,e=this.rotationInput.rotation.y),E=this.rotateToMovementDirection),h.copy(this.actor.position),l.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const N=!this.rotateToMovementDirection&&l.z<0?this.maxSpeedBackwards:(this.isSprinting?this.maxSpeedSprint:this.maxSpeed)*(this.normalizedDirection?1:Math.min(1,this.directionInput.vector.length()));if(u.set(0,0,0),y)e=this.rotationInput.rotation.y;else if(this.rotateToMovementDirection&&!y){if(l.lengthSq()>0&&this.mode!=S.falling){const t=this.smoothRotation,i=q.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,s=Math.atan2(l.x,l.z),n=.99*this.rotationInput.rotation.y+s;if(t){r.clamp(.5*l.dot(p)+.5,.001,1);const t=r.euclideanModulo(n-i+Math.PI,2*Math.PI)-Math.PI;let e=r.clamp(t*this.rotationSpeed*o,-this.maxRotationSpeed*o,this.maxRotationSpeed*o);Math.abs(e)>Math.abs(t)&&(e=t),this.actor.object.quaternion.setFromEuler(q.set(0,i+e,0))}else this.actor.object.quaternion.setFromEuler(q.set(0,n,0));p.lerp(l,o*this.rotationSpeed),e+=H,u.copy(this.actor.object.getWorldDirection(F).normalize())}}else b||(e+=H,this.actor.object.quaternion.multiply(G.setFromEuler(q.set(0,H,0))),l.lengthSq()>0&&u.copy(l).applyQuaternion(this.actor.object.quaternion).normalize());if(C.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,C),this.mode===S.walking?(0!==u.lengthSq()?(d=Math.min(N,d),d=r.lerp(d,N,4*o)):d=0,m.copy(u).multiplyScalar(d),this.pressedJump&&(this.mode=S.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),m.y=o*this.getEffectiveGravity(),m.add(C)):this.mode===S.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=S.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),this.velocity.y+=o*this.getEffectiveGravity(),m.copy(this.velocity),m.addScaledVector(u,this.fallingMovementControl),this.fallingReorientation&&m.applyAxisAngle(new a(0,1,0),H)),b&&(I.copy(M).applyQuaternion(this.actor.quaternion),A.copy(I).divideScalar(o),this.mode===S.walking?(m.x=A.x+C.x,m.z=A.z+C.z):(m.x=A.x,m.z=A.z),l.lengthSq()>0)){const t=Math.sqrt(A.x*A.x+A.z*A.z);t>.4&&(d=t)}if(this.impulse.lengthSq()>.1){const t=Math.min(1,this.impulse.length()/5);m.x=r.lerp(m.x,this.impulse.x,t),m.z=r.lerp(m.z,this.impulse.z,t),m.y+=this.impulse.y;const e=Math.exp(-this.impulseDamping*o);this.impulse.x*=e,this.impulse.y>0?this.impulse.y+=o*this.getEffectiveGravity():this.impulse.y*=e,this.impulse.z*=e}else this.impulse.set(0,0,0);if(n.copy(m).normalize(),i.copy(m),m.length()>0||!this.isGrounded){if(w.copy(m).multiplyScalar(o),this.isGrounded&&this.mode===S.walking&&(this.rayTestResult.distance>t.offset()||(w.y=Math.max(0,C.y*o)),this.physicsSystem.getActorComputedMovement(this.actor,t,w,k),t.computedCollision(0,D),null!=D&&null!=D.normal1)){const e=(new s.Vector3).copy(D.normal1);Math.acos(e.dot(T))>t.maxSlopeClimbAngle()&&(w.y=.016*this.getEffectiveGravity()*.5)}v.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,w,k))}else v.set(0,0,0);this.physicsSystem.setNextKinematicTranslation(this.actor,v);let P=function(t){if(t.numComputedCollisions()>0){const e=t.computedCollision(0);j.x=e.normal2.x,j.y=e.normal2.y,j.z=e.normal2.z;const i=j.angleTo(T);j.x=e.normal1.x,j.y=e.normal1.y,j.z=e.normal1.z;const o=j.angleTo(T);return!(i<100)&&o>t.minSlopeSlideAngle()}return!1}(t);this.isGrounded&&!P||this.mode!==S.falling&&(null==g?g=performance.now():performance.now()-g>100&&(this.mode=S.falling,this.velocity.copy(i))),this.isGrounded&&this.velocity.y<=0&&(this.mode,S.falling,this.mode=S.walking,this.velocity.y=0,g=null),this.mode,S.walking,this.horizontalSpeed=d})}applyImpulse(t){this.impulse.add(t)}debugDirection(){const t=new n(w,this.actor.position,1,65280);this.actor.object.parent.add(t),setTimeout(()=>{t.removeFromParent()},30);const e=new n(v,this.actor.position,1,16711680);this.actor.object.parent.add(e),setTimeout(()=>{e.removeFromParent()},30)}setRootMotionAction(t){const e=t?.getClip();if(e instanceof c){this.rootMotionAction=t,this.resetRootMotion=!0;const i=[];this.rootMotionInterpolant=e.motionTrack.InterpolantFactoryMethodSmooth(i);const o=s.PropertyBinding.parseTrackName(e.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(o.nodeName)}}getWallDirection(t,e){const i=t.clone().negate().cross(T);return i.dot(e)<0?i.negate():i}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){this.colliderHeight,this.colliderRadius;C.y=-.05,this.physicsSystem.rayTest(A.addVectors(this.actor.position,z.set(0,this.offset,0)),R.addVectors(this.actor.position,C),this.rayTestResult,{excludeActor:this.actor,excludeTriggers:!0})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new d(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2+this.offset,t.collisionGroup=b,t}step(t){}performMovement(t){}arrowHelper(t,e,i){const o=new n(t.clone().normalize(),e,1,i);this.actor.object.parent.add(o),setTimeout(()=>{o.removeFromParent()},30)}};I=t([f({inEditor:!1}),e("design:paramtypes",[])],I);export{I as CharacterMovementComponent};const T=new a(0,1,0),j=new a;const A=new a,R=new a,z=new a(0,1,0),C=new a(0,-.1,0),D=(new a(0,-1,0),new i.CharacterCollision),G=new s.Quaternion,q=new s.Euler,F=new s.Vector3;/*
1
+ import{__decorate as t,__metadata as o}from"tslib";import i from"@dimforge/rapier3d-compat";import{takeUntil as e}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Vector3 as a}from"three";import{RootMotionClip as c}from"../../../../../gameplay/animation/root-motion.js";import{ActionInput as h,AxisInput as l,RotationInput as p}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as m,RayTestResult as u}from"../../../../../gameplay/services/physics/physics-system.js";import{CapsuleCollisionShape as d}from"../../../../../scene/collision/collision-shape.js";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{ActorComponent as g,Component as M}from"../../../component.js";import{CharacterMovementMode as f}from"./modes.js";import{inject as S}from"../../../../../gameplay/inject.js";const w=new a,v=new a,x=1/30,A=131070;let I=class extends g{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}constructor(){super(),this.directionInput=new l,this.jumpInput=new h,this.sprintInput=new h,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.allowRootMotionJumpCancel=!1,this.enabled=!0,this.velocity=new a,this.mode=f.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new u,this.physicsSystem=S(m),this.resetRootMotion=!1,this.rootMotionOptions={},this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulse=new a,this.impulseDamping=2;const t=this.cc=this.physicsSystem.getCharacterController(.1);t.enableSnapToGround(.1),t.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation);let o=this.rotationInput.rotation.y;const i=new a,n=new a,h=new a,l=new a,p=new a,m=new a,u=new a;let d=0,g=null;const M=new a,S=new a,I=new a,j=new a,R=new a,z=new a,C=new a,k=this.characterCollision?null:A;let E=this.rotateToMovementDirection;this.physicsSystem.beforeStep.pipe(e(this.disposed)).subscribe(e=>{if(this.checkGrounded(e),!this.enabled)return;if(S.set(0,0,0),null==this.rootMotionAction||this.rootMotionAction.isRunning()||this.clearRootMotionAction(this.rootMotionAction),null!=this.rootMotionAction&&this.rootMotionOptions.cancelWithJump&&this.jumpInput.activated&&(this.isGrounded||this.jumpInAir)){const t=this.rootMotionAction,o=this.rootMotionOptions.onJumpCancel;this.clearRootMotionAction(t),t.stop(),o?.()}if(null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof c){const t=this.rootMotionInterpolant;this.resetRootMotion&&(M.fromArray(t.evaluate(0)),this.resetRootMotion=!1),z.fromArray(t.evaluate(this.rootMotionAction.time)),S.subVectors(z,M),M.copy(z);(this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(R),S.multiply(R)}}e>x&&(e=x);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled,A=y&&0!==S.lengthSq();this.pressedJump=!y&&this.jumpInput.activated,this.isSprinting=!y&&this.sprintInput.activated;const B=E!==this.rotateToMovementDirection;let H=r.euclideanModulo(this.rotationInput.rotation.y-o+Math.PI,2*Math.PI)-Math.PI;B&&(this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)),E?this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)):(H=0,o=this.rotationInput.rotation.y),E=this.rotateToMovementDirection),h.copy(this.actor.position),l.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const O=!this.rotateToMovementDirection&&l.z<0?this.maxSpeedBackwards:(this.isSprinting?this.maxSpeedSprint:this.maxSpeed)*(this.normalizedDirection?1:Math.min(1,this.directionInput.vector.length()));if(u.set(0,0,0),y)o=this.rotationInput.rotation.y;else if(this.rotateToMovementDirection&&!y){if(l.lengthSq()>0&&this.mode!=f.falling){const t=this.smoothRotation,i=q.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,s=Math.atan2(l.x,l.z),n=.99*this.rotationInput.rotation.y+s;if(t){r.clamp(.5*l.dot(p)+.5,.001,1);const t=r.euclideanModulo(n-i+Math.PI,2*Math.PI)-Math.PI;let o=r.clamp(t*this.rotationSpeed*e,-this.maxRotationSpeed*e,this.maxRotationSpeed*e);Math.abs(o)>Math.abs(t)&&(o=t),this.actor.object.quaternion.setFromEuler(q.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(q.set(0,n,0));p.lerp(l,e*this.rotationSpeed),o+=H,u.copy(this.actor.object.getWorldDirection(F).normalize())}}else A||(o+=H,this.actor.object.quaternion.multiply(G.setFromEuler(q.set(0,H,0))),l.lengthSq()>0&&u.copy(l).applyQuaternion(this.actor.object.quaternion).normalize());if(C.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,C),this.mode===f.walking?(0!==u.lengthSq()?(d=Math.min(O,d),d=r.lerp(d,O,4*e)):d=0,m.copy(u).multiplyScalar(d),this.pressedJump&&(this.mode=f.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),m.y=e*this.getEffectiveGravity(),m.add(C)):this.mode===f.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=f.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),this.velocity.y+=e*this.getEffectiveGravity(),m.copy(this.velocity),m.addScaledVector(u,this.fallingMovementControl),this.fallingReorientation&&m.applyAxisAngle(new a(0,1,0),H)),A&&(I.copy(S).applyQuaternion(this.actor.quaternion),j.copy(I).divideScalar(e),this.mode===f.walking?(m.x=j.x+C.x,m.z=j.z+C.z):(m.x=j.x,m.z=j.z),l.lengthSq()>0)){const t=Math.sqrt(j.x*j.x+j.z*j.z);t>.4&&(d=t)}if(this.impulse.lengthSq()>.1){const t=Math.min(1,this.impulse.length()/5);m.x=r.lerp(m.x,this.impulse.x,t),m.z=r.lerp(m.z,this.impulse.z,t),m.y+=this.impulse.y;const o=Math.exp(-this.impulseDamping*e);this.impulse.x*=o,this.impulse.y>0?this.impulse.y+=e*this.getEffectiveGravity():this.impulse.y*=o,this.impulse.z*=o}else this.impulse.set(0,0,0);if(n.copy(m).normalize(),i.copy(m),m.length()>0||!this.isGrounded){if(w.copy(m).multiplyScalar(e),this.isGrounded&&this.mode===f.walking&&(this.rayTestResult.distance>t.offset()||(w.y=Math.max(0,C.y*e)),this.physicsSystem.getActorComputedMovement(this.actor,t,w,k),t.computedCollision(0,D),null!=D&&null!=D.normal1)){const o=(new s.Vector3).copy(D.normal1);Math.acos(o.dot(b))>t.maxSlopeClimbAngle()&&(w.y=.016*this.getEffectiveGravity()*.5)}v.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,w,k))}else v.set(0,0,0);this.physicsSystem.setNextKinematicTranslation(this.actor,v);let N=function(t){if(t.numComputedCollisions()>0){const o=t.computedCollision(0);T.x=o.normal2.x,T.y=o.normal2.y,T.z=o.normal2.z;const i=T.angleTo(b);T.x=o.normal1.x,T.y=o.normal1.y,T.z=o.normal1.z;const e=T.angleTo(b);return!(i<100)&&e>t.minSlopeSlideAngle()}return!1}(t);this.isGrounded&&!N||this.mode!==f.falling&&(null==g?g=performance.now():performance.now()-g>100&&(this.mode=f.falling,this.velocity.copy(i))),this.isGrounded&&this.velocity.y<=0&&(this.mode,f.falling,this.mode=f.walking,this.velocity.y=0,g=null),this.mode,f.walking,this.horizontalSpeed=d})}applyImpulse(t){this.impulse.add(t)}debugDirection(){const t=new n(w,this.actor.position,1,65280);this.actor.object.parent.add(t),setTimeout(()=>{t.removeFromParent()},30);const o=new n(v,this.actor.position,1,16711680);this.actor.object.parent.add(o),setTimeout(()=>{o.removeFromParent()},30)}setRootMotionAction(t,o={}){const i=t?.getClip();if(i instanceof c){this.rootMotionAction=t,this.rootMotionOptions=o,this.resetRootMotion=!0;const e=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(e);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}getWallDirection(t,o){const i=t.clone().negate().cross(b);return i.dot(o)<0?i.negate():i}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){this.colliderHeight,this.colliderRadius;C.y=-.05,this.physicsSystem.rayTest(j.addVectors(this.actor.position,z.set(0,this.offset,0)),R.addVectors(this.actor.position,C),this.rayTestResult,{excludeActor:this.actor,excludeTriggers:!0})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new d(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2+this.offset,t.collisionGroup=A,t}step(t){}performMovement(t){}arrowHelper(t,o,i){const e=new n(t.clone().normalize(),o,1,i);this.actor.object.parent.add(e),setTimeout(()=>{e.removeFromParent()},30)}};I=t([M({inEditor:!1}),o("design:paramtypes",[])],I);export{I as CharacterMovementComponent};const b=new a(0,1,0),T=new a;const j=new a,R=new a,z=new a(0,1,0),C=new a(0,-.1,0),D=(new a(0,-1,0),new i.CharacterCollision),G=new s.Quaternion,q=new s.Euler,F=new s.Vector3;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,Object3D as f,Quaternion as w,Raycaster as x,Scene as b,Vector3 as B}from"three";import{Service as v}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as A,CapsuleCollisionShape as S,ConeCollisionShape as R,ConvexPolyhedronCollisionShape as D,CylinderCollisionShape as z,PhysicalShapeMesh as T,PlaneCollisionShape as E,SphereCollisionShape as M,toInstancedCollisionShape as P,TrimeshCollisionShape as F}from"../../../index.js";import{LandscapeGroup as I}from"../../../scene/landscape/landscape.js";import{ViewController as V}from"../render.js";import{World as _}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as j}from"../../../utils/three/traverse.js";import{AbstractPhysicsSystem as N}from"./abstract-physics-system.js";import{ActorComponent as W,Component as L}from"../../../gameplay/actors/component.js";import{inject as O}from"../../../gameplay/inject.js";export{Component,ActorComponent,attach,Attach}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new B,K=new B,U=new w,q=new w,H=(new w,[]);let Q=class extends N{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=O(V),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new i.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,s){const o=t+1e6*e+1e12*s;let n=this.shapeCacheBox.get(o);return null==n&&(n=new i.Cuboid(t,e,s),this.shapeCacheBox.set(o,n)),n}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,U,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,U,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(n instanceof i||null==i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,U)&&o.push(n)}return o}createDebugMesh(){return new g(new y,new d.LineBasicMaterial({color:255}))}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene?.add(this.debugMesh));const t=this.world.debugRender().vertices,e=this.debugMesh.geometry,i=e.getAttribute("position");null==i||(i.array.length,t.length);{const i=new u(t,3);i.setUsage(d.DynamicDrawUsage),e.setAttribute("position",i)}e.setDrawRange(0,t.length/3)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await at(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach(t=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;null!=e&&e.parent instanceof b&&(dt(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&ht(e.quaternion,t.rotation()),e.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t)})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})})}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ot,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,n=this._raytestDirection;if(o.subVectors(e,t),n.copy(o).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),i;lt(ft.origin,t),lt(ft.dir,n);const r=o.length(),a=this.world.castRayAndGetNormal(ft,r,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?t=>!t.isSensor():void 0);if(i.hasHit=null!=a,i.hasHit){const e=ft.pointAt(a.timeOfImpact);if(i._internal=a,dt(i.hitNormal,a.normal),dt(i.hitPoint,e),i.distance=yt.subVectors(i.hitPoint,t).length(),!1!==s?.resolveActor){const t=this.world.bodies.getAll().find(t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,t=>t===a.collider));i.actor=null!=t?this.bodyActors.get(t):null}}if(this.showDebug){let e;H.length>0?(e=H.pop(),e.setDirection(n),e.position.copy(t),e.setLength(r,.2,.1),e.setColor(s?.debugColor??255)):e=new h(n,t,r,s?.debugColor??255),this.scene?.add(e),setTimeout(()=>{this.scene?.remove(e),H.push(e)},s?.debugLifetime??200)}return i}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ut(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof T&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof I?this.addLandscapeGroup(t):(t instanceof p||t instanceof b)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map;for(let o=0;o<e.length;o++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[o])continue;const e=t.userData.collisionShapes;let n=e?.[o];if(null==n&&null==e&&t.parent instanceof C&&(n=t.parent.collisionShapes),null==n)continue;let r=s.get(n);null==r&&(r=this.instancedShapeReset(n),s.set(n,r));const a=new f;a.matrix.identity(),t.getMatrixAt(o,i),a.applyMatrix4(i);this.createStaticBody(a,r)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new f;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>P(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,gt);const a=e.computedMovement();return dt(pt,a),pt}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world);return this.colliders.set(i.handle,s),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const s=(()=>{switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return i.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return i.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyDesc.kinematicVelocityBased();default:return i.RigidBodyDesc.dynamic()}})();e.position&&s.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&s.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&s.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&s.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&s.setGravityScale(e.gravityScale),"number"==typeof e.mass&&s.setAdditionalMass(e.mass),void 0!==e.userData&&(s.userData=e.userData);const o=this.world.createRigidBody(s);return new PhysicsBody(o,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,gt);const r=e.computedMovement();return dt(pt,r),pt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setNextKinematicTranslation(nt(i)),t.setNextKinematicRotation(rt(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setAngvel(et,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setLinvel(et,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(nt(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&dt(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(rt(e),!1)}getRotation(t,e=new w){const i=this.actorBodies.get(t.id);i&&ht(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),s=n.scale,r=n.geometry.getAttribute("hole"),a=new Float32Array(t.getAttribute("position").array);for(let t=0;t<a.length;t+=3)a[t]*=s.x,a[t+1]*=s.y,a[t+2]*=s.z;const l=t.index;for(let t=0;t<l.count;t+=3){const e=r.getX(l.getX(t)),i=r.getX(l.getY(t)),s=r.getX(l.getZ(t));(e>.5||i>.5||s>.5)&&(l.setX(t,0),l.setY(t,0),l.setZ(t,0))}const c=i.ColliderDesc.trimesh(a,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(c,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new i.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e)}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let n;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:n=i.RigidBodyDesc.dynamic(),n.mass=s.mass??1;break;case PhysicsBodyType.kinematic:n=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:n=i.RigidBodyDesc.kinematicVelocityBased();break;default:n=s.isTrigger?i.RigidBodyDesc.kinematicVelocityBased():i.RigidBodyDesc.fixed()}const r=this.world.createRigidBody(n);r.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(r,t,o);return ut(r,t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.density&&t.setDensity(s.density),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)}),Y(r,o),!0===s.ignoreForNavMesh&&(r.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,r),this.bodyActors.set(r,t),new PhysicsBody(r,this.world)}applyTorque(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addTorque(et,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyTorqueImpulse(et,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addForce(et,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyImpulse(et,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s?.addForce(et,!0):(lt(it,i),s?.addForceAtPoint(et,it,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s.applyImpulse(et,!0):(lt(it,i),s.applyImpulseAtPoint(et,it,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=st;dt(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);et.x=a.x,et.y=a.y,et.z=a.z,o.applyImpulse(et,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof I){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&Y(e,t.object)}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t}sphereCast(t,e,i,s,o=ShapeCastResult.shared,n){o.reset();const r=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=n?.excludeActor?this.actorBodies.get(n.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,r,.01,s,!0,null,n?.collisionFilter??void 0,null,c,n?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){dt(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return dt(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){this.world?.bodies.forEach(t=>this.world.removeRigidBody(t)),this.world?.free(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),H.length=0}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.sleep(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(mt)??tt,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);lt(o.translation,n);const r=(new w).setFromEuler(e.rotation);ct(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof A)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof S){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof F){const i=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof D){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=j(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=J.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),J.set(o,a),a}if(t instanceof M){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new D(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new B(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof R?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([v(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const $=new B,X=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setTranslation(nt(i),!1),t.setRotation(rt(s),!1)}const Z=new B,J=new Map,tt=new B(1,1,1),et=new i.Vector3(0,0,0),it=new i.Vector3(0,0,0),st=new B,ot=new d.Vector2;function nt(t){return lt(et,t),et}function rt(t){return ct(q,t),q}const at=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const yt=new B,pt=new B,gt=t=>!t.isSensor(),mt=new B;const ft=new i.Ray(new i.Vector3(0,0,0),new i.Vector3(0,1,0));let wt=class extends W{constructor(){super(...arguments),this._active=!0,this.physics=O(Q),this.world=O(_)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([L()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e){this.collider=t,this.world=e,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t)}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e){this.body=t,this.world=e}dispose(){this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t)}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0)}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0)}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static)}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,Object3D as f,Quaternion as w,Raycaster as x,Scene as b,Vector3 as B}from"three";import{Service as v}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as A,CapsuleCollisionShape as S,ConeCollisionShape as R,ConvexPolyhedronCollisionShape as D,CylinderCollisionShape as z,PhysicalShapeMesh as T,PlaneCollisionShape as E,SphereCollisionShape as M,toInstancedCollisionShape as P,TrimeshCollisionShape as F}from"../../../index.js";import{LandscapeGroup as I}from"../../../scene/landscape/landscape.js";import{ViewController as V}from"../render.js";import{World as _}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as j}from"../../../utils/three/traverse.js";import{AbstractPhysicsSystem as N}from"./abstract-physics-system.js";import{ActorComponent as W,Component as L}from"../../../gameplay/actors/component.js";import{inject as O}from"../../../gameplay/inject.js";export{Component,ActorComponent,attach,Attach}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new B,K=new B,U=new w,q=new w,H=(new w,[]);let Q=class extends N{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=O(V),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new i.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,s){const o=t+1e6*e+1e12*s;let n=this.shapeCacheBox.get(o);return null==n&&(n=new i.Cuboid(t,e,s),this.shapeCacheBox.set(o,n)),n}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,U,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,U,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(n instanceof i||null==i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,U)&&o.push(n)}return o}createDebugMesh(){return new g(new y,new d.LineBasicMaterial({color:255}))}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene?.add(this.debugMesh));const t=this.world.debugRender().vertices,e=this.debugMesh.geometry,i=e.getAttribute("position");null==i||(i.array.length,t.length);{const i=new u(t,3);i.setUsage(d.DynamicDrawUsage),e.setAttribute("position",i)}e.setDrawRange(0,t.length/3)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await at(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach(t=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;null!=e&&e.parent instanceof b&&(dt(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&ht(e.quaternion,t.rotation()),e.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t)})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})})}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ot,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,n=this._raytestDirection;if(o.subVectors(e,t),n.copy(o).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),i;lt(ft.origin,t),lt(ft.dir,n);const r=o.length(),a=this.world.castRayAndGetNormal(ft,r,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?t=>!t.isSensor():void 0);if(i.hasHit=null!=a,i.hasHit){const e=ft.pointAt(a.timeOfImpact);if(i._internal=a,dt(i.hitNormal,a.normal),dt(i.hitPoint,e),i.distance=yt.subVectors(i.hitPoint,t).length(),!1!==s?.resolveActor){const t=this.world.bodies.getAll().find(t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,t=>t===a.collider));i.actor=null!=t?this.bodyActors.get(t):null}}if(this.showDebug){let e;H.length>0?(e=H.pop(),e.setDirection(n),e.position.copy(t),e.setLength(r,.2,.1),e.setColor(s?.debugColor??255)):e=new h(n,t,r,s?.debugColor??255),this.scene?.add(e),setTimeout(()=>{this.scene?.remove(e),H.push(e)},s?.debugLifetime??200)}return i}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ut(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof T&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof I?this.addLandscapeGroup(t):(t instanceof p||t instanceof b)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map;for(let o=0;o<e.length;o++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[o])continue;const e=t.userData.collisionShapes;let n=e?.[o];if(null==n&&null==e&&t.parent instanceof C&&(n=t.parent.collisionShapes),null==n)continue;let r=s.get(n);null==r&&(r=this.instancedShapeReset(n),s.set(n,r));const a=new f;a.matrix.identity(),t.getMatrixAt(o,i),a.applyMatrix4(i);this.createStaticBody(a,r)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new f;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>P(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,gt);const a=e.computedMovement();return dt(pt,a),pt}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world);return this.colliders.set(i.handle,s),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const s=(()=>{switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return i.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return i.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyDesc.kinematicVelocityBased();default:return i.RigidBodyDesc.dynamic()}})();e.position&&s.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&s.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&s.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&s.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&s.setGravityScale(e.gravityScale),"number"==typeof e.mass&&s.setAdditionalMass(e.mass),void 0!==e.userData&&(s.userData=e.userData);const o=this.world.createRigidBody(s);return new PhysicsBody(o,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,gt);const r=e.computedMovement();return dt(pt,r),pt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setNextKinematicTranslation(nt(i)),t.setNextKinematicRotation(rt(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setAngvel(et,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setLinvel(et,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(nt(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&dt(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(rt(e),!1)}getRotation(t,e=new w){const i=this.actorBodies.get(t.id);i&&ht(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(l,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new i.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e)}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let n;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:n=i.RigidBodyDesc.dynamic(),n.mass=s.mass??1;break;case PhysicsBodyType.kinematic:n=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:n=i.RigidBodyDesc.kinematicVelocityBased();break;default:n=s.isTrigger?i.RigidBodyDesc.kinematicVelocityBased():i.RigidBodyDesc.fixed()}const r=this.world.createRigidBody(n);r.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(r,t,o);return ut(r,t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.density&&t.setDensity(s.density),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)}),Y(r,o),!0===s.ignoreForNavMesh&&(r.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,r),this.bodyActors.set(r,t),new PhysicsBody(r,this.world)}applyTorque(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addTorque(et,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyTorqueImpulse(et,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addForce(et,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyImpulse(et,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s?.addForce(et,!0):(lt(it,i),s?.addForceAtPoint(et,it,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s.applyImpulse(et,!0):(lt(it,i),s.applyImpulseAtPoint(et,it,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=st;dt(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);et.x=a.x,et.y=a.y,et.z=a.z,o.applyImpulse(et,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof I){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&Y(e,t.object)}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t}sphereCast(t,e,i,s,o=ShapeCastResult.shared,n){o.reset();const r=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=n?.excludeActor?this.actorBodies.get(n.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,r,.01,s,!0,null,n?.collisionFilter??void 0,null,c,n?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){dt(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return dt(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){this.world?.bodies.forEach(t=>this.world.removeRigidBody(t)),this.world?.free(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),H.length=0}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.sleep(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(mt)??tt,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);lt(o.translation,n);const r=(new w).setFromEuler(e.rotation);ct(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof A)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof S){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof F){const i=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof D){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=j(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=J.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),J.set(o,a),a}if(t instanceof M){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new D(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new B(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof R?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([v(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const $=new B,X=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setTranslation(nt(i),!1),t.setRotation(rt(s),!1)}const Z=new B,J=new Map,tt=new B(1,1,1),et=new i.Vector3(0,0,0),it=new i.Vector3(0,0,0),st=new B,ot=new d.Vector2;function nt(t){return lt(et,t),et}function rt(t){return ct(q,t),q}const at=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const yt=new B,pt=new B,gt=t=>!t.isSensor(),mt=new B;const ft=new i.Ray(new i.Vector3(0,0,0),new i.Vector3(0,1,0));let wt=class extends W{constructor(){super(...arguments),this._active=!0,this.physics=O(Q),this.world=O(_)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([L()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e){this.collider=t,this.world=e,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t)}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e){this.body=t,this.world=e}dispose(){this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t)}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0)}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0)}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static)}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,35 @@
1
+ import type { ParameterType, PropertyParameter } from '../shader/parameter.js';
2
+ import { CustomParamValue, SerializedParamType } from './model.js';
3
+ export interface RuntimeSerializedParamTypeHint {
4
+ type: SerializedParamType;
5
+ element?: SerializedParamType;
6
+ }
7
+ export interface RuntimeParamConversionSkip {
8
+ key: string;
9
+ sourceType: SerializedParamType;
10
+ targetType: SerializedParamType;
11
+ }
12
+ /**
13
+ * Set to false to disable runtime correction of stale serialized parameter
14
+ * types and fall back to trusting the stored SerializedParamType.
15
+ */
16
+ export declare const applyRuntimeParamTypeInference = true;
17
+ export interface ConvertConfiguredParamsToRuntimeTypesOptions<TType extends RuntimeParameterType = RuntimeParameterType> {
18
+ parameterType?: TType | null;
19
+ parameterTarget?: object;
20
+ propertyParams?: PropertyParameter[];
21
+ extractPropertyParameters?: (type: TType) => PropertyParameter[];
22
+ toSerializedParamType?: (type: ParameterType) => SerializedParamType | undefined;
23
+ applyRuntimeParamTypeInference?: boolean;
24
+ }
25
+ export type RuntimeParameterType = {
26
+ new (...args: any[]): object;
27
+ };
28
+ export declare function convertConfiguredParamsToRuntimeTypes<TType extends RuntimeParameterType = RuntimeParameterType>(paramsSource: Record<string, CustomParamValue>, options?: ConvertConfiguredParamsToRuntimeTypesOptions<TType>): {
29
+ params: Record<string, CustomParamValue>;
30
+ skipped: RuntimeParamConversionSkip[];
31
+ };
32
+ export declare function getRuntimeParameterTypeHints<TType extends RuntimeParameterType = RuntimeParameterType>(paramsSource: Record<string, CustomParamValue>, options?: ConvertConfiguredParamsToRuntimeTypesOptions<TType>): Map<string, RuntimeSerializedParamTypeHint>;
33
+ export declare function inferRuntimeSerializedParamTypeHint(value: unknown): RuntimeSerializedParamTypeHint | undefined;
34
+ export declare function convertConfiguredParamValueToRuntimeType(param: CustomParamValue, target: RuntimeSerializedParamTypeHint): CustomParamValue | null;
35
+ //# sourceMappingURL=custom-param-runtime-types.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{Color as e,Euler as r,Material as t,Object3D as n,Texture as o,Vector2 as u,Vector3 as a,Vector4 as l,AnimationClip as c}from"three";import{BooleanNode as i,FloatNode as s,RgbNode as f,Sampler2DNode as y,Texture2dLookupNode as p,Vec2Node as m,Vec3Node as d,Vec4Node as b}from"three-shader-graph";import{Curve2 as A}from"../utils/curve.js";import{SerializedParamType as g}from"./model.js";export const applyRuntimeParamTypeInference=!0;export function convertConfiguredParamsToRuntimeTypes(e,r={}){const t={},n=[],o=Object.entries(e),u=r.applyRuntimeParamTypeInference??true;if(0===o.length||!u)return u?{params:t,skipped:n}:{params:e,skipped:n};const a=getRuntimeParameterTypeHints(e,r);for(const[e,r]of o){if(!1===r.override){t[e]=r;continue}const o=a.get(e),u=null!=o?convertConfiguredParamValueToRuntimeType(r,o):r;null!=u?t[e]=u:n.push({key:e,sourceType:r.type,targetType:o.type})}return{params:t,skipped:n}}export function getRuntimeParameterTypeHints(e,r={}){const t=new Map,n=Object.keys(e).filter(r=>!1!==e[r]?.override);if(0===n.length)return t;const o=new Set(n),u=r.parameterTarget??function(e){if(null==e)return null;try{return new e}catch{return null}}(r.parameterType),a=function(e,r){if(null!=r.propertyParams)return r.propertyParams;if(null==r.extractPropertyParameters)return[];if(null!=r.parameterType)return v(r.parameterType,r.extractPropertyParameters);if(null!=e)return v(e.constructor,r.extractPropertyParameters);return[]}(u,r);for(const e of a){if(!o.has(e.name))continue;const n=S(e,r.toSerializedParamType);null!=n&&t.set(e.name,n);const a=inferRuntimeSerializedParamTypeHint(T(u,e.name))??inferRuntimeSerializedParamTypeHint(e.options.defaultValue);null!=a&&t.set(e.name,C(a,n))}if(null!=u)for(const e of n){const r=inferRuntimeSerializedParamTypeHint(T(u,e));if(null!=r){const n=t.get(e);t.set(e,C(r,n))}}return t}const N=new WeakMap,V=new WeakMap,P=Symbol("noCachedSerializedParamType");function v(e,r){let t=N.get(r);null==t&&(t=new WeakMap,N.set(r,t));const n=t.get(e);if(null!=n)return n;const o=function(e,r){try{return r(e)}catch{return[]}}(e,r);return t.set(e,o),o}function T(e,r){return null!=e?e[r]:void 0}function S(e,r){const t=function(e,r){if(null==e||null==r)return;const t=function(e,r){const t=V.get(r);if(null==t||!t.has(e))return P;const n=t.get(e);return null===n?void 0:n}(e,r);if(t!==P)return t;try{const t=r(e);return h(e,r,t),t}catch{return void h(e,r,void 0)}}(e.type,r);return!0===e.options.array?{type:g.Array,...null!=t?{element:t}:{}}:null!=t?{type:t}:void 0}function h(e,r,t){let n=V.get(r);null==n&&(n=new WeakMap,V.set(r,n)),n.set(e,t??null)}function C(e,r){return e.type!==g.Array?e:{type:g.Array,element:e.element??r?.element}}export function inferRuntimeSerializedParamTypeHint(N){if(null==N)return;if(Array.isArray(N)){const e=N.map(e=>inferRuntimeSerializedParamTypeHint(e)).find(e=>null!=e);return{type:g.Array,...null!=e&&e.type!==g.Array?{element:e.type}:{}}}switch(typeof N){case"number":return{type:g.Number};case"boolean":return{type:g.Boolean};case"string":return{type:g.String}}const V=function(e){const r=e;if(e instanceof s||"function"==typeof r?.isFloat||!0===r?.isFloat)return g.FloatNode;if(e instanceof i||"function"==typeof r?.isBool||!0===r?.isBool)return g.BooleanNode;if(e instanceof f||"function"==typeof r?.isRgb||!0===r?.isRgb)return g.RgbNode;if(e instanceof m||"function"==typeof r?.isVec2||!0===r?.isVec2)return g.Vec2Node;if(e instanceof d||"function"==typeof r?.isVec3||!0===r?.isVec3)return g.Vec3Node;if(e instanceof b||"function"==typeof r?.isVec4||!0===r?.isVec4)return g.Vec4Node;if(e instanceof y||e instanceof p||"function"==typeof r?.isSampler2D||!0===r?.isSampler2D)return g.Sampler2DNode;return}(N);return null!=V?{type:V}:N instanceof u?{type:g.Vector2}:N instanceof a?{type:g.Vector3}:N instanceof l?{type:g.Vector4}:N instanceof e?{type:g.Color}:N instanceof r?{type:g.Euler}:N instanceof o?{type:g.Texture}:N instanceof t?{type:g.Material}:N instanceof n?{type:g.Object3D}:"undefined"!=typeof AudioBuffer&&N instanceof AudioBuffer?{type:g.AudioBuffer}:L(N,"VisualEffect")?{type:g.VisualEffect}:L(N,"PrefabOf")?{type:g.PrefabActor}:L(N,"Prefab")?{type:g.Prefab}:N instanceof A?{type:g.Curve}:L(N,"ColorLayer")?{type:g.ColorLayer}:L(N,"MaskLayer")?{type:g.MaskLayer}:N instanceof c?{type:g.AnimationClip}:L(N,"Sequence")?{type:g.Sequence}:void 0}export function convertConfiguredParamValueToRuntimeType(e,r){if(null==e||null==r)return e;if(e.type===g.Array||r.type===g.Array)return function(e,r){if(r.type===g.Array){const t=w(e),n=r.element??(t?e.element:e.type);if(null==n)return t?e:null;const o=t?e.element:e.type,u=(t?Array.isArray(e.value)?e.value:[]:[e.value]).map(e=>x(e,o,n));return u.some(e=>e===R)?null:{...e,type:g.Array,element:n,value:u}}if(!w(e))return null;const t=Array.isArray(e.value)?e.value[0]:void 0;if(null==t)return null;const n=x(t,e.element,r.type);if(n===R)return null;return{...e,type:r.type,value:n}}(e,r);const t=x(e.value,e.type,r.type);return t===R?null:{...e,type:r.type,value:t}}function w(e){return e.type===g.Array}const R=Symbol("skippedParamValue");function x(e,r,t){if(function(e,r){if(e===r)return!0;const t=k(e);return null!=t&&t===k(r)}(r,t)&&function(e,r){switch(r){case g.Number:case g.FloatNode:return"number"==typeof e||"string"==typeof e&&Number.isFinite(parseFloat(e));case g.Boolean:case g.BooleanNode:return"boolean"==typeof e;case g.Vector2:case g.Vec2Node:return B(e,2);case g.Vector3:case g.Vec3Node:return B(e,3);case g.Vector4:case g.Vec4Node:return B(e,4);case g.Euler:return Array.isArray(e)&&e.length>=3&&null!=z(e,3);case g.Color:case g.RgbNode:return null!=D(e);case g.String:return"string"==typeof e;case g.Array:return Array.isArray(e);case g.Texture:case g.Sampler2DNode:case g.BaseActor:case g.Object3D:case g.Material:case g.AudioBuffer:case g.VisualEffect:case g.Prefab:case g.PrefabActor:case g.AnimationClip:case g.Sequence:return null==e||"string"==typeof e||"object"==typeof e;case g.Curve:case g.ColorLayer:case g.MaskLayer:return null!=e}return!0}(e,t))return e;switch(t){case g.Number:case g.FloatNode:{const r=j(e);return null!=r?r:R}case g.Boolean:case g.BooleanNode:{const r=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const r=e.trim().toLowerCase();if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1}return null}(e);return null!=r?r:R}case g.Vector2:case g.Vec2Node:return M(e,2,r)??R;case g.Vector3:case g.Vec3Node:return M(e,3,r)??R;case g.Vector4:case g.Vec4Node:return M(e,4,r)??R;case g.Color:case g.RgbNode:return function(e,r){if(r===g.Color||r===g.RgbNode)return"string"==typeof e||"number"==typeof e?e:F(e);return F(e)}(e,r)??R;case g.Euler:return function(e,r){if(Array.isArray(e)){const r=z(e,3);if(null==r)return null;const t="string"==typeof e[3]?e[3]:"XYZ";return[r[0],r[1],r[2],t]}const t=M(e,3,r);return null!=t?[t[0],t[1],t[2],"XYZ"]:null}(e,r)??R;case g.String:return"string"==typeof e?e:String(e);case g.Texture:case g.Sampler2DNode:case g.BaseActor:case g.Object3D:case g.Material:case g.AudioBuffer:case g.VisualEffect:case g.Curve:case g.ColorLayer:case g.MaskLayer:case g.Prefab:case g.PrefabActor:case g.AnimationClip:case g.Sequence:return R}return R}function B(e,r){if(Array.isArray(e))return e.length>=r&&null!=z(e,r);if(null!=e&&"object"==typeof e){const t=e;return["x","y","z","w"].slice(0,r).every(e=>null!=j(t[e]))}return!1}function k(e){switch(e){case g.Number:case g.FloatNode:return"number";case g.Boolean:case g.BooleanNode:return"boolean";case g.Vector2:case g.Vec2Node:return"vector2";case g.Vector3:case g.Vec3Node:return"vector3";case g.Vector4:case g.Vec4Node:return"vector4";case g.Color:case g.RgbNode:return"color";case g.Texture:case g.Sampler2DNode:return"texture";case g.Prefab:case g.PrefabActor:return"prefab"}}function j(e){if("number"==typeof e)return Number.isFinite(e)?e:null;if("string"==typeof e){const r=parseFloat(e);return Number.isFinite(r)?r:null}if("boolean"==typeof e)return e?1:0;if(Array.isArray(e))return j(e[0]);if(null!=e&&"object"==typeof e){const r=e;return j(r.x??r.r??r.value)}return null}function M(e,r,t){if(t===g.Color||t===g.RgbNode){const t=D(e);if(null!=t)return z(t.toArray(),r,4===r?1:0)}if(Array.isArray(e))return z(e,r);if("number"==typeof e||"string"==typeof e||"boolean"==typeof e){const t=j(e);return null!=t?new Array(r).fill(t):null}if(null!=e&&"object"==typeof e){const t=e,n=["x","y","z","w"].slice(0,r).map(e=>t[e]);if(n.some(e=>null!=e))return z(n,r);const o=["r","g","b","a"].slice(0,r).map(e=>t[e]);if(o.some(e=>null!=e))return z(o,r,4===r?1:0)}return null}function z(e,r,t=0){const n=[];for(let o=0;o<r;o++){const r=j(e[o]??t);if(null==r)return null;n.push(r)}return n}function F(e){const r=D(e);return null!=r?"#"+r.getHexString():null}function D(r){try{if(r instanceof e)return r.clone();if("string"==typeof r)return function(e){return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e.trim())||/^(rgb|hsl)a?\(/i.test(e.trim())}(r)?new e(r):null;if("number"==typeof r)return Number.isInteger(r)&&r>=0?new e(r):null;if(Array.isArray(r)){const t=z(r,3);return null!=t?(new e).fromArray(t):null}if(null!=r&&"object"==typeof r){const t=r;if(null!=t.r||null!=t.g||null!=t.b){const r=z([t.r,t.g,t.b],3);return null!=r?(new e).fromArray(r):null}if(null!=t.x||null!=t.y||null!=t.z){const r=z([t.x,t.y,t.z],3);return null!=r?(new e).fromArray(r):null}}}catch{return null}return null}function L(e,r){return null!=e&&"object"==typeof e&&e.constructor?.name===r}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import{Group as e,Mesh as a}from"three";import{Color as r}from"three";import{varyingAttributes as t,float as n,mod as o,dot as c,vec2 as s,step as i,fract as l,mix as p,rgb as d,NodeShaderMaterial as u,rgba as f,standardMaterial as m,attributeFloat as h,RgbNode as L,varying as x}from"three-shader-graph";import{mixColorsByLayer as S,select as w}from"../../shader-nodes/index.js";export function initLandscape(e){e.sections.y,e.sectionSize,e.sections.x,e.sectionSize;return new LandscapeGroup}export function createLandscapeDefaultMaterial(e=!0,a=1){const L=t.uv.multiplyScalar(a),w=n(10),y=n(7),v=o(c(s(1,1),i(s(.5,.5),l(L.multiplyScalar(w)))),n(2)),D=o(c(s(1,1),i(s(.5,.5),l(L.multiplyScalar(y.multiply(w))))),n(2)),G=p(d(new r(4473924).convertLinearToSRGB()),d(new r(5592405).convertLinearToSRGB()),v),M=p(G,G.addScalar(n(.1)),D),g=S({layerColors:[f(M).rgb,...["#f3cc91","#e9a135","#f4a4a6","#ef767a","#e6373d","#55DDE0","#33658A","#2F4858"].map(e=>new r(e).convertLinearToSRGB()).map(e=>d(e)).reverse()],enableNoise:!1}),B=h("hole"),R=new u({color:m({color:e?g:M}),discard:x(B).gt(.5)});return R.color=new r("#aaaaaa"),R.name="Default",R}export const defaultLandscapeMaterial=createLandscapeDefaultMaterial();export class LandscapeMesh extends a{}export class LandscapeGroup extends e{get sections(){return this.children.filter(e=>e instanceof LandscapeMesh)}}/*
1
+ import{Group as e,Mesh as a}from"three";import{Color as r}from"three";import{varyingAttributes as t,float as n,mod as o,dot as c,vec2 as s,step as i,fract as l,mix as p,rgb as d,NodeShaderMaterial as u,rgba as f,standardMaterial as m,attributeFloat as x,RgbNode as S,varying as h}from"three-shader-graph";import{mixColorsByLayer as L,select as g}from"../../shader-nodes/index.js";export function initLandscape(e){e.sections.y,e.sectionSize,e.sections.x,e.sectionSize;return new LandscapeGroup}export function createLandscapeDefaultMaterial(e=!0,a=1){const S=t.uv.multiplyScalar(a),g=n(10),w=n(7),y=o(c(s(1,1),i(s(.5,.5),l(S.multiplyScalar(g)))),n(2)),v=o(c(s(1,1),i(s(.5,.5),l(S.multiplyScalar(w.multiply(g))))),n(2)),D=p(d("#"+new r(4473924).convertLinearToSRGB().getHexString()),d("#"+new r(5592405).convertLinearToSRGB().getHexString()),y),G=p(D,D.addScalar(n(.1)),v),M=L({layerColors:[f(G).rgb,...["#f3cc91","#e9a135","#f4a4a6","#ef767a","#e6373d","#55DDE0","#33658A","#2F4858"].map(e=>"#"+new r(e).convertLinearToSRGB().getHexString()).map(e=>d(e)).reverse()],enableNoise:!1}),B=x("hole"),H=new u({color:m({color:e?M:G}),discard:h(B).gt(.5)});return H.color=new r("#aaaaaa"),H.name="Default",H}export const defaultLandscapeMaterial=createLandscapeDefaultMaterial();export class LandscapeMesh extends a{}export class LandscapeGroup extends e{get sections(){return this.children.filter(e=>e instanceof LandscapeMesh)}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */