@hology/core 0.0.196 → 0.0.198

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 (67) hide show
  1. package/dist/effects/sequence/sequence-action.d.ts +8 -1
  2. package/dist/effects/sequence/sequence-actor.d.ts +14 -2
  3. package/dist/effects/sequence/sequence-actor.js +1 -1
  4. package/dist/effects/sequence/sequence-data.d.ts +98 -4
  5. package/dist/effects/sequence/sequence-data.js +1 -1
  6. package/dist/effects/sequence/sequence-definitions.d.ts +12 -8
  7. package/dist/effects/sequence/sequence-definitions.js +1 -1
  8. package/dist/effects/sequence/sequence-ops.js +1 -1
  9. package/dist/effects/sequence/sequence-player.d.ts +66 -2
  10. package/dist/effects/sequence/sequence-player.js +1 -1
  11. package/dist/effects/sequence/sequence-value-lane.d.ts +1 -0
  12. package/dist/effects/sequence/sequence-value-lane.js +1 -1
  13. package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +2 -0
  14. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  15. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  16. package/dist/gameplay/actors/builtin/post-process-volume-actor.js +1 -1
  17. package/dist/gameplay/index.d.ts +1 -0
  18. package/dist/gameplay/index.js +1 -1
  19. package/dist/gameplay/initiate.d.ts +1 -0
  20. package/dist/gameplay/initiate.js +1 -1
  21. package/dist/gameplay/services/camera-shake.d.ts +28 -0
  22. package/dist/gameplay/services/camera-shake.js +4 -0
  23. package/dist/gameplay/services/physics/physics-system.js +1 -1
  24. package/dist/gameplay/services/render.d.ts +47 -2
  25. package/dist/gameplay/services/render.js +1 -1
  26. package/dist/rendering/post-process-effect.d.ts +63 -0
  27. package/dist/rendering/post-process-effect.js +4 -0
  28. package/dist/rendering.d.ts +15 -1
  29. package/dist/rendering.js +1 -1
  30. package/dist/scene/asset-resource-loader.d.ts +3 -1
  31. package/dist/scene/asset-resource-loader.js +1 -1
  32. package/dist/scene/collision/collision-shape-import.js +1 -1
  33. package/dist/scene/collision/collision-shape.js +1 -1
  34. package/dist/scene/materializer.d.ts +20 -2
  35. package/dist/scene/materializer.js +1 -1
  36. package/dist/scene/scatter/surface-scatter-manager.d.ts +44 -0
  37. package/dist/scene/scatter/surface-scatter-manager.js +4 -0
  38. package/dist/scene/storage/storage.d.ts +2 -0
  39. package/dist/scene/storage/storage.js +1 -1
  40. package/dist/shader/builtin/landscape-composite-shader.js +1 -1
  41. package/dist/shader/builtin/standard-shader.d.ts +2 -0
  42. package/dist/shader/builtin/standard-shader.js +1 -1
  43. package/dist/shader/builtin/unlit-shader.d.ts +2 -1
  44. package/dist/shader/builtin/unlit-shader.js +1 -1
  45. package/dist/shader/index.d.ts +1 -0
  46. package/dist/shader/index.js +1 -1
  47. package/dist/shader/post-process-shader.d.ts +14 -0
  48. package/dist/shader/post-process-shader.js +4 -0
  49. package/dist/shader/uv-nodes.d.ts +4 -0
  50. package/dist/shader/uv-nodes.js +4 -0
  51. package/dist/shader-nodes/index.d.ts +1 -1
  52. package/dist/shader-nodes/index.js +1 -1
  53. package/dist/test/authored-collision-rescale.test.d.ts +2 -0
  54. package/dist/test/authored-collision-rescale.test.js +4 -0
  55. package/dist/test/camera-shake.test.d.ts +2 -0
  56. package/dist/test/camera-shake.test.js +4 -0
  57. package/dist/test/collision-shape-import.test.js +1 -1
  58. package/dist/test/post-process-effect.test.d.ts +2 -0
  59. package/dist/test/post-process-effect.test.js +4 -0
  60. package/dist/test/sequence-camera-control.test.d.ts +2 -0
  61. package/dist/test/sequence-camera-control.test.js +4 -0
  62. package/dist/test/sequence-property-parameters.test.d.ts +2 -0
  63. package/dist/test/sequence-property-parameters.test.js +4 -0
  64. package/dist/test/storage-case-collision.test.d.ts +2 -0
  65. package/dist/test/storage-case-collision.test.js +4 -0
  66. package/package.json +2 -2
  67. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as s}from"./actors/factory.js";import{World as n}from"./services/world.js";import{SceneMaterializer as r}from"../scene/materializer.js";import{ViewController as o}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as h}from"../scene/asset-resource-loader.js";import{AssetLoader as u}from"./services/asset-loader.js";import{polyfillClient as f}from"./polyfill.js";import{Subject as g}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as j}from"three";import{ShaderProvider as v}from"./services/shader-provider.js";import{SceneDataService as S}from"../scene/scene-data-service.js";import{AssetsProvider as x}from"../scene/assets-provider.js";export function initiateGame(g,y){if(f(),0!=y.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const I=e.of("default"),P=new HologyRuntime(I),D=new s(I,{inEditor:!1});var R;D.classes=y.actors,e.set(s,D),R=y.element,Object.assign(R.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",overflow:"hidden"});const A=new i(y.element,{enableXR:!0===y.xr?.enabled,maxPixelRatio:y.rendering?.maxPixelRatio,resolutionScale:y.rendering?.resolutionScale,msaa:y.rendering?.msaa,depthPrepass:{enabled:!0===y.rendering?.depthPrepass?.enabled},bloom:{enabled:!1!==y?.rendering?.bloom?.enabled},reflection:{enabled:!1!==y?.rendering?.reflection?.enabled},shadows:{cascadeUpdateIntervals:[22,135,250,500]}});A.renderer.shadowMap.enabled=y.rendering?.shadows?.enabled??!0,A.renderer.shadowMap.autoUpdate=y.rendering?.shadows?.autoUpdate??!0,A.renderer.debug.checkShaderErrors=!1,e.set(i,A);const E=new o(A);e.set(o,E);const G=new b,O=new p(G),z=new h;z.setDataDir(y.dataDir),z.initKtx2(A.renderer);const H=Object.entries(y.shaders).map(([e,t])=>({name:e,type:t})),M=Object.entries(y.actors).map(([e,t])=>({name:e,type:t})),T={...d,...y.components??{}},U=Object.entries(T).map(([e,t])=>({name:e,type:t})),W=new v(H);e.set(v,W);const k=new u(z,O,H);e.set(x,O),e.set(h,z),e.set(u,k);const F=new j,N=new r(F,new S,O,z,A,H,M,D,U);e.set(r,N);const _=e.get(n);return e.set(n,_),_.materializer=N,(async()=>{const s=e.get(a);if(await s.start(),P.isShutdown)return;if(await G.preloadData(),P.isShutdown)return;_.scene=F;const{scene:n,actors:r}=await t(A,y.sceneName,y.dataDir,y.shaders,y.actors,T,D,G,O,z,{detailTier:y.detailTier});_.scene=n,s.scene=_.scene;for(const e of F.children)_.scene.add(e);if(P.isShutdown)return void A.stop();e.import([c]);for(const e of r)_.addActor(e);s.addFromScene(n),console.log("Start compile shaders"),console.time("compile shaders"),await A.compileAsync(),console.timeEnd("compile shaders"),console.log("Finished compile shaders. Programs: ",A.renderer.info.programs?.length??0),console.log("Start init scene textures"),console.time("init scene textures"),A.initTextures(),console.timeEnd("init scene textures");const o=I.get(l);A.loop(e=>{o.update(e)}),P.status=5,P.shutdownStarted.subscribe(()=>{z.disposeAll()}),m.value=I,I.remove(g),I.set({id:g,type:g});const i=I.get(g);m.value=null,P.gameInstance=i,I.get(w).start(),i instanceof GameInstance&&await i.onStart(),P._resolver(!0)})(),P}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new g,this.ready=new Promise(e=>{this._resolver=e})}getWorld(){return this.containerInstance.get(n)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0;const e=this.shutdownStarted;e.next(),e.complete(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const t=this.containerInstance.get(i);t?.stop();const s=this.containerInstance.get(o);s.setMuted(!0),s.dispose();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.get(r).dispose(),this.containerInstance.get(w).stop(),this.containerInstance.reset()}}/*
1
+ import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as s}from"./actors/factory.js";import{World as n}from"./services/world.js";import{SceneMaterializer as r}from"../scene/materializer.js";import{ViewController as o}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as h}from"../scene/asset-resource-loader.js";import{AssetLoader as u}from"./services/asset-loader.js";import{polyfillClient as f}from"./polyfill.js";import{Subject as g}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as j}from"three";import{ShaderProvider as v}from"./services/shader-provider.js";import{SceneDataService as S}from"../scene/scene-data-service.js";import{AssetsProvider as x}from"../scene/assets-provider.js";export function initiateGame(g,y){if(f(),0!=y.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const I=e.of("default"),P=new HologyRuntime(I),D=new s(I,{inEditor:!1});var R;D.classes=y.actors,e.set(s,D),R=y.element,Object.assign(R.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",overflow:"hidden"});const A=new i(y.element,{enableXR:!0===y.xr?.enabled,maxPixelRatio:y.rendering?.maxPixelRatio,resolutionScale:y.rendering?.resolutionScale,msaa:y.rendering?.msaa,fpsCap:y.rendering?.fpsCap,depthPrepass:{enabled:!0===y.rendering?.depthPrepass?.enabled},bloom:{enabled:!1!==y?.rendering?.bloom?.enabled},reflection:{enabled:!1!==y?.rendering?.reflection?.enabled},shadows:{cascadeUpdateIntervals:[22,40,60,120]}});A.renderer.shadowMap.enabled=y.rendering?.shadows?.enabled??!0,A.renderer.shadowMap.autoUpdate=y.rendering?.shadows?.autoUpdate??!0,A.renderer.debug.checkShaderErrors=!1,e.set(i,A);const E=new o(A);e.set(o,E);const G=new b,O=new p(G),z=new h;z.setDataDir(y.dataDir),z.initKtx2(A.renderer);const C=Object.entries(y.shaders).map(([e,t])=>({name:e,type:t})),H=Object.entries(y.actors).map(([e,t])=>({name:e,type:t})),M={...d,...y.components??{}},T=Object.entries(M).map(([e,t])=>({name:e,type:t})),U=new v(C);e.set(v,U);const W=new u(z,O,C);e.set(x,O),e.set(h,z),e.set(u,W);const k=new j,F=new r(k,new S,O,z,A,C,H,D,T);e.set(r,F);const N=e.get(n);return e.set(n,N),N.materializer=F,(async()=>{const s=e.get(a);if(await s.start(),P.isShutdown)return;if(await G.preloadData(),P.isShutdown)return;N.scene=k;const{scene:n,actors:r}=await t(A,y.sceneName,y.dataDir,y.shaders,y.actors,M,D,G,O,z,{detailTier:y.detailTier});N.scene=n,s.scene=N.scene;for(const e of k.children)N.scene.add(e);if(P.isShutdown)return void A.stop();e.import([c]);for(const e of r)N.addActor(e);s.addFromScene(n),console.log("Start compile shaders"),console.time("compile shaders"),await A.compileAsync(),console.timeEnd("compile shaders"),console.log("Finished compile shaders. Programs: ",A.renderer.info.programs?.length??0),console.log("Start init scene textures"),console.time("init scene textures"),A.initTextures(),console.timeEnd("init scene textures");const o=I.get(l);A.loop(e=>{o.update(e)}),P.status=5,P.shutdownStarted.subscribe(()=>{z.disposeAll()}),m.value=I,I.remove(g),I.set({id:g,type:g});const i=I.get(g);m.value=null,P.gameInstance=i,I.get(w).start(),i instanceof GameInstance&&await i.onStart(),P._resolver(!0)})(),P}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new g,this.ready=new Promise(e=>{this._resolver=e})}getWorld(){return this.containerInstance.get(n)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0;const e=this.shutdownStarted;e.next(),e.complete(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const t=this.containerInstance.get(i);t?.stop();const s=this.containerInstance.get(o);s.setMuted(!0),s.dispose();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.get(r).dispose(),this.containerInstance.get(w).stop(),this.containerInstance.reset()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,28 @@
1
+ export type CameraShakeVector3 = [number, number, number];
2
+ export interface CameraShakeSettings {
3
+ /** Fade-in duration in seconds. */
4
+ attack?: number;
5
+ /** Fade-out duration in seconds. */
6
+ decay?: number;
7
+ /** Noise sampling frequency in Hz. */
8
+ frequency?: number;
9
+ /** Local-space positional amplitude in scene units. */
10
+ positionAmplitude?: CameraShakeVector3;
11
+ /** Local-space rotational amplitude in radians. */
12
+ rotationAmplitude?: CameraShakeVector3;
13
+ /** Optional deterministic seed. */
14
+ seed?: number;
15
+ }
16
+ export interface CameraShakeRequest extends CameraShakeSettings {
17
+ /** Total duration in seconds. */
18
+ duration: number;
19
+ }
20
+ export interface CameraShakeSample {
21
+ position: CameraShakeVector3;
22
+ rotation: CameraShakeVector3;
23
+ }
24
+ export declare function createCameraShakeSample(): CameraShakeSample;
25
+ export declare function resetCameraShakeSample(target: CameraShakeSample): CameraShakeSample;
26
+ export declare function sampleCameraShake(request: Readonly<CameraShakeRequest>, elapsedTime: number, target?: CameraShakeSample, seedOverride?: number): CameraShakeSample | null;
27
+ export declare function hashCameraShakeSeed(value: string | number): number;
28
+ //# sourceMappingURL=camera-shake.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function createCameraShakeSample(){return{position:[0,0,0],rotation:[0,0,0]}}export function resetCameraShakeSample(t){return t.position[0]=0,t.position[1]=0,t.position[2]=0,t.rotation[0]=0,t.rotation[1]=0,t.rotation[2]=0,t}export function sampleCameraShake(e,i,u=createCameraShakeSample(),m){resetCameraShakeSample(u);const c=Math.max(0,e.duration??0);if(c<=0||i<0||i>c)return null;const h=function(t,e,n){const r=Math.max(0,t.attack??0),o=Math.max(0,t.decay??0),i=r>0?a(e/r):1,u=o>0?a((n-e)/o):1;return Math.min(i,u)}(e,i,c);if(h<=0)return u;const s=Math.max(0,e.frequency??r),l=m??e.seed??0,f=e.positionAmplitude??o,p=e.rotationAmplitude??o;for(let e=0;e<3;e++){const a=t(i*s,n(l,e));u.position[e]=f[e]*h*a,u.rotation[e]=p[e]*h*a}return u}export function hashCameraShakeSeed(t){if("number"==typeof t&&Number.isFinite(t))return 0|t;let e=0;const n=String(t);for(let t=0;t<n.length;t++)e=Math.imul(e^n.charCodeAt(t),16777619);return 0|e}function t(t,n){const r=Math.floor(t),o=r+1,i=function(t){const e=a(t);return e*e*(3-2*e)}(t-r),u=e(r,n);return u+(e(o,n)-u)*i}function e(t,e){let n=Math.imul(t^e,73244475);return n^=n>>>16,n=Math.imul(n,73244475),n^=n>>>16,(n>>>0)/4294967295*2-1}function n(t,e){return Math.imul(hashCameraShakeSeed(t),31+17*e)^2654435769*e}function a(t){return Math.min(1,Math.max(0,t))}const r=24,o=[0,0,0];/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,Object3D as f,Quaternion as w,Raycaster as x,Scene as b,Vector3 as B}from"three";import{Service as v}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as A,CapsuleCollisionShape as S,ConeCollisionShape as R,ConvexPolyhedronCollisionShape as D,CylinderCollisionShape as z,PhysicalShapeMesh as T,PlaneCollisionShape as E,SphereCollisionShape as M,toInstancedCollisionShape as P,TrimeshCollisionShape as F}from"../../../index.js";import{LandscapeGroup as I}from"../../../scene/landscape/landscape.js";import{ViewController as V}from"../render.js";import{World as _}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as j}from"../../../utils/three/traverse.js";import{AbstractPhysicsSystem as N}from"./abstract-physics-system.js";import{ActorComponent as W,Component as L}from"../../../gameplay/actors/component.js";import{inject as O}from"../../../gameplay/inject.js";export{Component,ActorComponent,attach,Attach}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new B,K=new B,U=new w,q=new w,H=(new w,[]);let Q=class extends N{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=O(V),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new i.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,s){const o=t+1e6*e+1e12*s;let n=this.shapeCacheBox.get(o);return null==n&&(n=new i.Cuboid(t,e,s),this.shapeCacheBox.set(o,n)),n}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,U,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,U,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(n instanceof i||null==i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,U)&&o.push(n)}return o}createDebugMesh(){return new g(new y,new d.LineBasicMaterial({color:255}))}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene?.add(this.debugMesh));const t=this.world.debugRender().vertices,e=this.debugMesh.geometry,i=e.getAttribute("position");null==i||(i.array.length,t.length);{const i=new u(t,3);i.setUsage(d.DynamicDrawUsage),e.setAttribute("position",i)}e.setDrawRange(0,t.length/3)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await at(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach(t=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;null!=e&&e.parent instanceof b&&(dt(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&ht(e.quaternion,t.rotation()),e.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t)})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})})}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ot,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,n=this._raytestDirection;if(o.subVectors(e,t),n.copy(o).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),i;lt(ft.origin,t),lt(ft.dir,n);const r=o.length(),a=this.world.castRayAndGetNormal(ft,r,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?t=>!t.isSensor():void 0);if(i.hasHit=null!=a,i.hasHit){const e=ft.pointAt(a.timeOfImpact);if(i._internal=a,dt(i.hitNormal,a.normal),dt(i.hitPoint,e),i.distance=yt.subVectors(i.hitPoint,t).length(),!1!==s?.resolveActor){const t=this.world.bodies.getAll().find(t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,t=>t===a.collider));i.actor=null!=t?this.bodyActors.get(t):null}}if(this.showDebug){let e;H.length>0?(e=H.pop(),e.setDirection(n),e.position.copy(t),e.setLength(r,.2,.1),e.setColor(s?.debugColor??255)):e=new h(n,t,r,s?.debugColor??255),this.scene?.add(e),setTimeout(()=>{this.scene?.remove(e),H.push(e)},s?.debugLifetime??200)}return i}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ut(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof T&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof I?this.addLandscapeGroup(t):(t instanceof p||t instanceof b)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map;for(let o=0;o<e.length;o++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[o])continue;let e=t.userData.collisionShapes?.[o];if(null==e&&t.parent instanceof C&&(e=t.parent.collisionShapes),null==e)continue;let n=s.get(e);null==n&&(n=this.instancedShapeReset(e),s.set(e,n));const r=new f;r.matrix.identity(),t.getMatrixAt(o,i),r.applyMatrix4(i);this.createStaticBody(r,n)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new f;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>P(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,gt);const a=e.computedMovement();return dt(pt,a),pt}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world);return this.colliders.set(i.handle,s),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const s=(()=>{switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return i.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return i.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyDesc.kinematicVelocityBased();default:return i.RigidBodyDesc.dynamic()}})();e.position&&s.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&s.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&s.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&s.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&s.setGravityScale(e.gravityScale),"number"==typeof e.mass&&s.setAdditionalMass(e.mass),void 0!==e.userData&&(s.userData=e.userData);const o=this.world.createRigidBody(s);return new PhysicsBody(o,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,gt);const r=e.computedMovement();return dt(pt,r),pt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setNextKinematicTranslation(nt(i)),t.setNextKinematicRotation(rt(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setAngvel(et,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setLinvel(et,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(nt(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&dt(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(rt(e),!1)}getRotation(t,e=new w){const i=this.actorBodies.get(t.id);i&&ht(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),s=n.scale,r=n.geometry.getAttribute("hole"),a=new Float32Array(t.getAttribute("position").array);for(let t=0;t<a.length;t+=3)a[t]*=s.x,a[t+1]*=s.y,a[t+2]*=s.z;const l=t.index;for(let t=0;t<l.count;t+=3){const e=r.getX(l.getX(t)),i=r.getX(l.getY(t)),s=r.getX(l.getZ(t));(e>.5||i>.5||s>.5)&&(l.setX(t,0),l.setY(t,0),l.setZ(t,0))}const c=i.ColliderDesc.trimesh(a,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(c,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new i.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e)}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let n;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:n=i.RigidBodyDesc.dynamic(),n.mass=s.mass??1;break;case PhysicsBodyType.kinematic:n=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:n=i.RigidBodyDesc.kinematicVelocityBased();break;default:n=s.isTrigger?i.RigidBodyDesc.kinematicVelocityBased():i.RigidBodyDesc.fixed()}const r=this.world.createRigidBody(n);r.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(r,t,o);return ut(r,t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.density&&t.setDensity(s.density),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)}),Y(r,o),!0===s.ignoreForNavMesh&&(r.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,r),this.bodyActors.set(r,t),new PhysicsBody(r,this.world)}applyTorque(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addTorque(et,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyTorqueImpulse(et,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addForce(et,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyImpulse(et,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s?.addForce(et,!0):(lt(it,i),s?.addForceAtPoint(et,it,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s.applyImpulse(et,!0):(lt(it,i),s.applyImpulseAtPoint(et,it,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=st;dt(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);et.x=a.x,et.y=a.y,et.z=a.z,o.applyImpulse(et,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof I){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&Y(e,t.object)}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t}sphereCast(t,e,i,s,o=ShapeCastResult.shared,n){o.reset();const r=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=n?.excludeActor?this.actorBodies.get(n.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,r,.01,s,!0,null,n?.collisionFilter??void 0,null,c,n?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){dt(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return dt(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){this.world?.bodies.forEach(t=>this.world.removeRigidBody(t)),this.world?.free(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),H.length=0}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.sleep(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(mt)??tt,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);lt(o.translation,n);const r=(new w).setFromEuler(e.rotation);ct(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof A)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof S){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof F){const i=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof D){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=j(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=J.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),J.set(o,a),a}if(t instanceof M){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new D(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new B(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof R?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([v(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const $=new B,X=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setTranslation(nt(i),!1),t.setRotation(rt(s),!1)}const Z=new B,J=new Map,tt=new B(1,1,1),et=new i.Vector3(0,0,0),it=new i.Vector3(0,0,0),st=new B,ot=new d.Vector2;function nt(t){return lt(et,t),et}function rt(t){return ct(q,t),q}const at=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const yt=new B,pt=new B,gt=t=>!t.isSensor(),mt=new B;const ft=new i.Ray(new i.Vector3(0,0,0),new i.Vector3(0,1,0));let wt=class extends W{constructor(){super(...arguments),this._active=!0,this.physics=O(Q),this.world=O(_)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([L()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e){this.collider=t,this.world=e,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t)}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e){this.body=t,this.world=e}dispose(){this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t)}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0)}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0)}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static)}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,Object3D as f,Quaternion as w,Raycaster as x,Scene as b,Vector3 as B}from"three";import{Service as v}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as A,CapsuleCollisionShape as S,ConeCollisionShape as R,ConvexPolyhedronCollisionShape as D,CylinderCollisionShape as z,PhysicalShapeMesh as T,PlaneCollisionShape as E,SphereCollisionShape as M,toInstancedCollisionShape as P,TrimeshCollisionShape as F}from"../../../index.js";import{LandscapeGroup as I}from"../../../scene/landscape/landscape.js";import{ViewController as V}from"../render.js";import{World as _}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as j}from"../../../utils/three/traverse.js";import{AbstractPhysicsSystem as N}from"./abstract-physics-system.js";import{ActorComponent as W,Component as L}from"../../../gameplay/actors/component.js";import{inject as O}from"../../../gameplay/inject.js";export{Component,ActorComponent,attach,Attach}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new B,K=new B,U=new w,q=new w,H=(new w,[]);let Q=class extends N{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=O(V),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new i.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,s){const o=t+1e6*e+1e12*s;let n=this.shapeCacheBox.get(o);return null==n&&(n=new i.Cuboid(t,e,s),this.shapeCacheBox.set(o,n)),n}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,U,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,U,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(n instanceof i||null==i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,U)&&o.push(n)}return o}createDebugMesh(){return new g(new y,new d.LineBasicMaterial({color:255}))}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene?.add(this.debugMesh));const t=this.world.debugRender().vertices,e=this.debugMesh.geometry,i=e.getAttribute("position");null==i||(i.array.length,t.length);{const i=new u(t,3);i.setUsage(d.DynamicDrawUsage),e.setAttribute("position",i)}e.setDrawRange(0,t.length/3)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await at(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach(t=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;null!=e&&e.parent instanceof b&&(dt(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&ht(e.quaternion,t.rotation()),e.matrixWorldNeedsUpdate=!0)}),this.afterStep.next(t)})}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})})}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ot,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult);const o=this._raytestDiff,n=this._raytestDirection;if(o.subVectors(e,t),n.copy(o).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),i;lt(ft.origin,t),lt(ft.dir,n);const r=o.length(),a=this.world.castRayAndGetNormal(ft,r,!1,void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0,s?.excludeTriggers?t=>!t.isSensor():void 0);if(i.hasHit=null!=a,i.hasHit){const e=ft.pointAt(a.timeOfImpact);if(i._internal=a,dt(i.hitNormal,a.normal),dt(i.hitPoint,e),i.distance=yt.subVectors(i.hitPoint,t).length(),!1!==s?.resolveActor){const t=this.world.bodies.getAll().find(t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,t=>t===a.collider));i.actor=null!=t?this.bodyActors.get(t):null}}if(this.showDebug){let e;H.length>0?(e=H.pop(),e.setDirection(n),e.position.copy(t),e.setLength(r,.2,.1),e.setColor(s?.debugColor??255)):e=new h(n,t,r,s?.debugColor??255),this.scene?.add(e),setTimeout(()=>{this.scene?.remove(e),H.push(e)},s?.debugLifetime??200)}return i}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ut(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof T&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}}else t instanceof I?this.addLandscapeGroup(t):(t instanceof p||t instanceof b)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map;for(let o=0;o<e.length;o++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[o])continue;const e=t.userData.collisionShapes;let n=e?.[o];if(null==n&&null==e&&t.parent instanceof C&&(n=t.parent.collisionShapes),null==n)continue;let r=s.get(n);null==r&&(r=this.instancedShapeReset(n),s.set(n,r));const a=new f;a.matrix.identity(),t.getMatrixAt(o,i),a.applyMatrix4(i);this.createStaticBody(a,r)}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new f;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);this.createStaticBody(o,s)}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>P(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,o=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,o,gt);const a=e.computedMovement();return dt(pt,a),pt}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world);return this.colliders.set(i.handle,s),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const s=(()=>{switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return i.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return i.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyDesc.kinematicVelocityBased();default:return i.RigidBodyDesc.dynamic()}})();e.position&&s.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&s.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&s.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&s.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&s.setGravityScale(e.gravityScale),"number"==typeof e.mass&&s.setAdditionalMass(e.mass),void 0!==e.userData&&(s.userData=e.userData);const o=this.world.createRigidBody(s);return new PhysicsBody(o,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,gt);const r=e.computedMovement();return dt(pt,r),pt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setNextKinematicTranslation(nt(i)),t.setNextKinematicRotation(rt(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setAngvel(et,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.setLinvel(et,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(nt(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&dt(e,i.translation())}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(rt(e),!1)}getRotation(t,e=new w){const i=this.actorBodies.get(t.id);i&&ht(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),s=n.scale,r=n.geometry.getAttribute("hole"),a=new Float32Array(t.getAttribute("position").array);for(let t=0;t<a.length;t+=3)a[t]*=s.x,a[t+1]*=s.y,a[t+2]*=s.z;const l=t.index;for(let t=0;t<l.count;t+=3){const e=r.getX(l.getX(t)),i=r.getX(l.getY(t)),s=r.getX(l.getZ(t));(e>.5||i>.5||s>.5)&&(l.setX(t,0),l.setY(t,0),l.setZ(t,0))}const c=i.ColliderDesc.trimesh(a,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(c,t),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new i.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(i.RigidBodyDesc.fixed()),e=new i.Vector3(0,0,0);lt(e,o),t.setTranslation(e,!1),this.world.createCollider(h,t),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e)}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let n;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:n=i.RigidBodyDesc.dynamic(),n.mass=s.mass??1;break;case PhysicsBodyType.kinematic:n=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:n=i.RigidBodyDesc.kinematicVelocityBased();break;default:n=s.isTrigger?i.RigidBodyDesc.kinematicVelocityBased():i.RigidBodyDesc.fixed()}const r=this.world.createRigidBody(n);r.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(r,t,o);return ut(r,t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.density&&t.setDensity(s.density),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)}),Y(r,o),!0===s.ignoreForNavMesh&&(r.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,r),this.bodyActors.set(r,t),new PhysicsBody(r,this.world)}applyTorque(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addTorque(et,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyTorqueImpulse(et,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.addForce(et,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);et.x=e.x,et.y=e.y,et.z=e.z,i?.applyImpulse(et,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s?.addForce(et,!0):(lt(it,i),s?.addForceAtPoint(et,it,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);lt(et,e),null==i?s.applyImpulse(et,!0):(lt(it,i),s.applyImpulseAtPoint(et,it,!0))}applyRadiusImpulse(t,e,s){this.world.bodies.forEach(o=>{if(o.collider(0)?.isSensor())return;if(o.bodyType()!==i.RigidBodyType.Dynamic)return;const n=st;dt(n,o.translation());const r=n.clone().sub(t);if(r.length()>e)return;const a=r.clone().normalize().multiplyScalar(s);et.x=a.x,et.y=a.y,et.z=a.z,o.applyImpulse(et,!0)})}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.staticBodies.delete(t),this.world.removeRigidBody(i))}removeSceneObject(t){if(t instanceof I){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&Y(e,t.object)}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t}sphereCast(t,e,i,s,o=ShapeCastResult.shared,n){o.reset();const r=this.getBallShape(e);this.shapeCacheBall.get;const a={x:t.x,y:t.y,z:t.z},l={x:i.x,y:i.y,z:i.z},c=n?.excludeActor?this.actorBodies.get(n.excludeActor.id):null,d=this.world.castShape(a,{x:0,y:0,z:0,w:1},l,r,.01,s,!0,null,n?.collisionFilter??void 0,null,c,n?.excludeTriggers?t=>!t.isSensor():void 0);if(null!=d){dt(o.hitPoint,d.witness1),o.normal.set(d.normal1.x,d.normal1.y,d.normal1.z),o.distance=d.time_of_impact,o.hasHit=!0;const t=d.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(o.actor=e)}}return o}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return dt(s.hitPoint,u.witness1),xt(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){this.world?.bodies.forEach(t=>this.world.removeRigidBody(t)),this.world?.free(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),H.length=0}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed();o.setSleeping(!0);const n=this.world.createRigidBody(o);let r=0;for(const i of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==i){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,i,t);null!=o&&(null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution))}return Y(n,t),n.userData=t.uuid,n.sleep(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(mt)??tt,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);lt(o.translation,n);const r=(new w).setFromEuler(e.rotation);ct(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{return this.world.createCollider(o,t)}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof A)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof S){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof F){const i=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry),s=extractFloat32Array(i.getAttribute("position"));for(let t=0;t<s.length;t+=3)s[t]*=e.x,s[t+1]*=e.y,s[t+2]*=e.z;const o=i.getIndex();return null==o?(console.error("Trimesh collision shape is missing an index buffer.",t),null):this.rapier.ColliderDesc.trimesh(s,new Uint32Array(o.array))}if(t instanceof D){let i,s;t.mesh instanceof d.Mesh?i=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t}),t.mesh instanceof d.Mesh&&(s=j(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=J.get(o);if(void 0!==n)return n;const r=extractFloat32Array(i.getAttribute("position"));if(null!=s)for(let t=0;t<r.length;t+=3)r[t]*=s.x,r[t+1]*=s.y,r[t+2]*=s.z;for(let t=0;t<r.length;t+=3)r[t]*=e.x,r[t+1]*=e.y,r[t+2]*=e.z;const a=this.rapier.ColliderDesc.convexHull(r);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:r.length/3}),J.set(o,a),a}if(t instanceof M){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new D(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new B(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof R?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([v(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const $=new B,X=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition($),s=e.getWorldQuaternion(X);t.setTranslation(nt(i),!1),t.setRotation(rt(s),!1)}const Z=new B,J=new Map,tt=new B(1,1,1),et=new i.Vector3(0,0,0),it=new i.Vector3(0,0,0),st=new B,ot=new d.Vector2;function nt(t){return lt(et,t),et}function rt(t){return ct(q,t),q}const at=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function dt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ht(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function ut(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const yt=new B,pt=new B,gt=t=>!t.isSensor(),mt=new B;const ft=new i.Ray(new i.Vector3(0,0,0),new i.Vector3(0,1,0));let wt=class extends W{constructor(){super(...arguments),this._active=!0,this.physics=O(Q),this.world=O(_)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};wt=t([L()],wt);export function extractFloat32Array(t){const e=t.itemSize,i=t.count,s=new Float32Array(i*e);for(let o=0;o<i;o++)for(let i=0;i<e;i++)s[o*e+i]=t.getComponent(o,i);return s}function xt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e){this.collider=t,this.world=e,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t)}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e){this.body=t,this.world=e}dispose(){this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t)}isEnabled(){return this.body.isEnabled()}getPosition(t){const e=this.body.translation();return t.set(e.x,e.y,e.z),t}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0)}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0)}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static)}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -5,6 +5,19 @@ import * as THREE from "three";
5
5
  import type { CameraActor } from '../../gameplay/actors/builtin/camera-actor.js';
6
6
  import { BaseActor } from '../../gameplay/actors/actor.js';
7
7
  import { PostProcessVolume } from "@hology/core";
8
+ import type { PostProcessEffect, PostProcessEffectOptions } from '../../rendering/post-process-effect.js';
9
+ import type { PostProcessMaterialSource } from "../../shader/post-process-shader.js";
10
+ import { type CameraShakeRequest } from "./camera-shake.js";
11
+ export type { CameraShakeRequest, CameraShakeSample, CameraShakeSettings, CameraShakeVector3, } from "./camera-shake.js";
12
+ export type { PostProcessEffect, PostProcessEffectOptions, PostProcessEffectStage, } from '../../rendering/post-process-effect.js';
13
+ export { defaultPostProcessEffectStage, postProcessEffectStages, } from '../../rendering/post-process-effect.js';
14
+ export type { PostProcessMaterialSource } from "../../shader/post-process-shader.js";
15
+ export interface CameraOverrideHandle {
16
+ release(): void;
17
+ }
18
+ export interface CameraShakeHandle {
19
+ release(): void;
20
+ }
8
21
  export declare class ViewController {
9
22
  private view;
10
23
  private readonly tick;
@@ -16,6 +29,16 @@ export declare class ViewController {
16
29
  private _timeScale;
17
30
  private _hitStopRemaining;
18
31
  private scheduler;
32
+ private baseCamera;
33
+ private sourceCamera;
34
+ private cameraOverrideId;
35
+ private cameraOverrides;
36
+ private cameraShakeId;
37
+ private gameplayCameraShakes;
38
+ private cameraShakeContributions;
39
+ private presentationCamera;
40
+ private readonly accumulatedCameraShakeSample;
41
+ private readonly scratchCameraShakeSample;
19
42
  constructor(view: RenderingView);
20
43
  private handleFrame;
21
44
  set timeScale(value: number);
@@ -27,16 +50,38 @@ export declare class ViewController {
27
50
  * @param durationMs Duration of the pause in milliseconds
28
51
  */
29
52
  applyHitStop(durationMs: number): void;
30
- set fpsCap(fps: number);
31
- get fpsCap(): number;
53
+ set fpsCap(fps: number | null | undefined);
54
+ get fpsCap(): number | null;
32
55
  set showStats(value: boolean);
33
56
  get showStats(): boolean;
34
57
  addPostProcessVolume(volume: PostProcessVolume): void;
35
58
  removePostProcessVolume(volume: PostProcessVolume): void;
59
+ addPostProcessEffect(source: PostProcessMaterialSource, options?: PostProcessEffectOptions): PostProcessEffect;
36
60
  onUpdate(actor?: BaseActor): Observable<number>;
37
61
  onLateUpdate(actor?: BaseActor): Observable<number>;
38
62
  setCamera(camera: Camera | CameraActor): void;
39
63
  getCamera(): Camera;
64
+ getSourceCamera(): Camera;
65
+ getBaseCamera(): Camera;
66
+ applyCameraShake(request: CameraShakeRequest): CameraShakeHandle;
67
+ setCameraShakeContribution(owner: object, key: string, request: CameraShakeRequest, elapsedTime: number, seedOverride?: number): void;
68
+ removeCameraShakeContribution(owner: object, key: string): void;
69
+ clearCameraShakeContributionsForOwner(owner: object): void;
70
+ pushCameraOverride(camera: Camera, owner: object, priority?: number): CameraOverrideHandle;
71
+ releaseCameraOverridesForOwner(owner: object): void;
72
+ private releaseCameraOverrideEntry;
73
+ private applyTopCameraOverride;
74
+ private getTopCameraOverride;
75
+ private applyRenderedCamera;
76
+ private releaseGameplayCameraShake;
77
+ private advanceGameplayCameraShakes;
78
+ private refreshCameraPresentation;
79
+ private hasActiveCameraShake;
80
+ private ensurePresentationCamera;
81
+ private copyCameraState;
82
+ private accumulateCameraShakeSamples;
83
+ private accumulateCameraShakeEntry;
84
+ private applyCameraShakeSample;
40
85
  setMuted(muted: boolean): void;
41
86
  getMuted(): boolean;
42
87
  private outlined;
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Service as i}from"typedi";import{Camera as s}from"three";import{RenderingView as n}from"../../rendering.js";import{BehaviorSubject as h,Subject as r,takeUntil as a}from"rxjs";import*as o from"three";import{GameTimeScheduler as l}from"./game-time-scheduler.js";let u=class{constructor(e){this.view=e,this.tick=new r,this.lateTick=new r,this.audioListener=new o.AudioListener,this.pausedChanged=new h(!1),this.mutedChanged=new h(!1),this._muted=!1,this._timeScale=1,this._hitStopRemaining=0,this.scheduler=new l,this.outlined=[],e.onLoop(e=>{this.handleFrame(e)}),e.camera.add(this.audioListener),window.hology_view=this}handleFrame(e){let t=this._timeScale,i=0;this._hitStopRemaining>0?(this._hitStopRemaining-=1e3*e,this._hitStopRemaining<=0&&(this._hitStopRemaining=0),t=0):i=e*this._timeScale,this.tick.next(i),this.scheduler.update(1e3*i),this.lateTick.next(i),this.view.simulationTimeScale=t}set timeScale(e){this._timeScale=Math.max(0,e)}get timeScale(){return this._timeScale}applyHitStop(e){this._hitStopRemaining=Math.max(this._hitStopRemaining,e)}set fpsCap(e){this.view.fpsCap=e}get fpsCap(){return this.view.fpsCap}set showStats(e){this.view.showStats=e}get showStats(){return this.view.showStats}setLightVolume(e){this.view.lightVolume=e}getLightVolume(){return this.view.lightVolume}addPostProcessVolume(e){this.view.addPostProcessVolume(e)}removePostProcessVolume(e){this.view.removePostProcessVolume(e)}onUpdate(e){return null!=e&&this.tick.pipe(a(e.disposed)),this.tick}onLateUpdate(e){return null!=e&&this.lateTick.pipe(a(e.disposed)),this.lateTick}setCamera(e){const t=e instanceof s?e:e.camera.instance;this.view.setCamera(t),t.add(this.audioListener)}getCamera(){return this.view.camera}setMuted(e){this._muted=e,this.audioListener.gain.gain.setValueAtTime(e?0:1,this.audioListener.context.currentTime),this.mutedChanged.next(e)}getMuted(){return this._muted}setOutlined(e){this.outlined.length=0;const t=this.outlined;for(let i=0;i<e.length;i++)t[i]=e[i];this.view.setSelectedObjects(t),this.view.setEnableOutlines(e.length>0)}getOutlined(){return this.outlined}addOutlined(e){this.outlined.includes(e)||(this.outlined.push(e),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(!0))}removeOutlined(e){const t=this.outlined.indexOf(e);-1!==t&&(this.outlined.splice(t,1),this.view.setSelectedObjects(this.outlined))}setOutlineColor(e){this.view.outlinePass?.visibleEdgeColor.copy(e)}getOutlineColor(){return this.view.outlinePass?.visibleEdgeColor}setOutlineThickness(e){this.view.outlinePass.edgeThickness=e}getOutlineThickness(){return this.view.outlinePass.edgeThickness}get htmlElement(){return this.view.container}get paused(){return this.view.paused}set paused(e){e!=this.paused&&(e?this.pauseRendering():this.unpauseRendering())}pauseRendering(){this.view.paused=!0,this.pausedChanged.next(this.view.paused),this.scheduler.pause()}unpauseRendering(){this.view.paused=!1,this.pausedChanged.next(this.view.paused),this.scheduler.resume()}setInterval(e,t,i){return this.scheduler.setInterval(e,t,i)}clearInterval(e){this.scheduler.clearInterval(e)}dispose(){this.view.running&&this.view.stop(),this.scheduler.dispose(),this.audioListener.removeFromParent(),this.tick.complete(),this.lateTick.complete(),this.paused=!0}createTimer(e){return this.scheduler.createTimer(e)}getScreenPosition(e,t=m){const i=this.getCamera();return d.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),i instanceof o.PerspectiveCamera&&(c.setFromProjectionMatrix(d),!c.containsPoint(e))?null:(t.copy(e),t.project(i),t.x=(t.x+1)/2*this.htmlElement.clientWidth,t.y=(1-t.y)/2*this.htmlElement.clientHeight,t)}};u=e([i(),t("design:paramtypes",[n])],u);export{u as ViewController};const d=new o.Matrix4,m=new o.Vector3,c=new o.Frustum;/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Service as a}from"typedi";import{Camera as i}from"three";import{RenderingView as s}from"../../rendering.js";import{BehaviorSubject as r,Subject as n,takeUntil as o}from"rxjs";import*as h from"three";import{GameTimeScheduler as m}from"./game-time-scheduler.js";import{createCameraShakeSample as l,resetCameraShakeSample as u,sampleCameraShake as c}from"./camera-shake.js";export{defaultPostProcessEffectStage,postProcessEffectStages}from"../../rendering/post-process-effect.js";let d=class{constructor(e){this.view=e,this.tick=new n,this.lateTick=new n,this.audioListener=new h.AudioListener,this.pausedChanged=new r(!1),this.mutedChanged=new r(!1),this._muted=!1,this._timeScale=1,this._hitStopRemaining=0,this.scheduler=new m,this.cameraOverrideId=0,this.cameraOverrides=[],this.cameraShakeId=0,this.gameplayCameraShakes=[],this.cameraShakeContributions=new Map,this.presentationCamera=null,this.accumulatedCameraShakeSample=l(),this.scratchCameraShakeSample=l(),this.outlined=[],this.baseCamera=e.camera,this.sourceCamera=e.camera,e.onLoop(e=>{this.handleFrame(e)}),e.camera.add(this.audioListener),window.hology_view=this}handleFrame(e){let t=this._timeScale,a=0;this._hitStopRemaining>0?(this._hitStopRemaining-=1e3*e,this._hitStopRemaining<=0&&(this._hitStopRemaining=0),t=0):a=e*this._timeScale,this.advanceGameplayCameraShakes(a),this.tick.next(a),this.scheduler.update(1e3*a),this.lateTick.next(a),this.view.simulationTimeScale=t,this.refreshCameraPresentation()}set timeScale(e){this._timeScale=Math.max(0,e)}get timeScale(){return this._timeScale}applyHitStop(e){this._hitStopRemaining=Math.max(this._hitStopRemaining,e)}set fpsCap(e){this.view.fpsCap=e}get fpsCap(){return this.view.fpsCap}set showStats(e){this.view.showStats=e}get showStats(){return this.view.showStats}setLightVolume(e){this.view.lightVolume=e}getLightVolume(){return this.view.lightVolume}addPostProcessVolume(e){this.view.addPostProcessVolume(e)}removePostProcessVolume(e){this.view.removePostProcessVolume(e)}addPostProcessEffect(e,t){return this.view.addPostProcessEffect(e,t)}onUpdate(e){return null!=e&&this.tick.pipe(o(e.disposed)),this.tick}onLateUpdate(e){return null!=e&&this.lateTick.pipe(o(e.disposed)),this.lateTick}setCamera(e){const t=e instanceof i?e:e.camera.instance;this.baseCamera=t,0===this.cameraOverrides.length&&(this.sourceCamera=t,this.refreshCameraPresentation())}getCamera(){return this.view.camera}getSourceCamera(){return this.sourceCamera}getBaseCamera(){return this.baseCamera}applyCameraShake(e){const t=function(e){return{duration:Math.max(0,e.duration??0),attack:e.attack??0,decay:e.decay??0,frequency:e.frequency??24,positionAmplitude:e.positionAmplitude?[...e.positionAmplitude]:[0,0,0],rotationAmplitude:e.rotationAmplitude?[...e.rotationAmplitude]:[0,0,0],seed:e.seed}}(e);if(t.duration<=0)return{release:()=>{}};const a={id:++this.cameraShakeId,request:t,elapsedTime:0,seedOverride:t.seed};this.gameplayCameraShakes.push(a),this.refreshCameraPresentation();let i=!1;return{release:()=>{i||(i=!0,this.releaseGameplayCameraShake(a.id))}}}setCameraShakeContribution(e,t,a,i,s){if(a.duration<=0)return void this.removeCameraShakeContribution(e,t);let r=this.cameraShakeContributions.get(e);r||(r=new Map,this.cameraShakeContributions.set(e,r));const n=r.get(t);n?(n.request=a,n.elapsedTime=Math.max(0,i),n.seedOverride=s):r.set(t,{key:t,request:a,elapsedTime:Math.max(0,i),seedOverride:s}),this.refreshCameraPresentation()}removeCameraShakeContribution(e,t){const a=this.cameraShakeContributions.get(e);a?.delete(t)&&(0===a.size&&this.cameraShakeContributions.delete(e),this.refreshCameraPresentation())}clearCameraShakeContributionsForOwner(e){this.cameraShakeContributions.delete(e)&&this.refreshCameraPresentation()}pushCameraOverride(e,t,a=0){const i={id:++this.cameraOverrideId,camera:e,owner:t,priority:a};this.cameraOverrides.push(i),this.applyTopCameraOverride();let s=!1;return{release:()=>{s||(s=!0,this.releaseCameraOverrideEntry(i))}}}releaseCameraOverridesForOwner(e){const t=this.cameraOverrides.filter(t=>t.owner!==e);t.length!==this.cameraOverrides.length&&(this.cameraOverrides=t,this.applyTopCameraOverride())}releaseCameraOverrideEntry(e){const t=this.cameraOverrides.indexOf(e);-1!==t&&(this.cameraOverrides.splice(t,1),this.applyTopCameraOverride())}applyTopCameraOverride(){const e=this.getTopCameraOverride();this.sourceCamera=e?.camera??this.baseCamera,this.refreshCameraPresentation()}getTopCameraOverride(){let e;for(const t of this.cameraOverrides)(!e||t.priority>e.priority||t.priority===e.priority&&t.id>e.id)&&(e=t);return e}applyRenderedCamera(e){this.view.camera!==e&&this.view.setCamera(e),e.add(this.audioListener)}releaseGameplayCameraShake(e){const t=this.gameplayCameraShakes.findIndex(t=>t.id===e);-1!==t&&(this.gameplayCameraShakes.splice(t,1),this.refreshCameraPresentation())}advanceGameplayCameraShakes(e){if(!(e<=0||0===this.gameplayCameraShakes.length))for(let t=this.gameplayCameraShakes.length-1;t>=0;t--){const a=this.gameplayCameraShakes[t];a.elapsedTime+=e,a.elapsedTime>a.request.duration&&this.gameplayCameraShakes.splice(t,1)}}refreshCameraPresentation(){if(!this.hasActiveCameraShake())return void this.applyRenderedCamera(this.sourceCamera);const e=this.ensurePresentationCamera();this.copyCameraState(this.sourceCamera,e),this.accumulateCameraShakeSamples(),this.applyCameraShakeSample(e),this.applyRenderedCamera(e)}hasActiveCameraShake(){if(this.gameplayCameraShakes.length>0)return!0;for(const e of this.cameraShakeContributions.values())if(e.size>0)return!0;return!1}ensurePresentationCamera(){return this.presentationCamera||(this.presentationCamera=new h.PerspectiveCamera,this.presentationCamera.name="View Controller Presentation Camera"),this.presentationCamera}copyCameraState(e,t){e.updateWorldMatrix(!0,!1),t.position.copy(e.getWorldPosition(v)),t.quaternion.copy(e.getWorldQuaternion(g)),t.scale.copy(e.getWorldScale(f)),t.layers.mask=e.layers.mask,e instanceof h.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect,t.zoom=e.zoom,t.focus=e.focus,t.filmGauge=e.filmGauge,t.filmOffset=e.filmOffset,t.view=null==e.view?null:{enabled:e.view.enabled,fullWidth:e.view.fullWidth,fullHeight:e.view.fullHeight,offsetX:e.view.offsetX,offsetY:e.view.offsetY,width:e.view.width,height:e.view.height},t.updateProjectionMatrix()):(t.projectionMatrix.copy(e.projectionMatrix),t.projectionMatrixInverse.copy(e.projectionMatrixInverse))}accumulateCameraShakeSamples(){u(this.accumulatedCameraShakeSample);for(let e=0;e<this.gameplayCameraShakes.length;e++)this.accumulateCameraShakeEntry(this.gameplayCameraShakes[e]);for(const e of this.cameraShakeContributions.values())for(const t of e.values())this.accumulateCameraShakeEntry(t)}accumulateCameraShakeEntry(e){const t=c(e.request,e.elapsedTime,this.scratchCameraShakeSample,e.seedOverride);if(t)for(let e=0;e<3;e++)this.accumulatedCameraShakeSample.position[e]+=t.position[e],this.accumulatedCameraShakeSample.rotation[e]+=t.rotation[e]}applyCameraShakeSample(e){k.copy(e.quaternion),w.set(this.accumulatedCameraShakeSample.position[0],this.accumulatedCameraShakeSample.position[1],this.accumulatedCameraShakeSample.position[2]),w.applyQuaternion(k),e.position.add(w),y.set(this.accumulatedCameraShakeSample.rotation[0],this.accumulatedCameraShakeSample.rotation[1],this.accumulatedCameraShakeSample.rotation[2]),O.setFromEuler(y),e.quaternion.copy(k).multiply(O),e.updateMatrixWorld(!0)}setMuted(e){this._muted=e,this.audioListener.gain.gain.setValueAtTime(e?0:1,this.audioListener.context.currentTime),this.mutedChanged.next(e)}getMuted(){return this._muted}setOutlined(e){this.outlined.length=0;const t=this.outlined;for(let a=0;a<e.length;a++)t[a]=e[a];this.view.setSelectedObjects(t),this.view.setEnableOutlines(e.length>0)}getOutlined(){return this.outlined}addOutlined(e){this.outlined.includes(e)||(this.outlined.push(e),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(!0))}removeOutlined(e){const t=this.outlined.indexOf(e);-1!==t&&(this.outlined.splice(t,1),this.view.setSelectedObjects(this.outlined))}setOutlineColor(e){this.view.outlinePass?.visibleEdgeColor.copy(e)}getOutlineColor(){return this.view.outlinePass?.visibleEdgeColor}setOutlineThickness(e){this.view.outlinePass.edgeThickness=e}getOutlineThickness(){return this.view.outlinePass.edgeThickness}get htmlElement(){return this.view.container}get paused(){return this.view.paused}set paused(e){e!=this.paused&&(e?this.pauseRendering():this.unpauseRendering())}pauseRendering(){this.view.paused=!0,this.pausedChanged.next(this.view.paused),this.scheduler.pause()}unpauseRendering(){this.view.paused=!1,this.pausedChanged.next(this.view.paused),this.scheduler.resume()}setInterval(e,t,a){return this.scheduler.setInterval(e,t,a)}clearInterval(e){this.scheduler.clearInterval(e)}dispose(){this.view.running&&this.view.stop(),this.scheduler.dispose(),this.cameraOverrides.length=0,this.gameplayCameraShakes.length=0,this.cameraShakeContributions.clear(),this.audioListener.removeFromParent(),this.tick.complete(),this.lateTick.complete(),this.paused=!0}createTimer(e){return this.scheduler.createTimer(e)}getScreenPosition(e,t=C){const a=this.getCamera();return p.multiplyMatrices(a.projectionMatrix,a.matrixWorldInverse),a instanceof h.PerspectiveCamera&&(S.setFromProjectionMatrix(p),!S.containsPoint(e))?null:(t.copy(e),t.project(a),t.x=(t.x+1)/2*this.htmlElement.clientWidth,t.y=(1-t.y)/2*this.htmlElement.clientHeight,t)}};d=e([a(),t("design:paramtypes",[s])],d);export{d as ViewController};const p=new h.Matrix4,C=new h.Vector3,S=new h.Frustum,v=new h.Vector3,f=new h.Vector3,g=new h.Quaternion,k=new h.Quaternion,w=new h.Vector3,y=new h.Euler(0,0,0,"XYZ"),O=new h.Quaternion;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,63 @@
1
+ import { ShaderMaterial, Texture, Vector2, WebGLRenderTarget, WebGLRenderer } from 'three';
2
+ import { Pass } from 'three/examples/jsm/Addons.js';
3
+ import { type PostProcessMaterialSource } from '../shader/post-process-shader.js';
4
+ export declare const postProcessEffectStages: readonly ["beforeFog", "beforeDepthOfField", "beforeColorAdjustment", "beforeOutline", "beforeAntiAliasing", "beforeLut", "beforeOutput"];
5
+ export type PostProcessEffectStage = typeof postProcessEffectStages[number];
6
+ export declare const defaultPostProcessEffectStage: PostProcessEffectStage;
7
+ export interface PostProcessEffectOptions {
8
+ enabled?: boolean;
9
+ priority?: number;
10
+ stage?: PostProcessEffectStage;
11
+ }
12
+ export interface PostProcessEffect {
13
+ readonly material: ShaderMaterial;
14
+ enabled: boolean;
15
+ priority: number;
16
+ stage: PostProcessEffectStage;
17
+ dispose(): void;
18
+ }
19
+ export interface PostProcessEffectUniformState {
20
+ aoEnabled: boolean;
21
+ aoTexture: Texture | null;
22
+ cameraFar?: number;
23
+ cameraNear?: number;
24
+ depthTexture: Texture;
25
+ normalTexture: Texture;
26
+ resolution: Vector2;
27
+ simulationTime: number;
28
+ }
29
+ export declare function applyPostProcessEffectUniformState(material: ShaderMaterial, state: PostProcessEffectUniformState): void;
30
+ export declare function sanitizePostProcessEffectStage(stage: PostProcessEffectStage | undefined): PostProcessEffectStage;
31
+ export declare function sanitizePostProcessEffectPriority(priority: number | undefined): number;
32
+ export interface PostProcessEffectEntry {
33
+ pass: PostProcessEffectPass;
34
+ priority: number;
35
+ stage: PostProcessEffectStage;
36
+ }
37
+ export interface PostProcessEffectOwner {
38
+ refreshPostProcessEffectPassOrder(): void;
39
+ removePostProcessEffectEntry(entry: PostProcessEffectEntry): void;
40
+ }
41
+ export declare class PostProcessEffectRegistration implements PostProcessEffect {
42
+ private readonly owner;
43
+ private readonly entry;
44
+ private disposed;
45
+ constructor(owner: PostProcessEffectOwner, entry: PostProcessEffectEntry);
46
+ get material(): ShaderMaterial;
47
+ get enabled(): boolean;
48
+ set enabled(value: boolean);
49
+ get priority(): number;
50
+ set priority(value: number);
51
+ get stage(): PostProcessEffectStage;
52
+ set stage(value: PostProcessEffectStage);
53
+ dispose(): void;
54
+ }
55
+ export declare class PostProcessEffectPass extends Pass {
56
+ readonly material: ShaderMaterial;
57
+ private readonly fsQuad;
58
+ constructor(source: PostProcessMaterialSource);
59
+ updateUniformState(state: PostProcessEffectUniformState): void;
60
+ render(renderer: WebGLRenderer, writeBuffer: WebGLRenderTarget, readBuffer: WebGLRenderTarget, deltaTime?: number, maskActive?: boolean): void;
61
+ dispose(): void;
62
+ }
63
+ //# sourceMappingURL=post-process-effect.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{FullScreenQuad as e,Pass as t}from"three/examples/jsm/Addons.js";import{NodeShaderMaterial as s}from"../shader-nodes/index.js";import{depthUniformName as r,farUniformName as i,nearUniformName as o,resolutionUniformName as n,sceneNormalUniformName as a}from"../shader-nodes/depth.js";import{aoMapUniformName as f,sceneMapUniformName as u}from"../shader-nodes/scene-sample.js";import{elapsedTimeUniformName as l}from"../shader-nodes/time.js";import{resolvePostProcessMaterial as d}from"../shader/post-process-shader.js";export const postProcessEffectStages=["beforeFog","beforeDepthOfField","beforeColorAdjustment","beforeOutline","beforeAntiAliasing","beforeLut","beforeOutput"];export const defaultPostProcessEffectStage="beforeOutput";export function applyPostProcessEffectUniformState(e,t){null!=e.uniforms[n]&&e.uniforms[n].value.copy(t.resolution),null!=e.uniforms[r]&&(e.uniforms[r].value=t.depthTexture),null!=e.uniforms[a]&&(e.uniforms[a].value=t.normalTexture),null!=e.uniforms[o]&&null!=t.cameraNear&&(e.uniforms[o].value=t.cameraNear),null!=e.uniforms[i]&&null!=t.cameraFar&&(e.uniforms[i].value=t.cameraFar),null!=e.uniforms[l]&&(e.uniforms[l].value=t.simulationTime),null!=e.uniforms[f]&&(e.uniforms[f].value=t.aoTexture),e instanceof s&&null!=e.uniforms[f]&&(t.aoEnabled?(null==e.defines.USE_SSAO_MAP&&(e.needsUpdate=!0),e.defines.USE_SSAO_MAP=""):null!=e.defines.USE_SSAO_MAP&&(delete e.defines.USE_SSAO_MAP,e.needsUpdate=!0))}export function sanitizePostProcessEffectStage(e){return e??"beforeOutput"}export function sanitizePostProcessEffectPriority(e){return null!=e&&Number.isFinite(e)?e:0}export class PostProcessEffectRegistration{constructor(e,t){this.owner=e,this.entry=t,this.disposed=!1}get material(){return this.entry.pass.material}get enabled(){return this.entry.pass.enabled}set enabled(e){this.entry.pass.enabled=e}get priority(){return this.entry.priority}set priority(e){const t=sanitizePostProcessEffectPriority(e);this.entry.priority!==t&&(this.entry.priority=t,this.owner.refreshPostProcessEffectPassOrder())}get stage(){return this.entry.stage}set stage(e){const t=sanitizePostProcessEffectStage(e);this.entry.stage!==t&&(this.entry.stage=t,this.owner.refreshPostProcessEffectPassOrder())}dispose(){this.disposed||(this.disposed=!0,this.owner.removePostProcessEffectEntry(this.entry))}}export class PostProcessEffectPass extends t{constructor(t){super(),this.material=d(t),this.material.depthWrite=!1,this.material.depthTest=!1,this.material.toneMapped=!1,this.fsQuad=new e(this.material),this.needsSwap=!0,this.clear=!1}updateUniformState(e){applyPostProcessEffectUniformState(this.material,e)}render(e,t,s,r,i){if(null!=this.material.uniforms[u]&&(this.material.uniforms[u].value=s.texture),this.renderToScreen)return e.setRenderTarget(null),this.clear&&e.clear(),void this.fsQuad.render(e);e.setRenderTarget(t),this.clear&&e.clear(),this.fsQuad.render(e)}dispose(){this.fsQuad.dispose()}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -6,13 +6,16 @@ import { CSM } from "three/examples/jsm/csm/CSM.js";
6
6
  import { GTAOPass } from "three/examples/jsm/postprocessing/GTAOPass.js";
7
7
  import { OutlinePass } from './utils/three/outline-pass.js';
8
8
  import { type PostProcessSettings, type PostProcessVolume } from "./gameplay/actors/builtin/post-process-volume-actor.js";
9
+ import { type PostProcessEffect, type PostProcessEffectOptions } from "./rendering/post-process-effect.js";
9
10
  import { LightVolume } from "./rendering/light-probes/light-volume-capture.js";
11
+ import type { PostProcessMaterialSource } from "./shader/post-process-shader.js";
10
12
  export type RenderingViewOptions = {
11
13
  enableOutlines?: boolean;
12
14
  enableXR?: boolean;
13
15
  maxPixelRatio?: number;
14
16
  resolutionScale?: number;
15
17
  msaa?: number;
18
+ fpsCap?: number | null;
16
19
  depthPrepass?: {
17
20
  enabled?: boolean;
18
21
  };
@@ -56,7 +59,10 @@ export declare class RenderingView {
56
59
  depthRenderTarget: WebGLRenderTarget;
57
60
  sceneColorRenderTarget: WebGLRenderTarget;
58
61
  csm: CSM | null;
59
- fpsCap: number | null;
62
+ private _fpsCap;
63
+ private fpsCapRevision;
64
+ get fpsCap(): number | null;
65
+ set fpsCap(fps: number | null | undefined);
60
66
  postProcessVolumes: PostProcessVolume[];
61
67
  postProcessSettings: PostProcessSettings;
62
68
  baseToneMapping: THREE.ToneMapping;
@@ -69,8 +75,13 @@ export declare class RenderingView {
69
75
  private colorPass;
70
76
  private dofPass;
71
77
  private lutPass;
78
+ private outputPass;
72
79
  private ssrPass;
73
80
  private volumetricFogPass;
81
+ private postProcessEffectId;
82
+ private postProcessEffects;
83
+ private readonly postProcessEffectResolution;
84
+ private readonly postProcessEffectUniformState;
74
85
  private fquadCopy;
75
86
  private fquadCopyOpaque;
76
87
  simulationTime: number;
@@ -96,6 +107,8 @@ export declare class RenderingView {
96
107
  resizeRender(): void;
97
108
  addPostProcessVolume(volume: PostProcessVolume): void;
98
109
  removePostProcessVolume(volume: PostProcessVolume): void;
110
+ addPostProcessEffect(source: PostProcessMaterialSource, options?: PostProcessEffectOptions): PostProcessEffect;
111
+ private getPostProcessEffectStageAnchorPass;
99
112
  private onVisiblityChane;
100
113
  private isDepthTextureExtensionSupported;
101
114
  private outlineEffect;
@@ -181,6 +194,7 @@ export declare class RenderingView {
181
194
  private pmremGeneratorResults;
182
195
  getEnvTexture(texture: Texture): THREE.Texture;
183
196
  private applyPostProcessSettings;
197
+ private updatePostProcessEffectUniforms;
184
198
  private insetHeight;
185
199
  private insetWidth;
186
200
  private insetOffsetY;