@hology/core 0.0.270 → 0.0.271

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 (54) hide show
  1. package/dist/effects/sequence/sequence-player.js +1 -1
  2. package/dist/effects/vfx/gpu-vfx-world-service.d.ts +2 -0
  3. package/dist/effects/vfx/gpu-vfx-world-service.js +1 -1
  4. package/dist/effects/vfx/vfx-actor.js +1 -1
  5. package/dist/effects/vfx/vfx-render-preparation.d.ts +3 -0
  6. package/dist/effects/vfx/vfx-render-preparation.js +1 -1
  7. package/dist/gameplay/actors/builtin/components/spline-component.d.ts +7 -39
  8. package/dist/gameplay/actors/builtin/components/spline-component.js +1 -1
  9. package/dist/gameplay/actors/builtin/navmesh-actor.d.ts +16 -2
  10. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  11. package/dist/gameplay/actors/builtin/water-spline-volume-actor.d.ts +2 -2
  12. package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +1 -1
  13. package/dist/gameplay/ai/build-tile.js +1 -1
  14. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +1 -1
  15. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.js +1 -1
  16. package/dist/gameplay/ai/navigation.d.ts +2 -0
  17. package/dist/gameplay/ai/navigation.js +1 -1
  18. package/dist/gameplay/services/physics/physics-system.d.ts +1 -1
  19. package/dist/gameplay/services/physics/physics-system.js +1 -1
  20. package/dist/gameplay/services/render.js +1 -1
  21. package/dist/navigation/bake.d.ts +68 -0
  22. package/dist/navigation/bake.js +4 -0
  23. package/dist/navigation/cache.d.ts +11 -0
  24. package/dist/navigation/cache.js +4 -0
  25. package/dist/navigation/spline-data.d.ts +64 -0
  26. package/dist/navigation/spline-data.js +4 -0
  27. package/dist/navigation/water-spline-geometry.d.ts +23 -0
  28. package/dist/navigation/water-spline-geometry.js +4 -0
  29. package/dist/scene/asset-resource-loader.d.ts +2 -2
  30. package/dist/scene/asset-resource-loader.js +1 -1
  31. package/dist/scene/bootstrap.js +1 -1
  32. package/dist/scene/collision/authored-colliders.d.ts +4 -0
  33. package/dist/scene/collision/authored-colliders.js +4 -0
  34. package/dist/scene/collision/rapier-shape.d.ts +7 -0
  35. package/dist/scene/collision/rapier-shape.js +4 -0
  36. package/dist/scene/materializer.d.ts +3 -0
  37. package/dist/scene/materializer.js +1 -1
  38. package/dist/scene/objects/shapes.js +1 -1
  39. package/dist/scene/runtime-backend-service.d.ts +1 -0
  40. package/dist/scene/runtime-bundled-backend-service.d.ts +1 -0
  41. package/dist/scene/runtime-bundled-backend-service.js +1 -1
  42. package/dist/test/authored-collision-rescale.test.js +1 -1
  43. package/dist/test/gpu-vfx-preload.test.d.ts +2 -0
  44. package/dist/test/gpu-vfx-preload.test.js +4 -0
  45. package/dist/test/materializer-prefetch.test.js +1 -1
  46. package/dist/test/navigation-bake-backend.test.d.ts +2 -0
  47. package/dist/test/navigation-bake-backend.test.js +4 -0
  48. package/dist/test/navigation-bake.test.d.ts +2 -0
  49. package/dist/test/navigation-bake.test.js +4 -0
  50. package/dist/test/sequence-vfx.test.js +1 -1
  51. package/dist/test/shader-graph.test.js +1 -1
  52. package/dist/test/vfx-render-preparation.test.js +1 -1
  53. package/package.json +6 -2
  54. package/tsconfig.tsbuildinfo +1 -1
@@ -1,32 +1,14 @@
1
1
  import { Subject } from 'rxjs';
2
2
  import { Vector3 } from 'three';
3
3
  import { ActorComponent } from '../../component.js';
