@hology/core 0.0.237 → 0.0.239

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 (90) hide show
  1. package/dist/effects/sequence/sequence-player.js +1 -1
  2. package/dist/effects/vfx/gpu-particle-arena.d.ts +57 -0
  3. package/dist/effects/vfx/gpu-particle-arena.js +4 -0
  4. package/dist/effects/vfx/gpu-sprite-backend.d.ts +33 -0
  5. package/dist/effects/vfx/gpu-sprite-backend.js +4 -0
  6. package/dist/effects/vfx/gpu-sprite-compiler.d.ts +58 -0
  7. package/dist/effects/vfx/gpu-sprite-compiler.js +4 -0
  8. package/dist/effects/vfx/gpu-sprite-render-graph.d.ts +10 -0
  9. package/dist/effects/vfx/gpu-sprite-render-graph.js +4 -0
  10. package/dist/effects/vfx/gpu-sprite-runtime.d.ts +304 -0
  11. package/dist/effects/vfx/gpu-sprite-runtime.js +4 -0
  12. package/dist/effects/vfx/gpu-sprite-scheduler-runtime.d.ts +71 -0
  13. package/dist/effects/vfx/gpu-sprite-scheduler-runtime.js +4 -0
  14. package/dist/effects/vfx/gpu-sprite-template.d.ts +47 -0
  15. package/dist/effects/vfx/gpu-sprite-template.js +4 -0
  16. package/dist/effects/vfx/gpu-sprite-world-runtime.d.ts +61 -0
  17. package/dist/effects/vfx/gpu-sprite-world-runtime.js +4 -0
  18. package/dist/effects/vfx/gpu-vfx-capacity.d.ts +3 -0
  19. package/dist/effects/vfx/gpu-vfx-capacity.js +4 -0
  20. package/dist/effects/vfx/gpu-vfx-scheduler.d.ts +52 -0
  21. package/dist/effects/vfx/gpu-vfx-scheduler.js +4 -0
  22. package/dist/effects/vfx/gpu-vfx-world-service.d.ts +103 -0
  23. package/dist/effects/vfx/gpu-vfx-world-service.js +4 -0
  24. package/dist/effects/vfx/index.d.ts +11 -0
  25. package/dist/effects/vfx/index.js +1 -1
  26. package/dist/effects/vfx/trail-renderer.js +1 -1
  27. package/dist/effects/vfx/vfx-actor.d.ts +19 -2
  28. package/dist/effects/vfx/vfx-actor.js +1 -1
  29. package/dist/effects/vfx/vfx-asset.d.ts +2 -0
  30. package/dist/effects/vfx/vfx-default-sprite-texture.d.ts +3 -0
  31. package/dist/effects/vfx/vfx-default-sprite-texture.js +4 -0
  32. package/dist/effects/vfx/vfx-input-runtime.d.ts +3 -1
  33. package/dist/effects/vfx/vfx-materializer.d.ts +10 -0
  34. package/dist/effects/vfx/vfx-materializer.js +1 -1
  35. package/dist/effects/vfx/vfx-mesh-transform.d.ts +4 -0
  36. package/dist/effects/vfx/vfx-mesh-transform.js +4 -0
  37. package/dist/effects/vfx/vfx-param.d.ts +2 -0
  38. package/dist/effects/vfx/vfx-param.js +1 -1
  39. package/dist/effects/vfx/vfx-renderers.js +1 -1
  40. package/dist/effects/vfx/vfx-runtime.d.ts +35 -0
  41. package/dist/effects/vfx/vfx-runtime.js +4 -0
  42. package/dist/effects/vfx/vfx-service.d.ts +3 -0
  43. package/dist/effects/vfx/vfx-service.js +1 -1
  44. package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +14 -0
  45. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  46. package/dist/gameplay/actors/builtin/components/character/character-movement-like.d.ts +1 -1
  47. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +8 -3
  48. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  49. package/dist/gameplay/actors/builtin/components/character/root-motion-constraint.d.ts +10 -0
  50. package/dist/gameplay/actors/builtin/components/character/root-motion-constraint.js +1 -1
  51. package/dist/gameplay/ai/behavior-tree/move.d.ts +14 -0
  52. package/dist/gameplay/ai/behavior-tree/move.js +1 -1
  53. package/dist/gameplay/initiate.d.ts +3 -0
  54. package/dist/gameplay/initiate.js +1 -1
  55. package/dist/gameplay/services/physics/physics-system.js +1 -1
  56. package/dist/gameplay/services/render.d.ts +14 -1
  57. package/dist/gameplay/services/render.js +1 -1
  58. package/dist/rendering/webgpu-experimental-backend.d.ts +8 -2
  59. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  60. package/dist/rendering.d.ts +32 -3
  61. package/dist/rendering.js +1 -1
  62. package/dist/scene/asset-resource-loader.js +1 -1
  63. package/dist/scene/materializer.js +1 -1
  64. package/dist/scene/objects/shapes.js +1 -1
  65. package/dist/shader/builtin/decal-standard-shader.d.ts +1 -0
  66. package/dist/shader/builtin/decal-standard-shader.js +1 -1
  67. package/dist/shader/decal-shader.js +1 -1
  68. package/dist/shader-nodes/effects.js +1 -1
  69. package/dist/shader-nodes/material-flags.js +1 -1
  70. package/dist/shader-nodes/particle.d.ts +5 -2
  71. package/dist/shader-nodes/particle.js +1 -1
  72. package/dist/test/asset-resource-loader-skinned-merge.test.d.ts +2 -0
  73. package/dist/test/asset-resource-loader-skinned-merge.test.js +4 -0
  74. package/dist/test/character-root-motion-constraint.test.js +1 -1
  75. package/dist/test/gpu-particle-arena.test.d.ts +2 -0
  76. package/dist/test/gpu-particle-arena.test.js +4 -0
  77. package/dist/test/gpu-sprite-compiler.test.d.ts +2 -0
  78. package/dist/test/gpu-sprite-compiler.test.js +4 -0
  79. package/dist/test/gpu-vfx-scheduler.test.d.ts +2 -0
  80. package/dist/test/gpu-vfx-scheduler.test.js +4 -0
  81. package/dist/test/mesh-clone.test.d.ts +2 -0
  82. package/dist/test/mesh-clone.test.js +4 -0
  83. package/dist/test/sequence-scene-binding.test.js +1 -1
  84. package/dist/test/sequence-vfx.test.js +1 -1
  85. package/dist/test/vfx-mesh-transform.test.d.ts +2 -0
  86. package/dist/test/vfx-mesh-transform.test.js +4 -0
  87. package/dist/utils/mesh.d.ts +7 -1
  88. package/dist/utils/mesh.js +1 -1
  89. package/package.json +17 -5
  90. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{canCrossFadeFromAnimationAction as i}from"../../../../animation/animation-action.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as n}from"../../../../services/render.js";import{AnimationMixer as l,Bone as a,Object3D as h,LoopOnce as c,Raycaster as d,Vector3 as p,SkinnedMesh as u,Skeleton as f,Quaternion as g,Matrix4 as m,MathUtils as y,ArrowHelper as k,Group as S}from"three";import{getCharacterMovementLike as w}from"./character-movement-like.js";import{CCDIKSolver as b}from"three/addons/animation/CCDIKSolver.js";import{World as L}from"../../../../services/world.js";import{PhysicsSystem as v,RayTestResult as I}from"../../../../services/physics/physics-system.js";import{ArrayMap as P}from"../../../../../utils/collections.js";import{getAnimationClipRigId as B,getAnimationRigChainBoneNames as R,getAnimationRigDataFromObject as x,getAnimationRigIdFromObject as F,setAnimationClipRigId as A}from"../../../../animation/retarget.js";const D=new p(0,-1,0),M=new p(0,1,0),T=new p(1,1,1),W=new g,O=new p,C=new p,V=new p,q=new p,E=new p,H=new g,U=new g,z=new g,N=new g,j=new m,G=new m,Q=new p(1,0,0),$=new p(0,1,0),_=new p(0,0,1);function K(){return{point:new p,normal:new p,hasNormal:!1}}const Y=["mixamorigHips","Hips","hips","Pelvis","pelvis"],J={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},X={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},Z=["left","right"];let tt=class extends e{constructor(){super(...arguments),this.viewController=r(n),this.poseProcessors=new P,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.sequenceAnimationControlled=!1,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=0,this.externalControlActive=!1,this.world=r(L),this.physicsSystem=r(v),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 p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!1,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!1,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new d,this.raycastIntersections=[],this.footIkRayTo=new p,this.footIkRayTestResult=new I,this.footIkRayTestOptions={debug:!1,excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:K(),toe:K(),heel:K(),side:K()},this.footIkAxesScratch={up:new p,forward:new p,right:new p},this.footIkSampleAxesScratch={forward:new p,right:new p},this.footIkScratch={footWorldPos:new p,centerRayStart:new p,toeRayStart:new p,heelRayStart:new p,sideRayStart:new p,desiredTargetPos:new p,desiredNormal:new p,desiredForward:new p,debugRayEndA:new p,debugRayEndB:new p,debugRayEndC:new p,debugRayEndD:new p,debugRayEndE:new p,debugRayEndF:new p},this.ikPreSolve={left:{upper:new g,lower:new g,foot:new g},right:{upper:new g,lower:new g,foot:new g}},this.getFullBodyClip=st(t=>t.uuid,t=>et(this.fullBodyMask,t)),this.getUpperBodyClip=st(t=>t.uuid,t=>et(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=w(this.actor),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,D),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(D,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&&(nt(t,e)||nt(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 u||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=ot(e),this.fullBodyMask=function(t,e){const o=new Set(ot(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof a||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(rt(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new l(t),this.animationRigId=F(t),this.animationRigData=x(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:e.current.options.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:e.current.options.priority??0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}addPoseProcessor(t){const e={id:t.id,phase:t.phase??"afterMixer",order:t.order??0,update:t.update};this.removePoseProcessor(e.id);const o=this.poseProcessors.get(e.phase);let i=o.findIndex(t=>t.order>e.order);return-1===i&&(i=o.length),o.splice(i,0,e),()=>{const t=o.indexOf(e);-1!==t&&(o.splice(t,1),0===o.length&&this.poseProcessors.delete(e.phase))}}removePoseProcessor(t){for(const[e,o]of this.poseProcessors.entries()){const i=o.findIndex(e=>e.id===t);if(-1!==i)return o.splice(i,1),void(0===o.length&&this.poseProcessors.delete(e))}}runPoseProcessors(t,e){if(0===this.poseProcessors.size||null==this.mixer||!this.poseProcessors.present(t))return;const o=this.mixer.getRoot();if(!(o instanceof h))return;const i=this.poseProcessorContext??(this.poseProcessorContext={deltaTime:e,phase:t,animation:this,mixer:this.mixer,root:o});i.deltaTime=e,i.phase=t,i.mixer=this.mixer,i.root=o;const s=this.poseProcessors.get(t);for(let t=0;t<s.length;t++)s[t].update(i)}updateInternal(t){if(null==this.mixer)return;if(this.externalControlActive)return;this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1);let e=!1;this.sequenceAnimationReleasePending&&(this.sequenceAnimationReleaseFrames>0?(e=!0,this.sequenceAnimationReleaseFrames--):(this.sequenceAnimationReleasePending=!1,this.currentFullBodyPriority=-1,this.sequenceAnimationControlled=!1,this.overrideFadeTime=null,this.fullBodyTimer=0)),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.sequenceAnimationControlled&&!this.sequenceAnimationReleasePending&&this.fullBodyAction&&this.fullBodyAction.loop===c&&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),e||this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.runPoseProcessors("beforeMixer",t),this.mixer.update(t),this.runPoseProcessors("afterMixer",t),this.runPoseProcessors("beforeIk",t),this.updateFootIk(t),this.runPoseProcessors("afterIk",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=R(this.animationRigData,"leftLeg"),r=R(this.animationRigData,"rightLeg"),n=this.resolveLegBoneRefs(i,this.leftLegIkBones,J,s),l=this.resolveLegBoneRefs(i,this.rightLegIkBones,X,r);if(null==n||null==l)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:n,right:l},this.ikLegLengths={left:this.computeLegLengths(n),right:this.computeLegLengths(l)},this.ikFootAxes={left:this.detectFootAxisBasis(n.foot),right:this.detectFootAxisBasis(l.foot)};const h=this.animationRigData?.bones.find(t=>t.id===this.animationRigData?.pelvisBoneId)?.name;this.ikPelvisBone=this.resolvePelvisBone(i,n,l,h),this.ikLegState.left.targetPosition.copy(n.foot.getWorldPosition(O)),this.ikLegState.right.targetPosition.copy(l.foot.getWorldPosition(O)),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",n.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",l.foot),this.ikLegState.left.planted=!1,this.ikLegState.right.planted=!1,this.ikLegState.left.lastFootWorldPos.copy(n.foot.getWorldPosition(O)),this.ikLegState.right.lastFootWorldPos.copy(l.foot.getWorldPosition(O)),this.ikLegState.left.hasLastFootSample=!1,this.ikLegState.right.hasLastFootSample=!1;const c=this.resolveFootAxes("left",n.foot),d=this.resolveFootAxes("right",l.foot);this.ikLegState.left.forward.copy(c.forward),this.ikLegState.right.forward.copy(d.forward);const p=e??rt(t);if(null==p)return;let u=i.getBoneByName("_IKTargetLeftFoot"),g=i.getBoneByName("_IKTargetRightFoot"),y=!1;if(null==u&&(u=new a,u.name="_IKTargetLeftFoot",p.add(u),y=!0),null==g&&(g=new a,g.name="_IKTargetRightFoot",p.add(g),y=!0),this.setBoneWorldPosition(u,n.foot.getWorldPosition(O)),this.setBoneWorldPosition(g,l.foot.getWorldPosition(O)),y||i.bones.indexOf(u)<0||i.bones.indexOf(g)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(u)<0&&(t.push(u),e.push((new m).copy(u.matrixWorld).invert())),t.indexOf(g)<0&&(t.push(g),e.push((new m).copy(g.matrixWorld).invert())),o.bind(new f(t,e),o.bindMatrix)}this.ikTargetBones={left:u,right:g};const k=o.skeleton.bones,S={target:k.indexOf(u),effector:k.indexOf(n.foot),links:[{index:k.indexOf(n.lower)},{index:k.indexOf(n.upper)}],iteration:8},w={target:k.indexOf(g),effector:k.indexOf(l.foot),links:[{index:k.indexOf(l.lower)},{index:k.indexOf(l.upper)}],iteration:8};if(S.target<0||S.effector<0||S.links.some(t=>t.index<0)||w.target<0||w.effector<0||w.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 b(o,[S,w])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof u||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o,i=[]){const s=this.findBoneByNames(t,[i[0],e.upperLeg,...o.upper].filter(t=>null!=t)),r=this.findBoneByNames(t,[i.at(-2),e.lowerLeg,...o.lower].filter(t=>null!=t)),n=this.findBoneByNames(t,[i.at(-1),e.foot,...o.foot].filter(t=>null!=t));if(null!=s&&null!=r&&null!=n)return{upper:s,lower:r,foot:n}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o,i){const s=this.findBoneByNames(t,[i,this.footIkPelvisBone,...Y].filter(t=>null!=t));if(null!=s)return s;const r=e.upper.parent,n=o.upper.parent;return null!=r&&r===n&&(r instanceof a||!0===r.isBone)||null!=r&&(r instanceof a||!0===r.isBone)?r:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(O),o=t.lower.getWorldPosition(C),i=t.foot.getWorldPosition(V),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(O.copy(e))),t.quaternion.copy(W),t.scale.copy(T),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new S,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 S;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 k(M,new p,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){O.subVectors(o,e);const i=O.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(O.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 Z){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(O);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 Z){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(O),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(C),r=V.copy(s).addScaledVector(M,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),l=o.getWorldPosition(C),h=V.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(H)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof a)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=j.copy(t.boneInverses[i]).invert(),n=G.copy(r).multiply(s),d=O.setFromMatrixPosition(n),p=q.copy(d).applyMatrix4(o.matrixWorld).sub(l);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(O),i=t.foot.getWorldPosition(C),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=q.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(M),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(M,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 P=null!=g||null!=m||null!=k;let B=l.y;null!=g?B=g.point.y:null!=m&&null!=k?B=.5*(m.point.y+k.point.y):null!=m?B=m.point.y:null!=k&&(B=k.point.y);const R=this.ikBoneRefs?.[t],x=this.ikLegLengths?.[t],F=null!=R&&null!=x?this.computeLegExtensionRatio(R,x):1,A=Math.max(0,l.y-B,l.y-o.targetPosition.y),D=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,P,a,F,A);D?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=D&&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(M,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),P=l.desiredForward.copy(u.forward);let B=0,R=0,x=this.footIkWeightOutSpeed;const F=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 D=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,F,d,D,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,I)){this.computeDesiredFootForward(u.forward,u.right,I,w,b,P),B=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(B))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),R=1,x=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,I,null,null,P),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),C=1-Math.exp(-x*n);s.targetPosition.lerp(v,O),s.normal.lerp(I,O).normalize(),s.forward.lerp(P,O).normalize(),s.pitch=y.lerp(s.pitch,B,O),s.weight=y.lerp(s.weight,R,C),s.planted=W&&R>.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(D,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(D,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(D,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(D,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 p,right:new p},n=this.actor.object.getWorldDirection(q);n.addScaledVector(M,-n.dot(M)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(M,-s.forward.dot(M)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=E.crossVectors(M,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,q);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=C.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=V.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(M),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(M)<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(q)),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=q.copy(this.actor.object.getWorldDirection(q));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=C.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=H.copy(e.quaternion),l=U.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=z.setFromAxisAngle(t.rightLocal,.15);return V.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=C.subVectors(i,o),r=s.dot(M),n=V.copy(s).addScaledVector(M,-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(M,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(O).clone(),c=C.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(O).clone(),s=e.lower.getWorldPosition(C).clone(),r=e.foot.getWorldPosition(V).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new p).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,d=n+l-1e-4,u=y.clamp(h,c,d),f=a.multiplyScalar(1/h),g=(new p).subVectors(s,i).normalize(),m=(new p).subVectors(r,s).normalize(),k=(new p).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(O).cross(M)),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 p).copy(i).addScaledVector(f,S);let v=(new p).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new p).crossVectors(f,M),v.lengthSq()<1e-8&&(v=new p(1,0,0))),v.normalize();const I=(new p).copy(L).addScaledVector(v,b),P=(new p).copy(L).addScaledVector(v,-b),B=(new p).subVectors(s,L).dot(v)>=0?I:P;this.rotateBoneToward(e.upper,i,s,B),e.upper.updateMatrixWorld(!0);const R=e.lower.getWorldPosition(C),x=e.foot.getWorldPosition(V);this.rotateBoneToward(e.lower,R,x,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,B,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 p).subVectors(o,e),r=(new p).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 g).setFromUnitVectors(s,r),l=t.getWorldQuaternion(H),a=U.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(z),c=N.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(H),o=this.actor.object.getWorldDirection(O);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:Q.clone(),world:Q.clone().applyQuaternion(e)},{local:$.clone(),world:$.clone().applyQuaternion(e)},{local:_.clone(),world:_.clone().applyQuaternion(e)}];i.push({local:Q.clone().multiplyScalar(-1),world:Q.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:$.clone().multiplyScalar(-1),world:$.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:_.clone().multiplyScalar(-1),world:_.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(M);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 p,forward:new p,right:new p},r=e.getWorldQuaternion(H);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(M),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(M,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){H.copy(t.quaternion),t.quaternion.copy(e).slerp(H,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=O.copy(o.normal).normalize(),n=C.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=V.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(q.crossVectors(l,r)).normalize(),j.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),H.setFromRotationMatrix(j),G.makeBasis(l,r,n),U.setFromRotationMatrix(G);const a=z.copy(U).multiply(N.copy(H).invert()),h=e.parent.getWorldQuaternion(N),c=U.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.sequenceAnimationControlled=!1,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=0,this.upperBodyOverride=!1,this.overrideFadeTimeUpper=null,this.fullBodyTimer=0}requestSequenceAnimationRelease(){this.externalControlActive=!1,this.sequenceAnimationControlled=!1,this.currentFullBodyPriority=-1,this.sequenceAnimationReleasePending=!0,this.sequenceAnimationReleaseFrames=1,this.upperBodyOverride=!1,this.overrideFadeTimeUpper=null}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={}){it(null!=this.mixer,"Can't begin external control before setup is called"),this.assertClipRigCompatible(t),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(c,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 s&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof h&&(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={}){this.assertClipRigCompatible(t);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={}){it(null!=this.mixer,"Can't play animation before setup is called"),this.assertClipRigCompatible(t);const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,e.sequenceControlled&&(this.sequenceAnimationControlled=!0,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=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)}assertClipRigCompatible(t){const e=B(t);if(e===this.animationRigId||null==e&&null==this.animationRigId)return;const o=`${t.uuid}|${e??""}|${this.animationRigId??""}`;if(!lt.has(o)){if(lt.add(o),null==e||null==this.animationRigId)return void console.warn(`Animation clip "${t.name}" or its character has no rig assigned. Playing without rig compatibility validation for legacy compatibility.`);console.warn(`Animation clip "${t.name}" targets rig ${e??"no rig"}, but this character uses rig ${this.animationRigId??"no rig"}. Generate and assign a retargeted clip for the character rig.`)}}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 s=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return!t.isRunning()&&!1===o.loop&&t.clampWhenFinished||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(c,1),t.clampWhenFinished=!0)),t;if(i(t)){const i=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,i.crossFadeTo(r,s,!1),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(c,1),t.clampWhenFinished=!0),t}};tt=t([o({inEditor:!0})],tt);export{tt as CharacterAnimationComponent};function et(t,e){if(null==t)return e;const o=e.clone();A(o,B(e));const i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function ot(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof a)}function it(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function st(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 rt(t){let e;return t.traverse(t=>{(t instanceof a||t.isBone)&&null==e&&(e=t)}),e}function nt(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}const lt=new Set;/*
1
+ import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{canCrossFadeFromAnimationAction as i}from"../../../../animation/animation-action.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as n}from"../../../../services/render.js";import{AnimationMixer as l,Bone as a,Object3D as h,LoopOnce as c,Raycaster as d,Vector3 as p,SkinnedMesh as u,Skeleton as f,Quaternion as g,Matrix4 as m,MathUtils as y,ArrowHelper as k,Group as S}from"three";import{getCharacterMovementLike as w}from"./character-movement-like.js";import{CCDIKSolver as b}from"three/addons/animation/CCDIKSolver.js";import{World as v}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as x}from"../../../../services/physics/physics-system.js";import{ArrayMap as I}from"../../../../../utils/collections.js";import{getAnimationClipRigId as P,getAnimationRigChainBoneNames as B,getAnimationRigDataFromObject as R,getAnimationRigIdFromObject as F,setAnimationClipRigId as A}from"../../../../animation/retarget.js";const D=new p(0,-1,0),M=new p(0,1,0),W=new p(1,1,1),T=new g,C=new p,O=new p,q=new p,V=new p,U=new p,N=new g,E=new g,H=new g,z=new g,j=new m,Q=new m,G=new p(1,0,0),$=new p(0,1,0),_=new p(0,0,1);function K(){return{point:new p,normal:new p,hasNormal:!1}}const Y=["mixamorigHips","Hips","hips","Pelvis","pelvis"],J={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},X={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},Z=["left","right"];let tt=class extends e{constructor(){super(...arguments),this.viewController=r(n),this.poseProcessors=new I,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.sequenceAnimationControlled=!1,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=0,this.externalControlActive=!1,this.world=r(v),this.physicsSystem=r(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.ikPelvisDescendantStack=[],this.ikWorldUpdateNodes=[],this.footIkStateReset=!0,this.ikLegState={left:{targetPosition:new p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!1,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!1,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new d,this.raycastIntersections=[],this.footIkRayTo=new p,this.footIkRayTestResult=new x,this.footIkRayTestOptions={debug:!1,excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:K(),toe:K(),heel:K(),side:K()},this.footIkAxesScratch={up:new p,forward:new p,right:new p},this.footIkSampleAxesScratch={forward:new p,right:new p},this.footIkScratch={footWorldPos:new p,centerRayStart:new p,toeRayStart:new p,heelRayStart:new p,sideRayStart:new p,desiredTargetPos:new p,desiredNormal:new p,desiredForward:new p,debugRayEndA:new p,debugRayEndB:new p,debugRayEndC:new p,debugRayEndD:new p,debugRayEndE:new p,debugRayEndF:new p},this.ikPreSolve={left:{upper:new g,lower:new g,foot:new g},right:{upper:new g,lower:new g,foot:new g}},this.getFullBodyClip=st(t=>t.uuid,t=>et(this.fullBodyMask,t)),this.getUpperBodyClip=st(t=>t.uuid,t=>et(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=w(this.actor),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,D),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(D,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&&(nt(t,e)||nt(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 u||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=ot(e),this.fullBodyMask=function(t,e){const o=new Set(ot(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof a||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(rt(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new l(t),this.animationRigId=F(t),this.animationRigData=R(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:e.current.options.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:e.current.options.priority??0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}addPoseProcessor(t){const e={id:t.id,phase:t.phase??"afterMixer",order:t.order??0,update:t.update};this.removePoseProcessor(e.id);const o=this.poseProcessors.get(e.phase);let i=o.findIndex(t=>t.order>e.order);return-1===i&&(i=o.length),o.splice(i,0,e),()=>{const t=o.indexOf(e);-1!==t&&(o.splice(t,1),0===o.length&&this.poseProcessors.delete(e.phase))}}removePoseProcessor(t){for(const[e,o]of this.poseProcessors.entries()){const i=o.findIndex(e=>e.id===t);if(-1!==i)return o.splice(i,1),void(0===o.length&&this.poseProcessors.delete(e))}}runPoseProcessors(t,e){if(0===this.poseProcessors.size||null==this.mixer||!this.poseProcessors.present(t))return;const o=this.mixer.getRoot();if(!(o instanceof h))return;const i=this.poseProcessorContext??(this.poseProcessorContext={deltaTime:e,phase:t,animation:this,mixer:this.mixer,root:o});i.deltaTime=e,i.phase=t,i.mixer=this.mixer,i.root=o;const s=this.poseProcessors.get(t);for(let t=0;t<s.length;t++)s[t].update(i)}updateInternal(t){if(null==this.mixer)return;if(this.externalControlActive)return;this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1);let e=!1;this.sequenceAnimationReleasePending&&(this.sequenceAnimationReleaseFrames>0?(e=!0,this.sequenceAnimationReleaseFrames--):(this.sequenceAnimationReleasePending=!1,this.currentFullBodyPriority=-1,this.sequenceAnimationControlled=!1,this.overrideFadeTime=null,this.fullBodyTimer=0)),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.sequenceAnimationControlled&&!this.sequenceAnimationReleasePending&&this.fullBodyAction&&this.fullBodyAction.loop===c&&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),e||this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.runPoseProcessors("beforeMixer",t),this.mixer.update(t),this.runPoseProcessors("afterMixer",t),this.runPoseProcessors("beforeIk",t),this.updateFootIk(t),this.runPoseProcessors("afterIk",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.ikWorldUpdateNodes.length=0,this.footIkStateReset=!0,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=B(this.animationRigData,"leftLeg"),r=B(this.animationRigData,"rightLeg"),n=this.resolveLegBoneRefs(i,this.leftLegIkBones,J,s),l=this.resolveLegBoneRefs(i,this.rightLegIkBones,X,r);if(null==n||null==l)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:n,right:l},this.ikLegLengths={left:this.computeLegLengths(n),right:this.computeLegLengths(l)},this.ikFootAxes={left:this.detectFootAxisBasis(n.foot),right:this.detectFootAxisBasis(l.foot)};const h=this.animationRigData?.bones.find(t=>t.id===this.animationRigData?.pelvisBoneId)?.name;this.ikPelvisBone=this.resolvePelvisBone(i,n,l,h),this.rebuildFootIkWorldUpdateNodes(),this.ikLegState.left.targetPosition.copy(n.foot.getWorldPosition(C)),this.ikLegState.right.targetPosition.copy(l.foot.getWorldPosition(C)),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",n.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",l.foot),this.ikLegState.left.planted=!1,this.ikLegState.right.planted=!1,this.ikLegState.left.lastFootWorldPos.copy(n.foot.getWorldPosition(C)),this.ikLegState.right.lastFootWorldPos.copy(l.foot.getWorldPosition(C)),this.ikLegState.left.hasLastFootSample=!1,this.ikLegState.right.hasLastFootSample=!1;const c=this.resolveFootAxes("left",n.foot),d=this.resolveFootAxes("right",l.foot);this.ikLegState.left.forward.copy(c.forward),this.ikLegState.right.forward.copy(d.forward);const p=e??rt(t);if(null==p)return;let u=i.getBoneByName("_IKTargetLeftFoot"),g=i.getBoneByName("_IKTargetRightFoot"),y=!1;if(null==u&&(u=new a,u.name="_IKTargetLeftFoot",p.add(u),y=!0),null==g&&(g=new a,g.name="_IKTargetRightFoot",p.add(g),y=!0),this.setBoneWorldPosition(u,n.foot.getWorldPosition(C)),this.setBoneWorldPosition(g,l.foot.getWorldPosition(C)),y||i.bones.indexOf(u)<0||i.bones.indexOf(g)<0){const e=i.bones.slice(),o=i.boneInverses.map(t=>t.clone());e.indexOf(u)<0&&(e.push(u),o.push((new m).copy(u.matrixWorld).invert())),e.indexOf(g)<0&&(e.push(g),o.push((new m).copy(g.matrixWorld).invert()));const s=new f(e,o);t.traverse(t=>{const e=t;!0===e.isSkinnedMesh&&e.skeleton===i&&e.bind(s,e.bindMatrix)})}this.ikTargetBones={left:u,right:g},this.rebuildFootIkWorldUpdateNodes();const k=o.skeleton.bones,S={target:k.indexOf(u),effector:k.indexOf(n.foot),links:[{index:k.indexOf(n.lower)},{index:k.indexOf(n.upper)}],iteration:8},w={target:k.indexOf(g),effector:k.indexOf(l.foot),links:[{index:k.indexOf(l.lower)},{index:k.indexOf(l.upper)}],iteration:8};if(S.target<0||S.effector<0||S.links.some(t=>t.index<0)||w.target<0||w.effector<0||w.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 b(o,[S,w])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof u||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o,i=[]){const s=this.findBoneByNames(t,[i[0],e.upperLeg,...o.upper].filter(t=>null!=t)),r=this.findBoneByNames(t,[i.at(-2),e.lowerLeg,...o.lower].filter(t=>null!=t)),n=this.findBoneByNames(t,[i.at(-1),e.foot,...o.foot].filter(t=>null!=t));if(null!=s&&null!=r&&null!=n)return{upper:s,lower:r,foot:n}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o,i){const s=this.findBoneByNames(t,[i,this.footIkPelvisBone,...Y].filter(t=>null!=t));if(null!=s)return s;const r=e.upper.parent,n=o.upper.parent;return null!=r&&r===n&&(r instanceof a||!0===r.isBone)||null!=r&&(r instanceof a||!0===r.isBone)?r:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(C),o=t.lower.getWorldPosition(O),i=t.foot.getWorldPosition(q),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(C.copy(e).applyMatrix4(j.copy(o.matrixWorld).invert())),t.quaternion.copy(T),t.scale.copy(W),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new S,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 S;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 k(M,new p,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){C.subVectors(o,e);const i=C.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(C.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.footIkStateReset||(this.syncFootIkWorldMatrices(),this.resetFootIkState(),this.footIkStateReset=!0),void this.resetDebugVisibility();this.syncFootIkWorldMatrices(),this.footIkStateReset=!1;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 Z){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=C.setFromMatrixPosition(e.foot.matrixWorld);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 Z){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=C.setFromMatrixPosition(e.upper.matrixWorld),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=O.setFromMatrixPosition(this.ikPelvisBone.matrixWorld),r=q.copy(s).addScaledVector(M,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(r.applyMatrix4(j.copy(this.ikPelvisBone.parent.matrixWorld).invert())),this.updatePelvisWorldTranslation(s)}updatePelvisWorldTranslation(t){const e=this.ikPelvisBone;if(null==e)return;e.updateMatrix(),null==e.parent?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(e.parent.matrixWorld,e.matrix),e.matrixWorldNeedsUpdate=!1;const o=e.matrixWorld.elements,i=o[12]-t.x,s=o[13]-t.y,r=o[14]-t.z;if(0===i&&0===s&&0===r)return;const n=this.ikPelvisDescendantStack;n.length=0;for(let t=0;t<e.children.length;t++)n.push(e.children[t]);for(;n.length>0;){const t=n.pop(),e=t.matrixWorld.elements;e[12]+=i,e[13]+=s,e[14]+=r,t.matrixWorldNeedsUpdate=!1;for(let e=0;e<t.children.length;e++)n.push(t.children[e])}}rebuildFootIkWorldUpdateNodes(){const t=this.ikRoot,e=this.ikBoneRefs;if(null==t||null==e)return void(this.ikWorldUpdateNodes.length=0);const o=new Set,i=[this.ikPelvisBone,e.left.upper,e.left.lower,e.left.foot,e.right.upper,e.right.lower,e.right.foot,this.ikTargetBones?.left,this.ikTargetBones?.right];for(const e of i){let i=e;for(;null!=i&&(o.add(i),i!==t);)i=i.parent??void 0}this.ikWorldUpdateNodes.length=0,t.traverse(t=>{o.has(t)&&this.ikWorldUpdateNodes.push(t)})}syncFootIkWorldMatrices(){const t=this.ikRoot;if(null!=t){t.updateWorldMatrix(!0,!1);for(const e of this.ikWorldUpdateNodes)e!==t&&(e.matrixAutoUpdate&&e.updateMatrix(),e.matrixWorldAutoUpdate&&(null==e.parent?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(e.parent.matrixWorld,e.matrix)),e.matrixWorldNeedsUpdate=!1)}}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),l=o.getWorldPosition(O),h=q.copy(n.upLocal).applyQuaternion(this.getCurrentWorldQuaternion(o,N)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof a)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=j.copy(t.boneInverses[i]).invert(),n=Q.copy(r).multiply(s),d=C.setFromMatrixPosition(n),p=V.copy(d).applyMatrix4(o.matrixWorld).sub(l);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=C.setFromMatrixPosition(t.upper.matrixWorld),i=O.setFromMatrixPosition(t.foot.matrixWorld),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=V.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(M),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=r.footWorldPos.setFromMatrixPosition(e.matrixWorld),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(M,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 v=0,L=0,x=this.footIkWeightOutSpeed;const I=null!=g||null!=m||null!=k;let P=l.y;null!=g?P=g.point.y:null!=m&&null!=k?P=.5*(m.point.y+k.point.y):null!=m?P=m.point.y:null!=k&&(P=k.point.y);const B=this.ikBoneRefs?.[t],R=this.ikLegLengths?.[t],F=null!=B&&null!=R?this.computeLegExtensionRatio(B,R):1,A=Math.max(0,l.y-P,l.y-o.targetPosition.y),D=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,I,a,F,A);D?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),v=this.computeDesiredPitchAngle(m,k,c.forward),L=1,x=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const W=1-Math.exp(-this.footIkPositionLerpSpeed*s),T=1-Math.exp(-x*s);o.normal.lerp(w,W).normalize(),o.forward.lerp(b,W).normalize(),o.pitch=y.lerp(o.pitch,v,W),o.weight=y.lerp(o.weight,L,T),o.planted=D&&L>.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=l.footWorldPos.setFromMatrixPosition(h.matrixWorld),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(M,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),v=this.getFirstGroundHit(k,a.side),L=l.desiredTargetPos.copy(c),x=l.desiredNormal.set(0,1,0),I=l.desiredForward.copy(u.forward);let P=0,B=0,R=this.footIkWeightOutSpeed;const F=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 D=this.computeLegExtensionRatio(e,o),W=Math.max(0,c.y-A,c.y-s.targetPosition.y),T=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,F,d,D,W);if(T){if(L.copy(c),this.computeDesiredGroundNormal(u,S,w,b,v,x)){this.computeDesiredFootForward(u.forward,u.right,x,w,b,I),P=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(P))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);L.y=A+e+t,s.top&&(L.y-=this.ikPelvisOffsetY/2),B=1,R=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,x,null,null,I),L.copy(c),L.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,L);const C=1-Math.exp(-this.footIkPositionLerpSpeed*n),O=1-Math.exp(-R*n);s.targetPosition.lerp(L,C),s.normal.lerp(x,C).normalize(),s.forward.lerp(I,C).normalize(),s.pitch=y.lerp(s.pitch,P,C),s.weight=y.lerp(s.weight,B,O),s.planted=T&&B>.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:v,desiredNormal:x,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(D,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(D,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(D,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(D,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 p,right:new p},n=this.getCurrentWorldDirection(this.actor.object,V);n.addScaledVector(M,-n.dot(M)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(M,-s.forward.dot(M)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=U.crossVectors(M,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,V);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=O.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=q.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(M),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(M)<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.getCurrentWorldDirection(this.actor.object,V)),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=V.copy(this.getCurrentWorldDirection(this.actor.object,V));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=O.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=N.copy(e.quaternion),l=E.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=H.setFromAxisAngle(t.rightLocal,.15);return q.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=O.subVectors(i,o),r=s.dot(M),n=q.copy(s).addScaledVector(M,-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(M,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(C).clone(),c=O.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(C).clone(),s=e.lower.getWorldPosition(O).clone(),r=e.foot.getWorldPosition(q).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new p).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,d=n+l-1e-4,u=y.clamp(h,c,d),f=a.multiplyScalar(1/h),g=(new p).subVectors(s,i).normalize(),m=(new p).subVectors(r,s).normalize(),k=(new p).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.getCurrentWorldDirection(this.actor.object,C).cross(M)),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),v=(new p).copy(i).addScaledVector(f,S);let L=(new p).crossVectors(k,f);L.lengthSq()<1e-8&&(L=(new p).crossVectors(f,M),L.lengthSq()<1e-8&&(L=new p(1,0,0))),L.normalize();const x=(new p).copy(v).addScaledVector(L,b),I=(new p).copy(v).addScaledVector(L,-b),P=(new p).subVectors(s,v).dot(L)>=0?x:I;this.rotateBoneToward(e.upper,i,s,P),e.upper.updateMatrixWorld(!0);const B=e.lower.getWorldPosition(O),R=e.foot.getWorldPosition(q);this.rotateBoneToward(e.lower,B,R,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,P,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 p).subVectors(o,e),r=(new p).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 g).setFromUnitVectors(s,r),l=this.getCurrentWorldQuaternion(t,N),a=E.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=this.getCurrentWorldQuaternion(t.parent,H),c=z.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=this.getCurrentWorldQuaternion(t,N),o=this.getCurrentWorldDirection(this.actor.object,C);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:G.clone(),world:G.clone().applyQuaternion(e)},{local:$.clone(),world:$.clone().applyQuaternion(e)},{local:_.clone(),world:_.clone().applyQuaternion(e)}];i.push({local:G.clone().multiplyScalar(-1),world:G.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:$.clone().multiplyScalar(-1),world:$.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:_.clone().multiplyScalar(-1),world:_.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(M);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 p,forward:new p,right:new p},r=this.getCurrentWorldQuaternion(e,N);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}getCurrentWorldQuaternion(t,e){return t.matrixWorld.decompose(U,e,V),e}getCurrentWorldDirection(t,e){const o=t.matrixWorld.elements;return e.set(o[8],o[9],o[10]).normalize()}clampSlopeNormal(t){const e=y.clamp(t.dot(M),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(M,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){N.copy(t.quaternion),t.quaternion.copy(e).slerp(N,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=C.copy(o.normal).normalize(),n=O.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=q.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(V.crossVectors(l,r)).normalize(),j.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),N.setFromRotationMatrix(j),Q.makeBasis(l,r,n),E.setFromRotationMatrix(Q);const a=H.copy(E).multiply(z.copy(N).invert()),h=this.getCurrentWorldQuaternion(e.parent,z),c=E.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.sequenceAnimationControlled=!1,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=0,this.upperBodyOverride=!1,this.overrideFadeTimeUpper=null,this.fullBodyTimer=0}requestSequenceAnimationRelease(){this.externalControlActive=!1,this.sequenceAnimationControlled=!1,this.currentFullBodyPriority=-1,this.sequenceAnimationReleasePending=!0,this.sequenceAnimationReleaseFrames=1,this.upperBodyOverride=!1,this.overrideFadeTimeUpper=null}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={}){it(null!=this.mixer,"Can't begin external control before setup is called"),this.assertClipRigCompatible(t),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(c,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 s&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof h&&(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={}){this.assertClipRigCompatible(t);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={}){it(null!=this.mixer,"Can't play animation before setup is called"),this.assertClipRigCompatible(t);const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,e.sequenceControlled&&(this.sequenceAnimationControlled=!0,this.sequenceAnimationReleasePending=!1,this.sequenceAnimationReleaseFrames=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)}assertClipRigCompatible(t){const e=P(t);if(e===this.animationRigId||null==e&&null==this.animationRigId)return;const o=`${t.uuid}|${e??""}|${this.animationRigId??""}`;if(!lt.has(o)){if(lt.add(o),null==e||null==this.animationRigId)return void console.warn(`Animation clip "${t.name}" or its character has no rig assigned. Playing without rig compatibility validation for legacy compatibility.`);console.warn(`Animation clip "${t.name}" targets rig ${e??"no rig"}, but this character uses rig ${this.animationRigId??"no rig"}. Generate and assign a retargeted clip for the character rig.`)}}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 s=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return t.isRunning()||!1!==o.loop||!t.clampWhenFinished||o.sequenceControlled?(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(c,1),t.clampWhenFinished=!0)),t):t;if(i(t)){const i=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,i.crossFadeTo(r,s,!1),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(c,1),t.clampWhenFinished=!0),t}};tt=t([o({inEditor:!0})],tt);export{tt as CharacterAnimationComponent};function et(t,e){if(null==t)return e;const o=e.clone();A(o,P(e));const i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function ot(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof a)}function it(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function st(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 rt(t){let e;return t.traverse(t=>{(t instanceof a||t.isBone)&&null==e&&(e=t)}),e}function nt(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}const lt=new Set;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -23,7 +23,7 @@ export type CharacterMovementLike = {
23
23
  readonly slideSurfaceNormal?: Vector3;
24
24
  applyImpulse(impulse: Vector3): void;
25
25
  setRootMotionAction(action: AnimationAction, options?: RootMotionActionOptions): void;
26
- addRootMotionTargetConstraint?(targetPosition: Vector3, minimumHorizontalDistance: number): RootMotionConstraintHandle;
26
+ addRootMotionTargetConstraint?(targetPosition: Vector3, minimumHorizontalDistance: number, maximumAddedHorizontalDistance?: number): RootMotionConstraintHandle;
27
27
  readonly isDefaultCharacterMovementComponent?: boolean;
28
28
  };
29
29
  export declare function getCharacterMovementLike(actor: BaseActor): CharacterMovementLike | undefined;
@@ -39,8 +39,13 @@ export type NetCharacterMovementRuntimeState = {
39
39
  export type RootMotionTargetConstraint = {
40
40
  readonly targetPosition: Vector3;
41
41
  readonly minimumHorizontalDistance: number;
42
+ readonly maximumAddedHorizontalDistance: number;
43
+ readonly initialHorizontalDistance: number;
44
+ addedHorizontalDistance: number;
45
+ requestedProgress: number;
42
46
  };
43
47
  export type RootMotionConstraintHandle = {
48
+ setProgress(progress: number): void;
44
49
  dispose(): void;
45
50
  };
46
51
  export declare class CharacterMovementComponent extends ActorComponent {
@@ -184,10 +189,10 @@ export declare class CharacterMovementComponent extends ActorComponent {
184
189
  get isGrounded(): boolean;
185
190
  setRootMotionAction(action: AnimationAction, options?: RootMotionActionOptions): void;
186
191
  /**
187
- * Prevent root motion from approaching a moving target closer than the
188
- * requested horizontal distance.
192
+ * Optionally adds a bounded, progress-driven approach to root motion and
193
+ * prevents it from crossing the requested target-relative distance.
189
194
  */
190
- addRootMotionTargetConstraint(targetPosition: Vector3, minimumHorizontalDistance: number): RootMotionConstraintHandle;
195
+ addRootMotionTargetConstraint(targetPosition: Vector3, minimumHorizontalDistance: number, maximumAddedHorizontalDistance?: number): RootMotionConstraintHandle;
191
196
  serverMove(payload: Uint8Array): void;
192
197
  clientMoveAck(payload: Uint8Array): void;
193
198
  clientMoveCorrection(payload: Uint8Array): void;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-simd-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Quaternion as a,Vector3 as h}from"three";import{RootMotionClip as l}from"../../../../animation/root-motion.js";import{inject as c}from"../../../../inject.js";import{ActionInput as u,AxisInput as d,RotationInput as p}from"../../../../input/index.js";import{NetRole as m}from"../../../../net/service/net-actor-role.js";import{RunOnClient as v,RunOnNotOwner as y,RunOnServer as S}from"../../../../net/service/rpc-decorator.js";import{NetService as g}from"../../../../net/service/net-service.js";import{PhysicsSystem as M,RayTestResult as f}from"../../../../services/physics/physics-system.js";import{CapsuleCollisionShape as x}from"../../../../../scene/collision/collision-shape.js";import{Parameter as T}from"../../../../../shader/parameter.js";import{PhysicsBodyType as C}from"../../../../services/physics/physics-system.js";import{ActorComponent as R,Component as w}from"../../../component.js";import{CharacterMovementMode as A}from"./modes.js";import{constrainRootMotionTargetApproach as q}from"./root-motion-constraint.js";import{DEFAULT_MAX_CLIENT_TIME_AHEAD as D,DEFAULT_LARGE_CORRECTION_THRESHOLD as b,DEFAULT_MAX_COMBINED_MOVE_DELTA_TIME as k,DEFAULT_MAX_MOVE_DELTA_TIME as z,DEFAULT_MAX_MOVES_PER_PACKET as I,DEFAULT_MAX_REPLAYED_MOVES as P,DEFAULT_MAX_SERVER_MOVES_PER_TICK as j,DEFAULT_MAX_SAVED_MOVES as O,DEFAULT_MAX_SERVER_MOVE_DELTA_TIME_SCALAR as G,DEFAULT_MAX_SERVER_MOVE_TIME_BUDGET as Y,DEFAULT_MAX_SUBSTEP_DELTA_TIME as N,DEFAULT_MOVE_SEND_INTERVAL as F,DEFAULT_SIMULATED_INTERPOLATION_DELAY as V,DEFAULT_SIMULATED_STATE_INTERVAL as U,DEFAULT_SMALL_CORRECTION_TOLERANCE as X,DEFAULT_TELEPORT_SNAP_THRESHOLD as E,MOVE_FLAG_CROUCH as L,MOVE_FLAG_JUMP as B,MOVE_FLAG_ROOT_MOTION as H,MOVE_FLAG_SLIDE_START as Z,MOVE_FLAG_SPRINT as Q,MOVE_FLAG_SPRINT_START as W,SNAPSHOT_FLAG_CROUCH_SUPPRESSED as $,SNAPSHOT_FLAG_CROUCHING as J,NetCharacterProxySmoother as K,NetCharacterSavedMoveBuffer as _,accrueNetCharacterServerMoveTime as tt,createNetCharacterMovementSnapshot as et,createNetCharacterServerMoveTimingState as it,consumeNetCharacterServerMoveTime as ot,decodeNetCharacterMoveBatch as st,decodeNetCharacterOwnerAck as nt,decodeNetCharacterOwnerCorrection as rt,decodeNetCharacterSimulatedState as at,encodeNetCharacterMoveBatch as ht,encodeNetCharacterOwnerAck as lt,encodeNetCharacterOwnerCorrection as ct,encodeNetCharacterSimulatedState as ut,validateNetCharacterMove as dt}from"./net-character-movement-protocol.js";import{NetMode as pt}from"../../../../net/net-session.js";import{setSlideJumpVelocity as mt,shouldContinueSlide as vt,shouldStartSlide as yt,updateSlideVelocity as St,updateSlideVelocityFromDisplacement as gt}from"./character-slide.js";export*from"./net-character-movement-protocol.js";const Mt=131070,ft=new h(0,1,0),xt=new h,Tt=new h,Ct=new h,Rt=new h,wt=new h,At=new h,qt=new h,Dt=new h,bt=new h,kt=new h,zt=new h,It=new h,Pt=new h,jt=new h,Ot=new h(0,1,0),Gt=new h(0,-.05,0),Yt=new h,Nt=new a,Ft=new s.Euler,Vt=new h,Ut=new h,Xt=new h,Et=new h,Lt=new i.CharacterCollision;let Bt=class extends R{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.isDefaultCharacterMovementComponent=!0,this.directionInput=new d,this.jumpInput=new u,this.sprintInput=new u,this.crouchInput=new u,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.maxSpeedCrouch=4,this.slideEnabled=!1,this.slideMinStartSpeed=8,this.slideMinExitSpeed=4,this.slideDeceleration=3,this.slideGravityScale=1,this.slideSteeringRate=2,this.sprintStartBoostSpeed=0,this.sprintStartBoostDamping=6,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.groundAccelerationRate=4,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.crouchColliderHeight=1,this.crouchColliderRadius=null,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.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulseDamping=2,this.moveSendInterval=F,this.simulatedStateInterval=U,this.maxSavedMoves=O,this.maxReplayedMoves=P,this.maxServerMovesPerTick=j,this.maxMovesPerPacket=I,this.maxMoveDeltaTime=z,this.maxCombinedMoveDeltaTime=k,this.maxServerMoveDeltaTimeScalar=G,this.maxClientTimeAhead=D,this.maxServerMoveTimeBudget=Y,this.maxSubstepDeltaTime=N,this.fallGraceTime=.1,this.correctionToleranceSq=X*X,this.largeCorrectionThreshold=b,this.teleportSnapThreshold=E,this.listenServerSmoothing=!0,this.listenServerSmoothLocationTime=.04,this.listenServerMaxSmoothUpdateDistance=1,this.listenServerNoSmoothUpdateDistance=2.5,this.debugCorrections=!0,this.suppressUncrouchLift=!1,this.velocity=new h,this.visualSmoothingOffset=new h,this.slideDirection=new h,this.slideSurfaceNormal=new h(0,1,0),this.mode=A.walking,this.isSprinting=!1,this.isCrouching=!1,this.isSliding=!1,this.pressedJump=!1,this.rayTestResult=new f,this.groundRayTestOptions={debug:!1,excludeTriggers:!0,excludeActor:void 0,resolveActor:!1},this.physicsSystem=c(M),this.netService=c(g),this.state={sequence:0,position:new h,velocity:new h,yaw:0,lookYaw:0,mode:A.walking,grounded:!1,currentSpeed:0,fallGraceTime:0,prevInputDirection:new h,prevRotateToMovementDirection:!1},this.movementModes=new Map,this.savedMoves=new _(O),this.serverMoveTiming=it(),this.serverMoveQueue=[],this.inputMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.authoritativeMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.movementModeContext={component:this,state:this.state,move:this.inputMoveScratch,deltaTime:0,rotatedDirection:Tt,platformVelocity:Rt,outVelocity:Ct,rootMotionActive:!1,startedSprinting:!1},this.proxySmoother=new K(V,E),this.proxySample=et(),this.pendingSnapshot=et(),this.impulse=new h,this.prevRootMotionPos=new h,this.rootMotionOptions={},this.rootMotionTargetConstraints=new Set,this.resetRootMotion=!1,this.nextMoveSequence=0,this.clientMoveTime=0,this.lastSentClientMoveTime=0,this.moveSendAccumulator=0,this.simulatedStateAccumulator=0,this.proxyTime=0,this.lastServerProcessedSequence=0,this.lastServerReceivedSequence=0,this.lastAutonomousMoveFlags=0,this.previousSprintInput=!1,this.previousCrouchInput=!1,this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.initialized=!1,this.cc=this.physicsSystem.getCharacterController(.1),this.cc.enableSnapToGround(.1),this.cc.enableAutostep(0,.1,!1),this.registerMovementMode(Ht),this.registerMovementMode(Zt),this.registerMovementMode({mode:A.sliding,update:t=>this.updateSlidingMode(t)})}onInit(){this.groundRayTestOptions.excludeActor=this.actor,this.configureCharacterController(),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:C.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation),this.initializeStateFromActor(),this.initialized=!0,this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(t=>this.tick(t))}onLateUpdate(t){this.updateVisualSmoothing(t)}registerMovementMode(t){this.movementModes.set(t.mode,t)}applyImpulse(t){this.impulse.add(t)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}setRootMotionAction(t,e={}){const i=t?.getClip();if(i instanceof l){this.rootMotionAction=t,this.rootMotionOptions=e,this.resetRootMotion=!0;const o=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(o);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}addRootMotionTargetConstraint(t,e){const i={targetPosition:t,minimumHorizontalDistance:Math.max(0,e)};this.rootMotionTargetConstraints.add(i);let o=!1;return{dispose:()=>{o||(o=!0,this.rootMotionTargetConstraints.delete(i))}}}serverMove(t){const e=st(t);if(e.ok)for(const t of e.value.moves)dt(t,this.lastServerReceivedSequence,this.maxMoveDeltaTime)&&(this.lastServerReceivedSequence=t.sequence,this.serverMoveQueue.push(t))}clientMoveAck(t){const e=nt(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.savedMoves.ack(e.value.sequence),this.sprintPolicy?.ack?.(e.value.sequence,!1))}clientMoveCorrection(t){const e=rt(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.debugCorrections&&(null==this.correctionDebug&&(this.correctionDebug=new Jt(_t(this.actor.object))),this.correctionDebug.update(this.state.position,e.value.snapshot)),this.applyCorrection(e.value.snapshot))}simulatedState(t){const e=at(t);e.ok&&this.actor.netRole===m.simulatedProxy&&this.proxySmoother.push(e.value,this.proxyTime)}tick(t){if(!this.initialized)return;t=Math.min(.1,t);const e=this.actor.netRole,i=this.netService.mode;e!==m.simulatedProxy?this.enabled&&(e!==m.autonomousProxy?this.isRemoteControlledAuthority(i,e)?this.tickRemoteAuthority(t):this.tickAuthority(t,i):this.tickAutonomousProxy(t)):this.tickSimulatedProxy(t)}tickAutonomousProxy(t){const e=this.state.mode,i=this.lastAutonomousMoveFlags,o=this.createMoveFromInput(t,++this.nextMoveSequence,{quantizeClientTime:!0});this.performMove(o,te),this.resetToggleCrouchAfterSlide(e);const s=this.state.mode!==e||o.flags!==i;this.lastAutonomousMoveFlags=o.flags,this.savedMoves.capacity=this.maxSavedMoves,this.savedMoves.maxCombinedDeltaTime=Math.min(this.maxCombinedMoveDeltaTime,this.maxMoveDeltaTime),this.savedMoves.push(o),this.sendSavedMoves(t,s)}tickAuthority(t,e){const i=this.state.mode,o=this.createMoveFromInput(t,++this.nextMoveSequence);this.performMove(o,te),this.resetToggleCrouchAfterSlide(i),e!==pt.none&&this.sendSimulatedState(t,!1)}resetToggleCrouchAfterSlide(t){t===A.sliding&&this.state.mode!==A.sliding&&"toggle"===this.crouchInput.mode&&this.crouchInput.activated&&this.crouchInput.setActivated(!1)}tickRemoteAuthority(t){tt(this.serverMoveTiming,t,this.maxServerMoveTimeBudget);let e=!1;const i=Number.isFinite(this.maxServerMovesPerTick)?Math.max(1,Math.floor(this.maxServerMovesPerTick)):this.serverMoveQueue.length,o=Math.min(this.serverMoveQueue.length,i),s=Xt.copy(this.actor.position);let n=!1;for(let t=0;t<o;t++){const t=this.serverMoveQueue.shift();if(null==t)break;if(!dt(t,this.lastServerProcessedSequence,this.maxMoveDeltaTime)){console.log("Net: Invalid move",t),this.sendOwnerCorrection(!0),e=!0;continue}const i=ot(this.serverMoveTiming,t,{maxMoveDeltaTime:this.maxMoveDeltaTime,maxServerMoveDeltaTimeScalar:this.maxServerMoveDeltaTimeScalar,maxClientTimeAhead:this.maxClientTimeAhead});if(i<0){this.sendOwnerCorrection(!0),e=!0;continue}const o=Wt(t,this.authoritativeMoveScratch);o.dt=i,o.rootMotionX=0,o.rootMotionY=0,o.rootMotionZ=0,o.flags&=~H,this.performMove(o,{immediate:!0,savedRootMotion:!1}),n=!0,this.lastServerProcessedSequence=o.sequence;const s=$t(this.state,t);if(s>this.correctionToleranceSq){console.log(`Net server: Correction error: ${Math.sqrt(s)}`);const o=this.state.position.x-t.clientX,n=this.state.position.y-t.clientY,r=this.state.position.z-t.clientZ;console.log(`diff x: ${o}, y: ${n}, z: ${r}`),console.log({sequence:t.sequence,moveDt:t.dt,serverMoveDeltaTime:i,flags:t.flags,mode:this.state.mode,grounded:this.state.grounded,fallGraceTime:this.state.fallGraceTime}),this.sendOwnerCorrection(s>this.largeCorrectionThreshold*this.largeCorrectionThreshold),e=!0}}0===this.lastServerProcessedSequence||e||(this.sprintPolicy?.ack?.(this.lastServerProcessedSequence,!1),this.clientMoveAck(lt(this.lastServerProcessedSequence))),n&&this.accumulateListenServerVisualSmoothing(s,this.actor.position),this.sendSimulatedState(t,!1)}tickSimulatedProxy(t){this.proxyTime+=t,this.proxySmoother.sample(this.proxyTime,this.proxySample)&&this.applySnapshot(this.proxySample,!0)}accumulateListenServerVisualSmoothing(t,e){if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);Et.subVectors(t,e);const i=Et.lengthSq();i>1e-8&&(i>this.listenServerNoSmoothUpdateDistance*this.listenServerNoSmoothUpdateDistance?this.visualSmoothingOffset.set(0,0,0):(i>this.listenServerMaxSmoothUpdateDistance*this.listenServerMaxSmoothUpdateDistance&&Et.setLength(this.listenServerMaxSmoothUpdateDistance),this.visualSmoothingOffset.add(Et)))}updateVisualSmoothing(t){if(this.visualSmoothingOffset.lengthSq()<=1e-8)return void this.visualSmoothingOffset.set(0,0,0);if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);const e=Math.max(.001,this.listenServerSmoothLocationTime);t<e?this.visualSmoothingOffset.multiplyScalar(1-t/e):this.visualSmoothingOffset.set(0,0,0),this.visualSmoothingOffset.lengthSq()<=1e-4&&this.visualSmoothingOffset.set(0,0,0)}shouldSmoothListenServerRemoteAuthority(){return this.listenServerSmoothing&&this.actor.netRole===m.authority&&this.netService.isServer&&!this.netService.isDedicatedServer&&this.isRemoteControlledAuthority()}createMoveFromInput(t,e,i={}){const o=r.clamp(t,.001,this.maxMoveDeltaTime);this.clientMoveTime+=o;let s=this.clientMoveTime,n=o;!0===i.quantizeClientTime&&(s=Math.max(this.lastSentClientMoveTime+.001,Math.round(1e3*this.clientMoveTime)/1e3),n=r.clamp(s-this.lastSentClientMoveTime,.001,this.maxMoveDeltaTime),this.lastSentClientMoveTime=s),this.sampleRootMotion(qt);const a=this.crouchInput.activated,h=a&&!this.previousCrouchInput;this.previousCrouchInput=a;const l=!a&&this.sprintInput.activated,c=l&&!this.previousSprintInput;this.previousSprintInput=l;const u=(this.jumpInput.activated?B:0)|(l?Q:0)|(a?L:0)|(h&&this.slideEnabled?Z:0)|(c?W:0)|(qt.lengthSq()>0?H:0),d=function(t,e){e.set(t.x,0,t.y),e.lengthSq()>1&&e.normalize();return e}(this.directionInput.vector,Vt),p=this.inputMoveScratch;return p.sequence=e>>>0,p.clientTime=s,p.dt=n,p.inputX=d.x,p.inputY=d.z,p.yaw=this.rotationInput.rotation.y,p.flags=u,p.clientX=this.state.position.x,p.clientY=this.state.position.y,p.clientZ=this.state.position.z,p.rootMotionX=qt.x,p.rootMotionY=qt.y,p.rootMotionZ=qt.z,p}performMove(t,e){const i=r.clamp(t.dt,.001,this.maxMoveDeltaTime),o=Math.max(1,Math.ceil(i/this.maxSubstepDeltaTime)),s=0!==(t.flags&Q)&&0===(t.flags&L);this.sprintPolicy?.update?.(i,t.sequence,s),It.set(e.savedRootMotion?t.rootMotionX:0,e.savedRootMotion?t.rootMotionY:0,e.savedRootMotion?t.rootMotionZ:0),e.savedRootMotion||this.sampleRootMotion(It);let n=i;const a=i/o;for(let s=0;s<o;s++){const o=i>0?a/i:1;this.performSubstep(t,Math.min(a,n),It,o,e.immediate,0===s),n-=a}t.clientX=this.state.position.x,t.clientY=this.state.position.y,t.clientZ=this.state.position.z,t.flags=It.lengthSq()>0?t.flags|H:t.flags&~H,this.state.sequence=t.sequence,this.syncPublicState()}performSubstep(t,e,i,o,s,n){if(e<.001)return;this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded;const r=null!=this.rootMotionAction&&this.rootMotionAction.enabled,a=i.lengthSq()>0,h=!r&&0!==(t.flags&B),l=r||a;this.updateCrouchState(t,n,l,h),this.pressedJump=h,this.isSprinting=!1,this.updateRotation(t,e,r,a),this.resolvePlatformVelocity(Rt);const c=this.movementModeContext,u=this.movementModes.get(this.state.mode);if(null!=u){c.move=t,c.deltaTime=e,c.rootMotionActive=l,c.startedSprinting=n&&!l&&0===(t.flags&L)&&0!==(t.flags&W);const i=u.update(c);"number"==typeof i&&(this.state.mode=i)}else Ct.set(0,0,0);if(a){Dt.copy(i).multiplyScalar(o).applyQuaternion(this.actor.quaternion),bt.copy(Dt).divideScalar(e),this.state.mode===A.walking?(Ct.x=bt.x+Rt.x,Ct.z=bt.z+Rt.z):(Ct.x=bt.x,Ct.z=bt.z);const t=Math.sqrt(bt.x*bt.x+bt.z*bt.z);t>.4&&(this.state.currentSpeed=t)}if(this.applyImpulseToVelocity(Ct,e),h&&this.isSprinting){const t=Math.max(0,this.maxSpeedSprint),e=Qt(Ct);if(e>t){const i=t/e;Ct.x*=i,Ct.z*=i,this.state.velocity.x*=i,this.state.velocity.z*=i}}this.state.mode===A.walking&&this.state.velocity.copy(Ct),this.applyMovement(Ct,e,s),this.state.mode===A.sliding&&(gt(this.state.velocity,At,Rt,this.slideSurfaceNormal,e),this.state.currentSpeed=Qt(this.state.velocity)),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.updateModeAfterMove(Ct,e),this.state.mode===A.sliding&&this.state.velocity.length()<Math.max(0,this.slideMinExitSpeed)&&(this.state.mode=A.walking)}updateRotation(t,e,i,o){xt.set(-t.inputX,0,t.inputY),xt.lengthSq()>1&&xt.normalize();const s=this.state.prevRotateToMovementDirection!==this.rotateToMovementDirection;let n=r.euclideanModulo(t.yaw-this.state.lookYaw+Math.PI,2*Math.PI)-Math.PI;if(s&&(this.actor.object.quaternion.setFromEuler(Ft.set(0,t.yaw,0)),this.state.prevRotateToMovementDirection||(n=0,this.state.lookYaw=t.yaw),this.state.prevRotateToMovementDirection=this.rotateToMovementDirection),Tt.set(0,0,0),i)this.state.lookYaw=t.yaw;else if(this.rotateToMovementDirection){if(xt.lengthSq()>0&&this.state.mode!==A.falling){const i=Ft.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,o=Math.atan2(xt.x,xt.z),s=.99*t.yaw+o;if(this.smoothRotation){const t=r.euclideanModulo(s-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(Ft.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(Ft.set(0,s,0));this.state.prevInputDirection.lerp(xt,e*this.rotationSpeed),this.state.lookYaw+=n,Tt.copy(this.actor.object.getWorldDirection(Vt).normalize())}}else o||(this.state.lookYaw+=n,this.actor.object.quaternion.multiply(Nt.setFromEuler(Ft.set(0,n,0))),xt.lengthSq()>0&&Tt.copy(xt).applyQuaternion(this.actor.object.quaternion).normalize())}applyMovement(t,e,i){if(t.lengthSq()>0||!this.state.grounded){if(wt.copy(t).multiplyScalar(e),this.state.grounded&&((o=this.state.mode)===A.walking||o===A.sliding)&&(this.state.mode===A.walking&&this.rayTestResult.distance<=this.cc.offset()&&(wt.y=Math.max(0,Rt.y*e)),this.physicsSystem.getActorComputedMovement(this.actor,this.cc,wt,this.getCollisionGroup()),this.cc.computedCollision(0,Lt),null!=Lt.normal1)){const t=Vt.copy(Lt.normal1);Math.acos(r.clamp(t.dot(ft),-1,1))>this.cc.maxSlopeClimbAngle()&&(wt.y=.016*this.getEffectiveGravity()*.5)}At.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,wt,this.getCollisionGroup()))}else At.set(0,0,0);var o;this.suppressUncrouchLift&&(this.suppressUncrouchLift=!1,this.state.grounded&&this.state.mode===A.walking&&wt.y<=1e-6&&At.y>0&&(At.y=0)),this.state.position.add(At),i?(this.actor.position.copy(this.state.position),this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()):this.physicsSystem.setNextKinematicPosition(this.actor,this.state.position)}updateModeAfterMove(t,e){const i=function(t){if(0===t.numComputedCollisions())return!1;const e=t.computedCollision(0);Yt.set(e.normal2.x,e.normal2.y,e.normal2.z);const i=Yt.angleTo(ft);Yt.set(e.normal1.x,e.normal1.y,e.normal1.z);const o=Yt.angleTo(ft);if(i<100)return!1;return o>t.minSlopeSlideAngle()}(this.cc);!this.state.grounded||i?this.state.mode!==A.falling&&(this.state.fallGraceTime+=e,this.state.fallGraceTime>this.fallGraceTime+1e-6&&(this.state.mode=A.falling,this.state.velocity.copy(t))):this.state.velocity.y<=0&&(this.state.mode===A.falling&&(this.state.mode=A.walking),this.state.mode!==A.sliding&&(this.state.velocity.y=0),this.state.fallGraceTime=0)}applyImpulseToVelocity(t,e){if(this.impulse.lengthSq()<=.1)return void this.impulse.set(0,0,0);const i=Math.min(1,this.impulse.length()/5);t.x=r.lerp(t.x,this.impulse.x,i),t.z=r.lerp(t.z,this.impulse.z,i),t.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}sendSavedMoves(t,e=!1){if(this.moveSendAccumulator+=t,!e&&this.moveSendAccumulator<this.moveSendInterval)return;this.moveSendAccumulator=0;const i=this.savedMoves.getMovesForSend(this.maxMovesPerPacket);0!==i.length&&this.serverMove(ht(i))}sendOwnerCorrection(t){const e=this.toSnapshot(this.pendingSnapshot);t&&(e.horizontalSpeed=this.horizontalSpeed),this.sprintPolicy?.ack?.(e.sequence,!0),this.clientMoveCorrection(ct(e))}sendSimulatedState(t,e){this.simulatedStateAccumulator+=t,!e&&this.simulatedStateAccumulator<this.simulatedStateInterval||(this.simulatedStateAccumulator=0,this.simulatedState(ut(this.toSnapshot(this.pendingSnapshot))))}applyCorrection(t){this.sprintPolicy?.restore?.(t.sequence),this.savedMoves.ack(t.sequence),this.sprintPolicy?.ack?.(t.sequence,!0),this.applySnapshot(t,!0),this.savedMoves.replayAfter(t.sequence,t=>(this.performMove(t,{immediate:!0,savedRootMotion:!0}),null),this.maxReplayedMoves)}applySnapshot(t,e){this.state.sequence=t.sequence,this.state.position.set(t.x,t.y,t.z),this.state.velocity.set(t.velocityX,t.velocityY,t.velocityZ),this.state.yaw=t.yaw,this.state.lookYaw=t.yaw,this.state.mode=t.mode,this.state.currentSpeed=t.horizontalSpeed,this.state.fallGraceTime=0,this.actor.position.copy(this.state.position),this.actor.object.quaternion.setFromEuler(Ft.set(0,t.yaw,0)),this.crouchSuppressedUntilRelease=0!==(t.flags&$),this.setCrouching(0!==(t.flags&J)||t.mode===A.sliding),e&&(this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.syncPublicState()}toSnapshot(t){return t.sequence=this.state.sequence,t.x=this.state.position.x,t.y=this.state.position.y,t.z=this.state.position.z,t.velocityX=this.state.velocity.x,t.velocityY=this.state.velocity.y,t.velocityZ=this.state.velocity.z,t.yaw=Ft.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,t.mode=this.state.mode,t.flags=(this.isCrouching?J:0)|(this.crouchSuppressedUntilRelease?$:0),t.horizontalSpeed=this.state.currentSpeed,t}syncPublicState(){this.velocity.copy(this.state.velocity),this.mode=this.state.mode,this.horizontalSpeed=this.state.currentSpeed,this.isSliding=this.state.mode===A.sliding,this.isSliding?(this.resolveGroundNormal(this.slideSurfaceNormal),this.slideDirection.copy(this.state.velocity).projectOnPlane(this.slideSurfaceNormal),this.slideDirection.lengthSq()>1e-8?this.slideDirection.normalize():this.slideDirection.set(0,0,0)):(this.slideDirection.set(0,0,0),this.slideSurfaceNormal.copy(ft))}sampleRootMotion(t){if(t.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 e=this.rootMotionAction,i=this.rootMotionOptions.onJumpCancel;return this.clearRootMotionAction(e),e.stop(),i?.(),t}if(null==this.rootMotionAction)return t;if(!(this.rootMotionAction.getClip()instanceof l))return t;const e=this.rootMotionInterpolant;this.resetRootMotion&&(this.prevRootMotionPos.fromArray(e.evaluate(0)),this.resetRootMotion=!1),zt.fromArray(e.evaluate(this.rootMotionAction.time)),t.subVectors(zt,this.prevRootMotionPos),this.prevRootMotionPos.copy(zt);if((this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(kt),t.multiply(kt),t.lengthSq()>0&&this.rootMotionTargetConstraints.size>0){Dt.copy(t).applyQuaternion(this.actor.quaternion);for(const t of this.rootMotionTargetConstraints)q(Dt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance);t.copy(Dt).applyQuaternion(Nt.copy(this.actor.quaternion).invert())}return t}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}isRemoteControlledAuthority(t=this.netService.mode,e=this.actor.netRole){if(t===pt.none||e!==m.authority||t>=pt.client)return!1;return null!=this.netService.resolveActorConnection(this.actor)&&!this.netService.isLocalOwner(this.actor)}configureCharacterController(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding)}initializeStateFromActor(){this.state.position.copy(this.actor.position),this.state.velocity.set(0,0,0),this.state.yaw=this.actor.rotation.y,this.state.lookYaw=this.rotationInput.rotation.y,this.state.mode=this.mode,this.state.currentSpeed=this.horizontalSpeed,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection}createCollisionShape(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1),i=new x(t,e);return i.offset.y=this.getCapsuleOffsetY(t,e),i.collisionGroup=Mt,i}updateCrouchState(t,e,i,o){if(!(0!==(t.flags&L)))return this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.state.mode===A.sliding&&(this.state.mode=A.walking),void this.tryUncrouch();if(this.state.mode===A.sliding&&(!this.slideEnabled||i))return this.slideOnLandingRequested=!1,this.state.mode=A.walking,void(this.crouchSuppressedUntilRelease||this.setCrouching(!0));if(this.state.mode===A.sliding&&o)return this.crouchSuppressedUntilRelease=!0,this.slideOnLandingRequested=!1,void this.tryUncrouch();if(this.crouchSuppressedUntilRelease)return void(this.slideOnLandingRequested=!1);if(this.setCrouching(!0),!this.slideEnabled||i)return void(this.slideOnLandingRequested=!1);if(this.state.mode===A.falling)return void(this.slideOnLandingRequested=!0);this.resolveGroundNormal(Ut);const s=this.slideOnLandingRequested&&this.state.mode===A.walking&&this.state.grounded,n=e&&0!==(t.flags&Z)||s;s&&(this.slideOnLandingRequested=!1);const r=Qt(this.state.velocity);this.state.mode===A.walking&&yt(this.slideEnabled,n,this.state.grounded,this.isWalkableSlideSurface(Ut),i,r,this.slideMinStartSpeed)&&(this.state.mode=A.sliding,this.slideSurfaceNormal.copy(Ut),this.state.velocity.projectOnPlane(this.slideSurfaceNormal),this.state.currentSpeed=Qt(this.state.velocity))}updateSlidingMode(t){const e=t.state,i=t.move;this.resolveGroundNormal(this.slideSurfaceNormal);const o=this.isWalkableSlideSurface(this.slideSurfaceNormal),s=e.velocity.length();if(!e.grounded||!o)return e.mode=A.falling,Zt.update(t),A.falling;if(this.slideEnabled&&0!==(i.flags&L)&&!t.rootMotionActive&&0!==(i.flags&B))return mt(t.outVelocity,e.velocity,this.jumpVelocity),e.velocity.copy(t.outVelocity),e.currentSpeed=Qt(e.velocity),A.falling;if(!vt(this.slideEnabled,0!==(i.flags&L),e.grounded,o,t.rootMotionActive,s,this.slideMinExitSpeed))return e.mode=A.walking,Ht.update(t),A.walking;const n=St(e.velocity,e.velocity,this.slideSurfaceNormal,t.rotatedDirection,this.getEffectiveGravity(),t.deltaTime,this.slideDeceleration,this.slideGravityScale,this.slideSteeringRate);if(e.currentSpeed=Qt(e.velocity),n<Math.max(0,this.slideMinExitSpeed))return e.mode=A.walking,Ht.update(t),A.walking;t.outVelocity.copy(e.velocity).add(t.platformVelocity)}tryUncrouch(){this.isCrouching&&this.canUncrouch()&&this.setCrouching(!1)&&(this.suppressUncrouchLift=!0,this.state.fallGraceTime=0)}resolveGroundNormal(t){return!this.rayTestResult.hasHit||this.rayTestResult.hitNormal.lengthSq()<=1e-8?t.copy(ft):(t.copy(this.rayTestResult.hitNormal).normalize(),t.dot(ft)<0&&t.multiplyScalar(-1),t)}isWalkableSlideSurface(t){return t.dot(ft)>=Math.cos(this.cc.maxSlopeClimbAngle())}setCrouching(t){return this.isCrouching!==t&&(this.isCrouching=t,this.syncColliderShape(),!0)}canUncrouch(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1);return!this.physicsSystem.hasActorCapsuleIntersection(this.actor,this.state.position,t,e,this.getCapsuleOffsetY(t,e),this.getCollisionGroup())}syncColliderShape(){const t=this.getColliderHeight(this.isCrouching),e=this.getColliderRadius(this.isCrouching);this.physicsSystem.setActorCapsuleCollider(this.actor,t,e,this.getCapsuleOffsetY(t,e))}getColliderHeight(t){const e=Number.isFinite(this.colliderHeight)?Math.max(0,this.colliderHeight):0;if(!t)return e;const i=Number.isFinite(this.crouchColliderHeight)?this.crouchColliderHeight:e;return r.clamp(i,0,e)}getColliderRadius(t){const e=Number.isFinite(this.colliderRadius)?Math.max(.001,this.colliderRadius):.001;if(!t)return e;const i=this.crouchColliderRadius??e,o=Number.isFinite(i)?i:e;return r.clamp(o,.001,e)}getCapsuleOffsetY(t,e){return e+t/2+this.offset}checkGrounded(t){Gt.y=-Math.max(.05,this.cc.snapToGroundDistance()),this.physicsSystem.rayTest(Pt.addVectors(t,Ot.set(0,this.offset,0)),jt.addVectors(t,Gt),this.rayTestResult,this.groundRayTestOptions)}resolvePlatformVelocity(t){return t.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,t),t}getCollisionGroup(){return this.characterCollision?null:Mt}};t([T(),e("design:type",Number)],Bt.prototype,"colliderHeight",void 0),t([T(),e("design:type",Number)],Bt.prototype,"colliderRadius",void 0),t([T(),e("design:type",Number)],Bt.prototype,"crouchColliderHeight",void 0),t([T({optional:!0}),e("design:type",Number)],Bt.prototype,"crouchColliderRadius",void 0),t([S(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Bt.prototype,"serverMove",null),t([v(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Bt.prototype,"clientMoveAck",null),t([v(!0),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Bt.prototype,"clientMoveCorrection",null),t([y(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Bt.prototype,"simulatedState",null),Bt=t([w({inEditor:!1}),e("design:paramtypes",[])],Bt);export{Bt as CharacterMovementComponent};const Ht={mode:A.walking,update(t){const e=t.component,i=t.move,o=t.state,s=t.rotatedDirection,n=Math.min(1,Math.sqrt(i.inputX*i.inputX+i.inputY*i.inputY)),r=!e.rotateToMovementDirection&&i.inputY<0,a=e.isCrouching,h=!t.rootMotionActive&&!a&&0===(i.flags&L)&&0!==(i.flags&Q)&&!r&&0!==s.lengthSq()&&(e.sprintPolicy?.canSprint()??!0),l=(a?e.maxSpeedCrouch:r?e.maxSpeedBackwards:h?e.maxSpeedSprint:e.maxSpeed)*(e.normalizedDirection?1:n);if(0!==s.lengthSq()){e.isSprinting=h,h&&e.sprintPolicy?.commitSprint(t.deltaTime,i.sequence);let a=Math.min(l,o.currentSpeed),c=e.groundAccelerationRate;if(h&&t.startedSprinting&&e.sprintStartBoostSpeed>0){const t=e.normalizedDirection?1:n;a=Math.max(a,l+e.sprintStartBoostSpeed*t),c=e.sprintStartBoostDamping}else h&&!r&&e.sprintStartBoostSpeed>0&&o.currentSpeed>l&&(a=o.currentSpeed,c=e.sprintStartBoostDamping);o.currentSpeed=function(t,e,i,o){return e+(t-e)*Math.exp(-i*o)}(a,l,c,t.deltaTime),t.outVelocity.copy(s).multiplyScalar(function(t,e,i,o){const s=i*o;if(s<=1e-6)return t;return e+(t-e)*(1-Math.exp(-s))/s}(a,l,c,t.deltaTime))}else o.currentSpeed=0,t.outVelocity.set(0,0,0);if(0!==(i.flags&B))return o.mode=A.falling,o.velocity.copy(t.outVelocity),o.velocity.y=e.jumpVelocity,A.falling;t.outVelocity.y=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.add(t.platformVelocity)}},Zt={mode:A.falling,update(t){const e=t.component,i=t.state,o=t.move;0!==(o.flags&B)&&e.jumpInAir&&(i.velocity.copy(t.outVelocity),i.velocity.y=e.jumpVelocity),i.velocity.y+=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.copy(i.velocity),t.outVelocity.addScaledVector(t.rotatedDirection,e.fallingMovementControl),e.fallingReorientation&&t.outVelocity.applyAxisAngle(ft,r.euclideanModulo(o.yaw-i.lookYaw+Math.PI,2*Math.PI)-Math.PI)}};function Qt(t){return Math.sqrt(t.x*t.x+t.z*t.z)}function Wt(t,e){return e.sequence=t.sequence,e.clientTime=t.clientTime,e.dt=t.dt,e.inputX=t.inputX,e.inputY=t.inputY,e.yaw=t.yaw,e.flags=t.flags,e.clientX=t.clientX,e.clientY=t.clientY,e.clientZ=t.clientZ,e.rootMotionX=t.rootMotionX,e.rootMotionY=t.rootMotionY,e.rootMotionZ=t.rootMotionZ,e}function $t(t,e){const i=t.position.x-e.clientX,o=t.position.y-e.clientY,s=t.position.z-e.clientZ;return i*i+o*o+s*s}class Jt{constructor(t){this.scene=t,this.serverPosition=new h,this.direction=new h}update(t,e){const i=this.serverPosition.set(e.x,e.y,e.z),o=i.distanceTo(t);o>.1&&console.log(`Correction applied. Error: ${o.toFixed(3)}. Server position: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z.toFixed(2)}), Client position: (${t.x.toFixed(2)}, ${t.y.toFixed(2)}, ${t.z.toFixed(2)})`);const s=this.direction.copy(i).sub(t).normalize();Kt.position.copy(t),Kt.setDirection(s),Kt.setLength(o);const n=_t(this.scene);n.add(Kt),setTimeout(()=>{n.remove(Kt)},1e3)}}const Kt=new n(new h(0,1,0),new h,1,16711680);function _t(t){return null==t.parent?t:_t(t.parent)}const te={immediate:!1,savedRootMotion:!0};/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-simd-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Quaternion as a,Vector3 as h}from"three";import{RootMotionClip as l}from"../../../../animation/root-motion.js";import{inject as c}from"../../../../inject.js";import{ActionInput as d,AxisInput as u,RotationInput as m}from"../../../../input/index.js";import{NetRole as p}from"../../../../net/service/net-actor-role.js";import{RunOnClient as v,RunOnNotOwner as y,RunOnServer as g}from"../../../../net/service/rpc-decorator.js";import{NetService as S}from"../../../../net/service/net-service.js";import{PhysicsSystem as M,RayTestResult as f}from"../../../../services/physics/physics-system.js";import{CapsuleCollisionShape as x}from"../../../../../scene/collision/collision-shape.js";import{Parameter as T}from"../../../../../shader/parameter.js";import{PhysicsBodyType as C}from"../../../../services/physics/physics-system.js";import{ActorComponent as w,Component as R}from"../../../component.js";import{CharacterMovementMode as A}from"./modes.js";import{calculateRootMotionTargetApproachCorrection as D,constrainRootMotionTargetApproach as q,warpRootMotionTargetApproach as b}from"./root-motion-constraint.js";import{DEFAULT_MAX_CLIENT_TIME_AHEAD as z,DEFAULT_LARGE_CORRECTION_THRESHOLD as k,DEFAULT_MAX_COMBINED_MOVE_DELTA_TIME as P,DEFAULT_MAX_MOVE_DELTA_TIME as I,DEFAULT_MAX_MOVES_PER_PACKET as O,DEFAULT_MAX_REPLAYED_MOVES as j,DEFAULT_MAX_SERVER_MOVES_PER_TICK as G,DEFAULT_MAX_SAVED_MOVES as Y,DEFAULT_MAX_SERVER_MOVE_DELTA_TIME_SCALAR as N,DEFAULT_MAX_SERVER_MOVE_TIME_BUDGET as F,DEFAULT_MAX_SUBSTEP_DELTA_TIME as V,DEFAULT_MOVE_SEND_INTERVAL as H,DEFAULT_SIMULATED_INTERPOLATION_DELAY as U,DEFAULT_SIMULATED_STATE_INTERVAL as X,DEFAULT_SMALL_CORRECTION_TOLERANCE as E,DEFAULT_TELEPORT_SNAP_THRESHOLD as L,MOVE_FLAG_CROUCH as B,MOVE_FLAG_JUMP as Z,MOVE_FLAG_ROOT_MOTION as W,MOVE_FLAG_SLIDE_START as $,MOVE_FLAG_SPRINT as Q,MOVE_FLAG_SPRINT_START as J,SNAPSHOT_FLAG_CROUCH_SUPPRESSED as K,SNAPSHOT_FLAG_CROUCHING as _,NetCharacterProxySmoother as tt,NetCharacterSavedMoveBuffer as et,accrueNetCharacterServerMoveTime as it,createNetCharacterMovementSnapshot as ot,createNetCharacterServerMoveTimingState as st,consumeNetCharacterServerMoveTime as nt,decodeNetCharacterMoveBatch as rt,decodeNetCharacterOwnerAck as at,decodeNetCharacterOwnerCorrection as ht,decodeNetCharacterSimulatedState as lt,encodeNetCharacterMoveBatch as ct,encodeNetCharacterOwnerAck as dt,encodeNetCharacterOwnerCorrection as ut,encodeNetCharacterSimulatedState as mt,validateNetCharacterMove as pt}from"./net-character-movement-protocol.js";import{NetMode as vt}from"../../../../net/net-session.js";import{setSlideJumpVelocity as yt,shouldContinueSlide as gt,shouldStartSlide as St,updateSlideVelocity as Mt,updateSlideVelocityFromDisplacement as ft}from"./character-slide.js";export*from"./net-character-movement-protocol.js";const xt=131070,Tt=new h(0,1,0),Ct=new h,wt=new h,Rt=new h,At=new h,Dt=new h,qt=new h,bt=new h,zt=new h,kt=new h,Pt=new h,It=new h,Ot=new h,jt=new h,Gt=new h,Yt=new h(0,1,0),Nt=new h(0,-.05,0),Ft=new h,Vt=new a,Ht=new s.Euler,Ut=new h,Xt=new h,Et=new h,Lt=new h,Bt=new i.CharacterCollision;let Zt=class extends w{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.isDefaultCharacterMovementComponent=!0,this.directionInput=new u,this.jumpInput=new d,this.sprintInput=new d,this.crouchInput=new d,this.rotationInput=new m,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.maxSpeedCrouch=4,this.slideEnabled=!1,this.slideMinStartSpeed=8,this.slideMinExitSpeed=4,this.slideDeceleration=3,this.slideGravityScale=1,this.slideSteeringRate=2,this.sprintStartBoostSpeed=0,this.sprintStartBoostDamping=6,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.groundAccelerationRate=4,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.crouchColliderHeight=1,this.crouchColliderRadius=null,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.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulseDamping=2,this.moveSendInterval=H,this.simulatedStateInterval=X,this.maxSavedMoves=Y,this.maxReplayedMoves=j,this.maxServerMovesPerTick=G,this.maxMovesPerPacket=O,this.maxMoveDeltaTime=I,this.maxCombinedMoveDeltaTime=P,this.maxServerMoveDeltaTimeScalar=N,this.maxClientTimeAhead=z,this.maxServerMoveTimeBudget=F,this.maxSubstepDeltaTime=V,this.fallGraceTime=.1,this.correctionToleranceSq=E*E,this.largeCorrectionThreshold=k,this.teleportSnapThreshold=L,this.listenServerSmoothing=!0,this.listenServerSmoothLocationTime=.04,this.listenServerMaxSmoothUpdateDistance=1,this.listenServerNoSmoothUpdateDistance=2.5,this.debugCorrections=!0,this.suppressUncrouchLift=!1,this.velocity=new h,this.visualSmoothingOffset=new h,this.slideDirection=new h,this.slideSurfaceNormal=new h(0,1,0),this.mode=A.walking,this.isSprinting=!1,this.isCrouching=!1,this.isSliding=!1,this.pressedJump=!1,this.rayTestResult=new f,this.groundRayTestOptions={debug:!1,excludeTriggers:!0,excludeActor:void 0,resolveActor:!1},this.physicsSystem=c(M),this.netService=c(S),this.state={sequence:0,position:new h,velocity:new h,yaw:0,lookYaw:0,mode:A.walking,grounded:!1,currentSpeed:0,fallGraceTime:0,prevInputDirection:new h,prevRotateToMovementDirection:!1},this.movementModes=new Map,this.savedMoves=new et(Y),this.serverMoveTiming=st(),this.serverMoveQueue=[],this.inputMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.authoritativeMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.movementModeContext={component:this,state:this.state,move:this.inputMoveScratch,deltaTime:0,rotatedDirection:wt,platformVelocity:At,outVelocity:Rt,rootMotionActive:!1,startedSprinting:!1},this.proxySmoother=new tt(U,L),this.proxySample=ot(),this.pendingSnapshot=ot(),this.impulse=new h,this.prevRootMotionPos=new h,this.rootMotionOptions={},this.rootMotionTargetConstraints=new Set,this.resetRootMotion=!1,this.nextMoveSequence=0,this.clientMoveTime=0,this.lastSentClientMoveTime=0,this.moveSendAccumulator=0,this.simulatedStateAccumulator=0,this.proxyTime=0,this.lastServerProcessedSequence=0,this.lastServerReceivedSequence=0,this.lastAutonomousMoveFlags=0,this.previousSprintInput=!1,this.previousCrouchInput=!1,this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.initialized=!1,this.cc=this.physicsSystem.getCharacterController(.1),this.cc.enableSnapToGround(.1),this.cc.enableAutostep(0,.1,!1),this.registerMovementMode(Wt),this.registerMovementMode($t),this.registerMovementMode({mode:A.sliding,update:t=>this.updateSlidingMode(t)})}onInit(){this.groundRayTestOptions.excludeActor=this.actor,this.configureCharacterController(),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:C.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation),this.initializeStateFromActor(),this.initialized=!0,this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(t=>this.tick(t))}onLateUpdate(t){this.updateVisualSmoothing(t)}registerMovementMode(t){this.movementModes.set(t.mode,t)}applyImpulse(t){this.impulse.add(t)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}setRootMotionAction(t,e={}){const i=t?.getClip();if(i instanceof l){this.rootMotionAction=t,this.rootMotionOptions=e,this.resetRootMotion=!0;const o=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(o);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}addRootMotionTargetConstraint(t,e,i=0){const o={targetPosition:t,minimumHorizontalDistance:Math.max(0,e),maximumAddedHorizontalDistance:Math.max(0,i),initialHorizontalDistance:Math.hypot(t.x-this.actor.position.x,t.z-this.actor.position.z),addedHorizontalDistance:0,requestedProgress:0};this.rootMotionTargetConstraints.add(o);let s=!1;return{setProgress:t=>{o.requestedProgress=Math.max(o.requestedProgress,Math.min(1,Math.max(0,t)))},dispose:()=>{s||(s=!0,this.rootMotionTargetConstraints.delete(o))}}}serverMove(t){const e=rt(t);if(e.ok)for(const t of e.value.moves)pt(t,this.lastServerReceivedSequence,this.maxMoveDeltaTime)&&(this.lastServerReceivedSequence=t.sequence,this.serverMoveQueue.push(t))}clientMoveAck(t){const e=at(t);e.ok&&this.actor.netRole===p.autonomousProxy&&(this.savedMoves.ack(e.value.sequence),this.sprintPolicy?.ack?.(e.value.sequence,!1))}clientMoveCorrection(t){const e=ht(t);e.ok&&this.actor.netRole===p.autonomousProxy&&(this.debugCorrections&&(null==this.correctionDebug&&(this.correctionDebug=new _t(ee(this.actor.object))),this.correctionDebug.update(this.state.position,e.value.snapshot)),this.applyCorrection(e.value.snapshot))}simulatedState(t){const e=lt(t);e.ok&&this.actor.netRole===p.simulatedProxy&&this.proxySmoother.push(e.value,this.proxyTime)}tick(t){if(!this.initialized)return;t=Math.min(.1,t);const e=this.actor.netRole,i=this.netService.mode;e!==p.simulatedProxy?this.enabled&&(e!==p.autonomousProxy?this.isRemoteControlledAuthority(i,e)?this.tickRemoteAuthority(t):this.tickAuthority(t,i):this.tickAutonomousProxy(t)):this.tickSimulatedProxy(t)}tickAutonomousProxy(t){const e=this.state.mode,i=this.lastAutonomousMoveFlags,o=this.createMoveFromInput(t,++this.nextMoveSequence,{quantizeClientTime:!0});this.performMove(o,ie),this.resetToggleCrouchAfterSlide(e);const s=this.state.mode!==e||o.flags!==i;this.lastAutonomousMoveFlags=o.flags,this.savedMoves.capacity=this.maxSavedMoves,this.savedMoves.maxCombinedDeltaTime=Math.min(this.maxCombinedMoveDeltaTime,this.maxMoveDeltaTime),this.savedMoves.push(o),this.sendSavedMoves(t,s)}tickAuthority(t,e){const i=this.state.mode,o=this.createMoveFromInput(t,++this.nextMoveSequence);this.performMove(o,ie),this.resetToggleCrouchAfterSlide(i),e!==vt.none&&this.sendSimulatedState(t,!1)}resetToggleCrouchAfterSlide(t){t===A.sliding&&this.state.mode!==A.sliding&&"toggle"===this.crouchInput.mode&&this.crouchInput.activated&&this.crouchInput.setActivated(!1)}tickRemoteAuthority(t){it(this.serverMoveTiming,t,this.maxServerMoveTimeBudget);let e=!1;const i=Number.isFinite(this.maxServerMovesPerTick)?Math.max(1,Math.floor(this.maxServerMovesPerTick)):this.serverMoveQueue.length,o=Math.min(this.serverMoveQueue.length,i),s=Et.copy(this.actor.position);let n=!1;for(let t=0;t<o;t++){const t=this.serverMoveQueue.shift();if(null==t)break;if(!pt(t,this.lastServerProcessedSequence,this.maxMoveDeltaTime)){console.log("Net: Invalid move",t),this.sendOwnerCorrection(!0),e=!0;continue}const i=nt(this.serverMoveTiming,t,{maxMoveDeltaTime:this.maxMoveDeltaTime,maxServerMoveDeltaTimeScalar:this.maxServerMoveDeltaTimeScalar,maxClientTimeAhead:this.maxClientTimeAhead});if(i<0){this.sendOwnerCorrection(!0),e=!0;continue}const o=Jt(t,this.authoritativeMoveScratch);o.dt=i,o.rootMotionX=0,o.rootMotionY=0,o.rootMotionZ=0,o.flags&=~W,this.performMove(o,{immediate:!0,savedRootMotion:!1}),n=!0,this.lastServerProcessedSequence=o.sequence;const s=Kt(this.state,t);if(s>this.correctionToleranceSq){console.log(`Net server: Correction error: ${Math.sqrt(s)}`);const o=this.state.position.x-t.clientX,n=this.state.position.y-t.clientY,r=this.state.position.z-t.clientZ;console.log(`diff x: ${o}, y: ${n}, z: ${r}`),console.log({sequence:t.sequence,moveDt:t.dt,serverMoveDeltaTime:i,flags:t.flags,mode:this.state.mode,grounded:this.state.grounded,fallGraceTime:this.state.fallGraceTime}),this.sendOwnerCorrection(s>this.largeCorrectionThreshold*this.largeCorrectionThreshold),e=!0}}0===this.lastServerProcessedSequence||e||(this.sprintPolicy?.ack?.(this.lastServerProcessedSequence,!1),this.clientMoveAck(dt(this.lastServerProcessedSequence))),n&&this.accumulateListenServerVisualSmoothing(s,this.actor.position),this.sendSimulatedState(t,!1)}tickSimulatedProxy(t){this.proxyTime+=t,this.proxySmoother.sample(this.proxyTime,this.proxySample)&&this.applySnapshot(this.proxySample,!0)}accumulateListenServerVisualSmoothing(t,e){if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);Lt.subVectors(t,e);const i=Lt.lengthSq();i>1e-8&&(i>this.listenServerNoSmoothUpdateDistance*this.listenServerNoSmoothUpdateDistance?this.visualSmoothingOffset.set(0,0,0):(i>this.listenServerMaxSmoothUpdateDistance*this.listenServerMaxSmoothUpdateDistance&&Lt.setLength(this.listenServerMaxSmoothUpdateDistance),this.visualSmoothingOffset.add(Lt)))}updateVisualSmoothing(t){if(this.visualSmoothingOffset.lengthSq()<=1e-8)return void this.visualSmoothingOffset.set(0,0,0);if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);const e=Math.max(.001,this.listenServerSmoothLocationTime);t<e?this.visualSmoothingOffset.multiplyScalar(1-t/e):this.visualSmoothingOffset.set(0,0,0),this.visualSmoothingOffset.lengthSq()<=1e-4&&this.visualSmoothingOffset.set(0,0,0)}shouldSmoothListenServerRemoteAuthority(){return this.listenServerSmoothing&&this.actor.netRole===p.authority&&this.netService.isServer&&!this.netService.isDedicatedServer&&this.isRemoteControlledAuthority()}createMoveFromInput(t,e,i={}){const o=r.clamp(t,.001,this.maxMoveDeltaTime);this.clientMoveTime+=o;let s=this.clientMoveTime,n=o;!0===i.quantizeClientTime&&(s=Math.max(this.lastSentClientMoveTime+.001,Math.round(1e3*this.clientMoveTime)/1e3),n=r.clamp(s-this.lastSentClientMoveTime,.001,this.maxMoveDeltaTime),this.lastSentClientMoveTime=s),this.sampleRootMotion(bt);const a=this.crouchInput.activated,h=a&&!this.previousCrouchInput;this.previousCrouchInput=a;const l=!a&&this.sprintInput.activated,c=l&&!this.previousSprintInput;this.previousSprintInput=l;const d=(this.jumpInput.activated?Z:0)|(l?Q:0)|(a?B:0)|(h&&this.slideEnabled?$:0)|(c?J:0)|(bt.lengthSq()>0?W:0),u=function(t,e){e.set(t.x,0,t.y),e.lengthSq()>1&&e.normalize();return e}(this.directionInput.vector,Ut),m=this.inputMoveScratch;return m.sequence=e>>>0,m.clientTime=s,m.dt=n,m.inputX=u.x,m.inputY=u.z,m.yaw=this.rotationInput.rotation.y,m.flags=d,m.clientX=this.state.position.x,m.clientY=this.state.position.y,m.clientZ=this.state.position.z,m.rootMotionX=bt.x,m.rootMotionY=bt.y,m.rootMotionZ=bt.z,m}performMove(t,e){const i=r.clamp(t.dt,.001,this.maxMoveDeltaTime),o=Math.max(1,Math.ceil(i/this.maxSubstepDeltaTime)),s=0!==(t.flags&Q)&&0===(t.flags&B);this.sprintPolicy?.update?.(i,t.sequence,s),Ot.set(e.savedRootMotion?t.rootMotionX:0,e.savedRootMotion?t.rootMotionY:0,e.savedRootMotion?t.rootMotionZ:0),e.savedRootMotion||this.sampleRootMotion(Ot);let n=i;const a=i/o;for(let s=0;s<o;s++){const o=i>0?a/i:1;this.performSubstep(t,Math.min(a,n),Ot,o,e.immediate,0===s),n-=a}t.clientX=this.state.position.x,t.clientY=this.state.position.y,t.clientZ=this.state.position.z,t.flags=Ot.lengthSq()>0?t.flags|W:t.flags&~W,this.state.sequence=t.sequence,this.syncPublicState()}performSubstep(t,e,i,o,s,n){if(e<.001)return;this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded;const r=null!=this.rootMotionAction&&this.rootMotionAction.enabled,a=i.lengthSq()>0,h=!r&&0!==(t.flags&Z),l=r||a;this.updateCrouchState(t,n,l,h),this.pressedJump=h,this.isSprinting=!1,this.updateRotation(t,e,r,a),this.resolvePlatformVelocity(At);const c=this.movementModeContext,d=this.movementModes.get(this.state.mode);if(null!=d){c.move=t,c.deltaTime=e,c.rootMotionActive=l,c.startedSprinting=n&&!l&&0===(t.flags&B)&&0!==(t.flags&J);const i=d.update(c);"number"==typeof i&&(this.state.mode=i)}else Rt.set(0,0,0);if(a){zt.copy(i).multiplyScalar(o).applyQuaternion(this.actor.quaternion),kt.copy(zt).divideScalar(e),this.state.mode===A.walking?(Rt.x=kt.x+At.x,Rt.z=kt.z+At.z):(Rt.x=kt.x,Rt.z=kt.z);const t=Math.sqrt(kt.x*kt.x+kt.z*kt.z);t>.4&&(this.state.currentSpeed=t)}if(this.applyImpulseToVelocity(Rt,e),h&&this.isSprinting){const t=Math.max(0,this.maxSpeedSprint),e=Qt(Rt);if(e>t){const i=t/e;Rt.x*=i,Rt.z*=i,this.state.velocity.x*=i,this.state.velocity.z*=i}}this.state.mode===A.walking&&this.state.velocity.copy(Rt),this.applyMovement(Rt,e,s),this.state.mode===A.sliding&&(ft(this.state.velocity,qt,At,this.slideSurfaceNormal,e),this.state.currentSpeed=Qt(this.state.velocity)),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.updateModeAfterMove(Rt,e),this.state.mode===A.sliding&&this.state.velocity.length()<Math.max(0,this.slideMinExitSpeed)&&(this.state.mode=A.walking)}updateRotation(t,e,i,o){Ct.set(-t.inputX,0,t.inputY),Ct.lengthSq()>1&&Ct.normalize();const s=this.state.prevRotateToMovementDirection!==this.rotateToMovementDirection;let n=r.euclideanModulo(t.yaw-this.state.lookYaw+Math.PI,2*Math.PI)-Math.PI;if(s&&(this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),n=0,this.state.lookYaw=t.yaw,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection),wt.set(0,0,0),i)this.state.lookYaw=t.yaw;else if(this.rotateToMovementDirection){if(Ct.lengthSq()>0&&this.state.mode!==A.falling){const i=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,o=Math.atan2(Ct.x,Ct.z),s=.99*t.yaw+o;if(this.smoothRotation){const t=r.euclideanModulo(s-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(Ht.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(Ht.set(0,s,0));this.state.prevInputDirection.lerp(Ct,e*this.rotationSpeed),this.state.lookYaw+=n,wt.copy(this.actor.object.getWorldDirection(Ut).normalize())}}else o||(this.state.lookYaw=t.yaw,this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),Ct.lengthSq()>0&&wt.copy(Ct).applyAxisAngle(Tt,t.yaw).normalize())}applyMovement(t,e,i){if(t.lengthSq()>0||!this.state.grounded){if(Dt.copy(t).multiplyScalar(e),this.state.grounded&&((o=this.state.mode)===A.walking||o===A.sliding)&&(this.state.mode===A.walking&&this.rayTestResult.distance<=this.cc.offset()&&(Dt.y=Math.max(0,At.y*e)),this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup()),this.cc.computedCollision(0,Bt),null!=Bt.normal1)){const t=Ut.copy(Bt.normal1);Math.acos(r.clamp(t.dot(Tt),-1,1))>this.cc.maxSlopeClimbAngle()&&(Dt.y=.016*this.getEffectiveGravity()*.5)}qt.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup()))}else qt.set(0,0,0);var o;this.suppressUncrouchLift&&(this.suppressUncrouchLift=!1,this.state.grounded&&this.state.mode===A.walking&&Dt.y<=1e-6&&qt.y>0&&(qt.y=0)),this.state.position.add(qt),i?(this.actor.position.copy(this.state.position),this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()):this.physicsSystem.setNextKinematicPosition(this.actor,this.state.position)}updateModeAfterMove(t,e){const i=function(t){if(0===t.numComputedCollisions())return!1;const e=t.computedCollision(0);Ft.set(e.normal2.x,e.normal2.y,e.normal2.z);const i=Ft.angleTo(Tt);Ft.set(e.normal1.x,e.normal1.y,e.normal1.z);const o=Ft.angleTo(Tt);if(i<100)return!1;return o>t.minSlopeSlideAngle()}(this.cc);!this.state.grounded||i?this.state.mode!==A.falling&&(this.state.fallGraceTime+=e,this.state.fallGraceTime>this.fallGraceTime+1e-6&&(this.state.mode=A.falling,this.state.velocity.copy(t))):this.state.velocity.y<=0&&(this.state.mode===A.falling&&(this.state.mode=A.walking),this.state.mode!==A.sliding&&(this.state.velocity.y=0),this.state.fallGraceTime=0)}applyImpulseToVelocity(t,e){if(this.impulse.lengthSq()<=.1)return void this.impulse.set(0,0,0);const i=Math.min(1,this.impulse.length()/5);t.x=r.lerp(t.x,this.impulse.x,i),t.z=r.lerp(t.z,this.impulse.z,i),t.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}sendSavedMoves(t,e=!1){if(this.moveSendAccumulator+=t,!e&&this.moveSendAccumulator<this.moveSendInterval)return;this.moveSendAccumulator=0;const i=this.savedMoves.getMovesForSend(this.maxMovesPerPacket);0!==i.length&&this.serverMove(ct(i))}sendOwnerCorrection(t){const e=this.toSnapshot(this.pendingSnapshot);t&&(e.horizontalSpeed=this.horizontalSpeed),this.sprintPolicy?.ack?.(e.sequence,!0),this.clientMoveCorrection(ut(e))}sendSimulatedState(t,e){this.simulatedStateAccumulator+=t,!e&&this.simulatedStateAccumulator<this.simulatedStateInterval||(this.simulatedStateAccumulator=0,this.simulatedState(mt(this.toSnapshot(this.pendingSnapshot))))}applyCorrection(t){this.sprintPolicy?.restore?.(t.sequence),this.savedMoves.ack(t.sequence),this.sprintPolicy?.ack?.(t.sequence,!0),this.applySnapshot(t,!0),this.savedMoves.replayAfter(t.sequence,t=>(this.performMove(t,{immediate:!0,savedRootMotion:!0}),null),this.maxReplayedMoves)}applySnapshot(t,e){this.state.sequence=t.sequence,this.state.position.set(t.x,t.y,t.z),this.state.velocity.set(t.velocityX,t.velocityY,t.velocityZ),this.state.yaw=t.yaw,this.state.lookYaw=t.yaw,this.state.mode=t.mode,this.state.currentSpeed=t.horizontalSpeed,this.state.fallGraceTime=0,this.actor.position.copy(this.state.position),this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),this.crouchSuppressedUntilRelease=0!==(t.flags&K),this.setCrouching(0!==(t.flags&_)||t.mode===A.sliding),e&&(this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.syncPublicState()}toSnapshot(t){return t.sequence=this.state.sequence,t.x=this.state.position.x,t.y=this.state.position.y,t.z=this.state.position.z,t.velocityX=this.state.velocity.x,t.velocityY=this.state.velocity.y,t.velocityZ=this.state.velocity.z,t.yaw=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,t.mode=this.state.mode,t.flags=(this.isCrouching?_:0)|(this.crouchSuppressedUntilRelease?K:0),t.horizontalSpeed=this.state.currentSpeed,t}syncPublicState(){this.velocity.copy(this.state.velocity),this.mode=this.state.mode,this.horizontalSpeed=this.state.currentSpeed,this.isSliding=this.state.mode===A.sliding,this.isSliding?(this.resolveGroundNormal(this.slideSurfaceNormal),this.slideDirection.copy(this.state.velocity).projectOnPlane(this.slideSurfaceNormal),this.slideDirection.lengthSq()>1e-8?this.slideDirection.normalize():this.slideDirection.set(0,0,0)):(this.slideDirection.set(0,0,0),this.slideSurfaceNormal.copy(Tt))}sampleRootMotion(t){if(t.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 e=this.rootMotionAction,i=this.rootMotionOptions.onJumpCancel;return this.clearRootMotionAction(e),e.stop(),i?.(),t}if(null==this.rootMotionAction)return t;if(!(this.rootMotionAction.getClip()instanceof l))return t;const e=this.rootMotionInterpolant;this.resetRootMotion&&(this.prevRootMotionPos.fromArray(e.evaluate(0)),this.resetRootMotion=!1),It.fromArray(e.evaluate(this.rootMotionAction.time)),t.subVectors(It,this.prevRootMotionPos),this.prevRootMotionPos.copy(It);if((this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(Pt),t.multiply(Pt),this.rootMotionTargetConstraints.size>0){zt.copy(t).applyQuaternion(this.actor.quaternion);for(const t of this.rootMotionTargetConstraints)if(t.requestedProgress>0&&t.addedHorizontalDistance<t.maximumAddedHorizontalDistance){const e=r.lerp(t.initialHorizontalDistance,t.minimumHorizontalDistance,t.requestedProgress),i=Math.min(D(zt,this.actor.position,t.targetPosition,e),t.maximumAddedHorizontalDistance-t.addedHorizontalDistance);t.addedHorizontalDistance+=b(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance,i)}else q(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance);t.copy(zt).applyQuaternion(Vt.copy(this.actor.quaternion).invert())}return t}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}isRemoteControlledAuthority(t=this.netService.mode,e=this.actor.netRole){if(t===vt.none||e!==p.authority||t>=vt.client)return!1;return null!=this.netService.resolveActorConnection(this.actor)&&!this.netService.isLocalOwner(this.actor)}configureCharacterController(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding)}initializeStateFromActor(){this.state.position.copy(this.actor.position),this.state.velocity.set(0,0,0),this.state.yaw=this.actor.rotation.y,this.state.lookYaw=this.rotationInput.rotation.y,this.state.mode=this.mode,this.state.currentSpeed=this.horizontalSpeed,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection}createCollisionShape(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1),i=new x(t,e);return i.offset.y=this.getCapsuleOffsetY(t,e),i.collisionGroup=xt,i}updateCrouchState(t,e,i,o){if(!(0!==(t.flags&B)))return this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.state.mode===A.sliding&&(this.state.mode=A.walking),void this.tryUncrouch();if(this.state.mode===A.sliding&&(!this.slideEnabled||i))return this.slideOnLandingRequested=!1,this.state.mode=A.walking,void(this.crouchSuppressedUntilRelease||this.setCrouching(!0));if(this.state.mode===A.sliding&&o)return this.crouchSuppressedUntilRelease=!0,this.slideOnLandingRequested=!1,void this.tryUncrouch();if(this.crouchSuppressedUntilRelease)return void(this.slideOnLandingRequested=!1);if(this.setCrouching(!0),!this.slideEnabled||i)return void(this.slideOnLandingRequested=!1);if(this.state.mode===A.falling)return void(this.slideOnLandingRequested=!0);this.resolveGroundNormal(Xt);const s=this.slideOnLandingRequested&&this.state.mode===A.walking&&this.state.grounded,n=e&&0!==(t.flags&$)||s;s&&(this.slideOnLandingRequested=!1);const r=Qt(this.state.velocity);this.state.mode===A.walking&&St(this.slideEnabled,n,this.state.grounded,this.isWalkableSlideSurface(Xt),i,r,this.slideMinStartSpeed)&&(this.state.mode=A.sliding,this.slideSurfaceNormal.copy(Xt),this.state.velocity.projectOnPlane(this.slideSurfaceNormal),this.state.currentSpeed=Qt(this.state.velocity))}updateSlidingMode(t){const e=t.state,i=t.move;this.resolveGroundNormal(this.slideSurfaceNormal);const o=this.isWalkableSlideSurface(this.slideSurfaceNormal),s=e.velocity.length();if(!e.grounded||!o)return e.mode=A.falling,$t.update(t),A.falling;if(this.slideEnabled&&0!==(i.flags&B)&&!t.rootMotionActive&&0!==(i.flags&Z))return yt(t.outVelocity,e.velocity,this.jumpVelocity),e.velocity.copy(t.outVelocity),e.currentSpeed=Qt(e.velocity),A.falling;if(!gt(this.slideEnabled,0!==(i.flags&B),e.grounded,o,t.rootMotionActive,s,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;const n=Mt(e.velocity,e.velocity,this.slideSurfaceNormal,t.rotatedDirection,this.getEffectiveGravity(),t.deltaTime,this.slideDeceleration,this.slideGravityScale,this.slideSteeringRate);if(e.currentSpeed=Qt(e.velocity),n<Math.max(0,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;t.outVelocity.copy(e.velocity).add(t.platformVelocity)}tryUncrouch(){this.isCrouching&&this.canUncrouch()&&this.setCrouching(!1)&&(this.suppressUncrouchLift=!0,this.state.fallGraceTime=0)}resolveGroundNormal(t){return!this.rayTestResult.hasHit||this.rayTestResult.hitNormal.lengthSq()<=1e-8?t.copy(Tt):(t.copy(this.rayTestResult.hitNormal).normalize(),t.dot(Tt)<0&&t.multiplyScalar(-1),t)}isWalkableSlideSurface(t){return t.dot(Tt)>=Math.cos(this.cc.maxSlopeClimbAngle())}setCrouching(t){return this.isCrouching!==t&&(this.isCrouching=t,this.syncColliderShape(),!0)}canUncrouch(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1);return!this.physicsSystem.hasActorCapsuleIntersection(this.actor,this.state.position,t,e,this.getCapsuleOffsetY(t,e),this.getCollisionGroup())}syncColliderShape(){const t=this.getColliderHeight(this.isCrouching),e=this.getColliderRadius(this.isCrouching);this.physicsSystem.setActorCapsuleCollider(this.actor,t,e,this.getCapsuleOffsetY(t,e))}getColliderHeight(t){const e=Number.isFinite(this.colliderHeight)?Math.max(0,this.colliderHeight):0;if(!t)return e;const i=Number.isFinite(this.crouchColliderHeight)?this.crouchColliderHeight:e;return r.clamp(i,0,e)}getColliderRadius(t){const e=Number.isFinite(this.colliderRadius)?Math.max(.001,this.colliderRadius):.001;if(!t)return e;const i=this.crouchColliderRadius??e,o=Number.isFinite(i)?i:e;return r.clamp(o,.001,e)}getCapsuleOffsetY(t,e){return e+t/2+this.offset}checkGrounded(t){Nt.y=-Math.max(.05,this.cc.snapToGroundDistance()),this.physicsSystem.rayTest(jt.addVectors(t,Yt.set(0,this.offset,0)),Gt.addVectors(t,Nt),this.rayTestResult,this.groundRayTestOptions)}resolvePlatformVelocity(t){return t.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,t),t}getCollisionGroup(){return this.characterCollision?null:xt}};t([T(),e("design:type",Number)],Zt.prototype,"colliderHeight",void 0),t([T(),e("design:type",Number)],Zt.prototype,"colliderRadius",void 0),t([T(),e("design:type",Number)],Zt.prototype,"crouchColliderHeight",void 0),t([T({optional:!0}),e("design:type",Number)],Zt.prototype,"crouchColliderRadius",void 0),t([g(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"serverMove",null),t([v(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveAck",null),t([v(!0),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveCorrection",null),t([y(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"simulatedState",null),Zt=t([R({inEditor:!1}),e("design:paramtypes",[])],Zt);export{Zt as CharacterMovementComponent};const Wt={mode:A.walking,update(t){const e=t.component,i=t.move,o=t.state,s=t.rotatedDirection,n=Math.min(1,Math.sqrt(i.inputX*i.inputX+i.inputY*i.inputY)),r=!e.rotateToMovementDirection&&i.inputY<0,a=e.isCrouching,h=!t.rootMotionActive&&!a&&0===(i.flags&B)&&0!==(i.flags&Q)&&!r&&0!==s.lengthSq()&&(e.sprintPolicy?.canSprint()??!0),l=(a?e.maxSpeedCrouch:r?e.maxSpeedBackwards:h?e.maxSpeedSprint:e.maxSpeed)*(e.normalizedDirection?1:n);if(0!==s.lengthSq()){e.isSprinting=h,h&&e.sprintPolicy?.commitSprint(t.deltaTime,i.sequence);let a=Math.min(l,o.currentSpeed),c=e.groundAccelerationRate;if(h&&t.startedSprinting&&e.sprintStartBoostSpeed>0){const t=e.normalizedDirection?1:n;a=Math.max(a,l+e.sprintStartBoostSpeed*t),c=e.sprintStartBoostDamping}else h&&!r&&e.sprintStartBoostSpeed>0&&o.currentSpeed>l&&(a=o.currentSpeed,c=e.sprintStartBoostDamping);o.currentSpeed=function(t,e,i,o){return e+(t-e)*Math.exp(-i*o)}(a,l,c,t.deltaTime),t.outVelocity.copy(s).multiplyScalar(function(t,e,i,o){const s=i*o;if(s<=1e-6)return t;return e+(t-e)*(1-Math.exp(-s))/s}(a,l,c,t.deltaTime))}else o.currentSpeed=0,t.outVelocity.set(0,0,0);if(0!==(i.flags&Z))return o.mode=A.falling,o.velocity.copy(t.outVelocity),o.velocity.y=e.jumpVelocity,A.falling;t.outVelocity.y=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.add(t.platformVelocity)}},$t={mode:A.falling,update(t){const e=t.component,i=t.state,o=t.move;0!==(o.flags&Z)&&e.jumpInAir&&(i.velocity.copy(t.outVelocity),i.velocity.y=e.jumpVelocity),i.velocity.y+=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.copy(i.velocity),t.outVelocity.addScaledVector(t.rotatedDirection,e.fallingMovementControl),e.fallingReorientation&&t.outVelocity.applyAxisAngle(Tt,r.euclideanModulo(o.yaw-i.lookYaw+Math.PI,2*Math.PI)-Math.PI)}};function Qt(t){return Math.sqrt(t.x*t.x+t.z*t.z)}function Jt(t,e){return e.sequence=t.sequence,e.clientTime=t.clientTime,e.dt=t.dt,e.inputX=t.inputX,e.inputY=t.inputY,e.yaw=t.yaw,e.flags=t.flags,e.clientX=t.clientX,e.clientY=t.clientY,e.clientZ=t.clientZ,e.rootMotionX=t.rootMotionX,e.rootMotionY=t.rootMotionY,e.rootMotionZ=t.rootMotionZ,e}function Kt(t,e){const i=t.position.x-e.clientX,o=t.position.y-e.clientY,s=t.position.z-e.clientZ;return i*i+o*o+s*s}class _t{constructor(t){this.scene=t,this.serverPosition=new h,this.direction=new h}update(t,e){const i=this.serverPosition.set(e.x,e.y,e.z),o=i.distanceTo(t);o>.1&&console.log(`Correction applied. Error: ${o.toFixed(3)}. Server position: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z.toFixed(2)}), Client position: (${t.x.toFixed(2)}, ${t.y.toFixed(2)}, ${t.z.toFixed(2)})`);const s=this.direction.copy(i).sub(t).normalize();te.position.copy(t),te.setDirection(s),te.setLength(o);const n=ee(this.scene);n.add(te),setTimeout(()=>{n.remove(te)},1e3)}}const te=new n(new h(0,1,0),new h,1,16711680);function ee(t){return null==t.parent?t:ee(t.parent)}const ie={immediate:!1,savedRootMotion:!0};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -4,4 +4,14 @@ import type { Vector3 } from "three";
4
4
  * a target-relative horizontal minimum distance.
5
5
  */
6
6
  export declare function constrainRootMotionTargetApproach(worldDelta: Vector3, actorPosition: Vector3, targetPosition: Vector3, minimumHorizontalDistance: number): Vector3;
7
+ /**
8
+ * Adds a bounded amount of target-directed motion before applying the target's
9
+ * minimum-distance constraint. Returns the horizontal distance actually added.
10
+ */
11
+ export declare function warpRootMotionTargetApproach(worldDelta: Vector3, actorPosition: Vector3, targetPosition: Vector3, minimumHorizontalDistance: number, requestedAddedHorizontalDistance: number): number;
12
+ /**
13
+ * Returns the extra target-directed translation needed for the authored root
14
+ * motion to finish this step at the requested horizontal distance.
15
+ */
16
+ export declare function calculateRootMotionTargetApproachCorrection(worldDelta: Vector3, actorPosition: Vector3, targetPosition: Vector3, desiredHorizontalDistance: number): number;
7
17
  //# sourceMappingURL=root-motion-constraint.d.ts.map
@@ -1,4 +1,4 @@
1
- export function constrainRootMotionTargetApproach(t,n,o,r){const a=o.x-n.x,x=o.z-n.z,c=a*a+x*x;if(c<=1e-8)return t;const e=Math.sqrt(c),i=a/e,s=x/e,h=t.x*i+t.z*s,u=Math.max(0,e-Math.max(0,r));if(h<=u)return t;const z=h-u;return t.x-=i*z,t.z-=s*z,t}/*
1
+ export function constrainRootMotionTargetApproach(t,o,r,a){const n=r.x-o.x,c=r.z-o.z,e=n*n+c*c;if(e<=1e-8)return t;const x=Math.sqrt(e),i=n/x,h=c/x,M=t.x*i+t.z*h,p=Math.max(0,x-Math.max(0,a));if(M<=p)return t;const s=M-p;return t.x-=i*s,t.z-=h*s,t}export function warpRootMotionTargetApproach(t,o,r,a,n){const c=r.x-o.x,e=r.z-o.z,x=c*c+e*e;if(x<=1e-8||n<=0)return constrainRootMotionTargetApproach(t,o,r,a),0;const i=Math.sqrt(x),h=Math.max(0,i-Math.max(0,a)),M=Math.min(n,h);return t.x+=c/i*M,t.z+=e/i*M,constrainRootMotionTargetApproach(t,o,r,a),M}export function calculateRootMotionTargetApproachCorrection(t,o,r,a){const n=r.x-o.x,c=r.z-o.z,e=n*n+c*c;if(e<=1e-8)return 0;const x=Math.sqrt(e),i=t.x*n/x+t.z*c/x,h=Math.max(0,x-Math.max(0,a));return Math.max(0,h-i)}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -8,7 +8,21 @@ export declare class CharacterMoveToNode extends LeafNode {
8
8
  /** At what distance from the target movement should stop */
9
9
  distanceFrom: number;
10
10
  target: () => Vector3 | null | undefined;
11
+ /** Scales movement input without changing path selection. Requires movement
12
+ * with normalizedDirection disabled to affect physical speed. */
13
+ speedScale: number;
14
+ /** Additional input scale for lateral movement after facing-relative input
15
+ * has been resolved. Useful when strafe clips have a slower authored pace. */
16
+ lateralSpeedScale: number;
17
+ /** Restricts facing-relative movement to a cardinal axis for characters that
18
+ * have four-way locomotion clips but no diagonal blend space. */
19
+ cardinalMovement: boolean;
20
+ /** Optional point to face while navigating. When provided, movement input is
21
+ * expressed relative to that facing so characters can strafe or backpedal. */
22
+ facingTarget?: () => Vector3 | null | undefined;
11
23
  constructor(navigation: Navigation, movement: CharacterMovementLike);
24
+ private cardinalAxis?;
12
25
  tick(dt: number): NodeState;
26
+ private snapInputToCardinalAxis;
13
27
  }
14
28
  //# sourceMappingURL=move.d.ts.map
@@ -1,4 +1,4 @@
1
- import{Vector3 as t}from"three";import{LeafNode as e,NodeState as o}from"./bt.js";export class CharacterMoveToNode extends e{constructor(t,e){super(),this.navigation=t,this.movement=e,this.distanceFrom=.5}tick(t){const e=this.movement.actor.object.position,i=null!=this.target?this.target():null;if(null==i)return this.movement.directionInput.vector.set(0,0),o.FAILURE;if(e.distanceTo(i)<this.distanceFrom)return this.movement.directionInput.vector.set(0,0),o.SUCCESS;const{success:s,path:r}=this.navigation.findPath(e,i);if(!s||r.length<2)return o.FAILURE;const c=r[1],a=n.subVectors(c,e);return a.y=0,a.normalize(),this.movement.rotationInput.rotation.y=Math.atan2(a.x,a.z),this.movement.directionInput.togglePositiveY(!0),o.RUNNING}}const n=new t;/*
1
+ import{Vector3 as t}from"three";import{LeafNode as i,NodeState as e}from"./bt.js";export class CharacterMoveToNode extends i{constructor(t,i){super(),this.navigation=t,this.movement=i,this.distanceFrom=.5,this.speedScale=1,this.lateralSpeedScale=1,this.cardinalMovement=!1}tick(t){const i=this.movement.actor.object.position,s=null!=this.target?this.target():null;if(null==s)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;if(i.distanceTo(s)<this.distanceFrom)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.SUCCESS;const{success:a,path:o}=this.navigation.findPath(i,s);if(!a||o.length<2)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;const r=o[1],c=n.subVectors(r,i);c.y=0,c.normalize();const h=this.facingTarget?.(),l=null!=h?h.x-i.x:0,m=null!=h?h.z-i.z:0,d=l*l+m*m;if(null!=h&&d>1e-4){const t=Math.atan2(l,m),i=1/Math.sqrt(d),e=l*i,n=m*i,s=n,a=-e;this.movement.rotationInput.rotation.y=t,this.movement.directionInput.vector.set(-(c.x*s+c.z*a),c.x*e+c.z*n)}else this.movement.rotationInput.rotation.y=Math.atan2(c.x,c.z),this.movement.directionInput.vector.set(0,1);return this.cardinalMovement&&this.snapInputToCardinalAxis(),Math.abs(this.movement.directionInput.vector.x)>Math.abs(this.movement.directionInput.vector.y)&&this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.lateralSpeedScale))),this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.speedScale))),e.RUNNING}snapInputToCardinalAxis(){const t=this.movement.directionInput.vector,i=Math.abs(t.x),e=Math.abs(t.y);if(i+e<=1e-4)return void(this.cardinalAxis=void 0);const n=i>e?"x":"y";if(null==this.cardinalAxis)this.cardinalAxis=n;else{const t="x"===this.cardinalAxis?i:e;("x"===this.cardinalAxis?e:i)>t*s&&(this.cardinalAxis="x"===this.cardinalAxis?"y":"x")}"x"===this.cardinalAxis?t.set(Math.sign(t.x),0):t.set(0,Math.sign(t.y))}}const n=new t,s=1.25;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -6,6 +6,7 @@ import type { Observable } from 'rxjs';
6
6
  import type { DetailTier } from "../scene/model.js";
7
7
  import type { NetSession } from "./net/net-session.js";
8
8
  import type { ParameterType } from "../shader/parameter.js";
9
+ import type { VfxBackendPreference } from "../effects/vfx/gpu-sprite-compiler.js";
9
10
  type GameClass<T> = Constructable<T>;
10
11
  export type InitiateGameConfig = {
11
12
  element: HTMLElement;
@@ -38,6 +39,8 @@ export type InitiateGameConfig = {
38
39
  dynamicResolution: DynamicResolutionOptions;
39
40
  upscaling: UpscalingOptions;
40
41
  webgpuPostProcessing: ExperimentalWebGpuPostProcessingOptions;
42
+ /** Preferred VFX simulation backend. `auto` uses GPU when supported and otherwise falls back to CPU. */
43
+ webgpuVfx: VfxBackendPreference;
41
44
  msaa: number;
42
45
  fpsCap: number | null;
43
46
  depthPrepass: {
@@ -1,4 +1,4 @@
1
- import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as n}from"./actors/factory.js";import{World as s}from"./services/world.js";import{SceneMaterializer as o}from"../scene/materializer.js";import{ViewController as r}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as h}from"../scene/asset-resource-loader.js";import{AssetLoader as u}from"./services/asset-loader.js";import{polyfillClient as g}from"./polyfill.js";import{Subject as f}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as v}from"three";import{ShaderProvider as j}from"./services/shader-provider.js";import{SceneDataService as S}from"../scene/scene-data-service.js";import{NetMode as x}from"./net/net-session.js";import{AssetsProvider as y}from"../scene/assets-provider.js";export function initiateGame(f,w){if(g(),0!=w.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(r);const I=e.of("default"),P=new HologyRuntime(I),G=new n(I,{inEditor:!1});var E;G.classes=w.actors,e.set(n,G),E=w.element,Object.assign(E.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",overflow:"hidden"});const R=new i(w.element,{backend:w.rendering?.backend??"webgpu-experimental",enableXR:!0===w.xr?.enabled,maxPixelRatio:w.rendering?.maxPixelRatio,resolutionScale:w.rendering?.resolutionScale,dynamicResolution:w.rendering?.dynamicResolution,upscaling:w.rendering?.upscaling,webgpuPostProcessing:w.rendering?.webgpuPostProcessing,msaa:w.rendering?.msaa,fpsCap:w.rendering?.fpsCap,depthPrepass:{enabled:!0===w.rendering?.depthPrepass?.enabled},bloom:{enabled:!1!==w?.rendering?.bloom?.enabled},reflection:{enabled:!1!==w?.rendering?.reflection?.enabled},occlusionCulling:{enabled:!1!==w?.rendering?.occlusionCulling?.enabled},shadows:{cascadeUpdateIntervals:[22,40,60,120]}});R.renderer.shadowMap.enabled=w.rendering?.shadows?.enabled??!0,R.renderer.shadowMap.autoUpdate=w.rendering?.shadows?.autoUpdate??!0,R.renderer.debug.checkShaderErrors=!1,e.set(i,R);const k=new r(R);e.set(r,k);const C=new b,D=new p(C),M=new h;M.setDataDir(w.dataDir),M.initKtx2(R.renderer);const z=Object.entries(w.shaders).map(([e,t])=>({name:e,type:t})),A=Object.entries(w.actors).map(([e,t])=>({name:e,type:t})),O={...d,...w.components??{}},U=Object.entries(O).map(([e,t])=>({name:e,type:t})),F=new j(z);e.set(j,F);const H=new u(M,D,z);e.set(y,D),e.set(h,M),e.set(u,H);const N=new v,T=new o(N,new S,D,M,R,z,A,G,U);T.inEditor=!1,T.netMode=w.multi?.session?.mode??x.none,e.set(o,T);const W=e.get(s);return e.set(s,W),W.materializer=T,(async()=>{const n=e.get(a);if(await n.start(),P.isShutdown)return;if(await C.preloadData(),P.isShutdown)return;if(W.scene=N,null!=w.multi?.session){const{NetService:e}=await import("./net/service/net-service.js"),t=I.get(e);t.session=w.multi.session,t.start(),P.shutdownStarted.subscribe(()=>t.stop())}const{scene:s,actors:o,materializer:r}=await t(R,w.sceneName,w.dataDir,w.shaders,w.actors,O,G,C,D,M,{detailTier:w.detailTier,nodeMode:w.multi?.session?.mode??x.none});W.scene=s,n.scene=W.scene;for(const e of N.children)W.scene.add(e);if(P.isShutdown)return void R.stop();e.import([c]);for(const e of o)W.addActor(e);n.addFromScene(s),await W.startSceneEventGraphs(r),m.value=I,I.remove(f),I.set({id:f,type:f});const i=I.get(f);if(m.value=null,P.gameInstance=i,i instanceof GameInstance&&await i.onPreload(),P.isShutdown)return void R.stop();console.log("Start compile shaders"),console.time("compile shaders"),await R.compileAsync(),console.timeEnd("compile shaders"),"webgpu-experimental"===R.activeBackend?console.log("Finished compiling the experimental WebGPU scene."):console.log("Finished compile shaders. Programs: ",R.renderer.info.programs?.length??0),console.log("Start init scene textures"),console.time("init scene textures"),R.initTextures(),console.timeEnd("init scene textures");const d=I.get(l);R.loop(e=>{d.update(e)}),P.status=5,P.shutdownStarted.subscribe(()=>{M.disposeAll()}),i instanceof GameInstance&&await i.onStart(),P._resolver(!0)})(),P}export class GameInstance{onPreload(){}onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new f,this.ready=new Promise(e=>{this._resolver=e})}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0;const e=this.shutdownStarted;e.next(),e.complete(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const t=this.containerInstance.get(i);t?.stop();const n=this.getWorld();n.stopSceneEventGraphs();const s=this.containerInstance.get(r);s.setMuted(!0),s.dispose();for(const e of[...n.actors])n.removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.get(o).dispose();const c=this.containerInstance.get(y);c instanceof p&&c.dispose(),this.containerInstance.get(w).stop(),this.containerInstance.reset(),this.shutdownStarted.complete()}}/*
1
+ import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as n}from"./actors/factory.js";import{World as s}from"./services/world.js";import{SceneMaterializer as o}from"../scene/materializer.js";import{ViewController as r}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as u}from"../scene/asset-resource-loader.js";import{AssetLoader as h}from"./services/asset-loader.js";import{polyfillClient as g}from"./polyfill.js";import{Subject as f}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as v}from"three";import{ShaderProvider as j}from"./services/shader-provider.js";import{SceneDataService as S}from"../scene/scene-data-service.js";import{NetMode as x}from"./net/net-session.js";import{AssetsProvider as y}from"../scene/assets-provider.js";export function initiateGame(f,w){if(g(),0!=w.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(r);const I=e.of("default"),P=new HologyRuntime(I),G=new n(I,{inEditor:!1});var E;G.classes=w.actors,e.set(n,G),E=w.element,Object.assign(E.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",overflow:"hidden"});const R=new i(w.element,{backend:w.rendering?.backend??"webgpu-experimental",enableXR:!0===w.xr?.enabled,maxPixelRatio:w.rendering?.maxPixelRatio,resolutionScale:w.rendering?.resolutionScale,dynamicResolution:w.rendering?.dynamicResolution,upscaling:w.rendering?.upscaling,webgpuPostProcessing:w.rendering?.webgpuPostProcessing,webgpuVfx:w.rendering?.webgpuVfx??"auto",msaa:w.rendering?.msaa,fpsCap:w.rendering?.fpsCap,depthPrepass:{enabled:!0===w.rendering?.depthPrepass?.enabled},bloom:{enabled:!1!==w?.rendering?.bloom?.enabled},reflection:{enabled:!1!==w?.rendering?.reflection?.enabled},occlusionCulling:{enabled:!1!==w?.rendering?.occlusionCulling?.enabled},shadows:{cascadeUpdateIntervals:[22,40,60,120]}});R.renderer.shadowMap.enabled=w.rendering?.shadows?.enabled??!0,R.renderer.shadowMap.autoUpdate=w.rendering?.shadows?.autoUpdate??!0,R.renderer.debug.checkShaderErrors=!1,e.set(i,R);const k=new r(R);e.set(r,k);const C=new b,D=new p(C),M=new u;M.setDataDir(w.dataDir),M.initKtx2(R.renderer);const z=Object.entries(w.shaders).map(([e,t])=>({name:e,type:t})),A=Object.entries(w.actors).map(([e,t])=>({name:e,type:t})),O={...d,...w.components??{}},U=Object.entries(O).map(([e,t])=>({name:e,type:t})),F=new j(z);e.set(j,F);const H=new h(M,D,z);e.set(y,D),e.set(u,M),e.set(h,H);const N=new v,T=new o(N,new S,D,M,R,z,A,G,U);T.inEditor=!1,T.netMode=w.multi?.session?.mode??x.none,e.set(o,T);const W=e.get(s);return e.set(s,W),W.materializer=T,(async()=>{const n=e.get(a);if(await n.start(),P.isShutdown)return;if(await C.preloadData(),P.isShutdown)return;if(W.scene=N,null!=w.multi?.session){const{NetService:e}=await import("./net/service/net-service.js"),t=I.get(e);t.session=w.multi.session,t.start(),P.shutdownStarted.subscribe(()=>t.stop())}const{scene:s,actors:o,materializer:r}=await t(R,w.sceneName,w.dataDir,w.shaders,w.actors,O,G,C,D,M,{detailTier:w.detailTier,nodeMode:w.multi?.session?.mode??x.none});W.scene=s,n.scene=W.scene;for(const e of N.children)W.scene.add(e);if(P.isShutdown)return void R.stop();e.import([c]);for(const e of o)W.addActor(e);n.addFromScene(s),await W.startSceneEventGraphs(r),m.value=I,I.remove(f),I.set({id:f,type:f});const i=I.get(f);if(m.value=null,P.gameInstance=i,i instanceof GameInstance&&await i.onPreload(),P.isShutdown)return void R.stop();console.log("Start compile shaders"),console.time("compile shaders"),await R.compileAsync(),console.timeEnd("compile shaders"),"webgpu-experimental"===R.activeBackend?console.log("Finished compiling the experimental WebGPU scene."):console.log("Finished compile shaders. Programs: ",R.renderer.info.programs?.length??0),console.log("Start init scene textures"),console.time("init scene textures"),R.initTextures(),console.timeEnd("init scene textures");const d=I.get(l);R.loop(e=>{d.update(e)}),P.status=5,P.shutdownStarted.subscribe(()=>{M.disposeAll()}),i instanceof GameInstance&&await i.onStart(),P._resolver(!0)})(),P}export class GameInstance{onPreload(){}onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new f,this.ready=new Promise(e=>{this._resolver=e})}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0;const e=this.shutdownStarted;e.next(),e.complete(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const t=this.containerInstance.get(i);t?.stop();const n=this.getWorld();n.stopSceneEventGraphs();const s=this.containerInstance.get(r);s.setMuted(!0),s.dispose();for(const e of[...n.actors])n.removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.get(o).dispose();const c=this.containerInstance.get(y);c instanceof p&&c.dispose(),this.containerInstance.get(w).stop(),this.containerInstance.reset(),this.shutdownStarted.complete()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */