@hology/core 0.0.214 → 0.0.216

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 (59) hide show
  1. package/dist/config/project-config.d.ts +1 -0
  2. package/dist/effects/sequence/sequence-action.d.ts +4 -0
  3. package/dist/effects/sequence/sequence-actor.js +1 -1
  4. package/dist/effects/sequence/sequence-animation-retiming.d.ts +2 -1
  5. package/dist/effects/sequence/sequence-animation-retiming.js +1 -1
  6. package/dist/effects/sequence/sequence-data.d.ts +6 -0
  7. package/dist/effects/sequence/sequence-data.js +1 -1
  8. package/dist/effects/sequence/sequence-player.d.ts +11 -0
  9. package/dist/effects/sequence/sequence-player.js +1 -1
  10. package/dist/effects/vfx/vfx-collision-behaviour.js +1 -1
  11. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  12. package/dist/gameplay/actors/builtin/components/character/character-movement-like.d.ts +3 -0
  13. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +22 -0
  14. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  15. package/dist/gameplay/actors/builtin/components/character/character-slide.d.ts +7 -0
  16. package/dist/gameplay/actors/builtin/components/character/character-slide.js +4 -0
  17. package/dist/gameplay/actors/builtin/components/character/modes.d.ts +2 -1
  18. package/dist/gameplay/actors/builtin/components/character/modes.js +1 -1
  19. package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.d.ts +3 -1
  20. package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.js +1 -1
  21. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  22. package/dist/gameplay/actors/camera/third-person-camera-component.d.ts +1 -0
  23. package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
  24. package/dist/gameplay/ai/behavior-tree/move.js +1 -1
  25. package/dist/gameplay/ai/dynamic-tiled-navmesh.d.ts +20 -2
  26. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +1 -1
  27. package/dist/gameplay/animation/animation-action.d.ts +3 -0
  28. package/dist/gameplay/animation/animation-action.js +4 -0
  29. package/dist/gameplay/services/physics/physics-system.d.ts +56 -3
  30. package/dist/gameplay/services/physics/physics-system.js +1 -1
  31. package/dist/scene/asset-resource-loader.d.ts +10 -0
  32. package/dist/scene/asset-resource-loader.js +1 -1
  33. package/dist/scene/collision/collision-shape.d.ts +1 -1
  34. package/dist/scene/materializer.js +1 -1
  35. package/dist/scene/storage/storage.js +1 -1
  36. package/dist/shader/builtin/standard-shader.js +1 -1
  37. package/dist/shader/builtin/unlit-shader.js +1 -1
  38. package/dist/shader/decal-shader.d.ts +2 -2
  39. package/dist/shader/decal-shader.js +1 -1
  40. package/dist/shader/shader.d.ts +2 -1
  41. package/dist/shader/shader.js +1 -1
  42. package/dist/shader/sprite-shader.d.ts +2 -2
  43. package/dist/shader/sprite-shader.js +1 -1
  44. package/dist/shader/trail-shader.d.ts +2 -2
  45. package/dist/shader/trail-shader.js +1 -1
  46. package/dist/test/asset-resource-loader-texture-array.test.d.ts +2 -0
  47. package/dist/test/asset-resource-loader-texture-array.test.js +4 -0
  48. package/dist/test/character-animation-transition.test.d.ts +2 -0
  49. package/dist/test/character-animation-transition.test.js +4 -0
  50. package/dist/test/character-slide.test.d.ts +2 -0
  51. package/dist/test/character-slide.test.js +4 -0
  52. package/dist/test/navmesh-worker-pool.test.d.ts +2 -0
  53. package/dist/test/navmesh-worker-pool.test.js +4 -0
  54. package/dist/test/net-character-movement.test.js +1 -1
  55. package/dist/test/sequence-animation-retiming.test.js +1 -1
  56. package/dist/test/sequence-root-motion-axis-mask.test.d.ts +2 -0
  57. package/dist/test/sequence-root-motion-axis-mask.test.js +4 -0
  58. package/package.json +2 -2
  59. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{ActorComponent as o,Component as i}from"../component.js";import{Vector3 as s,MathUtils as n,PerspectiveCamera as h,Object3D as r}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as c,RestrictedRotationInput as d}from"../../input/index.js";import{PhysicsSystem as m}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as l}from"../../services/world.js";import{inject as u}from"../../inject.js";import{ease as f}from"@hology/nebula";const v=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let k=class extends o{constructor(){super(),this.viewController=u(a),this.physicsSystem=u(m),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=v?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.smoothCamera=!1,this.smoothSpeed=10,this.teleportSnapDistance=5,this.camera=new h(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new d(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new s,this.lookAtOffset=new s(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=u(l),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.pointerEventsRegistered=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.isMouseLocked||(this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default")},this.prevLookAt=new s,this.smoothedLookAt=new s,this.previousTargetLookAt=new s,this.hasSmoothedLookAt=!1,this.smoothedRotX=0,this.smoothedRotY=0,this.smoothZoom=0}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.smoothedRotX=this.rotationInput.rotation.x,this.smoothedRotY=this.rotationInput.rotation.y,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.smoothZoom=this.zoomInput.value,this.autoActivate&&this.activate(),this.disposed.subscribe(()=>{this.unregisterPointerEvents()})}activate(){this.activated=!0,this.hasSmoothedLookAt=!1,this.viewController.setCamera(this.camera),this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.registerPointerEvents()}deactivate(){this.activated=!1,this.isMouseLocked=!1,this.unregisterPointerEvents()}registerPointerEvents(){if(this.pointerEventsRegistered||null==document.body.requestPointerLock)return;const t=this.element;t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!0}unregisterPointerEvents(){if(!this.pointerEventsRegistered)return;const t=this.element;t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!1}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&this.canvas.requestPointerLock&&(this.canvas.requestPointerLock({unadjustedMovement:!0}),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",null==document.pointerLockElement&&null==document.mozPointerLockElement||window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);let e=this.zoomInput.value,o=this.rotationInput.rotation.x,i=this.rotationInput.rotation.y;if(this.smoothCamera){const s=1-Math.exp(-this.smoothSpeed*t*2);this.smoothedRotX=n.lerp(this.smoothedRotX,o,s),this.smoothedRotY=n.lerp(this.smoothedRotY,i,s),o=this.smoothedRotX,i=this.smoothedRotY,this.smoothZoom=n.lerp(this.smoothZoom,e,.4*s),e=this.smoothZoom}else this.smoothedRotX=o,this.smoothedRotY=i;const s=n.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*e,this.minDistance)),h=Math.cos(o)*s,r=this.fixedBehind?0:i;this.offset.x=Math.sin(-r)*h,this.offset.y=Math.sin(o)*s+2,this.offset.z=Math.cos(-r)*-h,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition(t)}checkForCollision(t){const e=this.getLookAtPosition(),o=this.camera.getWorldPosition(w),i=A.subVectors(o,e),s=i.length();if(s<.001)return;i.divideScalar(s);const h=this.physicsSystem.sphereCast(e,this.collisionSphereRadius,i,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(h.hasHit){const e=Math.max(this.minDistance,h.distance-.05);e<this.restrictedDistance?this.restrictedDistance=e:this.restrictedDistance=n.lerp(this.restrictedDistance,e,n.clamp(this.bounceBackSpeed*t,0,1))}else this.restrictedDistance=n.lerp(this.restrictedDistance,this.distance,n.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=y;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(t){this.actor.object.updateWorldMatrix(!0,!1),this.fixedBehind?(L.position.set(this.offset.x,this.offset.y,this.offset.z),L.rotation.set(0,0,0),L.scale.set(1,1,1),L.applyMatrix4(this.actor.object.matrix)):L.position.copy(this.actor.position).add(this.offset);const e=f.easeInOutCubic(1-this.blendDurationLeft);if(this.blendDurationLeft>0){const t=this.getLookAtPosition();this.prevLookAt.lerp(t,e),this.camera.lookAt(this.prevLookAt),this.camera.position.lerp(L.position,e),this.smoothedLookAt.copy(this.prevLookAt),this.previousTargetLookAt.copy(t),this.hasSmoothedLookAt=!0}else{const e=this.getLookAtPosition();if(this.smoothCamera){const o=1-Math.exp(-this.smoothSpeed*t),i=Math.max(0,this.teleportSnapDistance);!this.hasSmoothedLookAt||this.previousTargetLookAt.distanceToSquared(e)>i*i?this.smoothedLookAt.copy(e):this.smoothedLookAt.lerp(e,o)}else this.smoothedLookAt.copy(e);this.previousTargetLookAt.copy(e),this.hasSmoothedLookAt=!0,g.subVectors(L.position,e),this.camera.position.copy(this.smoothedLookAt).add(g),this.camera.lookAt(this.smoothedLookAt),this.prevLookAt.copy(this.smoothedLookAt)}}};t([p(),e("design:type",Number)],k.prototype,"near",void 0),t([p(),e("design:type",Number)],k.prototype,"far",void 0),t([p(),e("design:type",Number)],k.prototype,"viewAngle",void 0),t([p(),e("design:type",Boolean)],k.prototype,"collision",void 0),t([p(),e("design:type",Number)],k.prototype,"collisionSphereRadius",void 0),t([p(),e("design:type",Boolean)],k.prototype,"smoothCamera",void 0),t([p(),e("design:type",Number)],k.prototype,"smoothSpeed",void 0),t([p(),e("design:type",Number)],k.prototype,"teleportSnapDistance",void 0),k=t([i(),e("design:paramtypes",[])],k);export{k as ThirdPersonCameraComponent};const L=new r,y=new s,g=new s,A=new s,w=(new s,new s);export class ThirdPartyCameraComponent extends k{}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import{ActorComponent as o,Component as i}from"../component.js";import{Vector3 as s,MathUtils as n,PerspectiveCamera as h,Object3D as r}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as c,RestrictedRotationInput as d}from"../../input/index.js";import{PhysicsSystem as m}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as l}from"../../services/world.js";import{inject as u}from"../../inject.js";import{ease as f}from"@hology/nebula";const v=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let k=class extends o{constructor(){super(),this.viewController=u(a),this.physicsSystem=u(m),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=v?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.smoothCamera=!1,this.smoothSpeed=10,this.teleportSnapDistance=5,this.camera=new h(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetY=2,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new d(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new s,this.lookAtOffset=new s(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=u(l),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.pointerEventsRegistered=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.isMouseLocked||(this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default")},this.prevLookAt=new s,this.smoothedLookAt=new s,this.previousTargetLookAt=new s,this.hasSmoothedLookAt=!1,this.smoothedRotX=0,this.smoothedRotY=0,this.smoothZoom=0}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.smoothedRotX=this.rotationInput.rotation.x,this.smoothedRotY=this.rotationInput.rotation.y,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.smoothZoom=this.zoomInput.value,this.autoActivate&&this.activate(),this.disposed.subscribe(()=>{this.unregisterPointerEvents()})}activate(){this.activated=!0,this.hasSmoothedLookAt=!1,this.viewController.setCamera(this.camera),this.isMouseLocked=null!=document.pointerLockElement||null!=document.mozPointerLockElement,this.registerPointerEvents()}deactivate(){this.activated=!1,this.isMouseLocked=!1,this.unregisterPointerEvents()}registerPointerEvents(){if(this.pointerEventsRegistered||null==document.body.requestPointerLock)return;const t=this.element;t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!0}unregisterPointerEvents(){if(!this.pointerEventsRegistered)return;const t=this.element;t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1),this.pointerEventsRegistered=!1}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&this.canvas.requestPointerLock&&(this.canvas.requestPointerLock({unadjustedMovement:!0}),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",null==document.pointerLockElement&&null==document.mozPointerLockElement||window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);let e=this.zoomInput.value,o=this.rotationInput.rotation.x,i=this.rotationInput.rotation.y;if(this.smoothCamera){const s=1-Math.exp(-this.smoothSpeed*t*2);this.smoothedRotX=n.lerp(this.smoothedRotX,o,s),this.smoothedRotY=n.lerp(this.smoothedRotY,i,s),o=this.smoothedRotX,i=this.smoothedRotY,this.smoothZoom=n.lerp(this.smoothZoom,e,.4*s),e=this.smoothZoom}else this.smoothedRotX=o,this.smoothedRotY=i;const s=n.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*e,this.minDistance)),h=Math.cos(o)*s,r=this.fixedBehind?0:i;this.offset.x=Math.sin(-r)*h,this.offset.y=Math.sin(o)*s+this.offsetY,this.offset.z=Math.cos(-r)*-h,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition(t)}checkForCollision(t){const e=this.getLookAtPosition(),o=this.camera.getWorldPosition(w),i=A.subVectors(o,e),s=i.length();if(s<.001)return;i.divideScalar(s);const h=this.physicsSystem.sphereCast(e,this.collisionSphereRadius,i,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(h.hasHit){const e=Math.max(this.minDistance,h.distance-.05);e<this.restrictedDistance?this.restrictedDistance=e:this.restrictedDistance=n.lerp(this.restrictedDistance,e,n.clamp(this.bounceBackSpeed*t,0,1))}else this.restrictedDistance=n.lerp(this.restrictedDistance,this.distance,n.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=y;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(t){this.actor.object.updateWorldMatrix(!0,!1),this.fixedBehind?(L.position.set(this.offset.x,this.offset.y,this.offset.z),L.rotation.set(0,0,0),L.scale.set(1,1,1),L.applyMatrix4(this.actor.object.matrix)):L.position.copy(this.actor.position).add(this.offset);const e=f.easeInOutCubic(1-this.blendDurationLeft);if(this.blendDurationLeft>0){const t=this.getLookAtPosition();this.prevLookAt.lerp(t,e),this.camera.lookAt(this.prevLookAt),this.camera.position.lerp(L.position,e),this.smoothedLookAt.copy(this.prevLookAt),this.previousTargetLookAt.copy(t),this.hasSmoothedLookAt=!0}else{const e=this.getLookAtPosition();if(this.smoothCamera){const o=1-Math.exp(-this.smoothSpeed*t),i=Math.max(0,this.teleportSnapDistance);!this.hasSmoothedLookAt||this.previousTargetLookAt.distanceToSquared(e)>i*i?this.smoothedLookAt.copy(e):this.smoothedLookAt.lerp(e,o)}else this.smoothedLookAt.copy(e);this.previousTargetLookAt.copy(e),this.hasSmoothedLookAt=!0,g.subVectors(L.position,e),this.camera.position.copy(this.smoothedLookAt).add(g),this.camera.lookAt(this.smoothedLookAt),this.prevLookAt.copy(this.smoothedLookAt)}}};t([p(),e("design:type",Number)],k.prototype,"near",void 0),t([p(),e("design:type",Number)],k.prototype,"far",void 0),t([p(),e("design:type",Number)],k.prototype,"viewAngle",void 0),t([p(),e("design:type",Boolean)],k.prototype,"collision",void 0),t([p(),e("design:type",Number)],k.prototype,"collisionSphereRadius",void 0),t([p(),e("design:type",Boolean)],k.prototype,"smoothCamera",void 0),t([p(),e("design:type",Number)],k.prototype,"smoothSpeed",void 0),t([p(),e("design:type",Number)],k.prototype,"teleportSnapDistance",void 0),k=t([i(),e("design:paramtypes",[])],k);export{k as ThirdPersonCameraComponent};const L=new r,y=new s,g=new s,A=new s,w=(new s,new s);export class ThirdPartyCameraComponent extends k{}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{Vector3 as t}from"three";import{LeafNode as e,NodeState as o}from"./bt";import{clamp as n}from"../../../utils/math";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,c=null!=this.target?this.target():null;if(null==c)return this.movement.directionInput.vector.set(0,0),o.FAILURE;if(e.distanceTo(c)<this.distanceFrom)return this.movement.directionInput.vector.set(0,0),o.SUCCESS;const{success:m,path:a}=this.navigation.findPath(e,c);if(!m||a.length<2)return o.FAILURE;const h=a[1],u=i.subVectors(h,e);u.y=0,u.normalize(),this.movement.actor.object.getWorldDirection(r).normalize();const l=r.angleTo(u);s.crossVectors(r,u);const v=s.y<0?-l:l;return this.movement.rotationInput.rotation.y+=n(v,-.1,.1),this.movement.directionInput.togglePositiveY(!0),o.RUNNING}}const i=new t,r=new t,s=new t;/*
1
+ import{Vector3 as t}from"three";import{LeafNode as e,NodeState as o}from"./bt";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:r,path:s}=this.navigation.findPath(e,i);if(!r||s.length<2)return o.FAILURE;const c=s[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;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,5 +1,6 @@
1
1
  import { NavMesh, RecastConfig, Vector3Tuple } from 'recast-navigation';
2
2
  import * as THREE from 'three';
3
+ import { BuildTileMeshProps } from './build-tile.js';
3
4
  import { Subject } from 'rxjs';
4
5
  export type DynamicTiledNavMeshProps = {
5
6
  navMeshBounds: THREE.Box3;
@@ -8,6 +9,23 @@ export type DynamicTiledNavMeshProps = {
8
9
  workers: number;
9
10
  cacheId: string;
10
11
  };
12
+ export declare const MAX_NAV_MESH_WORKERS = 4;
13
+ type NavMeshWorkerResult = {
14
+ tileX: number;
15
+ tileY: number;
16
+ navMeshData: Uint8Array;
17
+ };
18
+ export declare class NavMeshWorkerPool {
19
+ private workerFactory;
20
+ private slots;
21
+ private queue;
22
+ private workerLimit;
23
+ constructor(workerFactory?: () => Worker);
24
+ schedule(owner: object, data: BuildTileMeshProps, transfer: Transferable[] | undefined, onResult: (event: MessageEvent<NavMeshWorkerResult>) => void, requestedWorkers: number): void;
25
+ cancel(owner: object): void;
26
+ private drain;
27
+ private createSlot;
28
+ }
11
29
  export declare class DynamicTiledNavMesh {
12
30
  navMesh: NavMesh;
13
31
  navMeshVersion: number;
@@ -20,9 +38,8 @@ export declare class DynamicTiledNavMesh {
20
38
  tileHeight: number;
21
39
  tcs: number;
22
40
  recastConfig: RecastConfig;
23
- workers: InstanceType<any>[];
24
- workerRoundRobin: number;
25
41
  private cacheId;
42
+ private workerLimit;
26
43
  constructor(props: DynamicTiledNavMeshProps);
27
44
  private onResult;
28
45
  buildTile(positions: Float32Array, indices: Uint32Array, [tileX, tileY]: [x: number, y: number], useTileCache?: boolean): Promise<unknown>;
@@ -31,4 +48,5 @@ export declare class DynamicTiledNavMesh {
31
48
  getTilesForBounds(bounds: THREE.Box3): [x: number, y: number][];
32
49
  destroy(): void;
33
50
  }
51
+ export {};
34
52
  //# sourceMappingURL=dynamic-tiled-navmesh.d.ts.map
@@ -1,4 +1,4 @@
1
- import{NavMesh as t,NavMeshParams as s,Raw as e,UnsignedCharArray as i,recastConfigDefaults as o,statusToReadableString as n}from"recast-navigation";import{buildConfig as r,buildTile as a}from"./build-tile.js";import{Subject as h}from"rxjs";import{hasWorkerBuilder as l,createWorker as d}from"../../worker/index.js";import{hasSharedArrayBufferSupport as u}from"../../utils/buffer.js";const c=[];export class DynamicTiledNavMesh{constructor(e){this.navMeshVersion=0,this.onNavMeshUpdate=new h,this.workerRoundRobin=0;const i=e.navMeshBounds.min,n=e.navMeshBounds.max,a=[i.toArray(),n.toArray()],u=e.navMeshBounds.min;this.navMeshBoundsMin=i,this.navMeshBoundsMax=n,this.navMeshBounds=a,this.navMeshOrigin=u,this.cacheId=e.cacheId;const M={...o,...e.recastConfig};this.recastConfig=M;const f=new t,{tileWidth:v,tileHeight:m,tcs:g,maxPolysPerTile:w}=r({recastConfig:M,navMeshBounds:a});this.tileWidth=v,this.tileHeight=m,this.tcs=g;const B=s.create({orig:u,tileWidth:M.tileSize*M.cs,tileHeight:M.tileSize*M.cs,maxTiles:e.maxTiles,maxPolys:w});if(f.initTiled(B),this.navMesh=f,this.workers=[],l())for(let t=0;t<e.workers;t++){let t=c.pop();void 0===t&&(t=d()),t.onmessage=t=>{this.onResult(t)},this.workers.push(t)}}onResult(t){const{tileX:s,tileY:o,navMeshData:r}=t.data,a=new i;a.copy(r),this.navMesh.removeTile(this.navMesh.getTileRefAt(s,o,0));const h=this.navMesh.addTile(a,e.Module.DT_TILE_FREE_DATA,0);e.Detour.statusFailed(h.status)&&(console.error(e.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${s}, ty: ${o},status: ${n(h.status)} (${h.status})`),a.destroy()),this.navMeshVersion++,this.onNavMeshUpdate.next([this.navMeshVersion,[s,o]])}buildTile(t,s,[e,i],o=!0){const n=u&&t.buffer instanceof window.SharedArrayBuffer,r=n?t:new Float32Array(t),h=n?s:new Uint32Array(s),l={tileX:e,tileY:i,tileBoundsMin:[this.navMeshBoundsMin.x+e*this.tcs,this.navMeshBoundsMin.y,this.navMeshBoundsMin.z+i*this.tcs],tileBoundsMax:[this.navMeshBoundsMax.x+(e+1)*this.tcs,this.navMeshBoundsMax.y,this.navMeshBoundsMax.z+(i+1)*this.tcs],recastConfig:this.recastConfig,navMeshBounds:this.navMeshBounds,keepIntermediates:!1,positions:r,indices:h};if(this.workers.length>0){this.workerRoundRobin=++this.workerRoundRobin%this.workers.length;return this.workers[this.workerRoundRobin].postMessage(l,n?void 0:[r.buffer,h.buffer]),Promise.resolve()}return new Promise(t=>{requestIdleCallback(()=>{const s=this.cacheId+JSON.stringify({tileX:l.tileX,tileY:l.tileY});if(o){const e=localStorage.getItem(s);if(null!=e){const s=f(e);return this.onResult({data:{tileX:l.tileX,tileY:l.tileY,navMeshData:s}}),void t({})}}else localStorage.removeItem(s);const e=a(l);if(!e.success||!e.data)return;const i=e.data.toTypedArray();localStorage.setItem(s,M(i)),this.onResult({data:{tileX:l.tileX,tileY:l.tileY,navMeshData:i}}),t(e)})})}buildAllTiles(t,s){const{tileWidth:e,tileHeight:i}=this;for(let o=0;o<i;o++)for(let i=0;i<e;i++)this.buildTile(t,s,[i,o])}getTileForWorldPosition(t){return[Math.floor((t.x-this.navMeshBoundsMin.x)/this.tcs),Math.floor((t.z-this.navMeshBoundsMin.z)/this.tcs)]}getTilesForBounds(t){const s=this.getTileForWorldPosition(t.min),e=this.getTileForWorldPosition(t.max),i=[];for(let t=s[1];t<=e[1];t++)for(let o=s[0];o<=e[0];o++)i.push([o,t]);return i}destroy(){this.navMesh.destroy(),this.onNavMeshUpdate.complete();for(const t of this.workers)t.onmessage=null,c.push(t)}}const M=function(t){return btoa(String.fromCharCode(...t))},f=function(t){if(!t)return null;const s=atob(t),e=s.length,i=new Uint8Array(e);for(let t=0;t<e;t++)i[t]=s.charCodeAt(t);return i};/*
1
+ import{NavMesh as t,NavMeshParams as e,Raw as s,UnsignedCharArray as i,recastConfigDefaults as o,statusToReadableString as n}from"recast-navigation";import{buildConfig as r,buildTile as a}from"./build-tile.js";import{Subject as h}from"rxjs";import{hasWorkerBuilder as l,createWorker as c}from"../../worker/index.js";import{hasSharedArrayBufferSupport as d}from"../../utils/buffer.js";export const MAX_NAV_MESH_WORKERS=4;export class NavMeshWorkerPool{constructor(t=c){this.workerFactory=t,this.slots=[],this.queue=[],this.workerLimit=0}schedule(t,e,s,i,o){this.workerLimit=Math.max(this.workerLimit,Math.min(4,Math.max(1,o))),this.queue.push({owner:t,data:e,transfer:s,onResult:i,cancelled:!1}),this.drain()}cancel(t){this.queue=this.queue.filter(e=>e.owner!==t);for(const e of this.slots)e.job?.owner===t&&(e.job.cancelled=!0)}drain(){for(;this.queue.length>0;){let t=this.slots.find(t=>null==t.job);if(null==t){if(this.slots.length>=this.workerLimit)return;t=this.createSlot(),this.slots.push(t)}const e=this.queue.shift();t.job=e,t.worker.postMessage(e.data,e.transfer)}}createSlot(){const t={worker:this.workerFactory()};return t.worker.onmessage=e=>{const s=t.job;t.job=void 0;try{null==s||s.cancelled||s.onResult(e)}finally{this.drain()}},t.worker.onerror=e=>{t.job=void 0,t.worker.terminate();const s=this.slots.indexOf(t);s>=0&&this.slots.splice(s,1),console.error("Navmesh worker failed",e),this.drain()},t}}const u=new NavMeshWorkerPool;export class DynamicTiledNavMesh{constructor(s){this.navMeshVersion=0,this.onNavMeshUpdate=new h;const i=s.navMeshBounds.min,n=s.navMeshBounds.max,a=[i.toArray(),n.toArray()],l=s.navMeshBounds.min;this.navMeshBoundsMin=i,this.navMeshBoundsMax=n,this.navMeshBounds=a,this.navMeshOrigin=l,this.cacheId=s.cacheId,this.workerLimit=Math.min(4,Math.max(0,s.workers));const c={...o,...s.recastConfig};this.recastConfig=c;const d=new t,{tileWidth:u,tileHeight:M,tcs:f,maxPolysPerTile:m}=r({recastConfig:c,navMeshBounds:a});this.tileWidth=u,this.tileHeight=M,this.tcs=f;const v=e.create({orig:l,tileWidth:c.tileSize*c.cs,tileHeight:c.tileSize*c.cs,maxTiles:s.maxTiles,maxPolys:m});d.initTiled(v),this.navMesh=d}onResult(t){const{tileX:e,tileY:o,navMeshData:r}=t.data,a=new i;a.copy(r),this.navMesh.removeTile(this.navMesh.getTileRefAt(e,o,0));const h=this.navMesh.addTile(a,s.Module.DT_TILE_FREE_DATA,0);s.Detour.statusFailed(h.status)&&(console.error(s.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${e}, ty: ${o},status: ${n(h.status)} (${h.status})`),a.destroy()),this.navMeshVersion++,this.onNavMeshUpdate.next([this.navMeshVersion,[e,o]])}buildTile(t,e,[s,i],o=!0){const n=d&&t.buffer instanceof window.SharedArrayBuffer,r=n?t:new Float32Array(t),h=n?e:new Uint32Array(e),c={tileX:s,tileY:i,tileBoundsMin:[this.navMeshBoundsMin.x+s*this.tcs,this.navMeshBoundsMin.y,this.navMeshBoundsMin.z+i*this.tcs],tileBoundsMax:[this.navMeshBoundsMax.x+(s+1)*this.tcs,this.navMeshBoundsMax.y,this.navMeshBoundsMax.z+(i+1)*this.tcs],recastConfig:this.recastConfig,navMeshBounds:this.navMeshBounds,keepIntermediates:!1,positions:r,indices:h};return this.workerLimit>0&&l()?(u.schedule(this,c,n?void 0:[r.buffer,h.buffer],t=>this.onResult(t),this.workerLimit),Promise.resolve()):new Promise(t=>{requestIdleCallback(()=>{const e=this.cacheId+JSON.stringify({tileX:c.tileX,tileY:c.tileY});if(o){const s=localStorage.getItem(e);if(null!=s){const e=f(s);return this.onResult({data:{tileX:c.tileX,tileY:c.tileY,navMeshData:e}}),void t({})}}else localStorage.removeItem(e);const s=a(c);if(!s.success||!s.data)return;const i=s.data.toTypedArray();localStorage.setItem(e,M(i)),this.onResult({data:{tileX:c.tileX,tileY:c.tileY,navMeshData:i}}),t(s)})})}buildAllTiles(t,e){const{tileWidth:s,tileHeight:i}=this;for(let o=0;o<i;o++)for(let i=0;i<s;i++)this.buildTile(t,e,[i,o])}getTileForWorldPosition(t){return[Math.floor((t.x-this.navMeshBoundsMin.x)/this.tcs),Math.floor((t.z-this.navMeshBoundsMin.z)/this.tcs)]}getTilesForBounds(t){const e=this.getTileForWorldPosition(t.min),s=this.getTileForWorldPosition(t.max),i=[];for(let t=e[1];t<=s[1];t++)for(let o=e[0];o<=s[0];o++)i.push([o,t]);return i}destroy(){u.cancel(this),this.navMesh.destroy(),this.onNavMeshUpdate.complete()}}const M=function(t){return btoa(String.fromCharCode(...t))},f=function(t){if(!t)return null;const e=atob(t),s=e.length,i=new Uint8Array(s);for(let t=0;t<s;t++)i[t]=e.charCodeAt(t);return i};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,3 @@
1
+ import type { AnimationAction } from "three";
2
+ export declare function canCrossFadeFromAnimationAction(action?: AnimationAction): boolean;
3
+ //# sourceMappingURL=animation-action.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function canCrossFadeFromAnimationAction(n){return null!=n&&(n.isRunning()||n.clampWhenFinished&&n.enabled&&n.isScheduled())}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -2,7 +2,7 @@ import * as RAPIER from "@dimforge/rapier3d-simd-compat";
2
2
  import { Observable, Subject } from "rxjs";
3
3
  import * as THREE from "three";
4
4
  import { ColorRepresentation, Object3D, Quaternion, Vector3 } from "three";
5
- import { CollisionShape } from '../../../index.js';
5
+ import { CollisionShape } from '../../../scene/collision/collision-shape.js';
6
6
  import { AbstractType, Type } from '../../../utils/type.js';
7
7
  import { BaseActor } from '../../actors/actor.js';
8
8
  import { ViewController } from '../render.js';
@@ -35,6 +35,11 @@ export declare class RayTestResult {
35
35
  hitNormal: Vector3;
36
36
  }
37
37
  export interface RayTestOptions {
38
+ /**
39
+ * Whether to draw the ray while physics debug rendering is enabled.
40
+ * @default true
41
+ */
42
+ debug?: boolean;
38
43
  debugColor?: ColorRepresentation;
39
44
  debugLifetime?: number;
40
45
  collisionFilter?: InteractionGroups;
@@ -73,6 +78,26 @@ export declare enum PhysicsBodyType {
73
78
  kinematic = 4,
74
79
  kinematicVelocityBased = 8
75
80
  }
81
+ export type PhysicsJointDescriptor = {
82
+ type: 'fixed';
83
+ anchor1: Vector3;
84
+ frame1: Quaternion;
85
+ anchor2: Vector3;
86
+ frame2: Quaternion;
87
+ contactsEnabled?: boolean;
88
+ } | {
89
+ type: 'spherical';
90
+ anchor1: Vector3;
91
+ anchor2: Vector3;
92
+ contactsEnabled?: boolean;
93
+ } | {
94
+ type: 'revolute';
95
+ anchor1: Vector3;
96
+ anchor2: Vector3;
97
+ axis: Vector3;
98
+ limits?: readonly [number, number];
99
+ contactsEnabled?: boolean;
100
+ };
76
101
  /**
77
102
  * A physics system implementation using the Rapier physics engine.
78
103
  * Handles rigid body physics, collisions, and physics-based character movement.
@@ -89,6 +114,8 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
89
114
  private eventQueue;
90
115
  private fixedupdateSub;
91
116
  private collisionSub;
117
+ private rayDebugArrowPool;
118
+ private activeRayDebugArrows;
92
119
  private readonly collisionEvents;
93
120
  readonly beforeStep: Subject<number>;
94
121
  readonly afterStep: Subject<number>;
@@ -129,7 +156,11 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
129
156
  */
130
157
  findActorsInRadius<T = BaseActor>(position: Vector3, radius: number, actorType?: Type<T>): T[];
131
158
  private debugMesh;
159
+ private staticDebugMesh;
160
+ private staticDebugNeedsUpdate;
161
+ private invalidateStaticDebug;
132
162
  private createDebugMesh;
163
+ private updateDebugMesh;
133
164
  /**
134
165
  * Initializes and starts the physics system.
135
166
  * @returns A promise that resolves when the physics system is ready
@@ -184,6 +215,9 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
184
215
  * @returns The result of the raycast test
185
216
  */
186
217
  rayTest(from: Vector3, to: Vector3, result?: RayTestResult, options?: RayTestOptions): RayTestResult;
218
+ private drawRayDebugArrow;
219
+ private releaseExpiredRayDebugArrows;
220
+ private clearRayDebugArrows;
187
221
  /**
188
222
  * Sets the gravity vector for the physics world.
189
223
  * @param x - Gravity force along X axis
@@ -274,6 +308,11 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
274
308
  mass?: number;
275
309
  userData?: any;
276
310
  }): PhysicsBody;
311
+ /**
312
+ * Creates an impulse joint between two generic physics bodies.
313
+ * Joint anchors, axes, and frames are expressed in the local spaces of the bodies.
314
+ */
315
+ createJoint(body1: PhysicsBody, body2: PhysicsBody, descriptor: PhysicsJointDescriptor): PhysicsJoint;
277
316
  /**
278
317
  * Computes the corrected movement vector for a collider using a kinematic character controller.
279
318
  * This function uses the provided character controller to calculate the actual movement that can be performed
@@ -661,6 +700,7 @@ type ColliderCollisionEvent = {
661
700
  actor: BaseActor;
662
701
  };
663
702
  export declare class PhysicsCollider {
703
+ private readonly invalidateStaticDebug?;
664
704
  readonly disposed: Subject<true>;
665
705
  readonly onBeginOverlapActor: Subject<ColliderCollisionEvent>;
666
706
  readonly onEndOverlapActor: Subject<ColliderCollisionEvent>;
@@ -668,7 +708,7 @@ export declare class PhysicsCollider {
668
708
  /** @internal */
669
709
  collider: RAPIER.Collider,
670
710
  /** @internal */
671
- world: RAPIER.World);
711
+ world: RAPIER.World, invalidateStaticDebug?: () => void);
672
712
  dispose(): void;
673
713
  set mass(mass: number);
674
714
  get mass(): number;
@@ -686,7 +726,8 @@ export declare class PhysicsCollider {
686
726
  get enabled(): boolean;
687
727
  }
688
728
  export declare class PhysicsBody {
689
- constructor(body: RAPIER.RigidBody, world: RAPIER.World);
729
+ private readonly invalidateStaticDebug?;
730
+ constructor(body: RAPIER.RigidBody, world: RAPIER.World, invalidateStaticDebug?: () => void);
690
731
  dispose(): void;
691
732
  setEnabled(enabled: boolean): void;
692
733
  isEnabled(): boolean;
@@ -698,6 +739,8 @@ export declare class PhysicsBody {
698
739
  setLinearVelocity(vel: Vector3): void;
699
740
  getAngularVelocity(target: Vector3): Vector3;
700
741
  setAngularVelocity(vel: Vector3): void;
742
+ setLinearDamping(damping: number): void;
743
+ setAngularDamping(damping: number): void;
701
744
  applyImpulse(impulse: Vector3, wakeUp?: boolean): void;
702
745
  applyTorqueImpulse(torque: Vector3, wakeUp?: boolean): void;
703
746
  setNextKinematicPosition(pos: Vector3): void;
@@ -718,4 +761,14 @@ export declare class PhysicsBody {
718
761
  sleep(): void;
719
762
  wakeUp(): void;
720
763
  }
764
+ export declare class PhysicsJoint {
765
+ constructor(
766
+ /** @internal */
767
+ joint: RAPIER.ImpulseJoint,
768
+ /** @internal */
769
+ world: RAPIER.World);
770
+ dispose(): void;
771
+ setContactsEnabled(enabled: boolean): void;
772
+ get contactsEnabled(): boolean;
773
+ }
721
774
  //# sourceMappingURL=physics-system.d.ts.map
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as p,Group as y,LineSegments as g,Matrix4 as m,Object3D as f,Quaternion as w,Raycaster as x,Scene as b,Vector3 as B}from"three";import*as v from"three/examples/jsm/utils/BufferGeometryUtils.js";import{Service as C}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as R}from"../../../gameplay/inject.js";import{BoxCollisionShape as z,CapsuleCollisionShape as D,ConeCollisionShape as T,ConvexPolyhedronCollisionShape as M,CylinderCollisionShape as E,PhysicalShapeMesh as P,PlaneCollisionShape as _,SphereCollisionShape as F,toInstancedCollisionShape as W,TrimeshCollisionShape as I}from"../../../index.js";import{AssetMeshInstance as j}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as V}from"../../../scene/landscape/landscape.js";import{calculateEffectiveScale as k}from"../../../utils/three/traverse.js";import{ViewController as N}from"../render.js";import{World as L}from"../world.js";import{AbstractPhysicsSystem as O}from"./abstract-physics-system.js";import{NetRole as G}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const K=new B,U=new B,H=new w,q=new w,Q=new w,X=[];let $=class extends O{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=R(N),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(K),i=t.getSize(U),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,H,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,H,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(n instanceof i||null==i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,H)&&o.push(n)}return o}createDebugMesh(){return new g(new p,new d.LineBasicMaterial({color:255}))}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene?.add(this.debugMesh));const t=this.world.debugRender().vertices,e=this.debugMesh.geometry,i=e.getAttribute("position");null==i||(i.array.length,t.length);{const i=new u(t,3);i.setUsage(d.DynamicDrawUsage),e.setAttribute("position",i)}e.setDrawRange(0,t.length/3)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await dt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{this._isStopped||(t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach(t=>{if(t.isFixed())return;let e,i=this.staticMeshes.get(t);if(null==i&&(e=this.bodyActors.get(t),null!=e)){if(e.netRole===G.simulatedProxy)return;i=e.object}null!=i&&i.parent instanceof b&&(pt(i.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&yt(i.quaternion,t.rotation()),i.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t))})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this._isStopped||(this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})}))}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(rt,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,n=this._raytestDirection;if(o.subVectors(e,t),n.copy(o).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),i;null==bt&&(bt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),ht(bt.origin,t),ht(bt.dir,n);const r=o.length(),a=this.world.castRayAndGetNormal(bt,r,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?t=>!t.isSensor():void 0);if(i.hasHit=null!=a,i.hasHit){const e=bt.pointAt(a.timeOfImpact);if(i._internal=a,pt(i.hitNormal,a.normal),pt(i.hitPoint,e),i.distance=mt.subVectors(i.hitPoint,t).length(),!1!==s?.resolveActor){const t=this.world.bodies.getAll().find(t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,t=>t===a.collider));i.actor=null!=t?this.bodyActors.get(t):null}}if(this.showDebug){let e;X.length>0?(e=X.pop(),e.setDirection(n),e.position.copy(t),e.setLength(r,.2,.1),e.setColor(s?.debugColor??255)):e=new h(n,t,r,s?.debugColor??255),this.scene?.add(e),setTimeout(()=>{this.scene?.remove(e),X.push(e)},s?.debugLifetime??200)}return i}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return tt.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())gt(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof P&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof j){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof V?this.addLandscapeGroup(t):(t instanceof y||t instanceof b)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map;for(let o=0;o<e.length;o++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[o])continue;const e=t.userData.collisionShapes;let n=e?.[o];if(null==n&&null==e&&t.parent instanceof j&&(n=t.parent.collisionShapes),null==n)continue;let r=s.get(n);null==r&&(r=this.instancedShapeReset(n),s.set(n,r));const a=new f;a.matrix.identity(),t.getMatrixAt(o,i),a.applyMatrix4(i);this.createStaticBody(a,r)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new f;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>W(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,wt);const a=e.computedMovement();return pt(ft,a),ft}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(xt)??it,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),nt.set(0,s,0).multiply(r),ht(st,nt),n.setTranslationWrtParent(st),o.recomputeMassPropertiesFromColliders(),!0}hasActorCapsuleIntersection(t,e,i,o,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(xt)??it,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,o*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(Q)??H;nt.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(nt,u,h,s.EXCLUDE_SENSORS,r??void 0,void 0,a,wt)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world);return this.colliders.set(i.handle,s),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return new PhysicsBody(s,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,wt);const r=e.computedMovement();return pt(ft,r),ft}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(Y),s=e.getWorldQuaternion(Z);t.setNextKinematicTranslation(at(i)),t.setNextKinematicRotation(lt(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.setAngvel(st,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.setLinvel(st,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(at(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&pt(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(lt(e),!1)}getRotation(t,e=new w){const i=this.actorBodies.get(t.id);i&&yt(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);ht(e,o),t.setTranslation(e,!1),this.world.createCollider(l,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);ht(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e)}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e)this.addShape(n,t,s);return gt(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),J(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),new PhysicsBody(n,this.world)}applyTorque(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.addTorque(st,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.applyTorqueImpulse(st,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.addForce(st,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);st.x=e.x,st.y=e.y,st.z=e.z,i?.applyImpulse(st,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);ht(st,e),null==i?s?.addForce(st,!0):(ht(ot,i),s?.addForceAtPoint(st,ot,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);ht(st,e),null==i?s.applyImpulse(st,!0):(ht(ot,i),s.applyImpulseAtPoint(st,ot,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=nt;pt(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);st.x=a.x,st.y=a.y,st.z=a.z,o.applyImpulse(st,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof V){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&J(e,t.object)}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t}sphereCast(t,e,i,s,o=ShapeCastResult.shared,n){o.reset();const r=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=n?.excludeActor?this.actorBodies.get(n.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,r,.01,s,!0,null,n?.collisionFilter??void 0,null,c,n?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){pt(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return pt(s.hitPoint,u.witness1),vt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>this.world.removeRigidBody(t));try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}X.length=0}}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return J(n,t),n.userData=t.uuid,n.sleep(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(xt)??it,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);ht(o.translation,n);const r=(new w).setFromEuler(e.rotation);ut(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof z)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof D){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof I){const i=null!=t.geometry.getIndex()?t.geometry:v.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof M){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=k(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=et.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),et.set(o,a),a}if(t instanceof F){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new M(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new B(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof E?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof T?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof _?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};$=t([C(),e("design:paramtypes",[])],$);export{$ as PhysicsSystem};const Y=new B,Z=new d.Quaternion;function J(t,e){const i=e.getWorldPosition(Y),s=e.getWorldQuaternion(Z);t.setTranslation(at(i),!1),t.setRotation(lt(s),!1)}const tt=new B,et=new Map,it=new B(1,1,1),st=new i.Vector3(0,0,0),ot=new i.Vector3(0,0,0),nt=new B,rt=new d.Vector2;function at(t){return ht(st,t),st}function lt(t){return ut(q,t),q}let ct=null;const dt=async()=>(null==ct&&(ct=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ct);function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ut(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function pt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function yt(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function gt(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const mt=new B,ft=new B,wt=t=>!t.isSensor(),xt=new B;let bt,Bt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=R($),this.world=R(L)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};Bt=t([A()],Bt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function vt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e){this.collider=t,this.world=e,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t)}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e){this.body=t,this.world=e}dispose(){this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t)}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0)}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0)}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static)}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as o,distinctUntilChanged as r,filter as n,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as p,Group as y,LineSegments as g,Matrix4 as m,Object3D as b,Quaternion as f,Raycaster as w,Scene as x,Vector3 as v}from"three";import*as D from"three/examples/jsm/utils/BufferGeometryUtils.js";import{Service as B}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{BoxCollisionShape as R,CapsuleCollisionShape as M,ConeCollisionShape as E,ConvexPolyhedronCollisionShape as z,CylinderCollisionShape as T,PhysicalShapeMesh as P,PlaneCollisionShape as F,SphereCollisionShape as _,toInstancedCollisionShape as I,TrimeshCollisionShape as j}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as W}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as N}from"../../../scene/landscape/landscape.js";import{calculateEffectiveScale as k}from"../../../utils/three/traverse.js";import{ViewController as V}from"../render.js";import{World as L}from"../world.js";import{AbstractPhysicsSystem as O}from"./abstract-physics-system.js";import{NetRole as U}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.hitNormal=new v}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.normal=new v}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new v,K=new v,H=new f,X=new f,q=new f;let Q=class extends O{set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=C(V),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this._raycaster=new w,this._reusableResult=new RayTestResult,this._raytestDiff=new v,this._raytestDirection=new v,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,H,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,H,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,r]of this.bodyActors)if(r instanceof i||null==i)for(let i=0,n=e.numColliders();i<n;i++){e.collider(i).intersectsShape(s,t,H)&&o.push(r)}return o}createDebugMesh(){const t=new g(new p,new d.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new u(t,3);o.setUsage(d.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(s.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(s.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await ct(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{this._isStopped||(t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows(),this.world.bodies.forEach(t=>{if(t.isFixed())return;let e,i=this.staticMeshes.get(t);if(null==i&&(e=this.bodyActors.get(t),null!=e)){if(e.netRole===U.simulatedProxy)return;i=e.object}null!=i&&i.parent instanceof x&&(ut(i.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&pt(i.quaternion,t.rotation()),i.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t))})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this._isStopped||(this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})}))}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(rt,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,r=this._raytestDirection;o.subVectors(e,t);const n=o.length();if(0===n)return console.warn("Ray test called with to and from being equal"),i;r.copy(o).multiplyScalar(1/n),null==ft&&(ft=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),dt(ft.origin,t),dt(ft.dir,r);const a=this.world.castRayAndGetNormal(ft,n,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?mt:void 0);if(i.hasHit=null!=a,i.actor=void 0,i.hasHit&&(i._internal=a,ut(i.hitNormal,a.normal),i.hitPoint.copy(t).addScaledVector(r,a.timeOfImpact),i.distance=a.timeOfImpact,!1!==s?.resolveActor)){const t=a.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}return this.showDebug&&!1!==s?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,n,s?.debugColor,s?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let r=this.rayDebugArrowPool.pop();null==r?r=new h(t,e,i,s,.2,.1):(r.setDirection(t),r.position.copy(e),r.setLength(i,.2,.1),r.setColor(s)),r.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(r),this.scene.add(r)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())yt(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof P&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof W){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof N?this.addLandscapeGroup(t):(t instanceof y||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let r=0;r<e.length;r++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[r])continue;const e=t.userData.collisionShapes;let n=e?.[r];if(null==n&&null==e&&t.parent instanceof W&&(n=t.parent.collisionShapes),null==n)continue;const a=o?.[r];let l=n;null==a&&(l=s.get(n),null==l&&(l=this.instancedShapeReset(n),s.set(n,l)));const c=new b;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(r,i),c.applyMatrix4(i);this.createStaticBody(c,l)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new b;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>I(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const r=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const n=r.collider(0);e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,mt);const a=e.computedMovement();return ut(gt,a),gt}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),r=o?.collider(0);if(null==o||null==r)return!1;const n=t.object?.getWorldScale(bt)??et,a=Math.max(0,e*Math.abs(n.y)),l=Math.max(.001,i*Math.max(Math.abs(n.x),Math.abs(n.z)));return r.setHalfHeight(a/2),r.setRadius(l),ot.set(0,s,0).multiply(n),dt(it,ot),r.setTranslationWrtParent(it),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,o,r,n=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(bt)??et,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,o*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(q)??H;ot.set(0,r,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(ot,u,h,s.EXCLUDE_SENSORS,n??void 0,void 0,a,mt)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const r=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){r.setLimits(o[0],o[1])}return r.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(r,this.world)}getCharacterComputedMovement(t,e,i,o=null){const r=t.collider;e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,mt);const n=e.computedMovement();return ut(gt,n),gt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setNextKinematicTranslation(nt(i)),t.setNextKinematicRotation(at(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setAngvel(it,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setLinvel(it,!0)}getLinearVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(nt(e),!1)}getPosition(t,e=new v){const i=this.actorBodies.get(t.id);i&&ut(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(at(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&pt(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,s=e.landscape.heightMaps;for(const r of t.sections){this.staticBodies.has(r)&&this.world.removeRigidBody(this.staticBodies.get(r));var o=r.getWorldPosition(new v);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===r.name&&0!==t.w[0])){const t=r.geometry.clone(),i=r.scale,s=r.geometry.getAttribute("hole"),n=new Float32Array(t.getAttribute("position").array);for(let t=0;t<n.length;t+=3)n[t]*=i.x,n[t+1]*=i.y,n[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(n,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);dt(e,o),t.setTranslation(e,!1),this.world.createCollider(l,t),this.staticBodies.set(r,t)}continue}const t=e.landscape.options.density+1,n=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===r.x&&t.y==r.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/n:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(n,n,n));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);dt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(r,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const r=this.world.createRigidBody(o);r.enableCcd(1==i.continousCollisionDetection);for(const t of e)this.addShape(r,t,s);return yt(r,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),Y(r,s),!0===i.ignoreForNavMesh&&(r.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,r),this.bodyActors.set(r,t),r.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(r,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addTorque(it,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyTorqueImpulse(it,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addForce(it,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyImpulse(it,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);dt(it,e),null==i?s?.addForce(it,!0):(dt(st,i),s?.addForceAtPoint(it,st,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);dt(it,e),null==i?s.applyImpulse(it,!0):(dt(st,i),s.applyImpulseAtPoint(it,st,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const r=ot;ut(r,o.translation());const n=r.clone().sub(t);if(n.length()>e)return;const a=n.clone().normalize().multiplyScalar(s);it.x=a.x,it.y=a.y,it.z=a.z,o.applyImpulse(it,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof N){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),n(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),n(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),n(t=>t.started),n(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),n(t=>!t.started),n(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(r())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(Y(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,s,o=ShapeCastResult.shared,r){o.reset();const n=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,n,.01,s,!0,null,r?.collisionFilter??void 0,null,c,r?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){ut(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const r=this.actorBodies.get(t.id);if(r&&r.numColliders()>0){for(let t=0;t<r.numColliders();t++){const n=r.collider(t);let a=n.shape,l=n.translation(),c=n.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,r,void 0);if(null!=u){u.collider;const t=n;return ut(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,X),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>this.world.removeRigidBody(t));try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const r=this.world.createRigidBody(o);let n=0;for(const i of e){if(n>128){console.warn("Too many collision shapes for object",t);break}if(n++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(r,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(r,t),r.userData=t.uuid,r.sleep(),r.isFixed()&&this.invalidateStaticDebug(),r}addShape(t=void 0,e,i){const s=i?.getWorldScale(bt)??et,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const r=e.offset.clone().multiply(s);dt(o.translation,r);const n=(new f).setFromEuler(e.rotation);ht(o.rotation,n),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof R)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof M){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof j){const i=null!=t.geometry.getIndex()?t.geometry:D.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof z){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=k(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,r=tt.get(o);if(void 0!==r)return r;const n=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<n.length;t+=3)n[t]*=s.x,n[t+1]*=s.y,n[t+2]*=s.z;for(let t=0;t<n.length;t+=3)n[t]*=e.x,n[t+1]*=e.y,n[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(n);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:n.length/3}),tt.set(o,a),a}if(t instanceof _){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new z(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new v(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof T?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof F?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([B(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const J=new v,$=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setTranslation(nt(i),!1),t.setRotation(at(s),!1)}const Z=new v,tt=new Map,et=new v(1,1,1),it=new i.Vector3(0,0,0),st=new i.Vector3(0,0,0),ot=new v,rt=new d.Vector2;function nt(t){return dt(it,t),it}function at(t){return ht(X,t),X}let lt=null;const ct=async()=>(null==lt&&(lt=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),lt);function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function pt(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function yt(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const gt=new v,mt=t=>!t.isSensor(),bt=new v;let ft,wt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(Q),this.world=C(L)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([A()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -37,6 +37,7 @@ export declare class AssetResourceLoader {
37
37
  private getUri;
38
38
  private _texturePromises;
39
39
  private _arrayTexturesByFileKey;
40
+ private _arrayTexturePromisesByFileKey;
40
41
  private _arrayTextureSettingsByFileKey;
41
42
  private _animationPromises;
42
43
  private _animationCache;
@@ -51,6 +52,7 @@ export declare class AssetResourceLoader {
51
52
  texture: Texture | null;
52
53
  layerIndex: number | null;
53
54
  }>;
55
+ private loadTextureArray;
54
56
  private applyTextureArraySettings;
55
57
  private _getTextureLoader;
56
58
  clearCache(asset: Asset): void;
@@ -132,5 +134,13 @@ export type GetMeshOptions = {
132
134
  * Resolver for material assets. Defaults to the global provider on the AssetResourceLoader if not provided.
133
135
  */
134
136
  materialResolver?: (materialId: AssetId) => Promise<Material>;
137
+ /**
138
+ * Whether to clone the cached scene before returning it. Set to false for read-only
139
+ * inspection (e.g. rig extraction, validation, tooltips) to avoid the expensive deep-copy
140
+ * of the full Object3D hierarchy. The returned scene must NOT be mutated or added to a
141
+ * live scene graph when clone is false.
142
+ * @default true
143
+ */
144
+ clone?: boolean;
135
145
  };
136
146
  //# sourceMappingURL=asset-resource-loader.d.ts.map
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as p}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as f,firstValueFrom as y}from"rxjs";import{BoxCollisionShape as g,CapsuleCollisionShape as w,CollisionShapeSource as x,CylinderCollisionShape as M,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as b,isCollisionMesh as _}from"./collision/collision-shape-import.js";import*as S from"three";import{iterateMaterials as L}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as v}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as R,EXRLoader as P,FBXLoader as K,GLTFLoader as I,KTX2Loader as k,TGALoader as B,UltraHDRLoader as D}from"three/examples/jsm/Addons.js";import{disposeScene as F}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as W,setAnimationClipRigId as j}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new S.DataTexture(e,1,1,S.RGBAFormat);t.needsUpdate=!0})();const U=new R;U.setDecoderConfig({type:"js"}),U.setDecoderPath("/assets/draco/");const E=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new I(this.loadingManager).setDRACOLoader(U),this.fbxLoader=new K(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new B(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new D(this.loadingManager),this.ktx2Loader=new k(this.loadingManager),this._textureLoader=new S.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new f,this.ready=y(this.makeReady),this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e),this.ktx2Loader.setWorkerLimit(6)}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return G.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?d(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(d("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=O(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(N(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=O(t,e),t.colorSpace=V(N(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};if(this._arrayTexturesByFileKey.has(t))this.applyTextureArraySettings(t,this._arrayTexturesByFileKey.get(t),e);else{const r=this._getTextureLoader(t);let a=await r.loadAsync(this.getUri(t));a instanceof o||(a=a.texture3D),this.applyTextureArraySettings(t,a,e),this._arrayTexturesByFileKey.set(t,a),this._retrievedTextures.push(a)}return{texture:this._arrayTexturesByFileKey.get(t),layerIndex:r}}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),z(e.fileKey)),null!=e.materialLib&&z(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!E.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r).scene,n=this.computeCollisionShapes(e,s);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(s);const o=p(s),l=this.cache.get(r).animations;o.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const c=new AssetMeshInstance;c.add(o),c.collisionShapes=n,c.animations=l,c.userData.assetId=e.id;const h=e.mesh?.animationRigId??e.anim?.rigId;if(c.userData.animationRigId=h,o.userData.animationRigId=h,null!=h&&null!=this.animationRigProvider){const e=await this.animationRigProvider(h);c.userData.animationRig=e,o.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&c.quaternion.copy(W(e))}const u=e.receiveShadow??!1,m=e.castShadow??!1;if(o.traverse(e=>{e.castShadow=m,e.receiveShadow=u}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&c.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(c,t,r,void 0,{textureFlipY:v(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:c,animations:l}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(j(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):b(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(e=>{e instanceof i&&e.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Z):e.material=Z(t)}(e),_(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{J.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(J);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=q;q.length=0,e.traverse(e=>{(e instanceof S.Camera||e instanceof S.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof S.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!_(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof S.SkinnedMesh||e instanceof S.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!_(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r;r=1===t.geometries.length?t.geometries[0]:C.mergeGeometries(t.geometries,!0),r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new S.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new S.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new S.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>($(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>F(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const G=new Map;function z(e){G.set(e,(G.get(e)??0)+1)}function $(e){if(e instanceof i)for(const t of L(e.material))t instanceof S.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach($)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new g((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new w(e.length*a,e.radius*a);break;case"cylinder":t=new M(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=x.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return S.ClampToEdgeWrapping;case"repeat":return S.RepeatWrapping;case"mirror":return S.MirroredRepeatWrapping}return S.RepeatWrapping}function O(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function N(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(X.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?S.LinearSRGBColorSpace:S.SRGBColorSpace}const X=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new S.Matrix4;const q=[];const J=/_LOD(\d+)/;function Z(e){let t=e instanceof S.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof S.MeshLambertMaterial||e instanceof S.MeshPhongMaterial||e instanceof S.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new S.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
1
+ import{AudioLoader as e,BufferGeometry as t,Euler as r,Group as a,LoadingManager as s,Mesh as i,Object3D as n,Texture as o,TextureLoader as l,Vector3 as c}from"three";import{MTLLoader as h,OBJLoader as u,LUTCubeLoader as m}from"three-stdlib";import{cloneMesh as p}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as f,firstValueFrom as y}from"rxjs";import{BoxCollisionShape as g,CapsuleCollisionShape as w,CollisionShapeSource as x,CylinderCollisionShape as M,SphereCollisionShape as A}from"./collision/collision-shape.js";import{importCollisionShapes as b,isCollisionMesh as _}from"./collision/collision-shape-import.js";import*as L from"three";import{iterateMaterials as S}from"../utils/materials.js";import{applyMaterial as T,getConvertedFbxToGlbAssignedMaterialTextureFlipY as v}from"./materializer.js";import{BufferGeometryUtils as C,DRACOLoader as R,EXRLoader as P,FBXLoader as K,GLTFLoader as B,KTX2Loader as I,TGALoader as k,UltraHDRLoader as D}from"three/examples/jsm/Addons.js";import{disposeScene as F}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as W,setAnimationClipRigId as j}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new L.DataTexture(e,1,1,L.RGBAFormat);t.needsUpdate=!0})();const U=new R;U.setDecoderConfig({type:"js"}),U.setDecoderPath("/assets/draco/");const E=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new B(this.loadingManager).setDRACOLoader(U),this.fbxLoader=new K(this.loadingManager),this.objLoader=new u(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.tgaLoader=new k(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new m(this.loadingManager),this.hdrLoader=new D(this.loadingManager),this.ktx2Loader=new I(this.loadingManager),this._textureLoader=new L.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new f,this.ready=y(this.makeReady),this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e),this.ktx2Loader.setWorkerLimit(6)}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return G.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?d(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(d("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=O(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=V(N(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=O(t,e),t.colorSpace=V(N(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof o||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),s=this._arrayTextureSettingsByFileKey.get(e);if(null!=s&&(n=a,(i=s).wrapS!==n.wrapS||i.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var i,n;null==s&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),z(e.fileKey)),null!=e.materialLib&&z(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new a,animations:[]};if(!E.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new a,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new a,animations:[]}}const s=this.cache.get(r),n=s.scene,o=s.animations;if(!1===t?.clone)return{scene:n,animations:o};const l=this.computeCollisionShapes(e,n);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(n);const c=p(n);c.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const h=new AssetMeshInstance;h.add(c),h.collisionShapes=l,h.animations=o,h.userData.assetId=e.id;const u=e.mesh?.animationRigId??e.anim?.rigId;if(h.userData.animationRigId=u,c.userData.animationRigId=u,null!=u&&null!=this.animationRigProvider){const e=await this.animationRigProvider(u);h.userData.animationRig=e,c.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&h.quaternion.copy(W(e))}const m=e.receiveShadow??!1,d=e.castShadow??!1;if(c.traverse(e=>{e.castShadow=d,e.receiveShadow=m}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&h.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await T(h,t,r,void 0,{textureFlipY:v(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:h,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,r=e.fileKey+"|"+t;if(this._animationCache.has(r))return this._animationCache.get(r);if(this._animationPromises.has(r))return this._animationPromises.get(r);const a=(async()=>{try{const a=await this.getMesh(e),s=a.animations.find(e=>e.name===t);return null!=s&&(j(s,e.anim?.rigId),this._animationCache.set(r,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(r),1e3)}})();return this._animationPromises.set(r,a),a}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],s=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):b(t,e);this.collisionShapeCache.set(r,s)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(r=>(r.scene.traverse(e=>{e instanceof i&&e.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(Z):e.material=Z(t)}(e),_(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(r.scene),r.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{J.test(e.name)&&(r=!0)}),!r)return t;const a=[],s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(J);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}s.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,r.scene),function(e){const t=q;q.length=0,e.traverse(e=>{(e instanceof L.Camera||e instanceof L.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(r.scene),r.scene.userData.assetId=e.id,r))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const r=[];e.traverse(e=>{e instanceof i&&!(e instanceof L.SkinnedMesh)&&e.geometry instanceof t&&Array.isArray(e.material)&&!_(e)&&r.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:a,materialArray:s,parent:n}of r){t.removeFromParent();for(let r=0;r<s.length;r++){const o=s[r],l=a.groups.filter(e=>e.materialIndex===r);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&C.mergeGroups(c);const h=new i(c,o);h.copy(t,!1),h.geometry=c,h.material=o,n?n.add(h):e.add(h)}a.dispose()}let a=!0,s=0,n=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){s++;const t=Object.keys(e.geometry.attributes).length;t!==n&&0!==n&&(a=!1),n=t}else(e instanceof L.SkinnedMesh||e instanceof L.Bone)&&(a=!1)}),s>1&&a){const r=new Map;e.traverse(a=>{if(a instanceof i&&a.geometry instanceof t&&!_(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const t=a.material?.uuid||"default";r.has(t)||r.set(t,{material:a.material,geometries:[],objects:[]});const s=r.get(t),i=e.matrixWorld.clone().invert().multiply(a.matrixWorld);s.geometries.push(a.geometry.clone().applyMatrix4(i)),s.objects.push(a)}});for(const e of r.values())for(const t of e.objects)t.removeFromParent();for(const t of r.values()){let r;r=1===t.geometries.length?t.geometries[0]:C.mergeGeometries(t.geometries,!0),r.groups.length>1&&C.mergeGroups(r),e.add(new i(r,t.material))}}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!_(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&C.mergeGroups(t)}})}extractGeometryGroups(e,r){const a=e.index;if(!a){const a=new t;let s=0;for(const e of r)s+=e.count;if(0===s)return a;for(const t in e.attributes){const i=e.attributes[t],n=i.itemSize,o=i.array,l=new(0,o.constructor)(s*n);let c=0;for(const e of r){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new L.BufferAttribute(l,n,i.normalized);a.setAttribute(t,h)}return a.groups=[{start:0,count:s,materialIndex:0}],a}const s=[];for(const e of r)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);s.push(r)}if(0===s.length)return new t;const i=new Map,n=[];let o=0;for(const e of s)i.has(e)||(i.set(e,o),o++),n.push(i.get(e));if(0===n.length||0===i.size)return new t;const l=new t;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,s=r.array,n=new(0,s.constructor)(i.size*a);for(const[e,t]of i)for(let r=0;r<a;r++)n[t*a+r]=s[e*a+r];const o=new L.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new L.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>($(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>F(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const G=new Map;function z(e){G.set(e,(G.get(e)??0)+1)}function $(e){if(e instanceof i)for(const t of S(e.material))t instanceof L.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach($)}export class AssetMeshInstance extends n{}export function createAuthoredCollisionShapes(e,t=1){const a=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new g((new c).fromArray(e.size).multiplyScalar(a));break;case"sphere":t=new A(e.radius*a);break;case"capsule":t=new w(e.length*a,e.radius*a);break;case"cylinder":t=new M(e.radius*a,e.radius*a,e.height*a,16,new r)}return t.source=x.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(a),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return L.ClampToEdgeWrapping;case"repeat":return L.RepeatWrapping;case"mirror":return L.MirroredRepeatWrapping}return L.RepeatWrapping}function O(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function N(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(X.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function V(e){return"linear"===e?L.LinearSRGBColorSpace:L.SRGBColorSpace}const X=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new L.Matrix4;const q=[];const J=/_LOD(\d+)/;function Z(e){let t=e instanceof L.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof L.MeshLambertMaterial||e instanceof L.MeshPhongMaterial||e instanceof L.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new L.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import { SceneObjectPhysicsSettings } from "../../scene/materializer.js";
1
+ import type { SceneObjectPhysicsSettings } from "../../scene/materializer.js";
2
2
  import { BufferGeometry, Euler, Material, Mesh, Vector3 } from "three";
3
3
  export declare enum CollisionShapeSource {
4
4
  /**