4
- export interface SplinePoint {
5
- /** Actor-local point position. */
6
- position: Vector3;
7
- /** Actor-local offset from position to the incoming Bezier handle. */
8
- inTangent: Vector3;
9
- /** Actor-local offset from position to the outgoing Bezier handle. */
10
- outTangent: Vector3;
11
- }
12
- export interface ClosestSplinePoint {
13
- position: Vector3;
14
- tangent: Vector3;
15
- t: number;
16
- distance: number;
17
- distanceAlongSpline: number;
18
- }
19
- /** A generic cubic Bezier spline whose points and tangents are actor-local. */
4
+ import { type SplinePoint } from '../../../../navigation/spline-data.js';
5
+ export { packSplineData, parseSplineData, type SplinePoint, type ClosestSplinePoint } from '../../../../navigation/spline-data.js';
6
+ /** Editable component around the renderer-independent spline model. */
20
7
  export declare class SplineComponent extends ActorComponent {
21
- /** Compact JSON is intentional: scene files keep the complete spline on one line. */
8
+ private readonly data;
22
9
  splineData: string;
23
- /** Emits after an in-place authoring/runtime edit. Consumers can update incrementally. */
24
10
  readonly changed: Subject<SplineComponent>;
25
- private _points;
26
- private _closed;
27
- private arcLengths;
28
- private arcTs;
29
- private _length;
11
+ constructor();
30
12
  onInit(): void;
31
13
  onEndPlay(): void;
32
14
  get points(): readonly SplinePoint[];
@@ -36,30 +18,16 @@ export declare class SplineComponent extends ActorComponent {
36
18
  setPoints(points: readonly SplinePoint[], closed?: boolean): void;
37
19
  updatePoint(index: number, point: SplinePoint): void;
38
20
  addPoint(point: SplinePoint, index?: number): void;
39
- /** Splits a Bezier segment without changing the shape of the spline. */
40
- insertPointOnSegment(segmentIndex: number, t?: number): number;
21
+ insertPointOnSegment(index: number, t?: number): number;
41
22
  removePoint(index: number): void;
42
23
  setClosed(closed: boolean): void;
43
24
  applySceneParameters(parameters: {
44
25
  splineData?: string;
45
26
  }, changed: Set<'splineData'>): boolean;
46
- /** Samples an actor-local position using normalized t. */
47
27
  samplePosition(t: number, target?: Vector3): Vector3;
48
28
  sampleTangent(t: number, target?: Vector3): Vector3;
49
29
  samplePositionAtDistance(distance: number, target?: Vector3): Vector3;
50
30
  sampleTangentAtDistance(distance: number, target?: Vector3): Vector3;
51
- /** Finds the closest actor-local point to an actor-local query position. */
52
- closestPoint(point: Vector3, target?: Vector3): ClosestSplinePoint;
53
- private commitChange;
54
- private get segmentCount();
55
- private resolveSegment;
56
- private rebuildArcLengths;
57
- private tAtDistance;
58
- private distanceAtT;
31
+ closestPoint(point: Vector3, target?: Vector3): import("./spline-component.js").ClosestSplinePoint;
59
32
  }
60
- export declare function packSplineData(points: readonly SplinePoint[], closed: boolean): string;
61
- export declare function parseSplineData(data: string): {
62
- points: SplinePoint[];
63
- closed: boolean;
64
- };
65
33
  //# sourceMappingURL=spline-component.d.ts.map
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as n}from"tslib";import{Subject as s}from"rxjs";import{Vector3 as i}from"three";import{Parameter as e}from"../../../../shader/parameter.js";import{ActorComponent as o,Component as a}from"../../component.js";const h='{"closed":false,"points":[[0,0,0,0,0,0,2,0,0],[5,0,0,-2,0,0,0,0,0]]}';let r=class extends o{constructor(){super(...arguments),this.splineData=h,this.changed=new s,this._points=[],this._closed=!1,this.arcLengths=new Float32Array(0),this.arcTs=new Float32Array(0),this._length=0}onInit(){this.setData(this.splineData,!1)}onEndPlay(){this.changed.complete()}get points(){return this._points}get closed(){return this._closed}get length(){return this._length}setData(t,n=!0){const s=parseSplineData(t);this._closed=s.closed,this._points=s.points,this.splineData=packSplineData(this._points,this._closed),this.rebuildArcLengths(),n&&this.changed.next(this)}setPoints(t,n=this._closed){this._points=t.map(p),this._closed=n,this.commitChange()}updatePoint(t,n){t<0||t>=this._points.length||(this._points[t]=p(n),this.commitChange())}addPoint(t,n=this._points.length){this._points.splice(Math.max(0,Math.min(n,this._points.length)),0,p(t)),this.commitChange()}insertPointOnSegment(t,n=.5){const s=this.segmentCount;if(t<0||t>=s)return-1;const i=(t+1)%this._points.length,e=this._points[t],o=this._points[i],a=e.position,h=e.position.clone().add(e.outTangent),r=o.position.clone().add(o.inTangent),p=o.position,l=a.clone().lerp(h,n),c=h.clone().lerp(r,n),g=r.clone().lerp(p,n),m=l.clone().lerp(c,n),u=c.clone().lerp(g,n),T=m.clone().lerp(u,n);e.outTangent.copy(l).sub(a),o.inTangent.copy(g).sub(p);const d=t+1;return this._points.splice(d,0,{position:T,inTangent:m.sub(T),outTangent:u.sub(T)}),this.commitChange(),d}removePoint(t){t<0||t>=this._points.length||(this._points.splice(t,1),this.commitChange())}setClosed(t){t!==this._closed&&(this._closed=t,this.commitChange())}applySceneParameters(t,n){return!(1!==n.size||!n.has("splineData")||"string"!=typeof t.splineData)&&(this.setData(t.splineData),!0)}samplePosition(t,n=new i){const s=this.resolveSegment(t);return s?function(t,n,s,i){const e=1-s,o=e*e*e,a=3*e*e*s,h=3*e*s*s,r=s*s*s;return i.set(t.position.x*o+(t.position.x+t.outTangent.x)*a+(n.position.x+n.inTangent.x)*h+n.position.x*r,t.position.y*o+(t.position.y+t.outTangent.y)*a+(n.position.y+n.inTangent.y)*h+n.position.y*r,t.position.z*o+(t.position.z+t.outTangent.z)*a+(n.position.z+n.inTangent.z)*h+n.position.z*r)}(s.a,s.b,s.u,n):n.set(0,0,0)}sampleTangent(t,n=new i){const s=this.resolveSegment(t);return s?function(t,n,s,i){const e=1-s;return i.set(3*e*e*t.outTangent.x+6*e*s*(n.position.x+n.inTangent.x-t.position.x-t.outTangent.x)-3*s*s*n.inTangent.x,3*e*e*t.outTangent.y+6*e*s*(n.position.y+n.inTangent.y-t.position.y-t.outTangent.y)-3*s*s*n.inTangent.y,3*e*e*t.outTangent.z+6*e*s*(n.position.z+n.inTangent.z-t.position.z-t.outTangent.z)-3*s*s*n.inTangent.z)}(s.a,s.b,s.u,n).normalize():n.set(0,0,0)}samplePositionAtDistance(t,n=new i){return this.samplePosition(this.tAtDistance(t),n)}sampleTangentAtDistance(t,n=new i){return this.sampleTangent(this.tAtDistance(t),n)}closestPoint(t,n=new i){if(0===this.arcTs.length)return{position:n.set(0,0,0),tangent:new i,t:0,distance:t.length(),distanceAlongSpline:0};let s=0,e=1/0;const o=new i;for(let n=0;n<this.arcTs.length;n++){this.samplePosition(this.arcTs[n],o);const i=o.distanceToSquared(t);i<e&&(e=i,s=this.arcTs[n])}const a=this.arcTs.length>1?1/(this.arcTs.length-1):1;let h=Math.max(0,s-a),r=Math.min(1,s+a);for(let n=0;n<8;n++){const n=h+(r-h)/3,s=r-(r-h)/3;this.samplePosition(n,o);const i=o.distanceToSquared(t);this.samplePosition(s,o),i<o.distanceToSquared(t)?r=s:h=n}return s=.5*(h+r),this.samplePosition(s,n),{position:n,tangent:this.sampleTangent(s),t:s,distance:n.distanceTo(t),distanceAlongSpline:this.distanceAtT(s)}}commitChange(){this.splineData=packSplineData(this._points,this._closed),this.rebuildArcLengths(),this.changed.next(this)}get segmentCount(){return this._points.length<2?0:this._closed?this._points.length:this._points.length-1}resolveSegment(t){const n=this.segmentCount;if(0===n)return this._points[0]?{a:this._points[0],b:this._points[0],u:0}:null;const s=Math.max(0,Math.min(1,t))*n,i=Math.min(Math.floor(s),n-1);return{a:this._points[i],b:this._points[(i+1)%this._points.length],u:s-i}}rebuildArcLengths(){const t=24*this.segmentCount;if(0===t)return this.arcTs=this._points.length?new Float32Array([0]):new Float32Array(0),this.arcLengths=this._points.length?new Float32Array([0]):new Float32Array(0),void(this._length=0);this.arcTs=new Float32Array(t+1),this.arcLengths=new Float32Array(t+1);const n=this.samplePosition(0,new i),s=new i;let e=0;for(let i=1;i<=t;i++){const o=i/t;this.samplePosition(o,s),e+=n.distanceTo(s),this.arcTs[i]=o,this.arcLengths[i]=e,n.copy(s)}this._length=e}tAtDistance(t){if(0===this._length)return 0;const n=Math.max(0,Math.min(this._length,t));let s=0,i=this.arcLengths.length-1;for(;s<i;){const t=s+i>>>1;this.arcLengths[t]<n?s=t+1:i=t}const e=s,o=Math.max(0,e-1),a=this.arcLengths[e]-this.arcLengths[o],h=a>0?(n-this.arcLengths[o])/a:0;return this.arcTs[o]+(this.arcTs[e]-this.arcTs[o])*h}distanceAtT(t){if(this.arcTs.length<2)return 0;const n=Math.max(0,Math.min(1,t))*(this.arcTs.length-1),s=Math.floor(n),i=Math.min(s+1,this.arcLengths.length-1);return this.arcLengths[s]+(this.arcLengths[i]-this.arcLengths[s])*(n-s)}};t([e({label:"Spline Data",type:String}),n("design:type",String)],r.prototype,"splineData",void 0),r=t([a({inEditor:!0,typeId:"SplineComponent"})],r);export{r as SplineComponent};export function packSplineData(t,n){return JSON.stringify({closed:n,points:t.map(t=>[...t.position.toArray(),...t.inTangent.toArray(),...t.outTangent.toArray()])})}export function parseSplineData(t){let n;try{n=JSON.parse(t)}catch{n=JSON.parse(h)}return{closed:!0===n.closed,points:(n.points??[]).filter(t=>t.length>=9).map(t=>({position:(new i).fromArray(t,0),inTangent:(new i).fromArray(t,3),outTangent:(new i).fromArray(t,6)}))}}function p(t){return{position:t.position.clone(),inTangent:t.inTangent.clone(),outTangent:t.outTangent.clone()}}/*
1
+ import{__decorate as t,__metadata as a}from"tslib";import{Subject as e}from"rxjs";import{Vector3 as s}from"three";import{Parameter as i}from"../../../../shader/parameter.js";import{ActorComponent as n,Component as o}from"../../component.js";import{SplineData as r}from"../../../../navigation/spline-data.js";export{packSplineData,parseSplineData}from"../../../../navigation/spline-data.js";let p=class extends n{constructor(){super(),this.data=new r,this.splineData=this.data.splineData,this.changed=new e,this.data.changed.subscribe(()=>{this.splineData=this.data.splineData,this.changed.next(this)})}onInit(){this.setData(this.splineData,!1)}onEndPlay(){this.data.changed.complete(),this.changed.complete()}get points(){return this.data.points}get closed(){return this.data.closed}get length(){return this.data.length}setData(t,a=!0){this.data.setData(t,a),this.splineData=this.data.splineData}setPoints(t,a=this.closed){this.data.setPoints(t,a)}updatePoint(t,a){this.data.updatePoint(t,a)}addPoint(t,a=this.points.length){this.data.addPoint(t,a)}insertPointOnSegment(t,a=.5){return this.data.insertPointOnSegment(t,a)}removePoint(t){this.data.removePoint(t)}setClosed(t){this.data.setClosed(t)}applySceneParameters(t,a){return!(1!==a.size||!a.has("splineData")||"string"!=typeof t.splineData)&&(this.setData(t.splineData),!0)}samplePosition(t,a=new s){return this.data.samplePosition(t,a)}sampleTangent(t,a=new s){return this.data.sampleTangent(t,a)}samplePositionAtDistance(t,a=new s){return this.data.samplePositionAtDistance(t,a)}sampleTangentAtDistance(t,a=new s){return this.data.sampleTangentAtDistance(t,a)}closestPoint(t,a=new s){return this.data.closestPoint(t,a)}};t([i({label:"Spline Data",type:String}),a("design:type",String)],p.prototype,"splineData",void 0),p=t([o({inEditor:!0,typeId:"SplineComponent"}),a("design:paramtypes",[])],p);export{p as SplineComponent};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,6 +1,6 @@
1
1
  import { NavMesh } from 'recast-navigation';
2
2
  import { BaseActor } from "../../index.js";
3
- export declare function safeRecastInit(): Promise<boolean | void>;
3
+ export declare function safeRecastInit(): Promise<void>;
4
4
  export type NavMeshLoader = {
5
5
  save(): any;
6
6
  };
@@ -10,6 +10,7 @@ declare class NavMeshActor extends BaseActor {
10
10
  private world;
11
11
  private editorVisualisation;
12
12
  debug: boolean;
13
+ dynamic: boolean;
13
14
  refreshMs: number;
14
15
  private tileSize;
15
16
  walkableClimb: number;
@@ -20,10 +21,23 @@ declare class NavMeshActor extends BaseActor {
20
21
  private debugDrawer;
21
22
  private bounds;
22
23
  private recreateInterval;
24
+ private ended;
25
+ private startTimer;
26
+ private bakeAbort;
27
+ private generationDisposed;
28
+ private staticNavMesh?;
29
+ private activeBakeKey;
30
+ private initializing;
31
+ private sourceRevision;
32
+ private sourceCheckedAt;
23
33
  onInit(): Promise<void>;
24
34
  onEndPlay(): void;
25
- applySceneParameters(parameters: Record<string, unknown>, changedParameters: ReadonlySet<string>): boolean;
35
+ private resetGeneration;
36
+ private stopNavigation;
37
+ private currentBounds;
26
38
  private init;
39
+ applySceneParameters(parameters: Record<string, unknown>, changedParameters: ReadonlySet<string>): boolean;
40
+ private initDynamic;
27
41
  }
28
42
  export default NavMeshActor;
29
43
  //# sourceMappingURL=navmesh-actor.d.ts.map
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Ball as n,Capsule as s,Cone as o,ConvexPolyhedron as i,Cuboid as r,Cylinder as a,Heightfield as c,ShapeType as l,TriMesh as h}from"@dimforge/rapier3d-simd-compat";import{init as u}from"@recast-navigation/core";import{DebugDrawer as p,getPositionsAndIndices as d}from"@recast-navigation/three";import{BehaviorSubject as f,Subject as m,debounceTime as w,filter as g,firstValueFrom as b,takeUntil as y}from"rxjs";import*as x from"three";import{BufferGeometryUtils as M,ConvexHull as v}from"three/examples/jsm/Addons.js";import{Actor as B,BaseActor as S,Parameter as z,PhysicsSystem as j,ViewController as k,World as A,attach as C,inject as P}from"../../index.js";import{sleepDelay as V}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as D,toSharedFloat32Array as F,toSharedUint32Array as I}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as N,MAX_NAV_MESH_WORKERS as H}from"../../ai/dynamic-tiled-navmesh.js";import{isNavigationAreaContributor as G}from"../../ai/navigation-areas.js";import{TriggerVolumeMesh as E}from"./components/volume-editor-component.js";var R;!function(e){e[e.none=0]="none",e[e.starting=1]="starting",e[e.started=2]="started"}(R||(R={}));let T=R.none,U=new f(!1);export async function safeRecastInit(){return T===R.none?(T=R.starting,u().then(()=>{U.next(!0),T=R.started})):b(U.pipe(g(e=>e)))}new x.Box3(new x.Vector3(-100,-100,-100),new x.Vector3(100,100,100));const O=Math.max(1,Math.min(H,(navigator.hardwareConcurrency??2)-1));let q=!1,W=class extends S{constructor(){super(...arguments),this.physics=P(j),this.view=P(k),this.world=P(A),this.editorVisualisation=C(E),this.debug=!0,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new x.Box3}async onInit(){q||(await safeRecastInit(),q=!0),setTimeout(()=>{this.init()},10),this.recreateInterval=setInterval(()=>{if("_hology_transform_group"===this.object.parent?.name)return;K.setFromCenterAndSize(this.position,this.object.scale).equals(this.bounds)||(this.disposed.next(!0),this.disposed=new m,this.init())},2e3)}onEndPlay(){clearInterval(this.recreateInterval)}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,!0)}init(){this.bounds.setFromCenterAndSize(this.position,this.object.scale);const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,n=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(n/2))),o=Math.max(this.cellSize,.01),i={tileSize:Math.max(32,Math.floor(s/o)),walkableClimb:this.walkableClimb/o,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/o,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:o,ch:o,maxSimplificationError:1.3,maxEdgeLen:200},r=new N({navMeshBounds:this.bounds,recastConfig:i,maxTiles:1024,workers:O,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const a=this.tileSize*i.cs*2,c=performance.now(),l=new Map,h=new p;h.userData.isDebugDrawer=!0,this.debugDrawer=h;r.navMesh;const u=this.bounds,f=()=>{const e=this.view.getCamera().getWorldPosition(new x.Vector3),t=new x.Box3((new x.Vector3).copy(e).subScalar(a),(new x.Vector3).copy(e).addScalar(a)),n=[],s=this.physics.world.bodies;if(null==s)return[];const o=new x.Box3;for(const e of s.getAll())for(let s=0,i=e.numColliders();s<i;s++){const i=e.collider(s);if(i.isSensor()||null!=i.parent().userData&&!0===i.parent().userData.ignoreForNavMesh)continue;const r=e.handle+","+s,a=l.get(r)?.mesh,c=a??J(i);if($(i,c),null!=c){o.copy(c.geometry.boundingBox),o.min.add(c.position),o.max.add(c.position);const e=o.intersectsBox(t)||!0,s=o.intersectsBox(this.bounds);l.set(r,{pos:i.translation(),mesh:c}),e&&s&&n.push(c)}}return n},m=new x.Box3,g=new Map,b=new Map,M=new Map,v=new Map;let B=!0,S=performance.now(),z=!1;const j=function(e,t){let n=!1;return(async()=>{for(;!n;)await e(),await V(t)})(),()=>{n=!0}}(async()=>{if(z)return;const e=new x.Box3,t=f();for(const n of t){const t=g.get(n);!0!==t?.equals(n.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(n),g.set(n,n.position.clone()))}const n=[],s=new Set;for(const t of this.world.actors){if(!G(t))continue;s.add(t);const o=t.getNavigationAreaModifiers();n.push(...o);const i=Q(o),r=JSON.stringify(o);if(M.get(t)!==r){const n=b.get(t);null!=n&&e.union(n),e.union(i),b.set(t,i),M.set(t,r)}}for(const t of[...b.keys()])s.has(t)||(e.union(b.get(t)),b.delete(t),M.delete(t));const o=e.isEmpty()?[]:r.getTilesForBounds(e.expandByScalar(50));o.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const i=o.slice(0,500);if(0!=i.length){const s=[];for(const n of t)m.setFromObject(n),m.intersectsBox(e)&&s.push(n);let[o,a]=d(s);a=function(e,t,n){const s=new x.Vector3,o=[];for(let i=0;i<t.length;i+=3){let r=!0;for(let o=0;o<3;o++){const a=3*t[i+o];if(s.fromArray(e,a),!n.containsPoint(s)){r=!1;break}}r&&o.push(t[i],t[i+1],t[i+2])}return new Uint32Array(o)}(o,a,u),D&&(o=F(o),a=I(a));const c=B;B=!1,await Promise.all(i.map(e=>{S=performance.now();const t=function(e,t,n){const s=(e.recastConfig.walkableRadius+3)*e.recastConfig.cs,o=new x.Vector3(e.navMeshBoundsMin.x+t[0]*e.tcs-s,e.navMeshBoundsMin.y,e.navMeshBoundsMin.z+t[1]*e.tcs-s),i=new x.Vector3(o.x+e.tcs+2*s,e.navMeshBoundsMax.y,o.z+e.tcs+2*s),r=new x.Box3(o,i);return n.filter(e=>Q([e]).intersectsBox(r))}(r,e,n);return r.buildTile(o,a,e,c,t).then(()=>{const t=e[0]+","+e[1];v.set(t,(v.get(t)??0)+1),this.debug})})).then(()=>{this.debug,z=!1})}else z=!1},this.refreshMs??1e4);this.disposed.subscribe(()=>j()),r.onNavMeshUpdate.pipe(y(this.disposed),w(200)).subscribe(()=>{h.clear(),h.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),h.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(h),this.disposed.subscribe(()=>{r?.destroy(),h.removeFromParent(),h.dispose()});const k=performance.now()-c;k>1e3&&console.warn(`NavMesh update took ${k} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([z(),t("design:type",Boolean)],W.prototype,"debug",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableClimb",void 0),e([z({range:[0,89]}),t("design:type",Number)],W.prototype,"walkableSlopeAngle",void 0),e([z(),t("design:type",Number)],W.prototype,"walkableHeight",void 0),e([z({range:[.01,10]}),t("design:type",Number)],W.prototype,"cellSize",void 0),W=e([B({icon:"route"})],W);export default W;const _=new Map,L=new WeakMap;function X(e){if(e.shape instanceof c)return function(e){const t=e.shape;if(t.type!==l.HeightField)throw new Error("The provided collider is not a height field.");let n=!1;const s=t,o=s.heights,i=s.nrows,r=s.ncols,a=s.scale.x,c=s.scale.z,h=s.scale.y,u=i+1,p=new x.PlaneGeometry(c,a,r,i);p.rotateX(-Math.PI/2);const d=p.attributes.position.array;let f=0;for(let e=0;e<u;e++)for(let t=0;t<u;t++)d[f+1]=o[t*u+e]*h,f+=3,0!=d[f+1]&&(n=!0);if(!n){const e=new x.PlaneGeometry(a,c,2,2);return e.rotateX(-Math.PI/2),e}return p}(e);if(e.shape instanceof n)return new x.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new x.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof i){const t=function(e){const t=L.get(e);if(void 0!==t)return t;const n=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<n.length;e++)s=Math.imul(s^n[e],16777619)>>>0;return L.set(e,s),s}(e.shape.vertices);let n=_.get(t);return n||(n=function(e){const t=[];for(let n=0;n<e.length;n+=3)t.push(new x.Vector3(e[n],e[n+1],e[n+2]));const n=(new v).setFromPoints(t),s=[];n.faces.forEach(e=>{const t=e.edge.head().point,n=e.edge.next.head().point,o=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(n.x,n.y,n.z),s.push(o.x,o.y,o.z)});const o=new x.BufferGeometry;return o.setAttribute("position",new x.Float32BufferAttribute(s,3)),o}(e.shape.vertices),_.set(t,n)),n}if(e.shape instanceof h){const t=e.shape.vertices,n=e.shape.indices;let s=new x.BufferGeometry;return s.setAttribute("position",new x.Float32BufferAttribute(t,3)),null!=n?s.setIndex(new x.Uint16BufferAttribute(n,1)):s=M.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof a){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CylinderGeometry(n,n,2*t)}if(e.shape instanceof o){const t=e.shape.halfHeight,n=e.shape.radius;return new x.ConeGeometry(n,2*t)}if(e.shape instanceof s){const t=e.shape.halfHeight,n=e.shape.radius;return new x.CapsuleGeometry(n,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function J(e){const t=X(e);if(null==t)return null;const n=Y,s=new x.Mesh(t,n);return s.geometry.computeBoundingBox(),s.geometry.scale(1.01,1.01,1.01),s}function $(e,t){const n=e.translation(),s=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(s.x,s.y,s.z,s.w)}const K=new x.Box3;function Q(e){const t=new x.Box3;for(const n of e)for(const e of n.vertices)t.expandByPoint(new x.Vector3(e[0],n.minHeight,e[2])),t.expandByPoint(new x.Vector3(e[0],n.maxHeight,e[2]));return t}const Y=new x.MeshBasicMaterial({wireframe:!1,color:16711680,side:x.FrontSide});/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{importNavMesh as i}from"recast-navigation";import{bakeNavigation as s,collectNavigationInputs as n,landscapeNavigationGeometry as o,navigationConfig as a,navigationEntries as r,navigationSettings as h,navigationShapeGeometry as c,navigationGeometryInput as d}from"../../../navigation/bake.js";import{navigationCacheKey as l,readEditorNavigation as u,writeEditorNavigation as p}from"../../../navigation/cache.js";import{executeTask as f,hasWorkerBuilder as g}from"../../../worker/index.js";import{Ball as m,Capsule as b,Cone as w,ConvexPolyhedron as v,Cuboid as y,Cylinder as x,Heightfield as M,ShapeType as B,TriMesh as D}from"@dimforge/rapier3d-simd-compat";import{init as k}from"@recast-navigation/core";import{DebugDrawer as S,getPositionsAndIndices as A}from"@recast-navigation/three";import{Subject as j,debounceTime as z,takeUntil as N}from"rxjs";import*as C from"three";import{Mesh as V}from"three";import{BufferGeometryUtils as P,ConvexHull as I}from"three/examples/jsm/Addons.js";import{Actor as G,BaseActor as F,Parameter as R,PhysicsSystem as W,ViewController as E,World as H,attach as T,inject as _}from"../../index.js";import{sleepDelay as K}from"../../../utils/async.js";import{hasSharedArrayBufferSupport as U,toSharedFloat32Array as q,toSharedUint32Array as O}from"../../../utils/buffer.js";import{DynamicTiledNavMesh as L,MAX_NAV_MESH_WORKERS as X}from"../../ai/dynamic-tiled-navmesh.js";import{isNavigationAreaContributor as J}from"../../ai/navigation-areas.js";import{TriggerVolumeMesh as Q}from"./components/volume-editor-component.js";let $;export function safeRecastInit(){return $??($=k().catch(e=>{throw $=void 0,e}))}new C.Box3(new C.Vector3(-100,-100,-100),new C.Vector3(100,100,100));const Y=Math.max(1,Math.min(X,(navigator.hardwareConcurrency??2)-1));let Z=class extends F{constructor(){super(...arguments),this.physics=_(W),this.view=_(E),this.world=_(H),this.editorVisualisation=T(Q),this.debug=!0,this.dynamic=!1,this.refreshMs=4e3,this.tileSize=50,this.walkableClimb=.3,this.walkableSlopeAngle=45,this.walkableHeight=2,this.cellSize=.2,this.bounds=new C.Box3,this.ended=!1,this.bakeAbort=new AbortController,this.generationDisposed=new j,this.activeBakeKey="",this.initializing=!1,this.sourceRevision=-1,this.sourceCheckedAt=0}async onInit(){this.disposed.subscribe(()=>this.stopNavigation()),await safeRecastInit(),this.ended||(this.object.userData.navigationBake&&!this.dynamic?await this.init():this.startTimer=setTimeout(()=>{this.init()},10),this.ended||(this.recreateInterval=setInterval(()=>{"_hology_transform_group"!==this.object.parent?.name&&(!this.object.userData.navigationBakeSource&&this.currentBounds().equals(this.bounds)||this.init())},2e3)))}onEndPlay(){this.stopNavigation()}resetGeneration(){this.generationDisposed.next(!0),this.generationDisposed.complete(),this.generationDisposed=new j}stopNavigation(){this.ended||(this.ended=!0,clearTimeout(this.startTimer),clearInterval(this.recreateInterval),this.bakeAbort.abort(),this.generationDisposed.next(!0),this.generationDisposed.complete(),this.staticNavMesh?.destroy(),this.staticNavMesh=void 0,this.debugDrawer?.removeFromParent(),this.debugDrawer?.dispose(),this.navMesh=void 0)}currentBounds(){this.object.updateWorldMatrix(!0,!1);const e=this.object.getWorldPosition(new C.Vector3),t=this.object.getWorldScale(new C.Vector3);return t.set(Math.abs(t.x),Math.abs(t.y),Math.abs(t.z)),(new C.Box3).setFromCenterAndSize(e,t)}async init(){if(!this.ended&&!this.initializing){this.initializing=!0;try{const e=this.currentBounds(),t=a(e,this),o=h(e,t),m=this.object.userData.navigationBake,b=this.object.userData.navigationBakeSource,w=this.object.userData.navigationBakeRevision?.()??0;if(b&&w===this.sourceRevision&&e.equals(this.bounds)&&performance.now()-this.sourceCheckedAt<3e4&&this.staticNavMesh)return;if(!this.dynamic&&(m||b)){let v,y,x=m?.file??"",M=!1;if(m&&m.settings===o){if(this.activeBakeKey===x)return;const e=await fetch(m.file,{signal:this.bakeAbort.signal});if(!e.ok)throw new Error("Unable to load baked navmesh: "+m.file);v=new Uint8Array(await e.arrayBuffer())}else if(b){const a=await b();if(x=await l(a,o),this.sourceRevision=w,this.sourceCheckedAt=performance.now(),x===this.activeBakeKey)return;if(v=await u(x),v)try{y=i(v).navMesh}catch{v=void 0}if(!v){const i=r(a.objects,a.assets);a.contribute=async e=>{const t=this.world.actors.find(t=>t.__netSceneId?.replace(/^\//,"")===e.id);if(!t||t===this||["WaterVolume","WaterSplineVolume"].includes(e.source.actor?.type))return;const i=[];return this.physics.forEachStaticActorNavigationCollider(t,e=>{const t=c(e.shape),s=e.translation(),n=e.rotation(),o=(new C.Matrix4).compose(new C.Vector3(s.x,s.y,s.z),new C.Quaternion(n.x,n.y,n.z,n.w),new C.Vector3(1,1,1));i.push(d(t,o)),t.dispose()}),{geometry:i,modifiers:J(t)?t.getNavigationAreaModifiers():[]}};const h=(t.walkableRadius+3)*t.cs,l=await n(a,i,e.clone().expandByScalar(h)),u={id:this.__netSceneId??"",bounds:e,config:t,settings:o};v=await s(u,l,g()?async e=>(await f("navmesh.buildTile",e,{signal:this.bakeAbort.signal,priority:"background"})).navMeshData:void 0,this.bakeAbort.signal),M=!0}}if(this.ended)return void y?.destroy();if(M&&b){const e=this.currentBounds(),t=h(e,a(e,this));if(x!==await l(await b(),t))return void(this.sourceRevision=-1);if(await p(this.__netSceneId??String(this.id),x,v).catch(e=>console.warn("Could not save editor navmesh",e)),this.ended)return}if(v){const t=y??i(v).navMesh;return this.resetGeneration(),this.staticNavMesh?.destroy(),this.staticNavMesh=this.navMesh=t,this.bounds.copy(e),this.activeBakeKey=x,this.debugDrawer?.removeFromParent(),this.debugDrawer?.dispose(),this.debugDrawer=new S,this.debugDrawer.userData.isDebugDrawer=!0,this.debugDrawer.visible=this.debug,this.debug&&this.debugDrawer.drawNavMesh(t),void this.object.parent?.add(this.debugDrawer)}}if(this.activeBakeKey===o&&this.navMesh)return;this.resetGeneration(),this.staticNavMesh?.destroy(),this.staticNavMesh=void 0,this.debugDrawer?.removeFromParent(),this.debugDrawer?.dispose(),this.activeBakeKey=o,this.initDynamic()}catch(e){this.ended||"AbortError"===e?.name||(console.warn("Could not load or bake static navigation; using live generation",e),this.navMesh||this.initDynamic())}finally{this.initializing=!1}}}applySceneParameters(e,t){return!(null==this.debugDrawer||!t.has("debug")||"boolean"!=typeof e.debug)&&(null==this.debugDrawer.parent&&this.object.parent?.add(this.debugDrawer),this.debugDrawer.visible=e.debug,e.debug&&this.navMesh&&(this.debugDrawer.clear(),this.debugDrawer.drawNavMesh(this.navMesh)),1===t.size)}initDynamic(){this.bounds.copy(this.currentBounds());const e=this.bounds.max.x-this.bounds.min.x,t=this.bounds.max.z-this.bounds.min.z,i=Math.max(1,Math.min(e,t)),s=Math.min(400,Math.max(50,Math.ceil(i/2))),n=Math.max(this.cellSize,.01),a={tileSize:Math.max(32,Math.floor(s/n)),walkableClimb:this.walkableClimb/n,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:2,walkableHeight:this.walkableHeight/n,detailSampleDist:1,minRegionArea:6,mergeRegionArea:400,cs:n,ch:n,maxSimplificationError:1.3,maxEdgeLen:200},r=new L({navMeshBounds:this.bounds,recastConfig:a,maxTiles:1024,workers:Y,cacheId:"nav"+this.object.userData?.src?.id});this.navMesh=r.navMesh;const h=this.tileSize*a.cs*2,c=performance.now(),d=new Map,l=[],u=this.bounds.clone().expandByScalar((a.walkableRadius+3)*a.cs);this.world.scene.traverse(e=>{const t=e.userData.src??e.userData._src;if("landscape"===t?.shape&&!1!==t.collisionDetection){e.updateWorldMatrix(!0,!1);for(const i of o(t,e.matrixWorld,u)){const e=new C.BufferGeometry;e.setAttribute("position",new C.BufferAttribute(i.positions,3)),e.setIndex(new C.BufferAttribute(i.indices,1)),l.push(new V(e,ae))}}}),this.generationDisposed.subscribe(()=>{for(const e of l)e.geometry.dispose()});const p=new S;p.userData.isDebugDrawer=!0,this.debugDrawer=p;r.navMesh;this.bounds;const f=()=>{const e=this.view.getCamera().getWorldPosition(new C.Vector3),t=new C.Box3((new C.Vector3).copy(e).subScalar(h),(new C.Vector3).copy(e).addScalar(h)),i=l.slice(),s=this.physics.world.bodies;if(null==s)return[];const n=new C.Box3;for(const e of s.getAll())for(let s=0,o=e.numColliders();s<o;s++){const o=e.collider(s);if(this.physics.isLandscapeNavigationCollider(o))continue;if(o.isSensor()||null!=o.parent().userData&&!0===o.parent().userData.ignoreForNavMesh)continue;const a=e.handle+","+s,r=d.get(a)?.mesh,h=r??se(o);if(h&&(ne(o,h),null!=h)){h.updateMatrixWorld(!0),n.copy(h.geometry.boundingBox).applyMatrix4(h.matrixWorld);const e=n.intersectsBox(t)||!0,s=n.intersectsBox(this.bounds);d.set(a,{pos:o.translation(),mesh:h}),e&&s&&i.push(h)}}return i},g=new C.Box3,m=new Map,b=new Map,w=new Map,v=new Map;let y=!0,x=performance.now(),M=!1;const B=function(e,t){let i=!1;return(async()=>{for(;!i;)await e(),await K(t)})(),()=>{i=!0}}(async()=>{if(M)return;console.time("generate navmesh");const e=new C.Box3,t=f();for(const i of t){const t=m.get(i);!0!==t?.equals(i.position)&&(null!=t&&e.expandByPoint(t),e.expandByObject(i),m.set(i,i.position.clone()))}const i=[],s=new Set;for(const t of this.world.actors){if(!J(t))continue;s.add(t);const n=t.getNavigationAreaModifiers();i.push(...n);const o=oe(n),a=JSON.stringify(n);if(w.get(t)!==a){const i=b.get(t);null!=i&&e.union(i),e.union(o),b.set(t,o),w.set(t,a)}}for(const t of[...b.keys()])s.has(t)||(e.union(b.get(t)),b.delete(t),w.delete(t));const n=e.isEmpty()?[]:r.getTilesForBounds(e.expandByScalar(50));n.length>500&&console.warn("Too many tiles to update. Consider increasing tile size");const o=n;if(0!=o.length){const s=[];for(const i of t)g.setFromObject(i),g.intersectsBox(e)&&s.push(i);let[n,a]=A(s);U&&(n=q(n),a=O(a)),console.timeEnd("generate navmesh");const h=!1;y=!1,await Promise.all(o.map(e=>{x=performance.now();const t=function(e,t,i){const s=(e.recastConfig.walkableRadius+3)*e.recastConfig.cs,n=new C.Vector3(e.navMeshBoundsMin.x+t[0]*e.tcs-s,e.navMeshBoundsMin.y,e.navMeshBoundsMin.z+t[1]*e.tcs-s),o=new C.Vector3(n.x+e.tcs+2*s,e.navMeshBoundsMax.y,n.z+e.tcs+2*s),a=new C.Box3(n,o);return i.filter(e=>oe([e]).intersectsBox(a))}(r,e,i);return r.buildTile(n,a,e,h,t).then(()=>{const t=e[0]+","+e[1];v.set(t,(v.get(t)??0)+1),this.debug})})).then(()=>{this.debug,M=!1})}else M=!1},this.refreshMs??1e4);this.generationDisposed.subscribe(()=>B()),r.onNavMeshUpdate.pipe(N(this.generationDisposed),z(200)).subscribe(()=>{p.clear(),this.debug&&p.drawNavMesh(r.navMesh)}),console.log("Create navmesh with debug",this.debug),p.visible=this.debug,this.object.rotation.set(0,0,0),this.object.updateMatrix(),this.object.updateMatrixWorld(),this.object.parent?.add(p),this.generationDisposed.subscribe(()=>{r?.destroy(),p.removeFromParent(),p.dispose(),this.debugDrawer===p&&(this.debugDrawer=void 0),this.navMesh===r.navMesh&&(this.navMesh=void 0)});const D=performance.now()-c;D>1e3&&console.warn(`NavMesh update took ${D} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([R(),t("design:type",Boolean)],Z.prototype,"debug",void 0),e([R({help:"Generate navigation from live physics and refresh moving geometry. Disables static baked navigation."}),t("design:type",Boolean)],Z.prototype,"dynamic",void 0),e([R(),t("design:type",Number)],Z.prototype,"walkableClimb",void 0),e([R({range:[0,89]}),t("design:type",Number)],Z.prototype,"walkableSlopeAngle",void 0),e([R(),t("design:type",Number)],Z.prototype,"walkableHeight",void 0),e([R({range:[.01,10]}),t("design:type",Number)],Z.prototype,"cellSize",void 0),Z=e([G({icon:"route"})],Z);export default Z;const ee=new Map,te=new WeakMap;function ie(e){if(e.shape instanceof M)return function(e){const t=e.shape;if(t.type!==B.HeightField)throw new Error("The provided collider is not a height field.");let i=!1;const s=t,n=s.heights,o=s.nrows,a=s.ncols,r=s.scale.x,h=s.scale.z,c=s.scale.y,d=o+1,l=new C.PlaneGeometry(h,r,a,o);l.rotateX(-Math.PI/2);const u=l.attributes.position.array;let p=0;for(let e=0;e<d;e++)for(let t=0;t<d;t++)u[p+1]=n[t*d+e]*c,p+=3,0!=u[p+1]&&(i=!0);if(!i){const e=new C.PlaneGeometry(r,h,2,2);return e.rotateX(-Math.PI/2),e}return l}(e);if(e.shape instanceof m)return new C.SphereGeometry(e.shape.radius);if(e.shape instanceof y){const t=e.shape.halfExtents;return new C.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof v){const t=function(e){const t=te.get(e);if(void 0!==t)return t;const i=new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2);let s=2166136261;for(let e=0;e<i.length;e++)s=Math.imul(s^i[e],16777619)>>>0;return te.set(e,s),s}(e.shape.vertices);let i=ee.get(t);return i||(i=function(e){const t=[];for(let i=0;i<e.length;i+=3)t.push(new C.Vector3(e[i],e[i+1],e[i+2]));const i=(new I).setFromPoints(t),s=[];i.faces.forEach(e=>{const t=e.edge.head().point,i=e.edge.next.head().point,n=e.edge.next.next.head().point;s.push(t.x,t.y,t.z),s.push(i.x,i.y,i.z),s.push(n.x,n.y,n.z)});const n=new C.BufferGeometry;return n.setAttribute("position",new C.Float32BufferAttribute(s,3)),n}(e.shape.vertices),ee.set(t,i)),i}if(e.shape instanceof D){const t=e.shape.vertices,i=e.shape.indices;let s=new C.BufferGeometry;return s.setAttribute("position",new C.Float32BufferAttribute(t,3)),null!=i?s.setIndex(new C.Uint32BufferAttribute(i,1)):s=P.mergeVertices(s),s.computeVertexNormals(),s}if(e.shape instanceof x){const t=e.shape.halfHeight,i=e.shape.radius;return new C.CylinderGeometry(i,i,2*t)}if(e.shape instanceof w){const t=e.shape.halfHeight,i=e.shape.radius;return new C.ConeGeometry(i,2*t)}if(e.shape instanceof b){const t=e.shape.halfHeight,i=e.shape.radius;return new C.CapsuleGeometry(i,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function se(e){const t=ie(e);if(null==t)return null;const i=ae,s=new C.Mesh(t,i);return s.geometry.computeBoundingBox(),s}function ne(e,t){const i=e.translation(),s=e.rotation();t.position.set(i.x,i.y,i.z),t.quaternion.set(s.x,s.y,s.z,s.w)}new C.Box3;function oe(e){const t=new C.Box3;for(const i of e)for(const e of i.vertices)t.expandByPoint(new C.Vector3(e[0],i.minHeight,e[2])),t.expandByPoint(new C.Vector3(e[0],i.maxHeight,e[2]));return t}const ae=new C.MeshBasicMaterial({wireframe:!1,color:16711680,side:C.FrontSide});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import { BufferGeometry, Material, Vector3 } from 'three';
1
+ import { Material, Vector3 } from 'three';
2
2
  import { type NavigationAreaContributor, type NavigationAreaModifier } from '../../ai/navigation-areas.js';
3
3
  import { BaseActor } from '../actor.js';
4
4
  import { SplineComponent } from './components/spline-component.js';
@@ -19,5 +19,5 @@ export declare class WaterSplineVolume extends BaseActor implements NavigationAr
19
19
  containsWaterPoint(point: Vector3): boolean;
20
20
  getNavigationAreaModifiers(): NavigationAreaModifier[];
21
21
  }
22
- export declare function createWaterSplineSurfaceGeometry(spline: SplineComponent, width: number, sampleDistance: number, widthSubdivisions: number): BufferGeometry;
22
+ export { createWaterSplineSurfaceGeometry } from '../../../navigation/water-spline-geometry.js';
23
23
  //# sourceMappingURL=water-spline-volume-actor.d.ts.map
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{BufferGeometry as i,EdgesGeometry as s,Float32BufferAttribute as r,Group as o,DoubleSide as a,LineBasicMaterial as n,LineSegments as l,Mesh as h,MeshBasicMaterial as c,Material as u,Matrix4 as p,Vector3 as d}from"three";import{takeUntil as f}from"rxjs";import{NavigationArea as m}from"../../ai/navigation-areas.js";import{Parameter as g}from"../../../shader/parameter.js";import{Actor as w,BaseActor as y}from"../actor.js";import{ActorComponent as b,Component as S,attach as x}from"../component.js";import{SplineComponent as M}from"./components/spline-component.js";import{WaterPostProcessSettings as z}from"./components/water-post-process-settings.js";const v=1477586;let A=class extends b{constructor(){super(...arguments),this.fallbackMaterial=new c({color:v,transparent:!0,opacity:.65,side:a}),this.surface=new h(new i,this.fallbackMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.surface.name="Water Surface",this.actor.object.add(this.surface),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.setMaterial(this.actor.surfaceMaterial),this.rebuild()}setMaterial(t){this.surface.material=t??this.fallbackMaterial}rebuild(){if(!this.initialized)return;const t=this.surface.geometry;this.surface.geometry=F(this.actor.spline,this.actor.width,this.actor.surfaceSampleDistance,this.actor.surfaceWidthSubdivisions),this.surface.visible=this.actor.showSurface,t.dispose()}onEndPlay(){this.surface.geometry.dispose(),this.fallbackMaterial.dispose(),this.surface.removeFromParent()}};A=t([S({inEditor:!0})],A);let T=class extends b{constructor(){super(...arguments),this.visual=new o,this.fillMaterial=new c({color:v,transparent:!0,opacity:.18,depthWrite:!1}),this.edgeMaterial=new n({color:3520767}),this.fill=new h(new i,this.fillMaterial),this.edges=new l(new i,this.edgeMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.visual.name="Water Spline Volume Visualization",this.visual.userData.isEditorVisualization=!0,this.fill.frustumCulled=!1,this.edges.frustumCulled=!1,this.visual.add(this.fill,this.edges),this.actor.object.add(this.visual),this.actor.spline.changed.pipe(f(this.disposed)).subscribe(()=>this.rebuild()),this.rebuild()}rebuild(){if(!this.initialized)return;const t=function(t,e,s,o=!1,a=.5){const n=new i,l=D(t,e,s,a);if(l.length<2)return n.setAttribute("position",new r([],3)),n;const h=l.flatMap(t=>[...t.leftTop.toArray(),...t.rightTop.toArray(),...t.leftBottom.toArray(),...t.rightBottom.toArray()]),c=[];for(let t=1;t<l.length;t++){const e=4*(t-1),i=4*t;o||k(c,e,i,i+1,e+1),k(c,e+2,e+3,i+3,i+2),k(c,e,e+2,i+2,i),k(c,e+1,i+1,i+3,e+3)}if(!t.closed){k(c,0,1,3,2);const t=4*(l.length-1);k(c,t,t+2,t+3,t+1)}return n.setAttribute("position",new r(h,3)),n.setIndex(c),n.computeVertexNormals(),n.computeBoundingBox(),n.computeBoundingSphere(),n}(this.actor.spline,this.actor.width,this.actor.depth,this.actor.showSurface,this.actor.surfaceSampleDistance),e=0===t.getAttribute("position").count?new i:new s(t,20),o=this.fill.geometry,a=this.edges.geometry;this.fill.geometry=t,this.edges.geometry=e,o.dispose(),a.dispose(),this.visual.updateMatrixWorld(!0)}onEndPlay(){this.fill.geometry.dispose(),this.edges.geometry.dispose(),this.fillMaterial.dispose(),this.edgeMaterial.dispose(),this.visual.removeFromParent()}};T=t([S({inEditor:!0,editorOnly:!0})],T);let W=class extends y{constructor(){super(...arguments),this.spline=x(M),this.surface=x(A),this.editorVisual=x(T),this.underwater=x(z),this.width=5,this.depth=2,this.showSurface=!0,this.surfaceSampleDistance=1,this.surfaceWidthSubdivisions=1}applySceneParameters(t,e){if(![...e].every(t=>["width","depth","showSurface","surfaceMaterial","surfaceSampleDistance","surfaceWidthSubdivisions"].includes(t)))return!1;const i=e.has("width")?t.width:this.width,s=e.has("depth")?t.depth:this.depth;if("number"!=typeof i||!Number.isFinite(i)||i<=0)return!1;if("number"!=typeof s||!Number.isFinite(s)||s<=0)return!1;if(e.has("showSurface")&&"boolean"!=typeof t.showSurface)return!1;if(e.has("surfaceMaterial")&&null!=t.surfaceMaterial&&!(t.surfaceMaterial instanceof u))return!1;const r=e.has("surfaceSampleDistance")?t.surfaceSampleDistance:this.surfaceSampleDistance,o=e.has("surfaceWidthSubdivisions")?t.surfaceWidthSubdivisions:this.surfaceWidthSubdivisions;return!("number"!=typeof r||!Number.isFinite(r)||r<=0)&&(!("number"!=typeof o||!Number.isFinite(o)||o<1)&&(this.width=i,this.depth=s,e.has("showSurface")&&(this.showSurface=t.showSurface),e.has("surfaceMaterial")&&(this.surfaceMaterial=t.surfaceMaterial,this.surface.setMaterial(this.surfaceMaterial)),this.surfaceSampleDistance=r,this.surfaceWidthSubdivisions=Math.round(o),this.editorVisual.rebuild(),this.surface.rebuild(),!0))}containsWaterPoint(t){this.object.updateWorldMatrix(!0,!1);const e=E.copy(t).applyMatrix4(q.copy(this.object.matrixWorld).invert()),i=D(this.spline,this.width,this.depth,this.surfaceSampleDistance);for(let t=1;t<i.length;t++){const s=i[t-1],r=i[t];if(C(e,s.leftTop,s.rightTop,r.rightTop,r.leftTop,this.depth))return!0}return!1}getNavigationAreaModifiers(){const t=D(this.spline,this.width,this.depth);if(t.length<2)return[];this.object.updateWorldMatrix(!0,!1);const e=this.object.matrixWorld,i=[];for(let s=1;s<t.length;s++){const r=t[s-1],o=t[s],a=[r.leftTop,r.rightTop,o.rightTop,o.leftTop,r.leftBottom,r.rightBottom,o.rightBottom,o.leftBottom].map(t=>t.clone().applyMatrix4(e));i.push({area:m.Water,vertices:a.slice(0,4).map(t=>t.toArray()),minHeight:Math.min(...a.map(t=>t.y)),maxHeight:Math.max(...a.map(t=>t.y))})}return i}};t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"width",void 0),t([g({range:[.01,1e3]}),e("design:type",Number)],W.prototype,"depth",void 0),t([g({group:"Surface"}),e("design:type",Boolean)],W.prototype,"showSurface",void 0),t([g({type:u,group:"Surface",requires:{showSurface:!0},help:"Optional. Uses a translucent debug material when unset."}),e("design:type",u)],W.prototype,"surfaceMaterial",void 0),t([g({range:[.1,100],group:"Surface",requires:{showSurface:!0},help:"Target spacing in world units between sections along the spline."}),e("design:type",Number)],W.prototype,"surfaceSampleDistance",void 0),t([g({range:[1,64],stepSize:1,group:"Surface",requires:{showSurface:!0},help:"Subdivisions across the water. Increase for vertex displacement and detailed bank effects."}),e("design:type",Number)],W.prototype,"surfaceWidthSubdivisions",void 0),W=t([w({typeId:"WaterSplineVolume",icon:"ripple"})],W);export{W as WaterSplineVolume};function D(t,e,i,s=.5){if(t.points.length<2||t.length<=0||e<=0||i<0)return[];const r=Math.min(513,Math.max(2,Math.ceil(t.length/Math.max(.01,s))+1)),o=[],a=Array.from({length:r},(e,i)=>t.samplePositionAtDistance(t.length*i/(r-1),new d)),n=Math.min(.5*e,.25*t.length),l=Array.from({length:r},(e,i)=>{const s=t.length*i/(r-1),o=V(t,s-n,new d),a=V(t,s+n,new d).sub(o).setY(0);return a.lengthSq()<1e-8&&t.sampleTangentAtDistance(s,a).setY(0),a.lengthSq()<1e-8&&a.set(1,0,0),a.normalize(),new d(-a.z,0,a.x)}),h=.5*e,c=Array(r).fill(h),u=Array(r).fill(h);for(let e=0;e<r;e++){if(!t.closed&&(0===e||e===r-1))continue;const i=a[0===e?r-2:e-1],s=a[e],o=a[e===r-1?1:e+1],n=Math.min(h,.6*P(i,s,o)),l=N(i,s,o);l>1e-8?c[e]=n:l<-1e-8&&(u[e]=n)}j(c,a),j(u,a);for(let e=0;e<r;e++){const s=l[e],n=a[e].clone().addScaledVector(s,c[e]),h=a[e].clone().addScaledVector(s,-u[e]);o.push({leftTop:n,rightTop:h,leftBottom:n.clone().addScaledVector(I,i),rightBottom:h.clone().addScaledVector(I,i),flowDirection:t.sampleTangentAtDistance(t.length*e/(r-1),new d).normalize(),distanceAlongSpline:t.length*e/(r-1),surfaceWidth:c[e]+u[e]})}return function(t,e,i){B(t.map(t=>t.leftTop),e),B(t.map(t=>t.rightTop),e);for(const e of t)e.leftBottom.copy(e.leftTop).addScaledVector(I,i),e.rightBottom.copy(e.rightTop).addScaledVector(I,i),e.surfaceWidth=e.leftTop.distanceTo(e.rightTop)}(o,t.closed,i),o}function B(t,e){const i=e?t.length-1:t.length;if(!(i<3))for(let s=0;s<2;s++){const s=t.map(t=>t.clone()),r=e?i:i-1;for(let o=e?0:1;o<r;o++){const e=s[(o-1+i)%i],r=s[(o+1)%i];t[o].lerpVectors(e,r,.5).lerp(s[o],.5)}e&&t[t.length-1].copy(t[0])}}function V(t,e,i){if(!t.closed)return t.samplePositionAtDistance(e,i);const s=(e%t.length+t.length)%t.length;return t.samplePositionAtDistance(s,i)}function j(t,e){for(let i=1;i<t.length;i++)t[i]=Math.min(t[i],t[i-1]+.5*e[i].distanceTo(e[i-1]));for(let i=t.length-2;i>=0;i--)t[i]=Math.min(t[i],t[i+1]+.5*e[i].distanceTo(e[i+1]))}function N(t,e,i){return(e.x-t.x)*(i.z-e.z)-(e.z-t.z)*(i.x-e.x)}function P(t,e,i){const s=Math.hypot(e.x-t.x,e.z-t.z),r=Math.hypot(i.x-e.x,i.z-e.z),o=Math.hypot(i.x-t.x,i.z-t.z),a=Math.abs((e.x-t.x)*(i.z-t.z)-(e.z-t.z)*(i.x-t.x));return s<1e-6||r<1e-6||o<1e-6||a<1e-8?1/0:s*r*o/(2*a)}export function createWaterSplineSurfaceGeometry(t,e,i,s){return F(t,e,i,s)}function F(t,e,s,o){const a=new i,n=D(t,e,0,s),l=Math.max(1,Math.round(o))+1;if(n.length<2)return a.setAttribute("position",new r([],3)),a;const h=[],c=[],u=[],p=[],d=[];for(const e of n)for(let i=0;i<l;i++){const s=i/(l-1);h.push(...e.leftTop.clone().lerp(e.rightTop,s).toArray()),c.push(s,t.length>0?e.distanceAlongSpline/t.length:0),u.push(...e.flowDirection.toArray()),p.push(Math.min(s,1-s)*e.surfaceWidth),d.push(e.distanceAlongSpline)}const f=[];for(let t=1;t<n.length;t++)for(let e=1;e<l;e++){const i=(t-1)*l+e-1,s=t*l+e-1;k(f,i,s,s+1,i+1)}return a.setAttribute("position",new r(h,3)),a.setAttribute("uv",new r(c,2)),a.setAttribute("waterFlowDirection",new r(u,3)),a.setAttribute("waterDistanceFromBank",new r(p,1)),a.setAttribute("waterDistanceAlongSpline",new r(d,1)),a.setIndex(f),a.computeVertexNormals(),a.computeBoundingBox(),a.computeBoundingSphere(),a}function k(t,e,i,s,r){t.push(e,i,s,e,s,r)}const I=new d(0,-1,0),q=new p,E=new d;function C(t,e,i,s,r,o){const a=H(t,e,i,s)??H(t,e,s,r);return null!=a&&t.y<=a&&t.y>=a-o}function H(t,e,i,s){const r=(i.z-s.z)*(e.x-s.x)+(s.x-i.x)*(e.z-s.z);if(Math.abs(r)<1e-8)return null;const o=((i.z-s.z)*(t.x-s.x)+(s.x-i.x)*(t.z-s.z))/r,a=((s.z-e.z)*(t.x-s.x)+(e.x-s.x)*(t.z-s.z))/r,n=1-o-a;return o>=0&&a>=0&&n>=0?o*e.y+a*i.y+n*s.y:null}/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{createCrossSections as i,createSurfaceGeometry as s,createVolumeGeometry as r}from"../../../navigation/water-spline-geometry.js";import{BufferGeometry as a,EdgesGeometry as o,Group as n,DoubleSide as h,LineBasicMaterial as l,LineSegments as u,Mesh as c,MeshBasicMaterial as p,Material as d,Matrix4 as f,Vector3 as m}from"three";import{takeUntil as g}from"rxjs";import{NavigationArea as b}from"../../ai/navigation-areas.js";import{Parameter as y}from"../../../shader/parameter.js";import{Actor as w,BaseActor as S}from"../actor.js";import{ActorComponent as v,Component as M,attach as x}from"../component.js";import{SplineComponent as z}from"./components/spline-component.js";import{WaterPostProcessSettings as W}from"./components/water-post-process-settings.js";const j=1477586;let D=class extends v{constructor(){super(...arguments),this.fallbackMaterial=new p({color:j,transparent:!0,opacity:.65,side:h}),this.surface=new c(new a,this.fallbackMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.surface.name="Water Surface",this.actor.object.add(this.surface),this.actor.spline.changed.pipe(g(this.disposed)).subscribe(()=>this.rebuild()),this.setMaterial(this.actor.surfaceMaterial),this.rebuild()}setMaterial(e){this.surface.material=e??this.fallbackMaterial}rebuild(){if(!this.initialized)return;const e=this.surface.geometry;this.surface.geometry=s(this.actor.spline,this.actor.width,this.actor.surfaceSampleDistance,this.actor.surfaceWidthSubdivisions),this.surface.visible=this.actor.showSurface,e.dispose()}onEndPlay(){this.surface.geometry.dispose(),this.fallbackMaterial.dispose(),this.surface.removeFromParent()}};D=e([M({inEditor:!0})],D);let N=class extends v{constructor(){super(...arguments),this.visual=new n,this.fillMaterial=new p({color:j,transparent:!0,opacity:.18,depthWrite:!1}),this.edgeMaterial=new l({color:3520767}),this.fill=new c(new a,this.fillMaterial),this.edges=new u(new a,this.edgeMaterial),this.initialized=!1}onInit(){this.initialized=!0,this.visual.name="Water Spline Volume Visualization",this.visual.userData.isEditorVisualization=!0,this.fill.frustumCulled=!1,this.edges.frustumCulled=!1,this.visual.add(this.fill,this.edges),this.actor.object.add(this.visual),this.actor.spline.changed.pipe(g(this.disposed)).subscribe(()=>this.rebuild()),this.rebuild()}rebuild(){if(!this.initialized)return;const e=r(this.actor.spline,this.actor.width,this.actor.depth,this.actor.showSurface,this.actor.surfaceSampleDistance),t=0===e.getAttribute("position").count?new a:new o(e,20),i=this.fill.geometry,s=this.edges.geometry;this.fill.geometry=e,this.edges.geometry=t,i.dispose(),s.dispose(),this.visual.updateMatrixWorld(!0)}onEndPlay(){this.fill.geometry.dispose(),this.edges.geometry.dispose(),this.fillMaterial.dispose(),this.edgeMaterial.dispose(),this.visual.removeFromParent()}};N=e([M({inEditor:!0,editorOnly:!0})],N);let T=class extends S{constructor(){super(...arguments),this.spline=x(z),this.surface=x(D),this.editorVisual=x(N),this.underwater=x(W),this.width=5,this.depth=2,this.showSurface=!0,this.surfaceSampleDistance=1,this.surfaceWidthSubdivisions=1}applySceneParameters(e,t){if(![...t].every(e=>["width","depth","showSurface","surfaceMaterial","surfaceSampleDistance","surfaceWidthSubdivisions"].includes(e)))return!1;const i=t.has("width")?e.width:this.width,s=t.has("depth")?e.depth:this.depth;if("number"!=typeof i||!Number.isFinite(i)||i<=0)return!1;if("number"!=typeof s||!Number.isFinite(s)||s<=0)return!1;if(t.has("showSurface")&&"boolean"!=typeof e.showSurface)return!1;if(t.has("surfaceMaterial")&&null!=e.surfaceMaterial&&!(e.surfaceMaterial instanceof d))return!1;const r=t.has("surfaceSampleDistance")?e.surfaceSampleDistance:this.surfaceSampleDistance,a=t.has("surfaceWidthSubdivisions")?e.surfaceWidthSubdivisions:this.surfaceWidthSubdivisions;return!("number"!=typeof r||!Number.isFinite(r)||r<=0)&&(!("number"!=typeof a||!Number.isFinite(a)||a<1)&&(this.width=i,this.depth=s,t.has("showSurface")&&(this.showSurface=e.showSurface),t.has("surfaceMaterial")&&(this.surfaceMaterial=e.surfaceMaterial,this.surface.setMaterial(this.surfaceMaterial)),this.surfaceSampleDistance=r,this.surfaceWidthSubdivisions=Math.round(a),this.editorVisual.rebuild(),this.surface.rebuild(),!0))}containsWaterPoint(e){this.object.updateWorldMatrix(!0,!1);const t=P.copy(e).applyMatrix4(F.copy(this.object.matrixWorld).invert()),s=i(this.spline,this.width,this.depth,this.surfaceSampleDistance);for(let e=1;e<s.length;e++){const i=s[e-1],r=s[e];if(V(t,i.leftTop,i.rightTop,r.rightTop,r.leftTop,this.depth))return!0}return!1}getNavigationAreaModifiers(){const e=i(this.spline,this.width,this.depth);if(e.length<2)return[];this.object.updateWorldMatrix(!0,!1);const t=this.object.matrixWorld,s=[];for(let i=1;i<e.length;i++){const r=e[i-1],a=e[i],o=[r.leftTop,r.rightTop,a.rightTop,a.leftTop,r.leftBottom,r.rightBottom,a.rightBottom,a.leftBottom].map(e=>e.clone().applyMatrix4(t));s.push({area:b.Water,vertices:o.slice(0,4).map(e=>e.toArray()),minHeight:Math.min(...o.map(e=>e.y)),maxHeight:Math.max(...o.map(e=>e.y))})}return s}};e([y({range:[.01,1e3]}),t("design:type",Number)],T.prototype,"width",void 0),e([y({range:[.01,1e3]}),t("design:type",Number)],T.prototype,"depth",void 0),e([y({group:"Surface"}),t("design:type",Boolean)],T.prototype,"showSurface",void 0),e([y({type:d,group:"Surface",requires:{showSurface:!0},help:"Optional. Uses a translucent debug material when unset."}),t("design:type",d)],T.prototype,"surfaceMaterial",void 0),e([y({range:[.1,100],group:"Surface",requires:{showSurface:!0},help:"Target spacing in world units between sections along the spline."}),t("design:type",Number)],T.prototype,"surfaceSampleDistance",void 0),e([y({range:[1,64],stepSize:1,group:"Surface",requires:{showSurface:!0},help:"Subdivisions across the water. Increase for vertex displacement and detailed bank effects."}),t("design:type",Number)],T.prototype,"surfaceWidthSubdivisions",void 0),T=e([w({typeId:"WaterSplineVolume",icon:"ripple"})],T);export{T as WaterSplineVolume};export{createWaterSplineSurfaceGeometry}from"../../../navigation/water-spline-geometry.js";const F=new f,P=new m;function V(e,t,i,s,r,a){const o=k(e,t,i,s)??k(e,t,s,r);return null!=o&&e.y<=o&&e.y>=o-a}function k(e,t,i,s){const r=(i.z-s.z)*(t.x-s.x)+(s.x-i.x)*(t.z-s.z);if(Math.abs(r)<1e-8)return null;const a=((i.z-s.z)*(e.x-s.x)+(s.x-i.x)*(e.z-s.z))/r,o=((s.z-t.z)*(e.x-s.x)+(t.x-s.x)*(e.z-s.z))/r,n=1-a-o;return a>=0&&o>=0&&n>=0?a*t.y+o*i.y+n*s.y:null}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{NavMeshCreateParams as e,Raw as t,RecastBuildContext as i,TriangleAreasArray as o,TrianglesArray as r,VerticesArray as l,allocCompactHeightfield as a,allocContourSet as s,allocHeightfield as n,allocPolyMesh as c,allocPolyMeshDetail as d,buildCompactHeightfield as h,buildContours as g,buildDistanceField as m,buildPolyMesh as u,buildPolyMeshDetail as f,buildRegions as b,calcGridSize as S,cloneRcConfig as w,createHeightfield as R,createNavMeshData as p,createRcConfig as C,erodeWalkableArea as M,filterLedgeSpans as _,filterLowHangingWalkableObstacles as x,filterWalkableLowHeightSpans as y,freeCompactHeightfield as A,freeContourSet as k,freeHeightfield as v,FloatArray as z,markConvexPolyArea as E,markWalkableTriangles as T,rasterizeTriangles as B,vec3 as H}from"@recast-navigation/core";import{dtIlog2 as O,dtNextPow2 as P}from"@recast-navigation/generators";import*as G from"three";import{NavigationArea as L,NavigationTraversalFlag as D}from"./navigation-areas.js";export const buildConfig=({recastConfig:e,navMeshBounds:[t,i]})=>{const o=C(e),r=S(t,i,o.cs);o.width=r.width,o.height=r.height,o.minRegionArea=o.minRegionArea*o.minRegionArea,o.mergeRegionArea=o.mergeRegionArea*o.mergeRegionArea,o.tileSize=Math.floor(o.tileSize),o.borderSize=o.walkableRadius+3,o.width=o.tileSize+2*o.borderSize,o.height=o.tileSize+2*o.borderSize,o.detailSampleDist=o.detailSampleDist<.9?0:o.cs*o.detailSampleDist,o.detailSampleMaxError=o.ch*o.detailSampleMaxError;const l=Math.floor(o.tileSize),a=Math.floor((r.width+l-1)/l),s=Math.floor((r.height+l-1)/l),n=o.tileSize*o.cs,c=H.fromArray(t);let d=Math.min(Math.floor(O(P(a*s))),14);d>14&&(d=14);const h=22-d;return{config:o,orig:c,tileBits:d,polyBits:h,maxTiles:1<<d,maxPolysPerTile:1<<h,tcs:n,tileWidth:a,tileHeight:s}};export const buildTile=({positions:S,indices:C,navMeshBounds:H,recastConfig:O,tileX:P,tileY:F,tileBoundsMin:W,tileBoundsMax:$,keepIntermediates:V,areaModifiers:I=[]})=>{const K=new i,X=S,Y=S.length/3,j=new l;j.copy(X);const N=C,U=C.length/3;(new r).copy(N);const q={tileX:P,tileY:F},J=()=>{V||(q.compactHeightfield&&A(q.compactHeightfield),q.heightfield&&v(q.heightfield),q.contourSet&&k(q.contourSet))},Q=e=>(K.log(t.Module.RC_LOG_ERROR,e),J(),{success:!1,error:e,tileIntermediates:q,buildContext:K}),{config:Z}=buildConfig({recastConfig:O,navMeshBounds:H}),ee=w(Z),te=[...W],ie=[...$];te[0]-=ee.borderSize*ee.cs,te[2]-=ee.borderSize*ee.cs,ie[0]+=ee.borderSize*ee.cs,ie[2]+=ee.borderSize*ee.cs,ee.set_bmin(0,te[0]),ee.set_bmin(1,te[1]),ee.set_bmin(2,te[2]),ee.set_bmax(0,ie[0]),ee.set_bmax(1,ie[1]),ee.set_bmax(2,ie[2]),K.resetTimers(),K.startTimer(t.Module.RC_TIMER_TOTAL),K.log(t.Module.RC_LOG_PROGRESS,`Building tile at x: ${P}, y: ${F}`),K.log(t.Module.RC_LOG_PROGRESS,` - ${Z.width} x ${Z.height} cells`),K.log(t.Module.RC_LOG_PROGRESS,` - ${Y/1e3}fK verts, ${U/1e3}K tris`);const oe=n();if(q.heightfield=oe,!R(K,oe,ee.width,ee.height,te,ie,ee.cs,ee.ch))return Q("Could not create heightfield");const re=((e,t,i)=>{const o=[],r=new G.Vector3,l=new G.Vector3,a=new G.Vector3,s=new G.Triangle;for(let n=0;n<t.length;n+=3){const c=t[n],d=t[n+1],h=t[n+2];r.fromArray(e,3*c),l.fromArray(e,3*d),a.fromArray(e,3*h),s.set(r,l,a),s.intersectsBox(i)&&o.push(c,d,h)}return o})(S,C,new G.Box3(new G.Vector3(te[0],te[1],te[2]),new G.Vector3(ie[0],ie[1],ie[2]))),le=re.length/3,ae=new r;ae.copy(re);const se=new o;se.resize(le),T(K,ee.walkableSlopeAngle,j,Y,ae,le,se);const ne=B(K,j,Y,ae,se,le,oe,ee.walkableClimb);if(se.destroy(),!ne)return Q("Could not rasterize triangles");x(K,ee.walkableClimb,oe),_(K,ee.walkableHeight,ee.walkableClimb,oe),y(K,ee.walkableHeight,oe);const ce=a();if(q.compactHeightfield=ce,!h(K,ee.walkableHeight,ee.walkableClimb,oe,ce))return Q("Could not build compact heightfield");if(V||(v(q.heightfield),q.heightfield=void 0),!M(K,ee.walkableRadius,ce))return Q("Could not erode walkable area");for(const e of I){if(e.vertices.length<3)continue;const t=new z;t.copy(e.vertices.flat()),E(K,t,e.vertices.length,e.minHeight,e.maxHeight,e.area,ce),t.destroy()}if(!m(K,ce))return Q("Failed to build distance field");if(!b(K,ce,ee.borderSize,ee.minRegionArea,ee.mergeRegionArea))return Q("Failed to build regions");const de=s();if(q.contourSet=de,!g(K,ce,ee.maxSimplificationError,ee.maxEdgeLen,de,t.Module.RC_CONTOUR_TESS_WALL_EDGES))return Q("Failed to create contours");const he=c();if(!u(K,de,ee.maxVertsPerPoly,he))return Q("Failed to triangulate contours");if(0===he.npolys())return J(),{success:!0,tileIntermediates:q,buildContext:K};const ge=d();if(!f(K,he,ce,ee.detailSampleDist,ee.detailSampleMaxError,ge))return Q("Failed to build detail mesh");V||(A(ce),q.compactHeightfield=void 0,k(de),q.contourSet=void 0);for(let e=0;e<he.npolys();e++){he.areas(e)==t.Recast.WALKABLE_AREA&&he.setAreas(e,0);const i=he.areas(e);i==L.Ground&&he.setFlags(e,D.Walk),i==L.Water&&he.setFlags(e,D.Swim)}const me=new e;me.setPolyMeshCreateParams(he),me.setPolyMeshDetailCreateParams(ge),me.setWalkableHeight(ee.walkableHeight),me.setWalkableRadius(ee.walkableRadius),me.setWalkableClimb(ee.walkableClimb),me.setCellSize(ee.cs),me.setCellHeight(ee.ch),me.setBuildBvTree(!0),me.setTileX(P),me.setTileY(F);const ue=p(me);return ue.success?(K.log(t.Module.RC_LOG_PROGRESS,`>> Polymesh: ${he.nverts()} vertices ${he.npolys()} polygons`),J(),{success:!0,data:ue.navMeshData,tileIntermediates:q,buildContext:K}):Q("Failed to create Detour navmesh data")};/*
1
+ import{NavMeshCreateParams as e,Raw as t,RecastBuildContext as i,TriangleAreasArray as o,TrianglesArray as r,VerticesArray as l,allocCompactHeightfield as a,allocContourSet as s,allocHeightfield as n,allocPolyMesh as d,allocPolyMeshDetail as c,buildCompactHeightfield as h,buildContours as g,buildDistanceField as u,buildPolyMesh as m,buildPolyMeshDetail as f,buildRegions as b,calcGridSize as S,cloneRcConfig as p,createHeightfield as w,createNavMeshData as R,createRcConfig as C,erodeWalkableArea as M,filterLedgeSpans as y,filterLowHangingWalkableObstacles as _,filterWalkableLowHeightSpans as x,freeCompactHeightfield as A,freeContourSet as k,freeHeightfield as v,freePolyMesh as z,freePolyMeshDetail as E,FloatArray as T,markConvexPolyArea as B,markWalkableTriangles as H,rasterizeTriangles as O,vec3 as P}from"@recast-navigation/core";import{dtIlog2 as G,dtNextPow2 as L}from"@recast-navigation/generators";import*as D from"three";import{NavigationArea as F,NavigationTraversalFlag as W}from"./navigation-areas.js";export const buildConfig=({recastConfig:e,navMeshBounds:[t,i]})=>{const o=C(e),r=S(t,i,o.cs);o.width=r.width,o.height=r.height,o.minRegionArea=o.minRegionArea*o.minRegionArea,o.mergeRegionArea=o.mergeRegionArea*o.mergeRegionArea,o.tileSize=Math.floor(o.tileSize),o.borderSize=o.walkableRadius+3,o.width=o.tileSize+2*o.borderSize,o.height=o.tileSize+2*o.borderSize,o.detailSampleDist=o.detailSampleDist<.9?0:o.cs*o.detailSampleDist,o.detailSampleMaxError=o.ch*o.detailSampleMaxError;const l=Math.floor(o.tileSize),a=Math.floor((r.width+l-1)/l),s=Math.floor((r.height+l-1)/l),n=o.tileSize*o.cs,d=P.fromArray(t);let c=Math.min(Math.floor(G(L(a*s))),14);c>14&&(c=14);const h=22-c;return{config:o,orig:d,tileBits:c,polyBits:h,maxTiles:1<<c,maxPolysPerTile:1<<h,tcs:n,tileWidth:a,tileHeight:s}};export const buildTile=({positions:S,indices:C,navMeshBounds:P,recastConfig:G,tileX:L,tileY:$,tileBoundsMin:V,tileBoundsMax:I,keepIntermediates:K,areaModifiers:X=[]})=>{const Y=new i,j=S,N=S.length/3,U=new l;U.copy(j);const q=C.length/3,J=[()=>U.destroy()],Q={tileX:L,tileY:$},Z=()=>{for(const e of J)e();J.length=0,K||(Q.compactHeightfield&&A(Q.compactHeightfield),Q.heightfield&&v(Q.heightfield),Q.contourSet&&k(Q.contourSet))},ee=e=>(Y.log(t.Module.RC_LOG_ERROR,e),Z(),{success:!1,error:e,tileIntermediates:Q,buildContext:Y}),{config:te}=buildConfig({recastConfig:G,navMeshBounds:P}),ie=p(te);J.push(()=>t.Module.destroy(te),()=>t.Module.destroy(ie));const oe=[...V],re=[...I];oe[0]-=ie.borderSize*ie.cs,oe[2]-=ie.borderSize*ie.cs,re[0]+=ie.borderSize*ie.cs,re[2]+=ie.borderSize*ie.cs,ie.set_bmin(0,oe[0]),ie.set_bmin(1,oe[1]),ie.set_bmin(2,oe[2]),ie.set_bmax(0,re[0]),ie.set_bmax(1,re[1]),ie.set_bmax(2,re[2]),Y.resetTimers(),Y.startTimer(t.Module.RC_TIMER_TOTAL),Y.log(t.Module.RC_LOG_PROGRESS,`Building tile at x: ${L}, y: ${$}`),Y.log(t.Module.RC_LOG_PROGRESS,` - ${te.width} x ${te.height} cells`),Y.log(t.Module.RC_LOG_PROGRESS,` - ${N/1e3}fK verts, ${q/1e3}K tris`);const le=n();if(Q.heightfield=le,!w(Y,le,ie.width,ie.height,oe,re,ie.cs,ie.ch))return ee("Could not create heightfield");const ae=((e,t,i)=>{const o=[],r=new D.Vector3,l=new D.Vector3,a=new D.Vector3,s=new D.Triangle;for(let n=0;n<t.length;n+=3){const d=t[n],c=t[n+1],h=t[n+2];r.fromArray(e,3*d),l.fromArray(e,3*c),a.fromArray(e,3*h),s.set(r,l,a),s.intersectsBox(i)&&o.push(d,c,h)}return o})(S,C,new D.Box3(new D.Vector3(oe[0],oe[1],oe[2]),new D.Vector3(re[0],re[1],re[2]))),se=ae.length/3,ne=new r;J.push(()=>ne.destroy()),ne.copy(ae);const de=new o;de.resize(se),H(Y,ie.walkableSlopeAngle,U,N,ne,se,de);const ce=O(Y,U,N,ne,de,se,le,ie.walkableClimb);if(de.destroy(),!ce)return ee("Could not rasterize triangles");_(Y,ie.walkableClimb,le),y(Y,ie.walkableHeight,ie.walkableClimb,le),x(Y,ie.walkableHeight,le);const he=a();if(Q.compactHeightfield=he,!h(Y,ie.walkableHeight,ie.walkableClimb,le,he))return ee("Could not build compact heightfield");if(K||(v(Q.heightfield),Q.heightfield=void 0),!M(Y,ie.walkableRadius,he))return ee("Could not erode walkable area");for(const e of X){if(e.vertices.length<3)continue;const t=new T;t.copy(e.vertices.flat()),B(Y,t,e.vertices.length,e.minHeight,e.maxHeight,e.area,he),t.destroy()}if(!u(Y,he))return ee("Failed to build distance field");if(!b(Y,he,ie.borderSize,ie.minRegionArea,ie.mergeRegionArea))return ee("Failed to build regions");const ge=s();if(Q.contourSet=ge,!g(Y,he,ie.maxSimplificationError,ie.maxEdgeLen,ge,t.Module.RC_CONTOUR_TESS_WALL_EDGES))return ee("Failed to create contours");const ue=d();if(J.push(()=>z(ue)),!m(Y,ge,ie.maxVertsPerPoly,ue))return ee("Failed to triangulate contours");if(0===ue.npolys())return Z(),{success:!0,tileIntermediates:Q,buildContext:Y};const me=c();if(J.push(()=>E(me)),!f(Y,ue,he,ie.detailSampleDist,ie.detailSampleMaxError,me))return ee("Failed to build detail mesh");K||(A(he),Q.compactHeightfield=void 0,k(ge),Q.contourSet=void 0);for(let e=0;e<ue.npolys();e++){ue.areas(e)==t.Recast.WALKABLE_AREA&&ue.setAreas(e,0);const i=ue.areas(e);i==F.Ground&&ue.setFlags(e,W.Walk),i==F.Water&&ue.setFlags(e,W.Swim)}const fe=new e;J.push(()=>t.Module.destroy(fe.raw)),fe.setPolyMeshCreateParams(ue),fe.setPolyMeshDetailCreateParams(me),fe.setWalkableHeight(ie.walkableHeight),fe.setWalkableRadius(ie.walkableRadius),fe.setWalkableClimb(ie.walkableClimb),fe.setCellSize(ie.cs),fe.setCellHeight(ie.ch),fe.setBuildBvTree(!0),fe.setTileX(L),fe.setTileY($);const be=R(fe);return be.success?(Y.log(t.Module.RC_LOG_PROGRESS,`>> Polymesh: ${ue.nverts()} vertices ${ue.npolys()} polygons`),Z(),{success:!0,data:be.navMeshData,tileIntermediates:Q,buildContext:Y}):ee("Failed to create Detour navmesh data")};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{NavMesh as t,NavMeshParams as e,Raw as i,UnsignedCharArray as s,recastConfigDefaults as o,statusToReadableString as r}from"recast-navigation";import*as n from"three";import{buildConfig as a,buildTile as h}from"./build-tile.js";import{Subject as l}from"rxjs";import{executeTask as d,hasWorkerBuilder as u}from"../../worker/index.js";import{hasSharedArrayBufferSupport as c}from"../../utils/buffer.js";export const MAX_NAV_MESH_WORKERS=4;export const getTileBounds=(t,e,i,s,o)=>[[t.x+i*o,t.y,t.z+s*o],[t.x+(i+1)*o,e.y,t.z+(s+1)*o]];export class DynamicTiledNavMesh{constructor(i){this.navMeshVersion=0,this.onNavMeshUpdate=new l,this.abortController=new AbortController;const s=i.navMeshBounds.min,r=i.navMeshBounds.max,n=[s.toArray(),r.toArray()],h=i.navMeshBounds.min;this.navMeshBoundsMin=s,this.navMeshBoundsMax=r,this.navMeshBounds=n,this.navMeshOrigin=h,this.cacheId=i.cacheId,this.workerLimit=Math.min(4,Math.max(0,i.workers));const d={...o,...i.recastConfig};this.recastConfig=d;const u=new t,{tileWidth:c,tileHeight:M,tcs:m,maxPolysPerTile:v}=a({recastConfig:d,navMeshBounds:n});this.tileWidth=c,this.tileHeight=M,this.tcs=m;const f=e.create({orig:h,tileWidth:d.tileSize*d.cs,tileHeight:d.tileSize*d.cs,maxTiles:i.maxTiles,maxPolys:v});u.initTiled(f),this.navMesh=u}onResult(t){if(t.data.error)return void console.error(t.data.error);const{tileX:e,tileY:o,navMeshData:n}=t.data;if(this.navMesh.removeTile(this.navMesh.getTileRefAt(e,o,0)),null==n)return this.navMeshVersion++,void this.onNavMeshUpdate.next([this.navMeshVersion,[e,o]]);const a=new s;a.copy(n);const h=this.navMesh.addTile(a,i.Module.DT_TILE_FREE_DATA,0);i.Detour.statusFailed(h.status)&&(console.error(i.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${e}, ty: ${o},status: ${r(h.status)} (${h.status})`),a.destroy()),this.navMeshVersion++,this.onNavMeshUpdate.next([this.navMeshVersion,[e,o]])}buildTile(t,e,[i,s],o=!1,r=[]){const n=c&&t.buffer instanceof window.SharedArrayBuffer,a=n?t:new Float32Array(t),l=n?e:new Uint32Array(e),[v,f]=getTileBounds(this.navMeshBoundsMin,this.navMeshBoundsMax,i,s,this.tcs),g={tileX:i,tileY:s,tileBoundsMin:v,tileBoundsMax:f,recastConfig:this.recastConfig,navMeshBounds:this.navMeshBounds,keepIntermediates:!1,positions:a,indices:l,areaModifiers:r};return this.workerLimit>0&&u()?d("navmesh.buildTile",g,{transfer:n?void 0:[a.buffer,l.buffer],signal:this.abortController.signal,priority:"background"}).then(t=>this.onResult({data:t})).catch(t=>{"AbortError"!==t?.name&&console.error("Navmesh worker failed",t)}):new Promise(t=>{(globalThis.requestIdleCallback??(t=>setTimeout(t,0)))(()=>{const e=this.cacheId+JSON.stringify({tileX:g.tileX,tileY:g.tileY,areaModifiers:g.areaModifiers});if(o){const i=localStorage.getItem(e);if(null!=i){const e=m(i);return this.onResult({data:{tileX:g.tileX,tileY:g.tileY,navMeshData:e}}),void t({})}}else localStorage.removeItem(e);const i=h(g);if(!i.success)return console.error("error"in i?i.error:"Unknown navmesh tile build error"),void t(i);if(!i.data)return localStorage.removeItem(e),this.onResult({data:{tileX:g.tileX,tileY:g.tileY}}),void t(i);const s=i.data.toTypedArray();localStorage.setItem(e,M(s)),this.onResult({data:{tileX:g.tileX,tileY:g.tileY,navMeshData:s}}),t(i)})})}buildAllTiles(t,e){const{tileWidth:i,tileHeight:s}=this;for(let o=0;o<s;o++)for(let s=0;s<i;s++)this.buildTile(t,e,[s,o])}getTileForWorldPosition(t){return[Math.floor((t.x-this.navMeshBoundsMin.x)/this.tcs),Math.floor((t.z-this.navMeshBoundsMin.z)/this.tcs)]}getTilesForBounds(t){if(!t.intersectsBox(new n.Box3(this.navMeshBoundsMin,this.navMeshBoundsMax)))return[];const e=this.getTileForWorldPosition(t.min),i=this.getTileForWorldPosition(t.max);e[0]=Math.max(0,Math.min(this.tileWidth-1,e[0])),e[1]=Math.max(0,Math.min(this.tileHeight-1,e[1])),i[0]=Math.max(0,Math.min(this.tileWidth-1,i[0])),i[1]=Math.max(0,Math.min(this.tileHeight-1,i[1]));const s=[];for(let t=e[1];t<=i[1];t++)for(let o=e[0];o<=i[0];o++)s.push([o,t]);return s}destroy(){this.abortController.abort(),this.navMesh.destroy(),this.onNavMeshUpdate.complete()}}const M=function(t){return btoa(String.fromCharCode(...t))},m=function(t){if(!t)return null;const e=atob(t),i=e.length,s=new Uint8Array(i);for(let t=0;t<i;t++)s[t]=e.charCodeAt(t);return s};/*
1
+ import{NavMesh as t,NavMeshParams as e,Raw as i,UnsignedCharArray as s,recastConfigDefaults as o,statusToReadableString as r}from"recast-navigation";import*as n from"three";import{buildConfig as a,buildTile as h}from"./build-tile.js";import{Subject as l}from"rxjs";import{executeTask as d,hasWorkerBuilder as u}from"../../worker/index.js";import{hasSharedArrayBufferSupport as M}from"../../utils/buffer.js";export const MAX_NAV_MESH_WORKERS=4;export const getTileBounds=(t,e,i,s,o)=>[[t.x+i*o,t.y,t.z+s*o],[t.x+(i+1)*o,e.y,t.z+(s+1)*o]];export class DynamicTiledNavMesh{constructor(s){this.navMeshVersion=0,this.onNavMeshUpdate=new l,this.abortController=new AbortController;const r=s.navMeshBounds.min,n=s.navMeshBounds.max,h=[r.toArray(),n.toArray()],d=s.navMeshBounds.min;this.navMeshBoundsMin=r,this.navMeshBoundsMax=n,this.navMeshBounds=h,this.navMeshOrigin=d,this.cacheId=s.cacheId,this.workerLimit=Math.min(4,Math.max(0,s.workers));const u={...o,...s.recastConfig};this.recastConfig=u;const M=new t,c=a({recastConfig:u,navMeshBounds:h}),{tileWidth:v,tileHeight:m,tcs:f,maxPolysPerTile:x}=c;i.Module.destroy(c.config),this.tileWidth=v,this.tileHeight=m,this.tcs=f;const g=e.create({orig:d,tileWidth:u.tileSize*u.cs,tileHeight:u.tileSize*u.cs,maxTiles:s.maxTiles,maxPolys:x});M.initTiled(g),i.Module.destroy(g.raw),this.navMesh=M}onResult(t){if(t.data.error)return void console.error(t.data.error);const{tileX:e,tileY:o,navMeshData:n}=t.data;if(this.navMesh.removeTile(this.navMesh.getTileRefAt(e,o,0)),null==n)return this.navMeshVersion++,void this.onNavMeshUpdate.next([this.navMeshVersion,[e,o]]);const a=new s;a.copy(n);const h=this.navMesh.addTile(a,i.Module.DT_TILE_FREE_DATA,0);i.Detour.statusFailed(h.status)&&(console.error(i.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${e}, ty: ${o},status: ${r(h.status)} (${h.status})`),a.destroy()),this.navMeshVersion++,this.onNavMeshUpdate.next([this.navMeshVersion,[e,o]])}buildTile(t,e,[s,o],r=!1,n=[]){const a=M&&t.buffer instanceof window.SharedArrayBuffer,l=a?t:new Float32Array(t),c=a?e:new Uint32Array(e),[v,m]=getTileBounds(this.navMeshBoundsMin,this.navMeshBoundsMax,s,o,this.tcs),f={tileX:s,tileY:o,tileBoundsMin:v,tileBoundsMax:m,recastConfig:this.recastConfig,navMeshBounds:this.navMeshBounds,keepIntermediates:!1,positions:l,indices:c,areaModifiers:n};return this.workerLimit>0&&u()?d("navmesh.buildTile",f,{transfer:a?void 0:[l.buffer,c.buffer],signal:this.abortController.signal,priority:"background"}).then(t=>this.onResult({data:t})).catch(t=>{"AbortError"!==t?.name&&console.error("Navmesh worker failed",t)}):new Promise(t=>{(globalThis.requestIdleCallback??(t=>setTimeout(t,0)))(()=>{if(this.abortController.signal.aborted)return void t(void 0);const e=h(f);if(i.Module.destroy(e.buildContext.raw),!e.success)return console.error("error"in e?e.error:"Unknown navmesh tile build error"),void t(e);if(!e.data)return this.onResult({data:{tileX:f.tileX,tileY:f.tileY}}),void t(e);const s=e.data.toTypedArray();e.data.destroy(),this.onResult({data:{tileX:f.tileX,tileY:f.tileY,navMeshData:s}}),t(e)})})}buildAllTiles(t,e){const{tileWidth:i,tileHeight:s}=this;for(let o=0;o<s;o++)for(let s=0;s<i;s++)this.buildTile(t,e,[s,o])}getTileForWorldPosition(t){return[Math.floor((t.x-this.navMeshBoundsMin.x)/this.tcs),Math.floor((t.z-this.navMeshBoundsMin.z)/this.tcs)]}getTilesForBounds(t){if(!t.intersectsBox(new n.Box3(this.navMeshBoundsMin,this.navMeshBoundsMax)))return[];const e=this.getTileForWorldPosition(t.min),i=this.getTileForWorldPosition(t.max);e[0]=Math.max(0,Math.min(this.tileWidth-1,e[0])),e[1]=Math.max(0,Math.min(this.tileHeight-1,e[1])),i[0]=Math.max(0,Math.min(this.tileWidth-1,i[0])),i[1]=Math.max(0,Math.min(this.tileHeight-1,i[1]));const s=[];for(let t=e[1];t<=i[1];t++)for(let o=e[0];o<=i[0];o++)s.push([o,t]);return s}destroy(){this.abortController.abort(),this.navMesh.destroy(),this.onNavMeshUpdate.complete()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{init as e}from"recast-navigation";import{buildTile as t}from"./build-tile.js";let r;export const navMeshTaskHandlers={"navmesh.buildTile":async a=>{r??(r=e()),await r;const i=t(a);if(!i.success){const e="error"in i?i.error:"Unknown navmesh tile build error";throw new Error(`NavMesh tile build failed (${a.tileX}, ${a.tileY}): ${e}`)}if(!i.data)return{payload:{tileX:a.tileX,tileY:a.tileY}};const l=i.data.toTypedArray();return i.data.destroy(),{payload:{tileX:a.tileX,tileY:a.tileY,navMeshData:l},transfer:[l.buffer]}}};/*
1
+ import{init as e,Raw as t}from"recast-navigation";import{buildTile as r}from"./build-tile.js";let a;export const navMeshTaskHandlers={"navmesh.buildTile":async i=>{a??(a=e()),await a;const l=r(i);if(t.Module.destroy(l.buildContext.raw),!l.success){const e="error"in l?l.error:"Unknown navmesh tile build error";throw new Error(`NavMesh tile build failed (${i.tileX}, ${i.tileY}): ${e}`)}if(!l.data)return{payload:{tileX:i.tileX,tileY:i.tileY}};const o=l.data.toTypedArray();return l.data.destroy(),{payload:{tileX:i.tileX,tileY:i.tileY,navMeshData:o},transfer:[o.buffer]}}};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -24,10 +24,12 @@ export declare const NavigationQueryProfiles: Readonly<{
24
24
  export declare class Navigation {
25
25
  private navMeshActor;
26
26
  private query?;
27
+ private queryMesh?;
27
28
  private world;
28
29
  private filters;
29
30
  constructor();
30
31
  private getFilter;
32
+ private resetQuery;
31
33
  private ensureQuery;
32
34
  /**
33
35
  * Finds a path from a start point to an end point.
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{NavMeshQuery as n,QueryFilter as s}from"recast-navigation";import{Vector3 as r}from"three";import{Service as i}from"typedi";import{inject as o}from"../inject.js";import{World as l}from"../services/world.js";import a,{safeRecastInit as u}from"../actors/builtin/navmesh-actor.js";import{NavigationArea as c,NavigationTraversalFlag as h}from"./navigation-areas.js";export const NavigationQueryProfiles=Object.freeze({Walker:Object.freeze({name:"Walker",includeFlags:h.Walk,excludeFlags:h.Swim}),Swimmer:Object.freeze({name:"Swimmer",includeFlags:h.Walk|h.Swim,excludeFlags:0,areaCosts:{[c.Water]:2}})});let d=class{constructor(){this.world=o(l),this.filters=new Map,u().then(()=>{const e=this.world.actors.find(e=>e instanceof a);null!=e&&(this.navMeshActor=e,this.query=null),this.world.actorAdded.subscribe(e=>{e instanceof a&&(this.navMeshActor=e,this.query=null)}),this.world.actorRemoved.subscribe(e=>{e instanceof a&&e.id===this.navMeshActor?.id&&(this.navMeshActor=null,this.query=null)})})}getFilter(e){let t=this.filters.get(e);if(null!=t)return t;t=new s,t.includeFlags=e.includeFlags,t.excludeFlags=e.excludeFlags;for(const[n,s]of Object.entries(e.areaCosts??{}))null!=s&&t.setAreaCost(Number(n),s);return this.filters.set(e,t),t}ensureQuery(){null==this.query&&null!=this.navMeshActor&&null!=this.navMeshActor.navMesh&&(this.query=new n(this.navMeshActor.navMesh))}findPath(e,t,n=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return y("NavMesh has not been generated yet"),f;const s=this.findClosestPoint(e,n);if(null==s)return y("Start point could not be found on NavMesh",e),f;const i=this.findClosestPoint(t,n);if(null==i)return y("End point could not be found on NavMesh",t),f;const{success:o,error:l,path:a}=this.query.computePath(s,i,{filter:this.getFilter(n)}),u=a.at(-1),c=null!=u&&function(e,t){const n=e.x-t.x,s=e.y-t.y,r=e.z-t.z;return n*n+s*s+r*r}(u,i)<=.01;return o&&c?{success:!0,path:a.map(e=>new r(e.x,e.y,e.z))}:(y("Failed to generate path",l),f)}findClosestPoint(e,t=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return y("NavMesh has not been generated yet"),null;const{success:n,point:s}=this.query.findClosestPoint(e,{filter:this.getFilter(t)});return n?new r(s.x,s.y,s.z):null}findRandomPoint(e=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return y("NavMesh has not been generated yet"),null;const t=this.query.findRandomPoint({filter:this.getFilter(e)});return{success:t.success,randomPoint:(new r).copy(t.randomPoint)}}findRandomPointAroundCircle(e,t,n=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return y("NavMesh has not been generated yet"),null;const s=this.query.findRandomPointAroundCircle(e,t,{filter:this.getFilter(n)});return{success:s.success,randomPoint:(new r).copy(s.randomPoint)}}};d=e([i(),t("design:paramtypes",[])],d);export{d as Navigation};const f={success:!1,path:[]};let m=new Set;function y(e,...t){m.has(e)||(m.add(e),setTimeout(()=>m.delete(e),2e3),console.warn(e,...t))}/*
1
+ import{__decorate as e,__metadata as t}from"tslib";import{NavMeshQuery as s,QueryFilter as r}from"recast-navigation";import{Vector3 as n}from"three";import{Service as i}from"typedi";import{inject as o}from"../inject.js";import{World as a}from"../services/world.js";import l,{safeRecastInit as u}from"../actors/builtin/navmesh-actor.js";import{NavigationArea as h,NavigationTraversalFlag as c}from"./navigation-areas.js";export const NavigationQueryProfiles=Object.freeze({Walker:Object.freeze({name:"Walker",includeFlags:c.Walk,excludeFlags:c.Swim}),Swimmer:Object.freeze({name:"Swimmer",includeFlags:c.Walk|c.Swim,excludeFlags:0,areaCosts:{[h.Water]:2}})});let d=class{constructor(){this.world=o(a),this.filters=new Map,u().then(()=>{const e=this.world.actors.find(e=>e instanceof l);null!=e&&(this.navMeshActor=e,this.resetQuery()),this.world.actorAdded.subscribe(e=>{e instanceof l&&(this.navMeshActor=e,this.resetQuery())}),this.world.actorRemoved.subscribe(e=>{e instanceof l&&e.id===this.navMeshActor?.id&&(this.navMeshActor=null,this.resetQuery())})})}getFilter(e){let t=this.filters.get(e);if(null!=t)return t;t=new r,t.includeFlags=e.includeFlags,t.excludeFlags=e.excludeFlags;for(const[s,r]of Object.entries(e.areaCosts??{}))null!=r&&t.setAreaCost(Number(s),r);return this.filters.set(e,t),t}resetQuery(){this.query?.destroy(),this.query=void 0,this.queryMesh=void 0}ensureQuery(){const e=this.navMeshActor?.navMesh;e!==this.queryMesh&&(this.query?.destroy(),this.query=void 0,this.queryMesh=e),null==this.query&&null!=this.navMeshActor&&null!=this.navMeshActor.navMesh&&(this.query=new s(this.navMeshActor.navMesh))}findPath(e,t,s=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return m("NavMesh has not been generated yet"),f;const r=this.findClosestPoint(e,s);if(null==r)return m("Start point could not be found on NavMesh",e),f;const i=this.findClosestPoint(t,s);if(null==i)return m("End point could not be found on NavMesh",t),f;const{success:o,error:a,path:l}=this.query.computePath(r,i,{filter:this.getFilter(s)}),u=l.at(-1),h=null!=u&&function(e,t){const s=e.x-t.x,r=e.y-t.y,n=e.z-t.z;return s*s+r*r+n*n}(u,i)<=.01;return o&&h?{success:!0,path:l.map(e=>new n(e.x,e.y,e.z))}:(m("Failed to generate path",a),f)}findClosestPoint(e,t=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return m("NavMesh has not been generated yet"),null;const{success:s,point:r}=this.query.findClosestPoint(e,{filter:this.getFilter(t)});return s?new n(r.x,r.y,r.z):null}findRandomPoint(e=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return m("NavMesh has not been generated yet"),null;const t=this.query.findRandomPoint({filter:this.getFilter(e)});return{success:t.success,randomPoint:(new n).copy(t.randomPoint)}}findRandomPointAroundCircle(e,t,s=NavigationQueryProfiles.Walker){if(this.ensureQuery(),null==this.query)return m("NavMesh has not been generated yet"),null;const r=this.query.findRandomPointAroundCircle(e,t,{filter:this.getFilter(s)});return{success:r.success,randomPoint:(new n).copy(r.randomPoint)}}};d=e([i(),t("design:paramtypes",[])],d);export{d as Navigation};const f={success:!1,path:[]};let y=new Set;function m(e,...t){y.has(e)||(y.add(e),setTimeout(()=>y.delete(e),2e3),console.warn(e,...t))}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -701,7 +701,7 @@ export declare class PhysicsSystem extends AbstractPhysicsSystem {
701
701
  * @param attr
702
702
  * @returns
703
703
  */
