@hology/core 0.0.270 → 0.0.272

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 (68) hide show
  1. package/dist/effects/sequence/sequence-player.js +1 -1
  2. package/dist/effects/vfx/gpu-sprite-compiler.js +1 -1
  3. package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
  4. package/dist/effects/vfx/gpu-vfx-world-service.d.ts +2 -0
  5. package/dist/effects/vfx/gpu-vfx-world-service.js +1 -1
  6. package/dist/effects/vfx/vfx-actor.js +1 -1
  7. package/dist/effects/vfx/vfx-materializer.js +1 -1
  8. package/dist/effects/vfx/vfx-render-preparation.d.ts +3 -0
  9. package/dist/effects/vfx/vfx-render-preparation.js +1 -1
  10. package/dist/gameplay/actors/builtin/components/spline-component.d.ts +7 -39
  11. package/dist/gameplay/actors/builtin/components/spline-component.js +1 -1
  12. package/dist/gameplay/actors/builtin/navmesh-actor.d.ts +16 -2
  13. package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
  14. package/dist/gameplay/actors/builtin/water-spline-volume-actor.d.ts +2 -2
  15. package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +1 -1
  16. package/dist/gameplay/ai/build-tile.js +1 -1
  17. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +1 -1
  18. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.js +1 -1
  19. package/dist/gameplay/ai/navigation.d.ts +2 -0
  20. package/dist/gameplay/ai/navigation.js +1 -1
  21. package/dist/gameplay/initiate.js +1 -1
  22. package/dist/gameplay/services/physics/physics-system.d.ts +1 -1
  23. package/dist/gameplay/services/physics/physics-system.js +1 -1
  24. package/dist/gameplay/services/render.js +1 -1
  25. package/dist/navigation/bake.d.ts +68 -0
  26. package/dist/navigation/bake.js +4 -0
  27. package/dist/navigation/cache.d.ts +11 -0
  28. package/dist/navigation/cache.js +4 -0
  29. package/dist/navigation/spline-data.d.ts +64 -0
  30. package/dist/navigation/spline-data.js +4 -0
  31. package/dist/navigation/water-spline-geometry.d.ts +23 -0
  32. package/dist/navigation/water-spline-geometry.js +4 -0
  33. package/dist/scene/asset-resource-loader.d.ts +7 -3
  34. package/dist/scene/asset-resource-loader.js +1 -1
  35. package/dist/scene/bootstrap.js +1 -1
  36. package/dist/scene/collision/authored-colliders.d.ts +4 -0
  37. package/dist/scene/collision/authored-colliders.js +4 -0
  38. package/dist/scene/collision/rapier-shape.d.ts +7 -0
  39. package/dist/scene/collision/rapier-shape.js +4 -0
  40. package/dist/scene/materializer.d.ts +4 -1
  41. package/dist/scene/materializer.js +1 -1
  42. package/dist/scene/model.d.ts +4 -0
  43. package/dist/scene/native-texture.d.ts +13 -0
  44. package/dist/scene/native-texture.js +4 -0
  45. package/dist/scene/objects/shapes.js +1 -1
  46. package/dist/scene/runtime-backend-service.d.ts +1 -0
  47. package/dist/scene/runtime-bundled-backend-service.d.ts +1 -0
  48. package/dist/scene/runtime-bundled-backend-service.js +1 -1
  49. package/dist/shader-nodes/particle-parameter.d.ts +4 -0
  50. package/dist/shader-nodes/particle-parameter.js +4 -0
  51. package/dist/test/asset-resource-loader-texture-array.test.js +1 -1
  52. package/dist/test/authored-collision-rescale.test.js +1 -1
  53. package/dist/test/gpu-sprite-compiler.test.js +1 -1
  54. package/dist/test/gpu-sprite-pipeline-cache.test.js +1 -1
  55. package/dist/test/gpu-vfx-preload.test.d.ts +2 -0
  56. package/dist/test/gpu-vfx-preload.test.js +4 -0
  57. package/dist/test/materializer-prefetch.test.js +1 -1
  58. package/dist/test/native-texture.test.d.ts +2 -0
  59. package/dist/test/native-texture.test.js +4 -0
  60. package/dist/test/navigation-bake-backend.test.d.ts +2 -0
  61. package/dist/test/navigation-bake-backend.test.js +4 -0
  62. package/dist/test/navigation-bake.test.d.ts +2 -0
  63. package/dist/test/navigation-bake.test.js +4 -0
  64. package/dist/test/sequence-vfx.test.js +1 -1
  65. package/dist/test/shader-graph.test.js +1 -1
  66. package/dist/test/vfx-render-preparation.test.js +1 -1
  67. package/package.json +6 -2
  68. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,4 @@
1
+ import{Subject as t}from"rxjs";import{Vector3 as n}from"three";const s='{"closed":false,"points":[[0,0,0,0,0,0,2,0,0],[5,0,0,-2,0,0,0,0,0]]}';export class SplineData{constructor(){this.splineData=s,this.changed=new t,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(i),this._closed=n,this.commitChange()}updatePoint(t,n){t<0||t>=this._points.length||(this._points[t]=i(n),this.commitChange())}addPoint(t,n=this._points.length){this._points.splice(Math.max(0,Math.min(n,this._points.length)),0,i(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),c=o.position,l=a.clone().lerp(h,n),p=h.clone().lerp(r,n),g=r.clone().lerp(c,n),u=l.clone().lerp(p,n),m=p.clone().lerp(g,n),T=u.clone().lerp(m,n);e.outTangent.copy(l).sub(a),o.inTangent.copy(g).sub(c);const d=t+1;return this._points.splice(d,0,{position:T,inTangent:u.sub(T),outTangent:m.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,s=new n){const i=this.resolveSegment(t);return i?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)}(i.a,i.b,i.u,s):s.set(0,0,0)}sampleTangent(t,s=new n){const i=this.resolveSegment(t);return i?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)}(i.a,i.b,i.u,s).normalize():s.set(0,0,0)}samplePositionAtDistance(t,s=new n){return this.samplePosition(this.tAtDistance(t),s)}sampleTangentAtDistance(t,s=new n){return this.sampleTangent(this.tAtDistance(t),s)}closestPoint(t,s=new n){if(0===this.arcTs.length)return{position:s.set(0,0,0),tangent:new n,t:0,distance:t.length(),distanceAlongSpline:0};let i=0,e=1/0;const o=new n;for(let n=0;n<this.arcTs.length;n++){this.samplePosition(this.arcTs[n],o);const s=o.distanceToSquared(t);s<e&&(e=s,i=this.arcTs[n])}const a=this.arcTs.length>1?1/(this.arcTs.length-1):1;let h=Math.max(0,i-a),r=Math.min(1,i+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 i=.5*(h+r),this.samplePosition(i,s),{position:s,tangent:this.sampleTangent(i),t:i,distance:s.distanceTo(t),distanceAlongSpline:this.distanceAtT(i)}}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 s=this.samplePosition(0,new n),i=new n;let e=0;for(let n=1;n<=t;n++){const o=n/t;this.samplePosition(o,i),e+=s.distanceTo(i),this.arcTs[n]=o,this.arcLengths[n]=e,s.copy(i)}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)}}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 i;try{i=JSON.parse(t)}catch{i=JSON.parse(s)}return{closed:!0===i.closed,points:(i.points??[]).filter(t=>t.length>=9).map(t=>({position:(new n).fromArray(t,0),inTangent:(new n).fromArray(t,3),outTangent:(new n).fromArray(t,6)}))}}function i(t){return{position:t.position.clone(),inTangent:t.inTangent.clone(),outTangent:t.outTangent.clone()}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,23 @@
1
+ import { BufferGeometry, Vector3 } from 'three';
2
+ export interface WaterSplineSampler {
3
+ readonly points: readonly unknown[];
4
+ readonly length: number;
5
+ readonly closed: boolean;
6
+ samplePositionAtDistance(distance: number, target: Vector3): Vector3;
7
+ sampleTangentAtDistance(distance: number, target: Vector3): Vector3;
8
+ }
9
+ type CrossSection = {
10
+ leftTop: Vector3;
11
+ rightTop: Vector3;
12
+ leftBottom: Vector3;
13
+ rightBottom: Vector3;
14
+ flowDirection: Vector3;
15
+ distanceAlongSpline: number;
16
+ surfaceWidth: number;
17
+ };
18
+ export declare function createCrossSections(spline: WaterSplineSampler, width: number, depth: number, sampleDistance?: number): CrossSection[];
19
+ export declare function createWaterSplineSurfaceGeometry(spline: WaterSplineSampler, width: number, sampleDistance: number, widthSubdivisions: number): BufferGeometry;
20
+ export declare function createSurfaceGeometry(spline: WaterSplineSampler, width: number, sampleDistance: number, widthSubdivisions: number): BufferGeometry;
21
+ export declare function createVolumeGeometry(spline: WaterSplineSampler, width: number, depth: number, showSurface?: boolean, sampleDistance?: number): BufferGeometry;
22
+ export {};
23
+ //# sourceMappingURL=water-spline-geometry.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{BufferGeometry as t,Float32BufferAttribute as e,Vector3 as n}from"three";export function createCrossSections(t,e,a,h=.5){if(t.points.length<2||t.length<=0||e<=0||a<0)return[];const p=Math.min(513,Math.max(2,Math.ceil(t.length/Math.max(.01,h))+1)),u=[],f=Array.from({length:p},(e,o)=>t.samplePositionAtDistance(t.length*o/(p-1),new n)),g=Math.min(.5*e,.25*t.length),m=Array.from({length:p},(e,o)=>{const c=t.length*o/(p-1),i=r(t,c-g,new n),l=r(t,c+g,new n).sub(i).setY(0);return l.lengthSq()<1e-8&&t.sampleTangentAtDistance(c,l).setY(0),l.lengthSq()<1e-8&&l.set(1,0,0),l.normalize(),new n(-l.z,0,l.x)}),d=.5*e,x=Array(p).fill(d),A=Array(p).fill(d);for(let e=0;e<p;e++){if(!t.closed&&(0===e||e===p-1))continue;const n=f[0===e?p-2:e-1],o=f[e],r=f[e===p-1?1:e+1],c=Math.min(d,.6*l(n,o,r)),a=i(n,o,r);a>1e-8?x[e]=c:a<-1e-8&&(A[e]=c)}c(x,f),c(A,f);for(let e=0;e<p;e++){const o=m[e],r=f[e].clone().addScaledVector(o,x[e]),c=f[e].clone().addScaledVector(o,-A[e]);u.push({leftTop:r,rightTop:c,leftBottom:r.clone().addScaledVector(s,a),rightBottom:c.clone().addScaledVector(s,a),flowDirection:t.sampleTangentAtDistance(t.length*e/(p-1),new n).normalize(),distanceAlongSpline:t.length*e/(p-1),surfaceWidth:x[e]+A[e]})}return function(t,e,n){o(t.map(t=>t.leftTop),e),o(t.map(t=>t.rightTop),e);for(const e of t)e.leftBottom.copy(e.leftTop).addScaledVector(s,n),e.rightBottom.copy(e.rightTop).addScaledVector(s,n),e.surfaceWidth=e.leftTop.distanceTo(e.rightTop)}(u,t.closed,a),u}function o(t,e){const n=e?t.length-1:t.length;if(!(n<3))for(let o=0;o<2;o++){const o=t.map(t=>t.clone()),r=e?n:n-1;for(let c=e?0:1;c<r;c++){const e=o[(c-1+n)%n],r=o[(c+1)%n];t[c].lerpVectors(e,r,.5).lerp(o[c],.5)}e&&t[t.length-1].copy(t[0])}}function r(t,e,n){if(!t.closed)return t.samplePositionAtDistance(e,n);const o=(e%t.length+t.length)%t.length;return t.samplePositionAtDistance(o,n)}function c(t,e){for(let n=1;n<t.length;n++)t[n]=Math.min(t[n],t[n-1]+.5*e[n].distanceTo(e[n-1]));for(let n=t.length-2;n>=0;n--)t[n]=Math.min(t[n],t[n+1]+.5*e[n].distanceTo(e[n+1]))}function i(t,e,n){return(e.x-t.x)*(n.z-e.z)-(e.z-t.z)*(n.x-e.x)}function l(t,e,n){const o=Math.hypot(e.x-t.x,e.z-t.z),r=Math.hypot(n.x-e.x,n.z-e.z),c=Math.hypot(n.x-t.x,n.z-t.z),i=Math.abs((e.x-t.x)*(n.z-t.z)-(e.z-t.z)*(n.x-t.x));return o<1e-6||r<1e-6||c<1e-6||i<1e-8?1/0:o*r*c/(2*i)}export function createWaterSplineSurfaceGeometry(t,e,n,o){return createSurfaceGeometry(t,e,n,o)}export function createSurfaceGeometry(n,o,r,c){const i=new t,l=createCrossSections(n,o,0,r),s=Math.max(1,Math.round(c))+1;if(l.length<2)return i.setAttribute("position",new e([],3)),i;const h=[],p=[],u=[],f=[],g=[];for(const t of l)for(let e=0;e<s;e++){const o=e/(s-1);h.push(...t.leftTop.clone().lerp(t.rightTop,o).toArray()),p.push(o,n.length>0?t.distanceAlongSpline/n.length:0),u.push(...t.flowDirection.toArray()),f.push(Math.min(o,1-o)*t.surfaceWidth),g.push(t.distanceAlongSpline)}const m=[];for(let t=1;t<l.length;t++)for(let e=1;e<s;e++){const n=(t-1)*s+e-1,o=t*s+e-1;a(m,n,o,o+1,n+1)}return i.setAttribute("position",new e(h,3)),i.setAttribute("uv",new e(p,2)),i.setAttribute("waterFlowDirection",new e(u,3)),i.setAttribute("waterDistanceFromBank",new e(f,1)),i.setAttribute("waterDistanceAlongSpline",new e(g,1)),i.setIndex(m),i.computeVertexNormals(),i.computeBoundingBox(),i.computeBoundingSphere(),i}export function createVolumeGeometry(n,o,r,c=!1,i=.5){const l=new t,s=createCrossSections(n,o,r,i);if(s.length<2)return l.setAttribute("position",new e([],3)),l;const h=s.flatMap(t=>[...t.leftTop.toArray(),...t.rightTop.toArray(),...t.leftBottom.toArray(),...t.rightBottom.toArray()]),p=[];for(let t=1;t<s.length;t++){const e=4*(t-1),n=4*t;c||a(p,e,n,n+1,e+1),a(p,e+2,e+3,n+3,n+2),a(p,e,e+2,n+2,n),a(p,e+1,n+1,n+3,e+3)}if(!n.closed){a(p,0,1,3,2);const t=4*(s.length-1);a(p,t,t+2,t+3,t+1)}return l.setAttribute("position",new e(h,3)),l.setIndex(p),l.computeVertexNormals(),l.computeBoundingBox(),l.computeBoundingSphere(),l}function a(t,e,n,o,r){t.push(e,n,o,e,o,r)}const s=new n(0,-1,0);/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,6 +1,6 @@
1
1
  import type { Material } from 'three';
2
2
  import { BufferGeometry, Object3D, Texture } from 'three';
3
- import type { AnimationRigData, Asset, AssetId, ModelColliderData } from './model.js';
3
+ import type { AnimationRigData, Asset, AssetId } from './model.js';
4
4
  import type { CollisionShape } from './collision/collision-shape.js';
5
5
  import * as THREE from 'three';
6
6
  import type { SceneObjectPhysicsSettings } from './materializer.js';
@@ -19,6 +19,9 @@ export declare class AssetResourceLoader {
19
19
  private hdrLoader;
20
20
  private ktx2Loader;
21
21
  private ktx2Ready;
22
+ private nativeTextureLoader;
23
+ private nativeBcSupported;
24
+ private nativeAstcSupported;
22
25
  private _textureLoader;
23
26
  private audioLoader;
24
27
  private initialisedKtx2;
@@ -41,7 +44,7 @@ export declare class AssetResourceLoader {
41
44
  decodeImageBitmap(url: string): Promise<ImageBitmap> | undefined;
42
45
  private configureKtx2;
43
46
  initKtx2(renderer: THREE.WebGLRenderer): void;
44
- initKtx2ForWebGpu(): void;
47
+ initKtx2ForWebGpu(device?: GPUDevice): void;
45
48
  setDataDir(path: string): void;
46
49
  private getUri;
47
50
  private _texturePromises;
@@ -61,6 +64,7 @@ export declare class AssetResourceLoader {
61
64
  texture: Texture | null;
62
65
  layerIndex: number | null;
63
66
  }>;
67
+ private loadKtx2Texture;
64
68
  private loadTextureArray;
65
69
  private applyTextureArraySettings;
66
70
  private _getTextureLoader;
@@ -117,7 +121,7 @@ export declare class AssetMeshInstance extends Object3D {
117
121
  collisionShapes?: CollisionShape[];
118
122
  physics?: SceneObjectPhysicsSettings;
119
123
  }
120
- export declare function createAuthoredCollisionShapes(colliders: ModelColliderData[], assetRescale?: number): CollisionShape[];
124
+ export { createAuthoredCollisionShapes } from './collision/authored-colliders.js';
121
125
  export declare function getElectronArg(name: string): string;
122
126
  /**
123
127
  * Removes triangles that contain non-finite positions or have effectively no
@@ -1,4 +1,4 @@
1
- import{parseAnimationClips as e}from"./animation-binary.js";import{AudioLoader as t,BufferGeometry as r,Euler as a,Group as i,LoadingManager as s,Mesh as n,Object3D as o,Texture as l,TextureLoader as c,Vector3 as h}from"three";import{MTLLoader as u,OBJLoader as m,LUTCubeLoader as d}from"three-stdlib";import{cloneMesh as p,mergeCompatibleSkinnedMeshes as f}from"../utils/mesh.js";import{pathJoin as g}from"../utils/files.js";import{Subject as y,firstValueFrom as w}from"rxjs";import{BoxCollisionShape as x,CapsuleCollisionShape as M,CollisionShapeSource as b,CylinderCollisionShape as A,SphereCollisionShape as L}from"./collision/collision-shape.js";import{importCollisionShapes as S,isCollisionMesh as _}from"./collision/collision-shape-import.js";import*as v from"three";import{iterateMaterials as T}from"../utils/materials.js";import{applyMaterial as R,getConvertedFbxToGlbAssignedMaterialTextureFlipY as C}from"./materializer.js";import{BufferGeometryUtils as B,DRACOLoader as F,EXRLoader as P,FBXLoader as I,GLTFLoader as k,KTX2Loader as K,TGALoader as D,UltraHDRLoader as j}from"three/examples/jsm/Addons.js";import{disposeScene as W}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as U,setAnimationClipRigId as z}from"../gameplay/animation/retarget.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new v.DataTexture(e,1,1,v.RGBAFormat);t.needsUpdate=!0})();const G=new F;G.setDecoderConfig({type:"js"}),G.setDecoderPath("/assets/draco/");const $=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new k(this.loadingManager).setDRACOLoader(G),this.fbxLoader=new I(this.loadingManager),this.objLoader=new m(this.loadingManager),this.textureLoader=new c(this.loadingManager),this.tgaLoader=new D(this.loadingManager),this.exrLoader=new P(this.loadingManager),this.cubeLoader=new d(this.loadingManager),this.hdrLoader=new j(this.loadingManager),this.ktx2Loader=new K(this.loadingManager),this.ktx2Ready=Promise.resolve(),this._textureLoader=new v.ImageBitmapLoader(this.loadingManager),this.audioLoader=new t(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new y,this.ready=w(this.makeReady),this.directFileLoading=!1,this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.clipsRequests=new Set,this.timeToLoadClips=0,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}setDirectFileLoading(e){this.directFileLoading=e}setImageBitmapDecoder(e){this.imageBitmapDecoder=e}decodeImageBitmap(e){return this.imageBitmapDecoder?.(e)}configureKtx2(){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.setWorkerLimit(6)}initKtx2(e){this.configureKtx2(),this.ktx2Loader.detectSupport(e)}initKtx2ForWebGpu(){this.configureKtx2(),this.ktx2Ready=Promise.resolve(navigator.gpu?.requestAdapter({powerPreference:"high-performance"})??null).then(e=>{this.ktx2Loader.detectSupport({isWebGPURenderer:!0,hasFeature:t=>!0===e?.features.has(t)})})}setDataDir(e){this.basePath=g(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){if(e.startsWith("asset://"))return e;const t=function(e){return E.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?g(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(g("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,e.fileKey.toLowerCase().endsWith(".ktx2")&&await this.ktx2Ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=X(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==Y(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=Y(e.texture?.wrapS)):t.wrapT!==Y(e.texture?.wrapT)&&(t.wrapT=Y(e.texture?.wrapT),t.needsUpdate=!0)}const r=J(V(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{const t=this._getTextureLoader(e.fileKey),r=null!=this.imageBitmapDecoder&&/\.(png|jpe?g)$/i.test(e.fileKey),a=r||this.directFileLoading&&t===this.textureLoader,i=this.getUri(e.fileKey),s=r?this.imageBitmapDecoder(i).catch(t=>(console.warn(`Worker image decode failed for ${e.name}; falling back to ImageBitmapLoader`,t),this._textureLoader.loadAsync(i))):(a?this._textureLoader:t).loadAsync(i);await s.then(t=>(a&&((t=new l(t)).needsUpdate=!0),t.texture3D?t=t.texture3D:(t.wrapS=Y(e.texture?.wrapS),t.wrapT=Y(e.texture?.wrapT),t.flipY=X(t,e),t.colorSpace=J(V(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let e=this._arrayTexturePromisesByFileKey.get(t);null==e&&(e=this.loadTextureArray(t).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,e)),a=await e}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadTextureArray(e){const t=this._getTextureLoader(e);let r=await t.loadAsync(this.getUri(e));return r instanceof l||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:Y(e.texture?.wrapS),wrapT:Y(e.texture?.wrapT)}}(r),i=this._arrayTextureSettingsByFileKey.get(e);if(null!=i&&(n=a,(s=i).wrapS!==n.wrapS||s.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var s,n;null==i&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),O(e.fileKey)),null!=e.materialLib&&O(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new i,animations:[]};if(!$.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new i,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new i,animations:[]}}const a=this.cache.get(r),s=a.scene,o=a.animations;if(!1===t?.clone)return{scene:s,animations:o};const l=this.computeCollisionShapes(e,s),c=(e.mesh?.secondaryMotion?.regions.length??0)>0;!0!==t?.mergeGeomtries||c||this.optimizeDrawGroups(s);const h=p(s);h.traverse(e=>{e instanceof n&&e.material instanceof Array&&(e.material=e.material.slice())});const u=new AssetMeshInstance;u.add(h),u.collisionShapes=l,u.animations=o,u.userData.assetId=e.id,u.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const i=e instanceof n?"Mesh":"Group",s=`${t}/${e.name?.trim()?.length>0?e.name:i}[${a}]`;e.userData.secondaryMotionMeshPath=s;for(let t=0;t<e.children.length;t++)r(e.children[t],s,t)}}(u);const m=e.mesh?.animationRigId??e.anim?.rigId;if(u.userData.animationRigId=m,h.userData.animationRigId=m,null!=m&&null!=this.animationRigProvider){const e=await this.animationRigProvider(m);u.userData.animationRig=e,h.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&u.quaternion.copy(U(e))}const d=e.receiveShadow??!1,f=e.castShadow??!1;if(h.traverse(e=>{e.castShadow=f,e.receiveShadow=d}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&u.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await R(u,t,r,void 0,{textureFlipY:C(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:u,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(t){if(null==t||null==t.fileKey||null==t.anim?.clip)return console.warn("Asset or animation clip name is not defined",t),null;const r=t.anim.clip,a=t.fileKey,i=a+"|"+r;if(this._animationCache.has(i))return this._animationCache.get(i);if(this._animationPromises.has(i))return this._animationPromises.get(i);this.clipsRequests.add(t.id);const s=(async()=>{try{const s=("anim"===t.fileFormat?e(await new v.FileLoader(this.loadingManager).setResponseType("arraybuffer").loadAsync(this.getUri(a))):(await this.getMesh(t,{mergeGeomtries:!1,clone:!1})).animations).find(e=>e.name===r);return null!=s&&(z(s,t.anim?.rigId),this._animationCache.set(i,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(i),1e3)}})();return this._animationPromises.set(i,s),s}computeCollisionShapes(e,t){if(!0!==e.collisionDetection)return[];const r=e.id+"|"+(e.mesh?.collisions?.shapeType??"")+"|"+(e.mesh?.rescale??1)+"|"+JSON.stringify(e.mesh?.colliders??[]);if(!this.collisionShapeCache.has(r)){const a=e.mesh?.colliders??[],i=a.length>0?createAuthoredCollisionShapes(a,e.mesh?.rescale):S(t,e);this.collisionShapeCache.set(r,i)}return this.collisionShapeCache.get(r)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(t=>(t.scene.traverse(t=>{if(t instanceof n&&t.geometry instanceof r){const r=removeInvalidFaces(t.geometry);r>0&&console.warn(`Removed ${r} invalid face${1===r?"":"s"} from ${e.name}/${t.name||"unnamed mesh"}`)}t instanceof n&&t.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(ee):e.material=ee(t)}(t),_(t)?t.visible=!1:t instanceof n&&t.geometry instanceof r&&(t.geometry.hasAttribute("normal")||t.geometry.computeVertexNormals())}),this._retrievedMeshes.push(t.scene),t.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{Q.test(e.name)&&(r=!0)}),!r)return t;const a=[],i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(Q);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}i.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,t.scene),function(e){const t=H;H.length=0,e.traverse(e=>{(e instanceof v.Camera||e instanceof v.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(t.scene),t.scene.userData.assetId=e.id,t))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const t=[];e.traverse(e=>{e instanceof n&&!(e instanceof v.SkinnedMesh)&&e.geometry instanceof r&&Array.isArray(e.material)&&!_(e)&&t.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:r,geometry:a,materialArray:i,parent:s}of t){r.removeFromParent();for(let t=0;t<i.length;t++){const o=i[t],l=a.groups.filter(e=>e.materialIndex===t);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&B.mergeGroups(c);const h=new n(c,o);h.copy(r,!1),h.geometry=c,h.material=o,s?s.add(h):e.add(h)}a.dispose()}f(e,_);let a=!0,i=0,s=0;if(e.traverse(e=>{if(e instanceof n&&e.geometry instanceof r&&!_(e)){i++;const t=Object.keys(e.geometry.attributes).length;t!==s&&0!==s&&(a=!1),s=t}else(e instanceof v.SkinnedMesh||e instanceof v.Bone)&&(a=!1)}),i>1&&a){const t=new Map;e.traverse(a=>{if(a instanceof n&&a.geometry instanceof r&&!_(a)){if(Array.isArray(a.material))return;a.updateWorldMatrix(!0,!0);const r=a.material?.uuid||"default";t.has(r)||t.set(r,{material:a.material,geometries:[],objects:[]});const i=t.get(r),s=e.matrixWorld.clone().invert().multiply(a.matrixWorld);i.geometries.push(a.geometry.clone().applyMatrix4(s)),i.objects.push(a)}});for(const e of t.values())for(const t of e.objects)t.removeFromParent();for(const r of t.values()){let t,a=r.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new v.BufferAttribute(r,1)),e})),t=1===r.geometries.length?a[0]:N(a)?B.mergeGeometries(a,!0):null,null!=t)t.groups.length>1&&B.mergeGroups(t),e.add(new n(t,r.material));else for(const t of a)e.add(new n(t,r.material))}}e.traverse(e=>{if(e instanceof n&&e.geometry instanceof r&&!_(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&B.mergeGroups(t)}})}extractGeometryGroups(e,t){const a=e.index;if(!a){const a=new r;let i=0;for(const e of t)i+=e.count;if(0===i)return a;for(const r in e.attributes){const s=e.attributes[r],n=s.itemSize,o=s.array,l=new(0,o.constructor)(i*n);let c=0;for(const e of t){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new v.BufferAttribute(l,n,s.normalized);a.setAttribute(r,h)}return a.groups=[{start:0,count:i,materialIndex:0}],a}const i=[];for(const e of t)for(let t=0;t<e.count;t++){const r=a.getX(e.start+t);i.push(r)}if(0===i.length)return new r;const s=new Map,n=[];let o=0;for(const e of i)s.has(e)||(s.set(e,o),o++),n.push(s.get(e));if(0===n.length||0===s.size)return new r;const l=new r;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,i=r.array,n=new(0,i.constructor)(s.size*a);for(const[e,t]of s)for(let r=0;r<a;r++)n[t*a+r]=i[e*a+r];const o=new v.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new v.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(t=>{const r=!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")&&1===t.scene.children.length?t.scene.children[0]:t.scene;return r!==t.scene&&t.scene.remove(r),{scene:r,animations:t.animations}});case"fbx":if(this.directFileLoading){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load FBX ${t}: ${e.status}`);const r=await e.arrayBuffer(),a=this.fbxLoader.parse(r,v.LoaderUtils.extractUrlBase(t));return{scene:a,animations:a.animations}}return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new u;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>(q(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>W(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const E=new Map;function O(e){E.set(e,(E.get(e)??0)+1)}function N(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const i=Object.keys(e.attributes).sort(),s=Object.keys(e.morphAttributes).sort();if(i.join("|")!==r.join("|"))return!1;if(s.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),i=e.getAttribute(a);if(r.itemSize!==i.itemSize||r.normalized!==i.normalized||r.array.constructor!==i.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],i=e.morphAttributes[r];if(a.length!==i.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==i[e].itemSize||a[e].normalized!==i[e].normalized||a[e].array.constructor!==i[e].array.constructor)return!1}return!0})}function q(e){if(e instanceof n)for(const t of T(e.material))t instanceof v.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(q)}export class AssetMeshInstance extends o{}export function createAuthoredCollisionShapes(e,t=1){const r=null!=t&&0!==t?1/t:1;return e.map(e=>{let t;switch(e.type){case"box":t=new x((new h).fromArray(e.size).multiplyScalar(r));break;case"sphere":t=new L(e.radius*r);break;case"capsule":t=new M(e.length*r,e.radius*r);break;case"cylinder":t=new A(e.radius*r,e.radius*r,e.height*r,16,new a)}return t.source=b.custom,t.offset.fromArray(e.position??[0,0,0]).multiplyScalar(r),t.rotation.fromArray(e.rotation??[0,0,0,"XYZ"]),t})}export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function Y(e){switch(e){case"clamp":return v.ClampToEdgeWrapping;case"repeat":return v.RepeatWrapping;case"mirror":return v.MirroredRepeatWrapping}return v.RepeatWrapping}function X(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function V(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(Z.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function J(e){return"linear"===e?v.LinearSRGBColorSpace:v.SRGBColorSpace}const Z=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new v.Matrix4;const H=[];const Q=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,i=Math.floor(a/3),s=[],n=new Uint32Array(i+1),o=new h,l=new h,c=new h;let u=0;for(let e=0;e<i;e++){const a=3*e,i=r?.getX(a)??a,h=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(i)&&Number.isInteger(h)&&Number.isInteger(m)&&i>=0&&h>=0&&m>=0&&i<t.count&&h<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,i),l.fromBufferAttribute(t,h).sub(o),c.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),c.lengthSq(),l.distanceToSquared(c)),r=l.cross(c).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?s.push(i,h,m):u++,n[e+1]=s.length}if(0===u)return 0;if(e.setIndex(s),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(i,Math.floor((r.start+r.count)/3));if(a<=t)continue;const s=n[t],o=n[a]-s;o>0&&e.addGroup(s,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(i,Math.floor((e.drawRange.start+e.drawRange.count)/3)):i,p=Math.min(m,i),f=Math.min(i,Math.max(p,d)),g=n[p];return e.setDrawRange(g,n[f]-g),u}function ee(e){let t=e instanceof v.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof v.MeshLambertMaterial||e instanceof v.MeshPhongMaterial||e instanceof v.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new v.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
1
+ import{createAuthoredCollisionShapes as e}from"./collision/authored-colliders.js";import{parseAnimationClips as t}from"./animation-binary.js";import{AudioLoader as r,BufferGeometry as a,Group as i,LoadingManager as s,Mesh as n,Object3D as o,Texture as l,TextureLoader as c,Vector3 as h}from"three";import{MTLLoader as u,OBJLoader as m,LUTCubeLoader as d}from"three-stdlib";import{cloneMesh as p,mergeCompatibleSkinnedMeshes as f}from"../utils/mesh.js";import{pathJoin as g}from"../utils/files.js";import{Subject as y,firstValueFrom as w}from"rxjs";import{importCollisionShapes as x,isCollisionMesh as M}from"./collision/collision-shape-import.js";import*as b from"three";import{iterateMaterials as A}from"../utils/materials.js";import{applyMaterial as L,getConvertedFbxToGlbAssignedMaterialTextureFlipY as v}from"./materializer.js";import{BufferGeometryUtils as S,DRACOLoader as _,EXRLoader as T,FBXLoader as R,GLTFLoader as K,KTX2Loader as B,TGALoader as F,UltraHDRLoader as C}from"three/examples/jsm/Addons.js";import{disposeScene as P}from"../utils/three/cleanup.js";import{resolveAnimationRigBasisRotation as I,setAnimationClipRigId as k}from"../gameplay/animation/retarget.js";import{parseNativeTexture as D,selectNativeTexture as j}from"./native-texture.js";(()=>{const e=new Uint8Array([255,0,0,255]),t=new b.DataTexture(e,1,1,b.RGBAFormat);t.needsUpdate=!0})();const W=new _;W.setDecoderConfig({type:"js"}),W.setDecoderPath("/assets/draco/");const U=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new K(this.loadingManager).setDRACOLoader(W),this.fbxLoader=new R(this.loadingManager),this.objLoader=new m(this.loadingManager),this.textureLoader=new c(this.loadingManager),this.tgaLoader=new F(this.loadingManager),this.exrLoader=new T(this.loadingManager),this.cubeLoader=new d(this.loadingManager),this.hdrLoader=new C(this.loadingManager),this.ktx2Loader=new B(this.loadingManager),this.ktx2Ready=Promise.resolve(),this.nativeTextureLoader=new b.FileLoader(this.loadingManager).setResponseType("arraybuffer"),this.nativeBcSupported=!1,this.nativeAstcSupported=!1,this._textureLoader=new b.ImageBitmapLoader(this.loadingManager),this.audioLoader=new r(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new y,this.ready=w(this.makeReady),this.directFileLoading=!1,this._texturePromises=new Map,this._arrayTexturesByFileKey=new Map,this._arrayTexturePromisesByFileKey=new Map,this._arrayTextureSettingsByFileKey=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.clipsRequests=new Set,this.timeToLoadClips=0,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}setDirectFileLoading(e){this.directFileLoading=e}setImageBitmapDecoder(e){this.imageBitmapDecoder=e}decodeImageBitmap(e){return this.imageBitmapDecoder?.(e)}configureKtx2(){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.setWorkerLimit(6)}initKtx2(e){this.configureKtx2(),this.ktx2Loader.detectSupport(e),this.nativeBcSupported=e.extensions.has("EXT_texture_compression_bptc"),this.nativeAstcSupported=e.extensions.has("WEBGL_compressed_texture_astc")}initKtx2ForWebGpu(e){this.configureKtx2(),this.ktx2Ready=Promise.resolve(e??navigator.gpu?.requestAdapter({powerPreference:"high-performance"})??null).then(e=>{this.nativeBcSupported=!0===e?.features.has("texture-compression-bc"),this.nativeAstcSupported=!0===e?.features.has("texture-compression-astc"),this.ktx2Loader.detectSupport({isWebGPURenderer:!0,hasFeature:t=>!0===e?.features.has(t)})})}setDataDir(e){this.basePath=g(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){if(e.startsWith("asset://"))return e;const t=function(e){return G.get(e)}(e),r=getElectronArg("windowId");return null!=r||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?g(this.basePath,e)+(null!=r?`?windowId=${r}${null!=t?`&v=${t}`:""}`:""):new URL(g("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if("png"===e.fileFormat||e.fileFormat,this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,e.fileKey.toLowerCase().endsWith(".ktx2")&&await this.ktx2Ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);if(null!=e.texture){const r=N(t,e);t.flipY!==r?(t.needsUpdate=!0,t.flipY=r):t.wrapS!==O(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=O(e.texture?.wrapS)):t.wrapT!==O(e.texture?.wrapT)&&(t.wrapT=O(e.texture?.wrapT),t.needsUpdate=!0)}const r=X(q(e));t.colorSpace!==r&&(t.colorSpace=r,t.needsUpdate=!0)}else try{const t=this._getTextureLoader(e.fileKey),r=null!=this.imageBitmapDecoder&&/\.(png|jpe?g)$/i.test(e.fileKey),a=r||this.directFileLoading&&t===this.textureLoader,i=this.getUri(e.fileKey),s=r?this.imageBitmapDecoder(i).catch(t=>(console.warn(`Worker image decode failed for ${e.name}; falling back to ImageBitmapLoader`,t),this._textureLoader.loadAsync(i))):e.texture?.nativeFileKeys&&t===this.ktx2Loader?this.loadKtx2Texture(e.fileKey,e.texture.nativeFileKeys):(a?this._textureLoader:t).loadAsync(i);await s.then(t=>(a&&((t=new l(t)).needsUpdate=!0),t.texture3D?t=t.texture3D:(t.wrapS=O(e.texture?.wrapS),t.wrapT=O(e.texture?.wrapT),t.flipY=N(t,e),t.colorSpace=X(q(e))),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}async getTextureArray(e){const t=e.texture?.textureArrayFileKey,r=e.texture?.textureArrayLayer;if(!t||null==r)return{texture:null,layerIndex:null};let a=this._arrayTexturesByFileKey.get(t);if(null==a){let r=this._arrayTexturePromisesByFileKey.get(t);null==r&&(r=this.loadTextureArray(t,e.texture?.nativeArrayFileKeys).finally(()=>{this._arrayTexturePromisesByFileKey.delete(t)}),this._arrayTexturePromisesByFileKey.set(t,r)),a=await r}return this.applyTextureArraySettings(t,a,e),{texture:a,layerIndex:r}}async loadKtx2Texture(e,t){await this.ktx2Ready;const r=j(t,this.nativeBcSupported,this.nativeAstcSupported);if(r)try{const e=await this.nativeTextureLoader.loadAsync(this.getUri(r.fileKey));return D(e,r.format)}catch(e){console.warn(`Failed to load native texture ${r.fileKey}; using portable KTX2`,e)}return this._getTextureLoader(e).loadAsync(this.getUri(e))}async loadTextureArray(e,t){let r=await this.loadKtx2Texture(e,t);return r instanceof l||(r=r.texture3D),this._arrayTexturesByFileKey.set(e,r),this._retrievedTextures.push(r),r}applyTextureArraySettings(e,t,r){const a=function(e){return{wrapS:O(e.texture?.wrapS),wrapT:O(e.texture?.wrapT)}}(r),i=this._arrayTextureSettingsByFileKey.get(e);if(null!=i&&(n=a,(s=i).wrapS!==n.wrapS||s.wrapT!==n.wrapT))return void console.warn(`Texture array ${e} is used with incompatible texture settings. Texture arrays share wrapping; rebuild arrays so incompatible textures are grouped separately.`);var s,n;null==i&&this._arrayTextureSettingsByFileKey.set(e,a);let o=!1;t.wrapS!==a.wrapS&&(t.wrapS=a.wrapS,o=!0),t.wrapT!==a.wrapT&&(t.wrapT=a.wrapT,o=!0),!1!==t.flipY&&(t.flipY=!1,o=!0),o&&(t.needsUpdate=!0)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){this.clearCacheByAsset(e)}clearCacheByAsset(e){null!=e&&(this.clearCacheById(e.id),null!=e.fileKey&&(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),Array.from(this.asyncMeshResults.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.asyncMeshResults.delete(t)}),Array.from(this._animationCache.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationCache.delete(t)}),Array.from(this._animationPromises.keys()).forEach(t=>{t.startsWith(e.fileKey+"|")&&this._animationPromises.delete(t)}),z(e.fileKey)),null!=e.materialLib&&z(e.materialLib))}clearCacheById(e){const t=Array.from(this.cache.values()).find(t=>t.scene.userData.assetId===e);t&&Array.from(this.cache.keys()).forEach(e=>{this.cache.get(e)===t&&this.cache.delete(e)}),this.textureCache.delete(e),this._texturePromises.delete(e),Array.from(this.collisionShapeCache.keys()).forEach(t=>{t.startsWith(e+"|")&&this.collisionShapeCache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new i,animations:[]};if(!U.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new i,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new i,animations:[]}}const a=this.cache.get(r),s=a.scene,o=a.animations;if(!1===t?.clone)return{scene:s,animations:o};const l=this.computeCollisionShapes(e,s),c=(e.mesh?.secondaryMotion?.regions.length??0)>0;!0!==t?.mergeGeomtries||c||this.optimizeDrawGroups(s);const h=p(s);h.traverse(e=>{e instanceof n&&e.material instanceof Array&&(e.material=e.material.slice())});const u=new AssetMeshInstance;u.add(h),u.collisionShapes=l,u.animations=o,u.userData.assetId=e.id,u.userData.secondaryMotion=e.mesh?.secondaryMotion,function(e){const t=e.children.length>0?e.children:[e];for(let e=0;e<t.length;e++)r(t[e],"",e);function r(e,t,a){const i=e instanceof n?"Mesh":"Group",s=`${t}/${e.name?.trim()?.length>0?e.name:i}[${a}]`;e.userData.secondaryMotionMeshPath=s;for(let t=0;t<e.children.length;t++)r(e.children[t],s,t)}}(u);const m=e.mesh?.animationRigId??e.anim?.rigId;if(u.userData.animationRigId=m,h.userData.animationRigId=m,null!=m&&null!=this.animationRigProvider){const e=await this.animationRigProvider(m);u.userData.animationRig=e,h.userData.animationRig=e,null!=e&&!1!==t?.applyRigBasis&&u.quaternion.copy(I(e))}const d=e.receiveShadow??!1,f=e.castShadow??!1;if(h.traverse(e=>{e.castShadow=f,e.receiveShadow=d}),!0===t?.rescale&&"number"==typeof e.mesh?.rescale&&u.scale.setScalar(e.mesh?.rescale),!0===t?.applyMaterials){const r=t?.materialResolver??this.materialProvider;if(null!=r)for(const t of e.materialAssignments??[])await L(u,t,r,void 0,{textureFlipY:v(e)});else console.warn(`applyMaterials was set to true for ${e.name} but no material resolver was provided.`)}return{scene:u,animations:o}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const r=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,r),r}async getAnimationClip(e){if(null==e||null==e.fileKey||null==e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const r=e.anim.clip,a=e.fileKey,i=a+"|"+r;if(this._animationCache.has(i))return this._animationCache.get(i);if(this._animationPromises.has(i))return this._animationPromises.get(i);this.clipsRequests.add(e.id);const s=(async()=>{try{const s=("anim"===e.fileFormat?t(await new b.FileLoader(this.loadingManager).setResponseType("arraybuffer").loadAsync(this.getUri(a))):(await this.getMesh(e,{mergeGeomtries:!1,clone:!1})).animations).find(e=>e.name===r);return null!=s&&(k(s,e.anim?.rigId),this._animationCache.set(i,s)),s}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(i),1e3)}})();return this._animationPromises.set(i,s),s}computeCollisionShapes(t,r){if(!0!==t.collisionDetection)return[];const a=t.id+"|"+(t.mesh?.collisions?.shapeType??"")+"|"+(t.mesh?.rescale??1)+"|"+JSON.stringify(t.mesh?.colliders??[]);if(!this.collisionShapeCache.has(a)){const i=t.mesh?.colliders??[],s=i.length>0?e(i,t.mesh?.rescale):x(r,t);this.collisionShapeCache.set(a,s)}return this.collisionShapeCache.get(a)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(t=>(t.scene.traverse(t=>{if(t instanceof n&&t.geometry instanceof a){const r=removeInvalidFaces(t.geometry);r>0&&console.warn(`Removed ${r} invalid face${1===r?"":"s"} from ${e.name}/${t.name||"unnamed mesh"}`)}t instanceof n&&t.material&&function(e){let t=e.material;if(null==t)return;Array.isArray(t)?e.material=t.map(H):e.material=H(t)}(t),M(t)?t.visible=!1:t instanceof n&&t.geometry instanceof a&&(t.geometry.hasAttribute("normal")||t.geometry.computeVertexNormals())}),this._retrievedMeshes.push(t.scene),t.scene=function(e,t){let r=!1;if(t.traverseVisible(e=>{J.test(e.name)&&(r=!0)}),!r)return t;const a=[],i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(J);if(null!=t){const r=parseInt(t[1]);if(0!==r){console.warn(`Skipping LOD level ${r} for now as LOD is not fully supported`),a.push(e);continue}}i.push(...e.children)}for(const e of a)e.removeFromParent();return t}(0,t.scene),function(e){const t=V;V.length=0,e.traverse(e=>{(e instanceof b.Camera||e instanceof b.Light)&&t.push(e)}),t.forEach(e=>e.removeFromParent())}(t.scene),t.scene.userData.assetId=e.id,t))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid),e.updateWorldMatrix(!0,!0);const t=[];e.traverse(e=>{e instanceof n&&!(e instanceof b.SkinnedMesh)&&e.geometry instanceof a&&Array.isArray(e.material)&&!M(e)&&t.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:r,geometry:a,materialArray:i,parent:s}of t){r.removeFromParent();for(let t=0;t<i.length;t++){const o=i[t],l=a.groups.filter(e=>e.materialIndex===t);if(0===l.length)continue;const c=this.extractGeometryGroups(a,l);c.groups.length>1&&S.mergeGroups(c);const h=new n(c,o);h.copy(r,!1),h.geometry=c,h.material=o,s?s.add(h):e.add(h)}a.dispose()}f(e,M);let r=!0,i=0,s=0;if(e.traverse(e=>{if(e instanceof n&&e.geometry instanceof a&&!M(e)){i++;const t=Object.keys(e.geometry.attributes).length;t!==s&&0!==s&&(r=!1),s=t}else(e instanceof b.SkinnedMesh||e instanceof b.Bone)&&(r=!1)}),i>1&&r){const t=new Map;e.traverse(r=>{if(r instanceof n&&r.geometry instanceof a&&!M(r)){if(Array.isArray(r.material))return;r.updateWorldMatrix(!0,!0);const a=r.material?.uuid||"default";t.has(a)||t.set(a,{material:r.material,geometries:[],objects:[]});const i=t.get(a),s=e.matrixWorld.clone().invert().multiply(r.matrixWorld);i.geometries.push(r.geometry.clone().applyMatrix4(s)),i.objects.push(r)}});for(const e of t.values())for(const t of e.objects)t.removeFromParent();for(const r of t.values()){let t,a=r.geometries;if(a.some(e=>null!=e.index)&&(a=a.map(e=>{if(null!=e.index)return e;const t=e.getAttribute("position");if(null==t)return e;const r=t.count>65535?new Uint32Array(t.count):new Uint16Array(t.count);for(let e=0;e<r.length;e++)r[e]=e;return e.setIndex(new b.BufferAttribute(r,1)),e})),t=1===r.geometries.length?a[0]:E(a)?S.mergeGeometries(a,!0):null,null!=t)t.groups.length>1&&S.mergeGroups(t),e.add(new n(t,r.material));else for(const t of a)e.add(new n(t,r.material))}}e.traverse(e=>{if(e instanceof n&&e.geometry instanceof a&&!M(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&S.mergeGroups(t)}})}extractGeometryGroups(e,t){const r=e.index;if(!r){const r=new a;let i=0;for(const e of t)i+=e.count;if(0===i)return r;for(const a in e.attributes){const s=e.attributes[a],n=s.itemSize,o=s.array,l=new(0,o.constructor)(i*n);let c=0;for(const e of t){const t=e.start*n,r=e.count*n;for(let e=0;e<r;e++)l[c+e]=o[t+e];c+=r}const h=new b.BufferAttribute(l,n,s.normalized);r.setAttribute(a,h)}return r.groups=[{start:0,count:i,materialIndex:0}],r}const i=[];for(const e of t)for(let t=0;t<e.count;t++){const a=r.getX(e.start+t);i.push(a)}if(0===i.length)return new a;const s=new Map,n=[];let o=0;for(const e of i)s.has(e)||(s.set(e,o),o++),n.push(s.get(e));if(0===n.length||0===s.size)return new a;const l=new a;for(const t in e.attributes){const r=e.attributes[t],a=r.itemSize,i=r.array,n=new(0,i.constructor)(s.size*a);for(const[e,t]of s)for(let r=0;r<a;r++)n[t*a+r]=i[e*a+r];const o=new b.BufferAttribute(n,a,r.normalized);l.setAttribute(t,o)}const c=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)c[e]=n[e];return l.setIndex(new b.BufferAttribute(c,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(t=>{const r=!0===e.originalFileKey?.toLowerCase().endsWith(".fbx")&&1===t.scene.children.length?t.scene.children[0]:t.scene;return r!==t.scene&&t.scene.remove(r),{scene:r,animations:t.animations}});case"fbx":if(this.directFileLoading){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load FBX ${t}: ${e.status}`);const r=await e.arrayBuffer(),a=this.fbxLoader.parse(r,b.LoaderUtils.extractUrlBase(t));return{scene:a,animations:a.animations}}return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new u;t.materialOptions={normalizeRGB:!1};const r=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(r)}return this.objLoader.loadAsync(t).then(e=>($(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>P(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const G=new Map;function z(e){G.set(e,(G.get(e)??0)+1)}function E(e){if(e.length<2)return!0;const t=e[0],r=Object.keys(t.attributes).sort(),a=Object.keys(t.morphAttributes).sort();return e.slice(1).every(e=>{if(null==e.index!=(null==t.index))return!1;if(e.morphTargetsRelative!==t.morphTargetsRelative)return!1;const i=Object.keys(e.attributes).sort(),s=Object.keys(e.morphAttributes).sort();if(i.join("|")!==r.join("|"))return!1;if(s.join("|")!==a.join("|"))return!1;for(const a of r){const r=t.getAttribute(a),i=e.getAttribute(a);if(r.itemSize!==i.itemSize||r.normalized!==i.normalized||r.array.constructor!==i.array.constructor)return!1}for(const r of a){const a=t.morphAttributes[r],i=e.morphAttributes[r];if(a.length!==i.length)return!1;for(let e=0;e<a.length;e++)if(a[e].itemSize!==i[e].itemSize||a[e].normalized!==i[e].normalized||a[e].array.constructor!==i[e].array.constructor)return!1}return!0})}function $(e){if(e instanceof n)for(const t of A(e.material))t instanceof b.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach($)}export class AssetMeshInstance extends o{}export{createAuthoredCollisionShapes}from"./collision/authored-colliders.js";export function getElectronArg(e){const t=`--${e}=`,r=window.process?.argv.find(e=>e.startsWith(t));return r?.substring(t.length)}function O(e){switch(e){case"clamp":return b.ClampToEdgeWrapping;case"repeat":return b.RepeatWrapping;case"mirror":return b.MirroredRepeatWrapping}return b.RepeatWrapping}function N(e,t){const r=e;return!0!==r.isCompressedTexture&&!0!==r.isCompressedArrayTexture&&(t.texture?.flipY??!0)}function q(e){return e.texture?.colorSpace??function(e){if("exr"===e.fileFormat||e.fileKey?.toLowerCase().endsWith(".exr"))return"linear";const t=`${e.name} ${e.fileKey??""}`.toLowerCase();if(Y.some(e=>t.includes(e)))return"linear";return"srgb"}(e)}function X(e){return"linear"===e?b.LinearSRGBColorSpace:b.SRGBColorSpace}const Y=["_normal","_nrm","_nor","_norm","_roughness","_rough","_metalness","_metallic","_metal","_ao","_ambient","_occlusion","_mask","_height","_disp","_displacement","_bump","_opacity"];new b.Matrix4;const V=[];const J=/_LOD(\d+)/;export function removeInvalidFaces(e){const t=e.getAttribute("position");if(null==t||t.itemSize<3)return 0;const r=e.index,a=r?.count??t.count,i=Math.floor(a/3),s=[],n=new Uint32Array(i+1),o=new h,l=new h,c=new h;let u=0;for(let e=0;e<i;e++){const a=3*e,i=r?.getX(a)??a,h=r?.getX(a+1)??a+1,m=r?.getX(a+2)??a+2;let d=Number.isInteger(i)&&Number.isInteger(h)&&Number.isInteger(m)&&i>=0&&h>=0&&m>=0&&i<t.count&&h<t.count&&m<t.count;if(d){o.fromBufferAttribute(t,i),l.fromBufferAttribute(t,h).sub(o),c.fromBufferAttribute(t,m).sub(o);const e=Math.max(l.lengthSq(),c.lengthSq(),l.distanceToSquared(c)),r=l.cross(c).lengthSq();d=Number.isFinite(e)&&Number.isFinite(r)&&e>0&&r>Number.EPSILON*e*e}d?s.push(i,h,m):u++,n[e+1]=s.length}if(0===u)return 0;if(e.setIndex(s),e.groups.length>0){const t=e.groups.slice();e.clearGroups();for(const r of t){const t=Math.max(0,Math.ceil(r.start/3)),a=Math.min(i,Math.floor((r.start+r.count)/3));if(a<=t)continue;const s=n[t],o=n[a]-s;o>0&&e.addGroup(s,o,r.materialIndex)}}const m=Math.max(0,Math.ceil(e.drawRange.start/3)),d=Number.isFinite(e.drawRange.count)?Math.min(i,Math.floor((e.drawRange.start+e.drawRange.count)/3)):i,p=Math.min(m,i),f=Math.min(i,Math.max(p,d)),g=n[p];return e.setDrawRange(g,n[f]-g),u}function H(e){let t=e instanceof b.MeshPhysicalMaterial&&0===e.sheen&&0===e.anisotropy;if("MeshLambertMaterial"===e.type||"MeshPhongMaterial"===e.type||t){let t={};(e instanceof b.MeshLambertMaterial||e instanceof b.MeshPhongMaterial||e instanceof b.MeshPhysicalMaterial)&&(t.color=e.color,t.map=e.map,t.bumpMap=e.bumpMap,t.bumpScale=e.bumpScale,t.lightMap=e.lightMap,t.lightMapIntensity=e.lightMapIntensity,t.aoMap=e.aoMap,t.aoMapIntensity=e.aoMapIntensity,t.emissiveMap=e.emissiveMap,t.alphaMap=e.alphaMap,t.envMap=e.envMap,t.envMapRotation=e.envMapRotation,t.wireframe=e.wireframe,t.wireframeLinewidth=e.wireframeLinewidth,t.fog=e.fog,t.opacity=e.opacity,t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.alphaTest=e.alphaTest,t.displacementMap=e.displacementMap,t.displacementScale=e.displacementScale,t.displacementBias=e.displacementBias);const r=new b.MeshStandardMaterial(t);return r.userData={...e.userData??{}},r.name=e.name,r}return e}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as i}from"./sky.js";import{NetMode as r}from"../gameplay/net/net-session.js";export async function loadScene(a,s,o,c,m,p,d,l,f,w,j){e();const{scene:y,renderer:h,camera:u}=a,S=new Set(y.children);i(y);const b=await l.getScene(s);if(null==b)throw Error(`Could not find scene with name ${s}`);const g=await l.getSceneData(b.id),v=new t,O=Object.entries(c).map(([e,t])=>({name:e,type:t})),z=Object.entries(m).map(([e,t])=>({name:e,type:t})),E=Object.entries(p).map(([e,t])=>({name:e,type:t})),I=new n(y,v,f,w,a,O,z,d,E);I.inEditor=!1,I.detailTier=j?.detailTier,I.netMode=j?.nodeMode??r.none;const M=j?.persistence?.enabled?await I.preparePersistence(j.persistence,b.id,g):g;return v.initiate(M),await I.initWithInstancing(),{scene:y,view:a,materializer:I,assetResourceLoader:w,assetsService:f,actors:I.actorInstances,sceneRoots:y.children.filter(e=>!S.has(e))}}/*
1
+ import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as i}from"./sky.js";import{NetMode as a}from"../gameplay/net/net-session.js";export async function loadScene(r,s,o,c,m,d,p,l,w,f,j){e();const{scene:g,renderer:y,camera:h}=r,u=new Set(g.children);i(g);const S=await l.getScene(s);if(null==S)throw Error(`Could not find scene with name ${s}`);const v=await l.getSceneData(S.id),b=new t,k=Object.entries(c).map(([e,t])=>({name:e,type:t})),O=Object.entries(m).map(([e,t])=>({name:e,type:t})),z=Object.entries(d).map(([e,t])=>({name:e,type:t})),B=new n(g,b,w,f,r,k,O,p,z);B.inEditor=!1,B.navigationBakes=await(l.getSceneNavigationBakes?.(S.id))??{},B.detailTier=j?.detailTier,B.netMode=j?.nodeMode??a.none;const E=j?.persistence?.enabled?await B.preparePersistence(j.persistence,S.id,v):v;return b.initiate(E),await B.initWithInstancing(),{scene:g,view:r,materializer:B,assetResourceLoader:f,assetsService:w,actors:B.actorInstances,sceneRoots:g.children.filter(e=>!u.has(e))}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,4 @@
1
+ import type { ModelColliderData } from '../model.js';
2
+ import { CollisionShape } from './collision-shape.js';
3
+ export declare function createAuthoredCollisionShapes(colliders: ModelColliderData[], assetRescale?: number): CollisionShape[];
4
+ //# sourceMappingURL=authored-colliders.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{Euler as r,Vector3 as e}from"three";import{BoxCollisionShape as a,CapsuleCollisionShape as o,CollisionShapeSource as t,CylinderCollisionShape as s,SphereCollisionShape as i}from"./collision-shape.js";export function createAuthoredCollisionShapes(n,l=1){const c=null!=l&&0!==l?1/l:1;return n.map(n=>{let l;switch(n.type){case"box":l=new a((new e).fromArray(n.size).multiplyScalar(c));break;case"sphere":l=new i(n.radius*c);break;case"capsule":l=new o(n.length*c,n.radius*c);break;case"cylinder":l=new s(n.radius*c,n.radius*c,n.height*c,16,new r)}return l.source=t.custom,l.offset.fromArray(n.position??[0,0,0]).multiplyScalar(c),l.rotation.fromArray(n.rotation??[0,0,0,"XYZ"]),l})}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,7 @@
1
+ import type * as RAPIER from '@dimforge/rapier3d-simd-compat';
2
+ import * as THREE from 'three';
3
+ import { Vector3 } from 'three';
4
+ import { CollisionShape } from './collision-shape.js';
5
+ export declare function createRapierCollisionShape(rapier: typeof RAPIER, shapeInfo: CollisionShape, scale: Vector3): RAPIER.ColliderDesc;
6
+ export declare function extractFloat32Array(attr: THREE.BufferAttribute | THREE.InterleavedBufferAttribute): Float32Array;
7
+ //# sourceMappingURL=rapier-shape.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as e from"three";import{Vector3 as t}from"three";import*as o from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as r}from"../../utils/three/traverse.js";import{BoxCollisionShape as n,CapsuleCollisionShape as i,ConeCollisionShape as s,ConvexPolyhedronCollisionShape as l,CylinderCollisionShape as a,PlaneCollisionShape as c,SphereCollisionShape as m,TrimeshCollisionShape as u}from"./collision-shape.js";const f=new WeakMap;export function createRapierCollisionShape(h,x,y){if(x instanceof n)return h.ColliderDesc.cuboid(x.dimensions.x*y.x/2,x.dimensions.y*y.y/2,x.dimensions.z*y.z/2);if(x instanceof i){return h.ColliderDesc.capsule(x.length/2*y.y,x.radius*Math.max(y.z,y.x))}if(x instanceof u){const e=null!=x.geometry.getIndex()?x.geometry:o.mergeVertices(x.geometry),t=extractFloat32Array(e.getAttribute("position"));for(let e=0;e<t.length;e+=3)t[e]*=y.x,t[e+1]*=y.y,t[e+2]*=y.z;const r=e.getIndex();return null==r?(console.error("Trimesh collision shape is missing an index buffer.",x),null):h.ColliderDesc.trimesh(t,new Uint32Array(r.array))}if(x instanceof l){let e;const t=x.mesh;if(t.isMesh)e=t.geometry;else{if(!x.mesh.isBufferGeometry)throw new Error("Unsupported convex collision geometry");e=x.mesh}let o;t.isMesh&&(o=r(t));const n=`${o?.x??1},${o?.y??1},${o?.z??1}|${y.x},${y.y},${y.z}`;let i=f.get(e);i||f.set(e,i=new Map);const s=i.get(n);if(void 0!==s)return s;const l=extractFloat32Array(e.getAttribute("position"));if(null!=o)for(let e=0;e<l.length;e+=3)l[e]*=o.x,l[e+1]*=o.y,l[e+2]*=o.z;for(let e=0;e<l.length;e+=3)l[e]*=y.x,l[e+1]*=y.y,l[e+2]*=y.z;const a=h.ColliderDesc.convexHull(l);return null==a&&console.error("Failed to compute convex hull. Points may be coplanar or too few.",{count:l.length/3}),i.set(n,a),a}if(x instanceof m){const o=2*y.x-y.y-y.z;return Math.abs(o)>.01?createRapierCollisionShape(h,new l(new e.SphereGeometry(x.radius).scale(y.x,y.y,y.z)),new t(1,1,1)):h.ColliderDesc.ball(x.radius*Math.max(y.x,y.y,y.z))}return x instanceof a?h.ColliderDesc.cylinder(x.height/2*y.y,x.radiusTop*Math.max(y.z,y.x)):x instanceof s?h.ColliderDesc.cone(x.height*y.y,x.radiusBottom/2*Math.max(y.z,y.x)):x instanceof c?h.ColliderDesc.cuboid(x.width/2*y.x,x.height/2*y.y,.001):(console.error("Unsupported shape",x),h.ColliderDesc.cuboid(1,1,1))}export function extractFloat32Array(e){const t=e.itemSize,o=e.count,r=new Float32Array(o*t);for(let n=0;n<o;n++)for(let o=0;o<t;o++)r[n*t+o]=e.getComponent(n,o);return r}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -361,6 +361,7 @@ export declare class SceneMaterializer {
361
361
  private actorTypes;
362
362
  private actorProvider;
363
363
  private componentTypes;
364
+ private navigationRevision;
364
365
  private objectMap;
365
366
  private sceneObjectMap;
366
367
  private updateSubscription;
@@ -458,11 +459,13 @@ export declare class SceneMaterializer {
458
459
  private canUseEditorStaticDrawSet;
459
460
  private disposeEditorStaticDrawSet;
460
461
  private disposeEditorStaticDrawChunk;
462
+ private readonly vfxPreloads;
461
463
  /**
462
464
  * Materialize visual effects to upload textures
463
465
  * and compile shaders before they are first used.
464
466
  */
465
467
  preloadVisualEffects(visualEffects: Iterable<VisualEffect>): Promise<void>;
468
+ private preloadVisualEffect;
466
469
  private initVfxTextures;
467
470
  private initVfx;
468
471
  /**
@@ -650,7 +653,7 @@ export declare function _materialFromAsset(key: string, asset: Asset, renderingV
650
653
  export declare function prepareCustomParamsFromShaderGraph(graph: ShaderGraphDocument, previous?: Record<string, CustomParamValue>): Record<string, CustomParamValue>;
651
654
  export declare function prepareShaderGraphParameters(paramsSource: {
652
655
  [key: string]: CustomParamValue;
653
- }, graph: ShaderGraphDocument, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, renderingView?: RenderingView, shaders?: ShaderImpl[]): Promise<{
656
+ }, graph: ShaderGraphDocument, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, renderingView?: RenderingView, shaders?: ShaderImpl[], stableParticleAnimation?: boolean): Promise<{
654
657
  [key: string]: unknown;
655
658
  }>;
656
659
  export declare function prepareClassParameters(paramsSource: {