704
- export declare function extractFloat32Array(attr: THREE.BufferAttribute | THREE.InterleavedBufferAttribute): Float32Array;
704
+ export { extractFloat32Array } from '../../../scene/collision/rapier-shape.js';
705
705
  type ColliderCollisionEvent = {
706
706
  actor: BaseActor;
707
707
  };
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as o,distinctUntilChanged as n,filter as r,map as a,Subject as l,takeUntil as c}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as p,Group as y,LineSegments as g,Matrix4 as m,Object3D as b,Quaternion as f,Raycaster as w,Scene as x,Vector3 as v}from"three";import*as B from"three/examples/jsm/utils/BufferGeometryUtils.js";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{BoxCollisionShape as R,CapsuleCollisionShape as M,ConeCollisionShape as E,ConvexPolyhedronCollisionShape as T,CylinderCollisionShape as z,PhysicalShapeMesh as P,PlaneCollisionShape as F,SphereCollisionShape as I,toInstancedCollisionShape as j,TrimeshCollisionShape as _}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as W}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as O}from"../../../scene/landscape/landscape.js";import{calculateEffectiveScale as N}from"../../../utils/three/traverse.js";import{ViewController as L}from"../render.js";import{World as k}from"../world.js";import{AbstractPhysicsSystem as V}from"./abstract-physics-system.js";import{NetRole as U}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.hitNormal=new v}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new v,this.normal=new v}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const G=new v,K=new v,X=new f,q=new f,H=new f;let Q=class extends V{set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.colliderObjects=new WeakMap,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new l,this.beforeStep=new l,this.afterStep=new l,this.shouldRenderDebug=!1,this.viewController=C(L),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new w,this._reusableResult=new RayTestResult,this._raytestDiff=new v,this._raytestDirection=new v,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(G),i=t.getSize(K),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,X,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,X,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,X)&&o.push(n)}return o}createDebugMesh(){const t=new g(new p,new d.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new u(t,3);o.setUsage(d.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(s.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(s.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await pt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!this._isStopped){t=Math.min(.04,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===U.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.lastEmptyPhysicsWorld=void 0,this.world.timestep=0,this.world.step()}updatePhysics(t){if(this._isStopped)return;this.world.timestep=t;const e=0===this.world.bodies.len()&&0===this.world.colliders.len();e&&this.lastEmptyPhysicsWorld===this.world||this.world.step(this.eventQueue),this.lastEmptyPhysicsWorld=e?this.world:void 0,this.eventQueue.drainCollisionEvents(this.handleCollisionEvent)}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(ct,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,o){null==i&&(i=this._reusableResult),i.hasHit=!1,i.actor=void 0,i.object=void 0,i.instanceId=void 0,i.batchId=void 0;const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==Bt&&(Bt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),yt(Bt.origin,t),yt(Bt.dir,r);const l=this.world.castRayAndGetNormal(Bt,a,!1,o?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,o?.collisionFilter,void 0,null!=o?.excludeActor?this.actorBodies.get(o.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit){const e=this.colliderObjects.get(l.collider);if(i.object=e?.object,i.instanceId=e?.instanceId,i.batchId=e?.batchId,i._internal=l,mt(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==o?.resolveActor){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}}return this.showDebug&&!1!==o?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,o?.debugColor,o?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new h(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return Z.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())bt(t,t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof P&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof W){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof O?this.addLandscapeGroup(t):(t instanceof y||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new m;if(t instanceof d.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof W&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new b;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);const d=this.createStaticBody(c,l),h={object:t,batchId:n};bt(d,t=>this.colliderObjects.set(t,h))}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new b;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);const n=this.createStaticBody(o,s),r={object:t,instanceId:e};bt(n,t=>this.colliderObjects.set(t,r))}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>j(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,void 0);const a=e.computedMovement();return mt(ft,a),ft}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(vt)??et,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),ot.set(0,s,0).multiply(r),yt(it,ot),n.setTranslationWrtParent(it),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,o,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(vt)??et,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,o*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(H)??X;ot.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(ot,u,h,s.EXCLUDE_SENSORS,r??void 0,void 0,a,xt)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,o=null){const n=t.collider;e.computeColliderMovement(n,i,s.EXCLUDE_SENSORS,o,void 0);const r=e.computedMovement();return mt(ft,r),ft}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(it);s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setNextKinematicTranslation(dt(i)),t.setNextKinematicRotation(ht(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setAngvel(it,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.setLinvel(it,!0)}getLinearVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new v){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(dt(e),!1)}getPosition(t,e=new v){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setRotation(ht(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,s=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new v);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);yt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(l,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=s.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=i.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);yt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(h,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);wt.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),bt(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),Y(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addTorque(it,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyTorqueImpulse(it,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.addForce(it,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);it.x=e.x,it.y=e.y,it.z=e.z,i?.applyImpulse(it,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);yt(it,e),null==i?s?.addForce(it,!0):(yt(st,i),s?.addForceAtPoint(it,st,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);yt(it,e),null==i?s.applyImpulse(it,!0):(yt(st,i),s.applyImpulseAtPoint(it,st,!0))}applyRadialImpulse(t,e,i){return e<=0||0===i?0:this.applyImpulseToBodiesInRadius(t,e,(t,s,o)=>{o<=1e-6?s.set(0,1,0):s.multiplyScalar(1/o),s.multiplyScalar(i*Math.max(0,1-o/e)),yt(it,s),t.applyImpulse(it,!0)})}applyDirectionalImpulse(t,e,i,s,o){if(i<=0||0===o||e.lengthSq()<=1e-12)return 0;nt.copy(e).normalize();const n=Math.cos(Math.max(0,Math.min(Math.PI,s)));return this.applyImpulseToBodiesInRadius(t,i,(t,e,i)=>{if(i>1e-6&&e.multiplyScalar(1/i).dot(nt)<n)return!1;it.x=nt.x*o,it.y=nt.y*o,it.z=nt.z*o,t.applyImpulse(it,!0)})}applyImpulseToBodiesInRadius(t,e,i){const o=at,n=lt;o.clear(),n.length=0;let r=0;this.world.intersectionsWithShape(t,X,this.getBallShape(e),t=>{const e=t.parent();return null==e||o.has(e.handle)||(o.add(e.handle),n.push(e)),!0},s.ONLY_DYNAMIC|s.EXCLUDE_SENSORS);for(const e of n)mt(rt,e.worldCom()),rt.sub(t),!1!==i(e,rt,rt.length())&&r++;return o.clear(),n.length=0,r}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof O){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(({started:t})=>t===i),a(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),r(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),a(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(c(t.disposed),r(t=>!t.started),r(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),a(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new o(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(n())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(Y(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,o,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);it.x=i.x,it.y=i.y,it.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,X,it,a,.01,o,!0,r?.excludeTriggers?s.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){mt(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}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 mt(s.hitPoint,u.witness1),St(t.rotation(),u.normal1,s.normal,q),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.fixed(),n=this.world.createRigidBody(o);s?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);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.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(vt)??et,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);yt(o.translation,n);const r=(new f).setFromEuler(e.rotation);gt(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{const s=this.world.createCollider(o,t),n=i??(e instanceof T&&e.mesh instanceof b?e.mesh:void 0);return null!=n&&this.colliderObjects.set(s,{object:n}),s}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=i.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=i.MassPropsMode.Mass)}createShape(t,e){if(t instanceof R)return this.rapier.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof M){return this.rapier.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof _){const i=null!=t.geometry.getIndex()?t.geometry:B.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 T){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=N(t.mesh));const o=`${i.uuid}|${s?.x??1},${s?.y??1},${s?.z??1}|${e.x},${e.y},${e.z}`,n=tt.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}),tt.set(o,a),a}if(t instanceof I){const i=2*e.x-e.y-e.z;return Math.abs(i)>.01?this.createShape(new T(new d.SphereGeometry(t.radius).scale(e.x,e.y,e.z)),new v(1,1,1)):this.rapier.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z))}return t instanceof z?this.rapier.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof E?this.rapier.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof F?this.rapier.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.001):(console.error("Unsupported shape",t),this.rapier.ColliderDesc.cuboid(1,1,1))}createCharacterCollision(){return new this.rapier.CharacterCollision}};Q=t([D(),e("design:paramtypes",[])],Q);export{Q as PhysicsSystem};const J=new v,$=new d.Quaternion;function Y(t,e){const i=e.getWorldPosition(J),s=e.getWorldQuaternion($);t.setTranslation(dt(i),!1),t.setRotation(ht(s),!1)}const Z=new v,tt=new Map,et=new v(1,1,1),it=new i.Vector3(0,0,0),st=new i.Vector3(0,0,0),ot=new v,nt=new v,rt=new v,at=new Set,lt=[],ct=new d.Vector2;function dt(t){return yt(it,t),it}function ht(t){return gt(q,t),q}let ut=null;const pt=async()=>(null==ut&&(ut=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ut);function yt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function gt(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function mt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function bt(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const ft=new v,wt=new WeakMap,xt=t=>wt.get(t)??!0,vt=new v;let Bt,Dt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(Q),this.world=C(k)}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}};Dt=t([A()],Dt);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 St(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new l,this.onBeginOverlapActor=new l,this.onEndOverlapActor=new l}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return i.RigidBodyType.Dynamic;case PhysicsBodyType.static:return i.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return i.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return i.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import{createRapierCollisionShape as i}from"../../../scene/collision/rapier-shape.js";import*as s from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as o}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as n,distinctUntilChanged as r,filter as a,map as l,Subject as c,takeUntil as d}from"rxjs";import*as h from"three";import{ArrowHelper as u,BufferAttribute as p,BufferGeometry as y,Group as g,LineSegments as m,Matrix4 as b,Object3D as w,Quaternion as f,Raycaster as v,Scene as x,Vector3 as B}from"three";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{ConvexPolyhedronCollisionShape as R,PhysicalShapeMesh as E,toInstancedCollisionShape as M}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as T}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as P,LandscapeMesh as z}from"../../../scene/landscape/landscape.js";import{ViewController as F}from"../render.js";import{World as j}from"../world.js";import{AbstractPhysicsSystem as I}from"./abstract-physics-system.js";import{NetRole as _}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const N=new B,W=new B,O=new f,L=new f,k=new f;let V=class extends I{isLandscapeNavigationCollider(t){return this.colliderObjects.get(t)?.object instanceof z}forEachStaticActorNavigationCollider(t,e){const i=this.actorBodies.get(t.id);if(i?.isFixed()&&i.isEnabled()&&!0!==i.userData?.ignoreForNavMesh)for(let t=0;t<i.numColliders();t++){const s=i.collider(t);s.isEnabled()&&!s.isSensor()&&e(s)}}set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.colliderObjects=new WeakMap,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new c,this.beforeStep=new c,this.afterStep=new c,this.shouldRenderDebug=!1,this.viewController=C(F),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new v,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(N),i=t.getSize(W),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,O,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,O,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,O)&&o.push(n)}return o}createDebugMesh(){const t=new m(new y,new h.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new p(t,3);o.setUsage(h.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(o.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(o.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await nt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!this._isStopped){t=Math.min(.04,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===_.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.lastEmptyPhysicsWorld=void 0,this.world.timestep=0,this.world.step()}updatePhysics(t){if(this._isStopped)return;this.world.timestep=t;const e=0===this.world.bodies.len()&&0===this.world.colliders.len();e&&this.lastEmptyPhysicsWorld===this.world||this.world.step(this.eventQueue),this.lastEmptyPhysicsWorld=e?this.world:void 0,this.eventQueue.drainCollisionEvents(this.handleCollisionEvent)}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(et,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),i.hasHit=!1,i.actor=void 0,i.object=void 0,i.instanceId=void 0,i.batchId=void 0;const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==yt&&(yt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),rt(yt.origin,t),rt(yt.dir,r);const l=this.world.castRayAndGetNormal(yt,a,!1,s?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit){const e=this.colliderObjects.get(l.collider);if(i.object=e?.object,i.instanceId=e?.instanceId,i.batchId=e?.batchId,i._internal=l,lt(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==s?.resolveActor){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}}return this.showDebug&&!1!==s?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,s?.debugColor,s?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new u(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return X.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())ct(t,t=>t.setActiveEvents(s.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 E&&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 T){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)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof P?this.addLandscapeGroup(t):(t instanceof g||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new b;if(t instanceof h.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof T&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new w;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);const d=this.createStaticBody(c,l),h={object:t,batchId:n};ct(d,t=>this.colliderObjects.set(t,h))}}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 w;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);const n=this.createStaticBody(o,s),r={object:t,instanceId:e};ct(n,t=>this.colliderObjects.set(t,r))}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>M(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,s=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,o.EXCLUDE_SENSORS,s,void 0);const a=e.computedMovement();return lt(dt,a),dt}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(pt)??q,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),J.set(0,s,0).multiply(r),rt(H,J),n.setTranslationWrtParent(H),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,s,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(pt)??q,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,s*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(k)??O;J.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(J,u,h,o.EXCLUDE_SENSORS,r??void 0,void 0,a,ut)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,s=null){const n=t.collider;e.computeColliderMovement(n,i,o.EXCLUDE_SENSORS,s,void 0);const r=e.computedMovement();return lt(dt,r),dt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(H);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(U),s=e.getWorldQuaternion(K);t.setNextKinematicTranslation(it(i)),t.setNextKinematicRotation(st(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setAngvel(H,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setLinvel(H,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(it(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setRotation(st(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,i=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(l,t);this.colliderObjects.set(i,{object:n}),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=i.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=s.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(h,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);ht.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),ct(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),G(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.addTorque(H,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyTorqueImpulse(H,!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);H.x=e.x,H.y=e.y,H.z=e.z,i?.addForce(H,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyImpulse(H,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s?.addForce(H,!0):(rt(Q,i),s?.addForceAtPoint(H,Q,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s.applyImpulse(H,!0):(rt(Q,i),s.applyImpulseAtPoint(H,Q,!0))}applyRadialImpulse(t,e,i){return e<=0||0===i?0:this.applyImpulseToBodiesInRadius(t,e,(t,s,o)=>{o<=1e-6?s.set(0,1,0):s.multiplyScalar(1/o),s.multiplyScalar(i*Math.max(0,1-o/e)),rt(H,s),t.applyImpulse(H,!0)})}applyDirectionalImpulse(t,e,i,s,o){if(i<=0||0===o||e.lengthSq()<=1e-12)return 0;Y.copy(e).normalize();const n=Math.cos(Math.max(0,Math.min(Math.PI,s)));return this.applyImpulseToBodiesInRadius(t,i,(t,e,i)=>{if(i>1e-6&&e.multiplyScalar(1/i).dot(Y)<n)return!1;H.x=Y.x*o,H.y=Y.y*o,H.z=Y.z*o,t.applyImpulse(H,!0)})}applyImpulseToBodiesInRadius(t,e,i){const s=$,n=tt;s.clear(),n.length=0;let r=0;this.world.intersectionsWithShape(t,O,this.getBallShape(e),t=>{const e=t.parent();return null==e||s.has(e.handle)||(s.add(e.handle),n.push(e)),!0},o.ONLY_DYNAMIC|o.EXCLUDE_SENSORS);for(const e of n)lt(Z,e.worldCom()),Z.sub(t),!1!==i(e,Z,Z.length())&&r++;return s.clear(),n.length=0,r}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof P){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(({started:t})=>t===i),l(({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})),a(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),l(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>!t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new n(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(r())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(G(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,s,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);H.x=i.x,H.y=i.y,H.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,O,H,a,.01,s,!0,r?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){lt(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}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 lt(s.hitPoint,u.witness1),mt(t.rotation(),u.normal1,s.normal,L),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,i){const o=i?.type===PhysicsBodyType.dynamic?s.RigidBodyDesc.dynamic():s.RigidBodyDesc.fixed(),n=this.world.createRigidBody(o);i?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);let r=0;for(const s of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==s){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,s,t);null!=o&&(null!=i?.friction&&o.setFriction(i.friction),null!=i?.density&&o.setDensity(i.density),null!=i?.mass&&o.setMass(i.mass/e.length),null!=i?.restitution&&o.setRestitution(i.restitution))}return G(n,t),n.userData=t.uuid,n.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(pt)??q,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);rt(o.translation,n);const r=(new f).setFromEuler(e.rotation);at(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{const s=this.world.createCollider(o,t),n=i??(e instanceof R&&e.mesh instanceof w?e.mesh:void 0);return null!=n&&this.colliderObjects.set(s,{object:n}),s}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=s.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=s.MassPropsMode.Mass)}createShape(t,e){return i(this.rapier,t,e)}createCharacterCollision(){return new this.rapier.CharacterCollision}};V=t([D(),e("design:paramtypes",[])],V);export{V as PhysicsSystem};const U=new B,K=new h.Quaternion;function G(t,e){const i=e.getWorldPosition(U),s=e.getWorldQuaternion(K);t.setTranslation(it(i),!1),t.setRotation(st(s),!1)}const X=new B,q=new B(1,1,1),H=new s.Vector3(0,0,0),Q=new s.Vector3(0,0,0),J=new B,Y=new B,Z=new B,$=new Set,tt=[],et=new h.Vector2;function it(t){return rt(H,t),H}function st(t){return at(L,t),L}let ot=null;const nt=async()=>(null==ot&&(ot=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ot);function rt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function at(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const dt=new B,ht=new WeakMap,ut=t=>ht.get(t)??!0,pt=new B;let yt,gt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(V),this.world=C(j)}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}};gt=t([A()],gt);export{extractFloat32Array}from"../../../scene/collision/rapier-shape.js";function mt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new c,this.onBeginOverlapActor=new c,this.onEndOverlapActor=new c}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return s.RigidBodyType.Dynamic;case PhysicsBodyType.static:return s.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return s.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return s.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */