@hology/core 0.0.67 → 0.0.68

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.
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import{ActorComponent as i,Component as e}from"../../../component.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as o}from"../../../../services/render.js";import{AnimationMixer as n,Bone as p,LoopOnce as l}from"three";let h=class extends i{constructor(){super(...arguments),this.viewController=r(o),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.getFullBodyClip=a((t=>t.uuid),(t=>u(this.fullBodyMask,t))),this.getUpperBodyClip=a((t=>t.uuid),(t=>u(this.upperBodyMask,t)))}onInit(){this.viewController.onUpdate(this.actor).subscribe((t=>this.updateInternal(t)))}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}setup(t,i,e){null!=i&&(this.upperBodyMask=c(i),this.fullBodyMask=function(t,i){const e=new Set(c(i).map((t=>t.uuid))),s=[];return t.traverse((t=>{(t instanceof p||t.isBone)&&!e.has(t.uuid)&&s.push(t)})),s}(function(t){let i;return t.traverse((t=>{(t instanceof p||t.isBone)&&null==i&&(i=t)})),i}(t),i)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t)}updateStateMachines(t){this.stateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e&&this.play(e,{priority:0})})),this.upperStateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e?this.playUpper(e,{priority:0}):this.play(this.fullBodyClip)}))}updateInternal(t){null!=this.mixer&&(this.upperBodyTimer+=t,this.fullBodyTimer+=t,this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*this.fadeTime<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip))),this.fullBodyAction&&this.fullBodyAction.loop===l&&this.fullBodyAction.getClip().duration-2*this.fadeTime<this.fullBodyTimer&&(this.currentFullBodyPriority=-1),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t))}syncMovementSpeed(t){if(null!=t){const i=t.getClip();i instanceof s&&i.fixedInPlace&&null!=this.movementSpeed&&(t.timeScale=i.duration/i.displacement*this.movementSpeed)}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const i=this.stateMachines.indexOf(t);i>=0&&this.stateMachines.splice(i,1)}removeUpperStateMachine(t){const i=this.upperStateMachines.indexOf(t);i>=0&&this.upperStateMachines.splice(i,1)}playUpper(t,i={}){const e=i?.priority??1;e<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=e,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i),this.upperBodyTimer=0,this.upperBodyOverride=!0)}play(t,i={}){!function(t,i){if(!1===t||"function"==typeof t&&!1===t())throw new Error(i)}(null!=this.mixer,"Can't play animation before setup is called");const e=i.priority??1;e<this.currentFullBodyPriority||(this.currentFullBodyPriority=e,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i)),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),i),this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction))}onActionDone(t){return new Promise((i=>{const e=s=>{s.action===t&&(i(s.action),this.mixer.removeEventListener("finished",e))};this.mixer.addEventListener("finished",e)}))}transition(t,i,e={}){if(null!=t&&t.getClip().uuid===i.uuid)return t;if(t){const e=t,s=t=this.mixer.clipAction(i);s.play(),s.enabled=!0,s.setEffectiveTimeScale(1),s.setEffectiveWeight(1),s.time=0,e.crossFadeTo(s,this.fadeTime,!0)}else t=this.mixer.clipAction(i),t?.fadeIn(.3),t?.play();return!1===e.loop&&(t.setLoop(l,1),t.clampWhenFinished=!0,t.reset()),t}};h=t([e()],h);export{h as CharacterAnimationComponent};function u(t,i){if(null==t)return i;const e=i.clone(),s=new Set(t.map((t=>t.name)));return e.tracks=e.tracks.filter((t=>s.has(t.name.split(".")[0]))),e}function c(t){return t.flatMap((t=>function(t){const i=[];return t.traverse((t=>{i.push(t)})),i}(t))).filter((t=>t instanceof p))}function a(t,i){const e=new Map;return(s,...r)=>{const o=t(s);return e.has(o)||e.set(o,i(s,...r)),e.get(o)}}
1
+ import{__decorate as t}from"tslib";import{ActorComponent as i,Component as e}from"../../../component.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as o}from"../../../../services/render.js";import{AnimationMixer as n,Bone as p,LoopOnce as l}from"three";let h=class extends i{constructor(){super(...arguments),this.viewController=r(o),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.getFullBodyClip=a((t=>t.uuid),(t=>u(this.fullBodyMask,t))),this.getUpperBodyClip=a((t=>t.uuid),(t=>u(this.upperBodyMask,t)))}onInit(){this.viewController.onUpdate(this.actor).subscribe((t=>this.updateInternal(t)))}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}setup(t,i,e){null!=i&&(this.upperBodyMask=c(i),this.fullBodyMask=function(t,i){const e=new Set(c(i).map((t=>t.uuid))),s=[];return t.traverse((t=>{(t instanceof p||t.isBone)&&!e.has(t.uuid)&&s.push(t)})),s}(function(t){let i;return t.traverse((t=>{(t instanceof p||t.isBone)&&null==i&&(i=t)})),i}(t),i)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t)}updateStateMachines(t){this.stateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e&&this.play(e,{priority:0})})),this.upperStateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e?this.playUpper(e,{priority:0}):this.play(this.fullBodyClip)}))}updateInternal(t){null!=this.mixer&&(this.upperBodyTimer+=t,this.fullBodyTimer+=t,this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*this.fadeTime<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip))),this.fullBodyAction&&this.fullBodyAction.loop===l&&this.fullBodyAction.getClip().duration-2*this.fadeTime<this.fullBodyTimer&&(this.currentFullBodyPriority=-1),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t))}syncMovementSpeed(t){if(null!=t){const i=t.getClip();i instanceof s&&i.fixedInPlace&&null!=this.movementSpeed&&(t.timeScale=i.duration/i.displacement*this.movementSpeed)}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const i=this.stateMachines.indexOf(t);i>=0&&this.stateMachines.splice(i,1)}removeUpperStateMachine(t){const i=this.upperStateMachines.indexOf(t);i>=0&&this.upperStateMachines.splice(i,1)}playUpper(t,i={}){const e=i?.priority??1;e<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=e,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i),this.upperBodyTimer=0,this.upperBodyOverride=!0)}play(t,i={}){!function(t,i){if(!1===t||"function"==typeof t&&!1===t())throw new Error(i)}(null!=this.mixer,"Can't play animation before setup is called");const e=i.priority??1;e<this.currentFullBodyPriority||(this.currentFullBodyPriority=e,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i)),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),i),this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction))}onActionDone(t){return new Promise((i=>{const e=s=>{s.action===t&&(i(s.action),this.mixer.removeEventListener("finished",e))};this.mixer.addEventListener("finished",e)}))}transition(t,i,e={}){if(null!=t&&t.getClip().uuid===i.uuid)return t;if(t){const e=t,s=t=this.mixer.clipAction(i);s.play(),s.enabled=!0,s.setEffectiveTimeScale(1),s.setEffectiveWeight(1),s.time=0,e.crossFadeTo(s,this.fadeTime,!0)}else t=this.mixer.clipAction(i),t?.fadeIn(.3),t?.play();return!1===e.loop&&(t.setLoop(l,1),t.clampWhenFinished=!0,t.reset()),t}};h=t([e({inEditor:!0})],h);export{h as CharacterAnimationComponent};function u(t,i){if(null==t)return i;const e=i.clone(),s=new Set(t.map((t=>t.name)));return e.tracks=e.tracks.filter((t=>s.has(t.name.split(".")[0]))),e}function c(t){return t.flatMap((t=>function(t){const i=[];return t.traverse((t=>{i.push(t)})),i}(t))).filter((t=>t instanceof p))}function a(t,i){const e=new Map;return(s,...r)=>{const o=t(s);return e.has(o)||e.set(o,i(s,...r)),e.get(o)}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -16,10 +16,12 @@ export declare class AssetResourceLoader {
16
16
  private ktx2Loader;
17
17
  private _textureLoader;
18
18
  private audioLoader;
19
+ private initialisedKtx2;
19
20
  protected onError(error: unknown): void;
20
21
  private makeReady;
21
22
  private ready;
22
23
  constructor();
24
+ initKtx2(renderer: THREE.WebGLRenderer): void;
23
25
  setDataDir(path: string): void;
24
26
  private getUri;
25
27
  getTexture(asset: Asset): Promise<Texture>;
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as a,Mesh as i,Object3D as r,TextureLoader as o}from"three";import{GLTFLoader as n,MTLLoader as h,OBJLoader as c}from"three-stdlib";import{FBXLoader as l}from"three-stdlib";import{cloneMesh as d}from"../utils/mesh.js";import{pathJoin as m}from"../utils/files.js";import{Subject as p,firstValueFrom as u}from"rxjs";import{importCollisionShapes as f,isCollisionMesh as g}from"./collision/collision-shape-import.js";import*as w from"three";import{iterateMaterials as y}from"../utils/materials.js";import{BufferGeometryUtils as x,KTX2Loader as L,TGALoader as M}from"three/examples/jsm/Addons.js";const b=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new l(this.loadingManager),this.objLoader=new c(this.loadingManager),this.textureLoader=new o(this.loadingManager),this.tgaLoader=new M(this.loadingManager),this.ktx2Loader=new L(this.loadingManager),this._textureLoader=new w.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=u(this.makeReady),this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}setDataDir(e){this.basePath=m(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return m(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.textureCache.has(e.id)||await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=S(e.texture?.wrapS),t.wrapT=S(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}_getTextureLoader(e){return e.toLowerCase().endsWith(".tga")?this.tgaLoader:e.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:this.textureLoader}async getMesh(e,t){if(await this.ready,!b.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,animations:[]};const a=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(a))try{this.cache.set(a,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new s,animations:[]}}const r=this.cache.get(a).scene,o=this.computeCollisionShapes(e,r);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(r);const n=d(r),h=this.cache.get(a).animations;n.traverse((e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())}));const c=new AssetMeshInstance;c.add(n),c.collisionShapes=o,c.animations=h;const l=e.receiveShadow??!0,m=e.castShadow??!1;return n.traverse((e=>{e.castShadow=m,e.receiveShadow=l})),{scene:c,animations:h}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,f(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let s=!1;if(t.traverseVisible((e=>{C.test(e.name)&&(s=!0)})),!s)return t;const a=new w.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(C);if(null!=t){const s=parseInt(t[1]);0===s?a.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return a}(0,e.scene),e)))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,a=0;if(e.traverse((e=>{e instanceof i&&e.geometry instanceof t&&!g(e)?a++:(e instanceof w.SkinnedMesh||e instanceof w.Bone)&&(s=!1)})),a>1&&s){const s=[],a=[],r=[];e.updateWorldMatrix(!0,!0),e.traverse((e=>{e instanceof i&&e.geometry instanceof t&&!g(e)&&!Array.isArray(e.material)&&(e.updateWorldMatrix(!0,!0),e.geometry.applyMatrix4(e.matrixWorld),s.push(e.geometry),a.push(e.material),r.push(e))}));for(const e of r)e.removeFromParent();const o=x.mergeGeometries(s,!0),n=[];let h=0;e:for(const e of a){for(const t of n)if(t.m.id===e.id){t.indices.push(h),h++;continue e}n.push({m:e,indices:[h]}),h++}let c=0;for(const e of n){for(const t of e.indices)o.groups[t].materialIndex=c;c++}e.add(new i(o,n.map((e=>e.m))))}e.traverse((e=>{if(e instanceof i&&e.geometry instanceof t){const t=e.geometry;Array.isArray(e.material)&&t.groups.length>1&&t.groups.length>e.material.length&&x.mergeGroups(t)}}))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then((e=>(A(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function A(e){if(e instanceof i)for(const t of y(e.material))t instanceof w.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(A)}export class AssetMeshInstance extends r{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find((e=>e.startsWith(t)));return s?.substring(t.length)}function S(e){switch(e){case"clamp":return w.ClampToEdgeWrapping;case"repeat":return w.RepeatWrapping;case"mirror":return w.MirroredRepeatWrapping}return w.RepeatWrapping}const C=/_LOD(\d+)$/;
1
+ import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as i,Mesh as a,Object3D as r,TextureLoader as o}from"three";import{GLTFLoader as n,MTLLoader as h,OBJLoader as c}from"three-stdlib";import{FBXLoader as l}from"three-stdlib";import{cloneMesh as d}from"../utils/mesh.js";import{pathJoin as m}from"../utils/files.js";import{Subject as p,firstValueFrom as u}from"rxjs";import{importCollisionShapes as f,isCollisionMesh as g}from"./collision/collision-shape-import.js";import*as w from"three";import{iterateMaterials as y}from"../utils/materials.js";import{BufferGeometryUtils as x,KTX2Loader as L,TGALoader as M}from"three/examples/jsm/Addons.js";const b=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new i,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new l(this.loadingManager),this.objLoader=new c(this.loadingManager),this.textureLoader=new o(this.loadingManager),this.tgaLoader=new M(this.loadingManager),this.ktx2Loader=new L(this.loadingManager),this._textureLoader=new w.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this.makeReady=new p,this.ready=u(this.makeReady),this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0,this.ktx2Loader.setTranscoderPath("/assets/basis/"),this.ktx2Loader.detectSupport(e)}setDataDir(e){this.basePath=m(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return m(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.textureCache.has(e.id)||await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=S(e.texture?.wrapS),t.wrapT=S(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}_getTextureLoader(e){return e.toLowerCase().endsWith(".tga")?this.tgaLoader:e.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:this.textureLoader}async getMesh(e,t){if(await this.ready,!b.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,animations:[]};const i=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(i))try{this.cache.set(i,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new s,animations:[]}}const r=this.cache.get(i).scene,o=this.computeCollisionShapes(e,r);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(r);const n=d(r),h=this.cache.get(i).animations;n.traverse((e=>{e instanceof a&&e.material instanceof Array&&(e.material=e.material.slice())}));const c=new AssetMeshInstance;c.add(n),c.collisionShapes=o,c.animations=h;const l=e.receiveShadow??!0,m=e.castShadow??!1;return n.traverse((e=>{e.castShadow=m,e.receiveShadow=l})),{scene:c,animations:h}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,f(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let s=!1;if(t.traverseVisible((e=>{C.test(e.name)&&(s=!0)})),!s)return t;const i=new w.LOD,a=[t];for(;a.length>0;){const e=a.shift(),t=e.name.match(C);if(null!=t){const s=parseInt(t[1]);0===s?i.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else a.push(...e.children)}return i}(0,e.scene),e)))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,i=0;if(e.traverse((e=>{e instanceof a&&e.geometry instanceof t&&!g(e)?i++:(e instanceof w.SkinnedMesh||e instanceof w.Bone)&&(s=!1)})),i>1&&s){const s=[],i=[],r=[];e.updateWorldMatrix(!0,!0),e.traverse((e=>{e instanceof a&&e.geometry instanceof t&&!g(e)&&!Array.isArray(e.material)&&(e.updateWorldMatrix(!0,!0),e.geometry.applyMatrix4(e.matrixWorld),s.push(e.geometry),i.push(e.material),r.push(e))}));for(const e of r)e.removeFromParent();const o=x.mergeGeometries(s,!0),n=[];let h=0;e:for(const e of i){for(const t of n)if(t.m.id===e.id){t.indices.push(h),h++;continue e}n.push({m:e,indices:[h]}),h++}let c=0;for(const e of n){for(const t of e.indices)o.groups[t].materialIndex=c;c++}e.add(new a(o,n.map((e=>e.m))))}e.traverse((e=>{if(e instanceof a&&e.geometry instanceof t){const t=e.geometry;Array.isArray(e.material)&&t.groups.length>1&&t.groups.length>e.material.length&&x.mergeGroups(t)}}))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then((e=>(A(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function A(e){if(e instanceof a)for(const t of y(e.material))t instanceof w.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(A)}export class AssetMeshInstance extends r{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find((e=>e.startsWith(t)));return s?.substring(t.length)}function S(e){switch(e){case"clamp":return w.ClampToEdgeWrapping;case"repeat":return w.RepeatWrapping;case"mirror":return w.MirroredRepeatWrapping}return w.RepeatWrapping}const C=/_LOD(\d+)$/;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{Group as e,Mesh as a}from"three";import{Color as r}from"three";import{varyingAttributes as t,float as n,mod as o,dot as s,vec2 as c,step as i,fract as l,mix as p,rgb as d,NodeShaderMaterial as u,rgba as m,standardMaterial as f,attributeFloat as h,varyingFloat as L,RgbNode as x,varying as S}from"three-shader-graph";import{mixColorsByLayer as w,select as v}from"../../shader-nodes/index.js";export function initLandscape(e){e.sections.y,e.sectionSize,e.sections.x,e.sectionSize;return new LandscapeGroup}export function createLandscapeDefaultMaterial(){const e=t.uv,a=n(10),x=n(7),v=o(s(c(1,1),i(c(.5,.5),l(e.multiplyScalar(a)))),n(2)),y=o(s(c(1,1),i(c(.5,.5),l(e.multiplyScalar(x.multiply(a))))),n(2)),D=p(d(new r(4473924).convertLinearToSRGB()),d(new r(5592405).convertLinearToSRGB()),v),G=p(D,D.addScalar(n(.1)),y),M=w({layerColors:[m(G).rgb,...["#55DDE0","#33658A","#2F4858"].map((e=>new r(e).convertLinearToSRGB())).map((e=>d(e))).reverse()],enableNoise:!1}),g=h("hole"),B=(i(.5,L(g)),new u({color:f({color:M}),discard:S(g).gt(.5)}));return B.color=new r("#aaaaaa"),B.name="Default",B}export const defaultLandscapeMaterial=createLandscapeDefaultMaterial();export class LandscapeMesh extends a{}export class LandscapeGroup extends e{get sections(){return this.children.filter((e=>e instanceof LandscapeMesh))}}
1
+ import{Group as e,Mesh as a}from"three";import{Color as r}from"three";import{varyingAttributes as t,float as n,mod as o,dot as s,vec2 as c,step as i,fract as l,mix as p,rgb as d,NodeShaderMaterial as f,rgba as u,standardMaterial as m,attributeFloat as h,RgbNode as L,varying as x}from"three-shader-graph";import{mixColorsByLayer as S,select as w}from"../../shader-nodes/index.js";export function initLandscape(e){e.sections.y,e.sectionSize,e.sections.x,e.sectionSize;return new LandscapeGroup}export function createLandscapeDefaultMaterial(){const e=t.uv,a=n(10),L=n(7),w=o(s(c(1,1),i(c(.5,.5),l(e.multiplyScalar(a)))),n(2)),v=o(s(c(1,1),i(c(.5,.5),l(e.multiplyScalar(L.multiply(a))))),n(2)),y=p(d(new r(4473924).convertLinearToSRGB()),d(new r(5592405).convertLinearToSRGB()),w),D=p(y,y.addScalar(n(.1)),v),G=S({layerColors:[u(D).rgb,...["#f3cc91","#e9a135","#f4a4a6","#ef767a","#e6373d","#55DDE0","#33658A","#2F4858"].map((e=>new r(e).convertLinearToSRGB())).map((e=>d(e))).reverse()],enableNoise:!1}),M=h("hole"),g=new f({color:m({color:G}),discard:x(M).gt(.5)});return g.color=new r("#aaaaaa"),g.name="Default",g}export const defaultLandscapeMaterial=createLandscapeDefaultMaterial();export class LandscapeMesh extends a{}export class LandscapeGroup extends e{get sections(){return this.children.filter((e=>e instanceof LandscapeMesh))}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{Subject as e}from"rxjs";import*as t from"three";import{BoxGeometry as a,Color as s,Euler as r,Fog as i,FogExp2 as n,Group as o,Material as l,Matrix4 as c,Mesh as h,MeshLambertMaterial as m,MeshPhongMaterial as p,MeshStandardMaterial as d,Object3D as u,PointLight as f,Quaternion as y,SphereGeometry as g,Texture as w,Vector2 as S,Vector3 as v,Vector4 as A}from"three";import b,{SpriteRenderer as M}from"three-nebula";import{bool as x,BooleanNode as j,float as I,FloatNode as P,NodeShaderMaterial as D,rgb as N,RgbNode as E,Texture2dLookupNode as V,textureSampler2d as C,vec2 as F,Vec2Node as k,vec3 as z,Vec3Node as O,vec4 as _}from"three-shader-graph";import{VfxActor as B}from"../effects/vfx/vfx-actor.js";import{VisualEffect as T}from"../effects/vfx/vfx-param.js";import{BaseActor as $}from"../gameplay/actors/actor.js";import L from"../gameplay/actors/builtin/index.js";import{PhysicsBodyType as U,withInjectionContext as R}from"../gameplay/index.js";import{Sampler2DNode as W}from"../shader-nodes/index.js";import{LambertShader as J}from"../shader/builtin/lambert-shader.js";import{StandardShader as H}from"../shader/builtin/standard-shader.js";import{UnlitShader as q}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as G}from"../shader/parameter.js";import{ArrayMap as X,groupBy as Y}from"../utils/collections.js";import{iterateMaterials as Z}from"../utils/materials.js";import{filterChildrenShallow as Q,filterSceneShallow as K,findFirstVisibleObject as ee}from"../utils/three/traverse.js";import{AssetMeshInstance as te}from"./asset-resource-loader.js";import{isCollisionMesh as ae}from"./collision/collision-shape-import.js";import{BoxCollisionShape as se,PhysicalShapeMesh as re}from"./collision/collision-shape.js";import{LandscapeManager as ie}from"./landscape/landscape-manager.js";import{initLandscape as ne}from"./landscape/landscape.js";import{SectionGrid as oe,smoothNormalsCrossMeshes as le}from"./landscape/utils.js";import{createGrassFoliageMaterial as ce}from"./materials/grass-foliage.js";import{createGrassMaterial as he}from"./materials/grass.js";import{getMaterialAttribute as me}from"./materials/utils/material-painting.js";import{createWaterMaterial as pe}from"./materials/water.js";import{SerializedParamType as de}from"./model.js";import{ShapeLibrary as ue,ShapeLibraryKeys as fe}from"./objects/shapes.js";import{ambientLightName as ye,createSky as ge,defaultSkyMaterial as we}from"./sky.js";import{LandscapeShader as Se}from"../shader/builtin/landscape-shader.js";const ve={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new SceneMaterializer(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}export class SceneMaterializer{constructor(a,s,r,i,n,o,l,c){this.scene=a,this.dataProvider=s,this.assetsService=r,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new e,this.removed$=new e,this.error$=new e,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,s.onUpdate((e=>this.update(e))),s.onRemove((e=>this.remove(e))),this.createAssetSubscription=r.onCreate.subscribe((e=>{this.assets.set(e.id,e)})),this.updateSubscription=r.onUpdate.subscribe((async e=>{this.assets.set(e.id,e),"material"==e.type?a.traverse((a=>{if(a instanceof t.Mesh)if(Array.isArray(a.material))for(let t=0;t<a.material.length;t++)this.refreshMaterial(a,a.material[t],e,t);else this.refreshMaterial(a,a.material,e)})):"mesh"==e.type?(this.findByAssetId(e.id).forEach((t=>{Ve(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})),this.landscapeManagers.forEach((t=>{t.source.grass.layers.some((t=>t.meshes.some((t=>t.assetId===e.id))))&&t.queueRefreshScatter(this.renderingView?.camera.position??new v,!0)}))):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}async refreshMaterial(e,t,a,s){if(t?.userData?.assetId!==a.id)return;const r=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);r.userData=t.userData,null!=s?Fe(e.material[s],r)||(e.material[s]=r):Fe(e.material,r)||(e.material=r)}get actorInstances(){return Array.from(this.materializedActors.values())}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));await Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>{if(null!=e)return this.assetManagerService.getMesh(e)})))))}async init(){await this.preInit(),be.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map((e=>this.materialize(e)))),await this.initActorsPostInit()}initActorsPostInit(e=this.actorInstances){const t=e.map((async e=>{const t=e.object.userData.src;if("vfx"===t.type)return Promise.resolve();const a=await this.assetsService.getAsset(t.assetId),s={...a?.actor?.params??{},...t.actor?.params??{}};for(const a of t.actor.innerParams??[])await this.applyActorComponentParams(e,a.path.slice(),a.params);const r=await je(s,e.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,r);try{return await this.actorProvider.initActor(e)}catch(e){console.error(`Failed to initiate actor (name="${t.name}", id=${t.id})`,e)}}));return Promise.all(t)}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await je(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[r]&&await this.applyActorComponentParams(e[r],t,a)}canObjectBeInstanced(e){return e.physics?.type!==U.dynamic&&"sky"!==e.type&&"global_fog"!==e.type}async canAssetBeInstanced(e){if(!this._canBeInstancedCache.has(e.assetId)){const t=await this.createFromAsset(e);if(null==t)return!1;const a=[];t.traverse((e=>{!ae(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=a[0]instanceof h&&null!=a[0].geometry.morphAttributes&&Object.keys(a[0].geometry.morphAttributes).length>0,i=!0;this._canBeInstancedCache.set(e.assetId,s&&i&&!r)}return this._canBeInstancedCache.get(e.assetId)}async preInit(){this.renderingView?.onLoop((()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)})),this.assetsService.getAssets().then((e=>{for(const t of e)this.assets.set(t.id,t)}))}async initWithInstancing(){await this.preInit(),await this.prefetchAssets();const e=[],a=new X,i=new X;for(const t of this.dataProvider.getObjects())await Ee(t,(async(t,r,n)=>{const o="asset_mesh"==t.type&&this.canObjectBeInstanced(t)&&await this.canAssetBeInstanced(t),l="shape_mesh"===t.type&&"landscape"!==t.shape&&t.physics?.type!==U.dynamic;if(o||l)if(r&&r.children?.length>0&&r.children.splice(r.children.findIndex((e=>e.id===t.id)),1),l){let e=t.shape+JSON.stringify(t.shapeParams??{})+t.castShadow+t.receiveShadow;const a=t.materialAssignments?.at(0)?.materialId,r=null!=a?this.assets.get(a):null;let o=null;if(null!=r&&"shader"!==r.material.type){if(e+=r.material.type+r.material.shader,null!=r.material.shaderParams){if(e+=Object.entries(r.material.shaderParams).filter((([e,t])=>"color"!=e)).map((e=>JSON.stringify(e))).join(),null!=r.material.shaderParams.color){const e=r.material.shaderParams.color;e.type===de.Color&&null!=e.value&&(o=new s(e.value))}}}else e+=a;i.push(e,{object:{...t,parentTransform:n},color:o})}else{const e=t.assetId+JSON.stringify(t.materialAssignments??[]);a.push(e,{...t,parentTransform:n})}else null==r&&e.push({...t,parentTransform:n})}));for(const e of a.values()){if(0==e.length)continue;const t=await this.createFromAsset(e[0]);if(null==t)continue;const a=await this.createInstancedMesh(e,t),s=new te;s.add(a),s.userData.src=e[0],t instanceof te&&(s.collisionShapes=t.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}for(const e of i.values()){if(0==e.length)continue;const a=e[0].object,i=await this.createFromShape(a),n=ee(i,(e=>!ae(e)&&null!=e.geometry)),o=n.material.clone();null!=e[0].color&&null!=o.color&&(o.color=new s(16777215));const l=n.geometry,h=new t.InstancedMesh(l,o,e.length);for(let a=0;a<e.length;a++){const s=e[a],o=(new t.Matrix4).compose((new v).fromArray(s.object.position),(new y).setFromEuler((new r).fromArray(s.object.rotation)),(new v).fromArray(s.object.scale)),l=(new c).copy(s.object.parentTransform).multiply(o);h.setMatrixAt(a,l),null!=s.color&&h.setColorAt(a,s.color),h.castShadow=i.castShadow??!0,h.receiveShadow=n.receiveShadow??!0;const m=new te;m.add(h),m.userData.src=e[0],i instanceof re&&(m.collisionShapes=[i.collisionShape]),m.castShadow=!1,m.receiveShadow=!1,this.scene.add(m)}}await Promise.all(e.map((e=>this.materialize(e)))),await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=ee(a,(e=>!ae(e)&&null!=e.geometry)),i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,Ve(e[0].materialAssignments,i.materialAssignments)),s.updateMatrix();const n=s.geometry.clone().applyMatrix4(s.matrix),o=new t.InstancedMesh(n,s.material,e.length);s.material instanceof l&&(o.material.side=t.FrontSide);for(let a=0;a<e.length;a++){const s=(new t.Matrix4).compose((new v).fromArray(e[a].position),(new y).setFromEuler((new r).fromArray(e[a].rotation)),(new v).fromArray(e[a].scale)),i=(new c).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=e[0].castShadow??i.castShadow??!0,o.receiveShadow=e[0].receiveShadow??i.receiveShadow??!0,o}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("actor"==e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>t.object.userData.src?.id===e.id)).forEach((e=>this.components.splice(this.components.indexOf(e,1)))),this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))})),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex((t=>t.source.id===e.id));if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return K(this.scene,(t=>t.userData.src?.assetId==e),(e=>null!=e.userData.src))}applyMaterials(e,t){return null==t?Promise.resolve([]):Promise.all(t.filter((e=>"null"!==e.materialId)).map((t=>this.applyMaterial(e,t))))}async applyMaterial(e,t){await applyMaterial(e,t,(e=>{const t=this.assets.get(e);if(null!=t)return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}),this._originalMaterials)}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof h)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material}))}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(L));K(this.scene,(e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&!t.has(e.userData.src.actor.type))).forEach((async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)}))}updateShaders(e){this.shaders=e;for(const[e,t]of be.entries())t.userData.customShaderName&&be.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),K(this.scene,(e=>!0)).forEach((e=>{e.traverse((async e=>{if(e instanceof h)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}}))}))}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);const t=this.sceneObjectMap.get(e.id);if(t){let r=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(r=!0)})),!r){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof h&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof h&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);Ve(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(r||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new s(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0)}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient);else if("landscape"===e.shape){const a=this.landscapeManagers.find((t=>t.source.id===e.id)).source.landscape.options.density!==e.landscape.options.density;if(this.inEditor&&a){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}this.applyHeightMaps(t,e.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>!0))))}else if("global_fog"===e.type){const t=(this.scene.fog instanceof n?"density":"linear")!==e.fog.type;this.scene.fog=De(e.fog),t&&(a=this.scene).traverse((e=>{if(e instanceof h){const t=e.material;t instanceof D&&(a.fog instanceof i?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof n&&(t.uniforms.density={value:a.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}})),this.fixFogColor()}else if("actor"===e.type){if(this.materializedActors.has(e.id)){const t=this.editorActorParamSnapshot.get(e.id);null!=t&&t===JSON.stringify(e.actor)||(console.log("Rematerializing actor because parameters changed"),r||(this.remove(e),await this.materializeAndInitActor(e)))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof re&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&Ae(t,e.castShadow,e.receiveShadow),e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a}async materializeAndInitActor(e,t=this.findParent(e)){console.log("materialize actor and init");const a=await this.materialize(e,t);return Ee(e,(async e=>{if("actor"===e.type){const t=this.materializedActors.get(e.id);null!=t?await this.initActorsPostInit([t]):console.error(`Something went wrong when creating actor ${e.id}`)}})),a}findParent(e){const t=this.dataProvider.getObjects().flatMap((t=>t.id===e.id?null:Q(t,(t=>t.children?.some((t=>t.id===e.id))),(()=>!0))))[0];return null==t?this.scene:null!=t?K(this.scene,(e=>e.userData?.src?.id===t.id),(e=>null!=e.userData?.src))[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new s(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof h&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const a=Y(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof h){const t=me(e,!1);if(null!=t){for(let e=0;e<t.array.length;e++)t.setX(e,0);t.needsUpdate=!0}}}));const s=new Set;for(const[e,r]of a.entries()){const a=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let i=!1;if(null==a)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const n=me(a,!0);for(let e=0;e<n.array.length;e++)n.setX(e,0);for(const e of r)n.setX(e.i,e.w[0]),n.setY(e.i,e.w[1]),n.setZ(e.i,e.w[2]),i=!0;i&&s.add(e)}this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>s.has(e.name)))))}async materialize(e,t,s=!1){let r;switch(e.type){case"asset_mesh":r=await this.createFromAsset(e);break;case"shape_mesh":r=await this.createFromShape(e);break;case"light":r=await this.createLight(e);break;case"particles":r=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=De(e.fog),this.fixFogColor(),r=new o;break;case"sky":this.sky=ge(),this.updateSky(e),r=this.sky;break;case"actor":r=await this.createFromActor(e);break;case"group":r=new o;break;case"prefab":r=await this.createFromPrefabAsset(e);break;case"vfx":r=await this.createFromVfx(e);break;default:if(this.inEditor)throw new Error("unknown type "+e.type);console.warn(`Failed to materialize object. Unknown type '${e.type}'. This might be because the hology/core library is not compatible with the editor version.`)}if(null!=r){if(e.name&&e.name.length>0&&(r.name=e.name),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),s||(r.userData.src=e),this.inEditor,this.inEditor){let e=null;r instanceof re&&(e=function(e){if(e instanceof se)return new h(new a(...e.offset.toArray()),Ne);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}return this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==U.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):t?.add(r):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),this.inEditor||"asset_mesh"!=e.type&&"shape_mesh"!==e.type||null!=e.physics?.type&&e.physics.type==U.dynamic||Pe(r),r}}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=we);const a=await this.assetsService.getAsset(e.sky.materialId),s=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1);s.side=t.BackSide,null!=this.sky?this.sky.material=s:console.warn("No sky has been created")}async createComponent(e,t,a,s){const r=new ve[a.path+"/"+a.className],i=t.id+s;r.id=i,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),i}async createFromActor(e){const t=this.actorTypes.find((t=>t.name===e.actor?.type))?.type??L[e.actor?.type];if(null==t)return null;this.inEditor&&this.editorActorParamSnapshot.set(e.id,JSON.stringify(e.actor));const a=await this.actorProvider.create(t,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!0);return this.materializedActors.set(e.id,a),a?.object}async createFromVfx(e){const t=await this.assetsService.getAsset(e.assetId);null==t&&console.error("Could not find asset",e);const a=await this.actorProvider.create(B,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!1);return await a.fromAsset(t),a.play(),this.materializedActors.set(e.id,a),a?.object}cleanup(){this.materializedActors.clear()}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse((e=>{e instanceof h&&this._originalMaterials.set(e.id,e.material)}));else{let r=new d({name:"Default",color:new s("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const i=await this.createMeshByShape(e.shape,r,e.shapeParams);i.castShadow=e.castShadow??!0,i.receiveShadow=e.castShadow??!1,e.collisionDetection||(i.collisionShape=null),i.physics=e.physics,a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||(await Promise.all((e.materialAssignments??[]).filter((e=>null!=e.materialId)).map((e=>this.applyMaterial(a,e)))),this.applyVertexMaterials(e,a)),a}createLandscape(e){const t=e.landscape?.options;if(null==t)return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new o;const a=ne(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new ie(e,this.renderingView,a,this.assetManagerService,this.assetsService,this.shaders,(t=>{(e.materialAssignments??[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(t,e)))}));return this.landscapeManagers.push(s),s.refreshGeometry(),a}applyHeightMaps(e,t,a=!1){const s=new oe(e.sections);for(const e of t??[]){const t=s.find(e.x,e.y);if(!t)return;const a=t.geometry.getAttribute("position");for(const t of e.points)a.setY(t.i,t.y);a.needsUpdate=!0}const r=e.sections;r.forEach((e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()})),this.inEditor&&!a||setTimeout((()=>le(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&fe.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);return this.geometryCache.has(r)||this.geometryCache.set(r,ue[e].geometry(s)),this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,ue[e].collision(s)),new re(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:a}=await this.assetManagerService.getMesh(t,{mergeGeomtries:!0});Ve(e.materialAssignments,t.materialAssignments).forEach((e=>this.applyMaterial(a,e)));const s=e.receiveShadow??!!t.receiveShadow??!0,r=e.castShadow??!!t.castShadow??!1;return a.receiveShadow=s,Ae(a,r,s),e.collisionDetection||(a.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(a.physics=e.physics),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof h&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()})),a}async createFromPrefabAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);const a=new o;return t.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,a,!0))),a}async createParticleSystem(e){const a=await this.assetsService.getAsset(e.assetId),s=new u;return await b.fromJSONAsync(a.particleSystem,t).then((e=>{const a=new M(s,t);e.addRenderer(a),this.renderingView.onLoop((t=>e.update()))})),s}async createLight(e){if("point"===e.light.type){const t=new f(e.light.point.color,e.light.point.intensity,e.light.point.distance,e.light.point.decay);if(t.castShadow=e.light.point.castShadow??!0,this.inEditor){const e=new g(.3,10,10),a=new d({color:new s(16771709)}),r=new h(e,a);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional),new o):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient),new o):void 0}applyDirectionalAmbientLight(e,t){const a=this.scene.children.find((e=>e.name===ye));null!=a?(a.intensity=t.intensity,a.color.set(t.color),a.groundColor.set(t.color)):console.warn("Couldn't find ambient light")}applyDirectionalLight(e){for(const t of this.renderingView.csm.lights)t.intensity=e.intensity,t.color.set(e.color),t.castShadow=e.castShadow;this.renderingView.csm.lightDirection.fromArray(e.direction).normalize()}dispose(){this.updateSubscription.unsubscribe(),this.createAssetSubscription.unsubscribe(),this.materializedActors.forEach((e=>e.disposed.next(!0)))}}function Ae(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse((e=>{e.castShadow=t,e.receiveShadow=a}))}const be=new Map,Me=new m({color:16711935}),xe=new Map;export async function materialFromAsset(e,a,r,i,n,o=!0){const l=JSON.stringify(e.material);if(o&&be.has(l))return be.get(l);const c={opacity:e.material.params.opacity,map:null,emissive:e.material.params.emissive??null,metalness:e.material.params.metalness??0,flatShading:e.material.params.flatShading??!1,color:new s(e.material.params.color),transparent:null!=e.material.params.opacity&&e.material.params.opacity<1},h={};if(null!=e.material.params.map){const t=e.material.params.map,a=await r.getAsset(t);null!=a&&(c.map=await i.getTexture(a))}let m;switch(e.material.type){case"phong":m=new p({...c,...h});break;case"water":m=pe(c,a);break;case"grassFoliage":m=ce({color:c.color,map:c.map},a);break;case"grass":m=he({...c,colorTwo:new s(e.material.params.colorTwo),colorThree:new s(e.material.params.colorThree)},a);break;case"standard":case"unlit":case"lambert":case"shader":case"landscape":const t={standard:H,lambert:J,unlit:q,landscape:Se}[e.material.type]??n.find((t=>t.name==e.material.shader))?.type;if(t){const s=new t,o=await je(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{m=s.build()}catch(t){console.log("Shader runtime error: "+t),xe.has(e.material.shader)||xe.set(e.material.shader,Me.clone()),m=xe.get(e.material.shader)}m.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),m=Me;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(m),o&&be.set(l,m),m.side=e.material.side??m.side??t.FrontSide,m.transparent=(e.material.transparent??c.transparent??!1)||m.transparent,e.material.bloom&&(m.userData.hasBloom=!0),m.userData.assetId=e.id,m}async function je(e,t,a,s,r,i,n,o){const l={};for(const[t,c]of Object.entries(e)){const e=await Ie(c,a,s,r,i,n,o);null!=e&&(l[t]=e)}return l}export async function prepareShapeParameters(e){const t={};for(const[a,s]of Object.entries(e)){const e=await Ie(s,null,null,null);null!=e&&(t[a]=e)}return t}async function Ie(e,t,a,i,n,o,l){if(de.String,null==e||null==e.value||""===e.value)return null;const c=e.value;switch(e.type){case de.Number:case de.FloatNode:let h="string"==typeof c?parseFloat(c):c;return e.type===de.FloatNode?I(h):h;case de.Texture:return await a.getTexture(await t.getAsset(c));case de.Sampler2DNode:return C(await a.getTexture(await t.getAsset(c)));case de.Boolean:return c;case de.BooleanNode:return x(c);case de.Vector2:case de.Vec2Node:if("object"==typeof c){const t=c instanceof Array?(new S).fromArray(c):new S(c.x,c.y);return e.type===de.Vec2Node?F(t):t}return null;case de.Vector3:case de.Vec3Node:if("object"==typeof c){const t=c instanceof Array?(new v).fromArray(c):new v(c.x,c.y,c.z);return e.type===de.Vec3Node?z(t):t}return null;case de.Color:case de.RgbNode:const m=new s(c);return e.type===de.RgbNode?N(m):m;case de.String:return c;case de.BaseActor:const p=c;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(p);case de.Euler:const d=c;return(new r).fromArray(d);case de.Object3D:return(await a.getMesh(await t.getAsset(c))).scene;case de.Material:return await materialFromAsset(await t.getAsset(c),n,t,a,o);case de.AudioBuffer:return await a.getAudio(await t.getAsset(c));case de.VisualEffect:const u=await t.getAsset(c);if(null==l){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in u)return new T(l,u);console.error("Using a non-vfx asset for visual effect parameter")}return null}function Pe(e){e.updateWorldMatrix(!1,!0),e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}function De(e){return"linear"===e.type?new i(new s(e.color),e.near??100,e.far??1e3):"density"===e.type?new n(e.color,e.density):void console.warn("Invalid fog type",e)}const Ne=new d({color:4229780});async function Ee(e,a,s,i){null==i&&(i=(new c).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){if(null==e.position||null==e.rotation||null==e.scale)return t.identity();return t.compose((new v).fromArray(e.position),(new y).setFromEuler((new r).fromArray(e.rotation)),(new v).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Ee(t,a,e,n))))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?de.Number:t instanceof P||"function"==typeof e.prototype.isFloat?de.FloatNode:t instanceof w||e===w||e.isTexture?de.Texture:t instanceof W||e===V?de.Sampler2DNode:t instanceof Boolean||e===Boolean?de.Boolean:t instanceof j?de.BooleanNode:t instanceof s||e==s?de.Color:t instanceof E||"function"==typeof e.prototype.isRgb?de.RgbNode:t instanceof S||e==S?de.Vector2:t instanceof k||"function"==typeof e.prototype.isVec2?de.Vec2Node:t instanceof v||e==v?de.Vector3:t instanceof O||"function"==typeof e.prototype.isVec3?de.Vec3Node:t instanceof String||e===String?de.String:t instanceof $||e==$||e.prototype instanceof $||e.prototype==$?de.BaseActor:t instanceof r||e==r?de.Euler:t instanceof u||e==u?de.Object3D:t instanceof l||e==l?de.Material:t instanceof AudioBuffer||e==AudioBuffer?de.AudioBuffer:t instanceof T||e==T?de.VisualEffect:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map((e=>[e.name,{type:toSerializedParamType(e.type),value:t[e.name]?.value??a[e.name]??customParameterDefaultValueByType.get(toSerializedParamType(e.type))}])))}export function prepareCustomParamsFromType(e,t,a=null){const s=G(e);if(0===s.length)return{};let r;null!=a?R(a,(()=>{r=a.get(e)})):r=new e;const i={};for(const e of s){const t=r[e.name];if(null!=t){const a=serializeCustomParameter(e.type,t);null!=a&&(i[e.name]=a)}}return prepareCustomParams(s,t,i)}export function serializeCustomParameter(e,t){function a(){console.error("Failed to serialize value",{type:e,value:t})}switch(e){case Number:case Boolean:return t;case S:return t instanceof S?t.toArray():void a();case v:return t instanceof v?t.toArray():void a();case A:return t instanceof A?t.toArray():void a();case s:return t instanceof s?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new s(t).getHexString():void a();case String:return t;case r:return t instanceof r?t.toArray():void a()}}function Ve(e,t){return function(e,t,a){const s=[],r=new Set;for(const i of[...e??[],...t??[]]){const e=a(i);r.has(e)||(r.add(e),s.push(i))}return s}((e??[]).filter((e=>Ce(e.materialId))),(t??[]).filter((e=>Ce(e.materialId))),(e=>e.color+e.name))}function Ce(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[de.RgbNode,"#000000"],[de.Color,"#000000"],[de.Vector4,[0,0,0,0]],[de.Vec4Node,[0,0,0,0]],[de.Vector3,[0,0,0]],[de.Vec3Node,[0,0,0]],[de.Vector2,[0,0]],[de.Vec2Node,[0,0]],[de.Euler,[0,0,0,"XYZ"]]]);export function applyMaterial(e,a,r,i){const n=[];return e.traverse((async e=>{if(e instanceof h||e.isMesh||e instanceof t.SkinnedMesh||e.isSkinnedMesh)for(const t of Z(e.material))t.hasOwnProperty("color")&&n.push(e)})),Promise.all(n.map((async e=>{if(e.material instanceof Array)for(let t=0;t<e.material.length;t++){const n=e.material[t];if(null==n.color||!(n.color instanceof s))continue;const o="#"+n.color.getHexString(),l=n.name;if(o===a.color&&(n.name===a.name||null==a.name)||e.userData["originalColor_"+t]===a.color&&e.userData["originalMaterialName_"+t]===a.name){const s=await r(a.materialId),n=e.material[t];null!=s&&(e.material[t]=s,e.userData["originalColor_"+t]=e.userData["originalColor_"+t]??o,e.userData["originalMaterialName_"+t]=e.userData["originalMaterialName_"+t]??l,null!=i&&i.set(e.id+"#"+t,n))}}else if("color"in e.material){const t="#"+e.material.color.getHexString(),s=e.material.name;if(t===a.color&&(e.material.name===a.name||null==a.name)||e.userData.originalColor===a.color&&e.userData.originalName===a.name){const n=await r(a.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??t,e.userData.originalMaterialName=e.userData.originalMaterialName??s,null!=i&&(i.has(e.id)||i.set(e.id,o)))}}})))}function Fe(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){return e.fragmentShader+e.vertexShader==a.fragmentShader+a.vertexShader&&function(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){for(const t in e.uniforms){if(null==a.uniforms[t])return!1;if(a.uniforms[t].value!==e.uniforms[t].value)return console.log("Different values",a.uniforms[t].value,e.uniforms[t].value),!1}return!0}return!1}(e,a)}return!1}
1
+ import{Subject as e}from"rxjs";import*as t from"three";import{BoxGeometry as a,Color as s,Euler as r,Fog as i,FogExp2 as n,Group as o,Material as l,Matrix4 as c,Mesh as h,MeshLambertMaterial as m,MeshPhongMaterial as d,MeshStandardMaterial as p,Object3D as u,PointLight as f,Quaternion as y,SphereGeometry as g,Texture as w,Vector2 as S,Vector3 as v,Vector4 as A}from"three";import b,{SpriteRenderer as M}from"three-nebula";import{bool as x,BooleanNode as j,float as I,FloatNode as P,NodeShaderMaterial as D,rgb as N,RgbNode as E,Texture2dLookupNode as V,textureSampler2d as C,vec2 as F,Vec2Node as k,vec3 as z,Vec3Node as O,vec4 as _}from"three-shader-graph";import{VfxActor as B}from"../effects/vfx/vfx-actor.js";import{VisualEffect as T}from"../effects/vfx/vfx-param.js";import{BaseActor as $}from"../gameplay/actors/actor.js";import U from"../gameplay/actors/builtin/index.js";import{PhysicsBodyType as W,withInjectionContext as L}from"../gameplay/index.js";import{Sampler2DNode as R}from"../shader-nodes/index.js";import{LambertShader as J}from"../shader/builtin/lambert-shader.js";import{StandardShader as H}from"../shader/builtin/standard-shader.js";import{UnlitShader as X}from"../shader/builtin/unlit-shader.js";import{extractShaderParameters as q}from"../shader/parameter.js";import{ArrayMap as G,groupBy as Y}from"../utils/collections.js";import{iterateMaterials as Z}from"../utils/materials.js";import{filterChildrenShallow as Q,filterSceneShallow as K,findFirstVisibleObject as ee}from"../utils/three/traverse.js";import{AssetMeshInstance as te}from"./asset-resource-loader.js";import{isCollisionMesh as ae}from"./collision/collision-shape-import.js";import{BoxCollisionShape as se,PhysicalShapeMesh as re}from"./collision/collision-shape.js";import{LandscapeManager as ie}from"./landscape/landscape-manager.js";import{initLandscape as ne}from"./landscape/landscape.js";import{SectionGrid as oe,smoothNormalsCrossMeshes as le}from"./landscape/utils.js";import{createGrassFoliageMaterial as ce}from"./materials/grass-foliage.js";import{createGrassMaterial as he}from"./materials/grass.js";import{getMaterialAttribute as me}from"./materials/utils/material-painting.js";import{createWaterMaterial as de}from"./materials/water.js";import{SerializedParamType as pe}from"./model.js";import{ShapeLibrary as ue,ShapeLibraryKeys as fe}from"./objects/shapes.js";import{ambientLightName as ye,createSky as ge,defaultSkyMaterial as we}from"./sky.js";import{LandscapeShader as Se}from"../shader/builtin/landscape-shader.js";const ve={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new SceneMaterializer(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}export class SceneMaterializer{constructor(a,s,r,i,n,o,l,c){this.scene=a,this.dataProvider=s,this.assetsService=r,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new e,this.removed$=new e,this.error$=new e,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,s.onUpdate((e=>this.update(e))),s.onRemove((e=>this.remove(e))),this.createAssetSubscription=r.onCreate.subscribe((e=>{this.assets.set(e.id,e)})),this.updateSubscription=r.onUpdate.subscribe((async e=>{this.assets.set(e.id,e),"material"==e.type?a.traverse((a=>{if(a instanceof t.Mesh)if(Array.isArray(a.material))for(let t=0;t<a.material.length;t++)this.refreshMaterial(a,a.material[t],e,t);else this.refreshMaterial(a,a.material,e)})):"mesh"==e.type?(this.findByAssetId(e.id).forEach((t=>{Ve(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})),this.landscapeManagers.forEach((t=>{t.source.grass.layers.some((t=>t.meshes.some((t=>t.assetId===e.id))))&&t.queueRefreshScatter(this.renderingView?.camera.position??new v,!0)}))):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}async refreshMaterial(e,t,a,s){if(t?.userData?.assetId!==a.id)return;const r=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);r.userData=t.userData,null!=s?Fe(e.material[s],r)||(e.material[s]=r):Fe(e.material,r)||(e.material=r)}get actorInstances(){return Array.from(this.materializedActors.values())}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));await Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>{if(null!=e)return this.assetManagerService.getMesh(e)})))))}async init(){await this.preInit(),be.clear(),await this.prefetchAssets(),await Promise.all(this.dataProvider.getObjects().map((e=>this.materialize(e)))),await this.initActorsPostInit()}initActorsPostInit(e=this.actorInstances){const t=e.map((async e=>{const t=e.object.userData.src;if("vfx"===t.type)return Promise.resolve();const a=await this.assetsService.getAsset(t.assetId),s={...a?.actor?.params??{},...t.actor?.params??{}};for(const a of t.actor.innerParams??[])await this.applyActorComponentParams(e,a.path.slice(),a.params);const r=await je(s,e.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,r);try{return await this.actorProvider.initActor(e)}catch(e){console.error(`Failed to initiate actor (name="${t.name}", id=${t.id})`,e)}}));return Promise.all(t)}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await je(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[r]&&await this.applyActorComponentParams(e[r],t,a)}canObjectBeInstanced(e){return e.physics?.type!==W.dynamic&&"sky"!==e.type&&"global_fog"!==e.type}async canAssetBeInstanced(e){if(!this._canBeInstancedCache.has(e.assetId)){const t=await this.createFromAsset(e);if(null==t)return!1;const a=[];t.traverse((e=>{!ae(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=a[0]instanceof h&&null!=a[0].geometry.morphAttributes&&Object.keys(a[0].geometry.morphAttributes).length>0,i=!0;this._canBeInstancedCache.set(e.assetId,s&&i&&!r)}return this._canBeInstancedCache.get(e.assetId)}async preInit(){this.renderingView?.onLoop((()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)})),this.assetsService.getAssets().then((e=>{for(const t of e)this.assets.set(t.id,t)}))}async initWithInstancing(){await this.preInit(),await this.prefetchAssets();const e=[],a=new G,i=new G;for(const t of this.dataProvider.getObjects())await Ee(t,(async(t,r,n)=>{const o="asset_mesh"==t.type&&this.canObjectBeInstanced(t)&&await this.canAssetBeInstanced(t),l="shape_mesh"===t.type&&"landscape"!==t.shape&&t.physics?.type!==W.dynamic;if(o||l)if(r&&r.children?.length>0&&r.children.splice(r.children.findIndex((e=>e.id===t.id)),1),l){let e=t.shape+JSON.stringify(t.shapeParams??{})+t.castShadow+t.receiveShadow;const a=t.materialAssignments?.at(0)?.materialId,r=null!=a?this.assets.get(a):null;let o=null;if(null!=r&&"shader"!==r.material.type){if(e+=r.material.type+r.material.shader,null!=r.material.shaderParams){if(e+=Object.entries(r.material.shaderParams).filter((([e,t])=>"color"!=e)).map((e=>JSON.stringify(e))).join(),null!=r.material.shaderParams.color){const e=r.material.shaderParams.color;e.type===pe.Color&&null!=e.value&&(o=new s(e.value))}}}else e+=a;i.push(e,{object:{...t,parentTransform:n},color:o})}else{const e=t.assetId+JSON.stringify(t.materialAssignments??[]);a.push(e,{...t,parentTransform:n})}else null==r&&e.push({...t,parentTransform:n})}));for(const e of a.values()){if(0==e.length)continue;const t=await this.createFromAsset(e[0]);if(null==t)continue;const a=await this.createInstancedMesh(e,t),s=new te;s.add(a),s.userData.src=e[0],t instanceof te&&(s.collisionShapes=t.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}for(const e of i.values()){if(0==e.length)continue;const a=e[0].object,i=await this.createFromShape(a),n=ee(i,(e=>!ae(e)&&null!=e.geometry)),o=n.material.clone();null!=e[0].color&&null!=o.color&&(o.color=new s(16777215));const l=n.geometry,h=new t.InstancedMesh(l,o,e.length);for(let a=0;a<e.length;a++){const s=e[a],o=(new t.Matrix4).compose((new v).fromArray(s.object.position),(new y).setFromEuler((new r).fromArray(s.object.rotation)),(new v).fromArray(s.object.scale)),l=(new c).copy(s.object.parentTransform).multiply(o);h.setMatrixAt(a,l),null!=s.color&&h.setColorAt(a,s.color),h.castShadow=i.castShadow??!0,h.receiveShadow=n.receiveShadow??!0;const m=new te;m.add(h),m.userData.src=e[0],i instanceof re&&(m.collisionShapes=[i.collisionShape]),m.castShadow=!1,m.receiveShadow=!1,this.scene.add(m)}}await Promise.all(e.map((e=>this.materialize(e)))),await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=ee(a,(e=>!ae(e)&&null!=e.geometry)),i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,Ve(e[0].materialAssignments,i.materialAssignments)),s.updateMatrix();const n=s.geometry.clone().applyMatrix4(s.matrix),o=new t.InstancedMesh(n,s.material,e.length);s.material instanceof l&&(o.material.side=t.FrontSide);for(let a=0;a<e.length;a++){const s=(new t.Matrix4).compose((new v).fromArray(e[a].position),(new y).setFromEuler((new r).fromArray(e[a].rotation)),(new v).fromArray(e[a].scale)),i=(new c).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=e[0].castShadow??i.castShadow??!0,o.receiveShadow=e[0].receiveShadow??i.receiveShadow??!0,o}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("actor"==e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>t.object.userData.src?.id===e.id)).forEach((e=>this.components.splice(this.components.indexOf(e,1)))),this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))})),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex((t=>t.source.id===e.id));if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return K(this.scene,(t=>t.userData.src?.assetId==e),(e=>null!=e.userData.src))}applyMaterials(e,t){return null==t?Promise.resolve([]):Promise.all(t.filter((e=>"null"!==e.materialId)).map((t=>this.applyMaterial(e,t))))}async applyMaterial(e,t){await applyMaterial(e,t,(e=>{const t=this.assets.get(e);if(null!=t)return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}),this._originalMaterials)}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof h)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material}))}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(U));K(this.scene,(e=>e.userData.src?.id&&"actor"===e.userData.src.type&&this.materializedActors.has(e.userData.src?.id)&&!t.has(e.userData.src.actor.type))).forEach((async e=>{this.remove(e.userData.src),await this.materializeAndInitActor(e.userData.src)}))}updateShaders(e){this.shaders=e;for(const[e,t]of be.entries())t.userData.customShaderName&&be.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),K(this.scene,(e=>!0)).forEach((e=>{e.traverse((async e=>{if(e instanceof h)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}}))}))}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);const t=this.sceneObjectMap.get(e.id);if(t){let r=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(r=!0)})),!r){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof h&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof h&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);Ve(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(r||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new s(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0)}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient);else if("landscape"===e.shape){const a=this.landscapeManagers.find((t=>t.source.id===e.id)).source.landscape.options.density!==e.landscape.options.density;if(this.inEditor&&a){this.remove(e);const t=await this.materializeAndInitActor(e);return void this.updated$.next({object:t,source:e})}this.applyHeightMaps(t,e.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>!0))))}else if("global_fog"===e.type){const t=(this.scene.fog instanceof n?"density":"linear")!==e.fog.type;this.scene.fog=De(e.fog),t&&(a=this.scene).traverse((e=>{if(e instanceof h){const t=e.material;t instanceof D&&(a.fog instanceof i?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof n&&(t.uniforms.density={value:a.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}})),this.fixFogColor()}else if("actor"===e.type){if(this.materializedActors.has(e.id)){const t=this.editorActorParamSnapshot.get(e.id);null!=t&&t===JSON.stringify(e.actor)||(console.log("Rematerializing actor because parameters changed"),r||(this.remove(e),await this.materializeAndInitActor(e)))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof re&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&Ae(t,e.castShadow,e.receiveShadow),e.name&&e.name.length>0&&(t.name=e.name),this.updated$.next({object:t,source:e})}else{const t=await this.materializeAndInitActor(e);this.updated$.next({object:t,source:e})}var a}async materializeAndInitActor(e,t=this.findParent(e)){console.log("materialize actor and init");const a=await this.materialize(e,t);return Ee(e,(async e=>{if("actor"===e.type){const t=this.materializedActors.get(e.id);null!=t?await this.initActorsPostInit([t]):console.error(`Something went wrong when creating actor ${e.id}`)}})),a}findParent(e){const t=this.dataProvider.getObjects().flatMap((t=>t.id===e.id?null:Q(t,(t=>t.children?.some((t=>t.id===e.id))),(()=>!0))))[0];return null==t?this.scene:null!=t?K(this.scene,(e=>e.userData?.src?.id===t.id),(e=>null!=e.userData?.src))[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new s(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof h&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;let a=1;for(const t of e.vertexMaterials)a=Math.max(t.w.length,a);const s=Y(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof h){const t=me(e,0,!1);if(null!=t){for(let e=0;e<t.array.length;e++)t.setX(e,0);t.needsUpdate=!0}if(a>4){const t=me(e,4,!1);if(null!=t){for(let e=0;e<t.array.length;e++)t.setX(e,0);t.needsUpdate=!0}}}}));const r=new Set;for(const[e,i]of s.entries()){const s=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let n=!1;if(null==s)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const o=me(s,0,!0);ke(o);for(const e of i)o.setX(e.i,e.w[0]??0),o.setY(e.i,e.w[1]??0),o.setZ(e.i,e.w[2]??0),o.setW(e.i,e.w[3]??0),n=!0;if(a>4){const e=me(s,4,!0);ke(e);for(const t of i)e.setX(t.i,t.w[4]??0),e.setY(t.i,t.w[5]??0),e.setZ(t.i,t.w[6]??0),e.setW(t.i,t.w[7]??0),n=!0}n&&r.add(e)}this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>r.has(e.name)))))}async materialize(e,t,s=!1){let r;switch(e.type){case"asset_mesh":r=await this.createFromAsset(e);break;case"shape_mesh":r=await this.createFromShape(e);break;case"light":r=await this.createLight(e);break;case"particles":r=await this.createParticleSystem(e),e.collisionDetection=!1;break;case"global_fog":this.scene.fog=De(e.fog),this.fixFogColor(),r=new o;break;case"sky":this.sky=ge(),this.updateSky(e),r=this.sky;break;case"actor":r=await this.createFromActor(e);break;case"group":r=new o;break;case"prefab":r=await this.createFromPrefabAsset(e);break;case"vfx":r=await this.createFromVfx(e);break;default:if(this.inEditor)throw new Error("unknown type "+e.type);console.warn(`Failed to materialize object. Unknown type '${e.type}'. This might be because the hology/core library is not compatible with the editor version.`)}if(null!=r){if(e.name&&e.name.length>0&&(r.name=e.name),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),s||(r.userData.src=e),this.inEditor,this.inEditor){let e=null;r instanceof re&&(e=function(e){if(e instanceof se)return new h(new a(...e.offset.toArray()),Ne);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}return this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==W.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):t?.add(r):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),this.inEditor||"asset_mesh"!=e.type&&"shape_mesh"!==e.type||null!=e.physics?.type&&e.physics.type==W.dynamic||Pe(r),r}}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=we);const a=await this.assetsService.getAsset(e.sky.materialId),s=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!1);s.side=t.BackSide,null!=this.sky?this.sky.material=s:console.warn("No sky has been created")}async createComponent(e,t,a,s){const r=new ve[a.path+"/"+a.className],i=t.id+s;r.id=i,r.object=e;for(const e of a.params)null!=e.value&&(r[e.name]=e.value);return this.components.push(r),i}async createFromActor(e){const t=this.actorTypes.find((t=>t.name===e.actor?.type))?.type??U[e.actor?.type];if(null==t)return null;this.inEditor&&this.editorActorParamSnapshot.set(e.id,JSON.stringify(e.actor));const a=await this.actorProvider.create(t,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!0);return this.materializedActors.set(e.id,a),a?.object}async createFromVfx(e){const t=await this.assetsService.getAsset(e.assetId);null==t&&console.error("Could not find asset",e);const a=await this.actorProvider.create(B,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!1);return await a.fromAsset(t),a.play(),this.materializedActors.set(e.id,a),a?.object}cleanup(){this.materializedActors.clear()}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse((e=>{e instanceof h&&this._originalMaterials.set(e.id,e.material)}));else{let r=new p({name:"Default",color:new s("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const i=await this.createMeshByShape(e.shape,r,e.shapeParams);i.castShadow=e.castShadow??!0,i.receiveShadow=e.castShadow??!1,e.collisionDetection||(i.collisionShape=null),i.physics=e.physics,a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||(await Promise.all((e.materialAssignments??[]).filter((e=>null!=e.materialId)).map((e=>this.applyMaterial(a,e)))),this.applyVertexMaterials(e,a)),a}createLandscape(e){const t=e.landscape?.options;if(null==t)return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new o;const a=ne(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new ie(e,this.renderingView,a,this.assetManagerService,this.assetsService,this.shaders,(t=>{(e.materialAssignments??[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(t,e)))}));return this.landscapeManagers.push(s),s.refreshGeometry(),a}applyHeightMaps(e,t,a=!1){const s=new oe(e.sections);for(const e of t??[]){const t=s.find(e.x,e.y);if(!t)return;const a=t.geometry.getAttribute("position");for(const t of e.points)a.setY(t.i,t.y);a.needsUpdate=!0}const r=e.sections;r.forEach((e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()})),this.inEditor&&!a||setTimeout((()=>le(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&fe.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);return this.geometryCache.has(r)||this.geometryCache.set(r,ue[e].geometry(s)),this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,ue[e].collision(s)),new re(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:a}=await this.assetManagerService.getMesh(t,{mergeGeomtries:!0});Ve(e.materialAssignments,t.materialAssignments).forEach((e=>this.applyMaterial(a,e)));const s=e.receiveShadow??!!t.receiveShadow??!0,r=e.castShadow??!!t.castShadow??!1;return a.receiveShadow=s,Ae(a,r,s),e.collisionDetection||(a.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(a.physics=e.physics),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof h&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()})),a}async createFromPrefabAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);const a=new o;return t.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,a,!0))),a}async createParticleSystem(e){const a=await this.assetsService.getAsset(e.assetId),s=new u;return await b.fromJSONAsync(a.particleSystem,t).then((e=>{const a=new M(s,t);e.addRenderer(a),this.renderingView.onLoop((t=>e.update()))})),s}async createLight(e){if("point"===e.light.type){const t=new f(e.light.point.color,e.light.point.intensity,e.light.point.distance,e.light.point.decay);if(t.castShadow=e.light.point.castShadow??!0,this.inEditor){const e=new g(.3,10,10),a=new p({color:new s(16771709)}),r=new h(e,a);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional),new o):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient),new o):void 0}applyDirectionalAmbientLight(e,t){const a=this.scene.children.find((e=>e.name===ye));null!=a?(a.intensity=t.intensity,a.color.set(t.color),a.groundColor.set(t.color)):console.warn("Couldn't find ambient light")}applyDirectionalLight(e){for(const t of this.renderingView.csm.lights)t.intensity=e.intensity,t.color.set(e.color),t.castShadow=e.castShadow;this.renderingView.csm.lightDirection.fromArray(e.direction).normalize()}dispose(){this.updateSubscription.unsubscribe(),this.createAssetSubscription.unsubscribe(),this.materializedActors.forEach((e=>e.disposed.next(!0)))}}function Ae(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse((e=>{e.castShadow=t,e.receiveShadow=a}))}const be=new Map,Me=new m({color:16711935}),xe=new Map;export async function materialFromAsset(e,a,r,i,n,o=!0){const l=JSON.stringify(e.material);if(o&&be.has(l))return be.get(l);const c={opacity:e.material.params.opacity,map:null,emissive:e.material.params.emissive??null,metalness:e.material.params.metalness??0,flatShading:e.material.params.flatShading??!1,color:new s(e.material.params.color),transparent:null!=e.material.params.opacity&&e.material.params.opacity<1},h={};if(null!=e.material.params.map){const t=e.material.params.map,a=await r.getAsset(t);null!=a&&(c.map=await i.getTexture(a))}let m;switch(e.material.type){case"phong":m=new d({...c,...h});break;case"water":m=de(c,a);break;case"grassFoliage":m=ce({color:c.color,map:c.map},a);break;case"grass":m=he({...c,colorTwo:new s(e.material.params.colorTwo),colorThree:new s(e.material.params.colorThree)},a);break;case"standard":case"unlit":case"lambert":case"shader":case"landscape":const t={standard:H,lambert:J,unlit:X,landscape:Se}[e.material.type]??n.find((t=>t.name==e.material.shader))?.type;if(t){const s=new t,o=await je(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{m=s.build()}catch(t){console.log("Shader runtime error: "+t),xe.has(e.material.shader)||xe.set(e.material.shader,Me.clone()),m=xe.get(e.material.shader)}m.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),m=Me;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(m),o&&be.set(l,m),m.side=e.material.side??m.side??t.FrontSide,m.transparent=(e.material.transparent??c.transparent??!1)||m.transparent,e.material.bloom&&(m.userData.hasBloom=!0),m.userData.assetId=e.id,m}async function je(e,t,a,s,r,i,n,o){const l={};for(const[t,c]of Object.entries(e)){const e=await Ie(c,a,s,r,i,n,o);null!=e&&(l[t]=e)}return l}export async function prepareShapeParameters(e){const t={};for(const[a,s]of Object.entries(e)){const e=await Ie(s,null,null,null);null!=e&&(t[a]=e)}return t}async function Ie(e,t,a,i,n,o,l){if(pe.String,null==e||null==e.value||""===e.value)return null;const c=e.value;switch(e.type){case pe.Number:case pe.FloatNode:let h="string"==typeof c?parseFloat(c):c;return e.type===pe.FloatNode?I(h):h;case pe.Texture:return await a.getTexture(await t.getAsset(c));case pe.Sampler2DNode:return C(await a.getTexture(await t.getAsset(c)));case pe.Boolean:return c;case pe.BooleanNode:return x(c);case pe.Vector2:case pe.Vec2Node:if("object"==typeof c){const t=c instanceof Array?(new S).fromArray(c):new S(c.x,c.y);return e.type===pe.Vec2Node?F(t):t}return null;case pe.Vector3:case pe.Vec3Node:if("object"==typeof c){const t=c instanceof Array?(new v).fromArray(c):new v(c.x,c.y,c.z);return e.type===pe.Vec3Node?z(t):t}return null;case pe.Color:case pe.RgbNode:const m=new s(c);return e.type===pe.RgbNode?N(m):m;case pe.String:return c;case pe.BaseActor:const d=c;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(d);case pe.Euler:const p=c;return(new r).fromArray(p);case pe.Object3D:return(await a.getMesh(await t.getAsset(c))).scene;case pe.Material:return await materialFromAsset(await t.getAsset(c),n,t,a,o);case pe.AudioBuffer:return await a.getAudio(await t.getAsset(c));case pe.VisualEffect:const u=await t.getAsset(c);if(null==l){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in u)return new T(l,u);console.error("Using a non-vfx asset for visual effect parameter")}return null}function Pe(e){e.updateWorldMatrix(!1,!0),e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}function De(e){return"linear"===e.type?new i(new s(e.color),e.near??100,e.far??1e3):"density"===e.type?new n(e.color,e.density):void console.warn("Invalid fog type",e)}const Ne=new p({color:4229780});async function Ee(e,a,s,i){null==i&&(i=(new c).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){if(null==e.position||null==e.rotation||null==e.scale)return t.identity();return t.compose((new v).fromArray(e.position),(new y).setFromEuler((new r).fromArray(e.rotation)),(new v).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Ee(t,a,e,n))))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?pe.Number:t instanceof P||"function"==typeof e.prototype.isFloat?pe.FloatNode:t instanceof w||e===w||e.isTexture?pe.Texture:t instanceof R||e===V?pe.Sampler2DNode:t instanceof Boolean||e===Boolean?pe.Boolean:t instanceof j?pe.BooleanNode:t instanceof s||e==s?pe.Color:t instanceof E||"function"==typeof e.prototype.isRgb?pe.RgbNode:t instanceof S||e==S?pe.Vector2:t instanceof k||"function"==typeof e.prototype.isVec2?pe.Vec2Node:t instanceof v||e==v?pe.Vector3:t instanceof O||"function"==typeof e.prototype.isVec3?pe.Vec3Node:t instanceof String||e===String?pe.String:t instanceof $||e==$||e.prototype instanceof $||e.prototype==$?pe.BaseActor:t instanceof r||e==r?pe.Euler:t instanceof u||e==u?pe.Object3D:t instanceof l||e==l?pe.Material:t instanceof AudioBuffer||e==AudioBuffer?pe.AudioBuffer:t instanceof T||e==T?pe.VisualEffect:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map((e=>[e.name,{type:toSerializedParamType(e.type),value:t[e.name]?.value??a[e.name]??customParameterDefaultValueByType.get(toSerializedParamType(e.type))}])))}export function prepareCustomParamsFromType(e,t,a=null){const s=q(e);if(0===s.length)return{};let r;null!=a?L(a,(()=>{r=a.get(e)})):r=new e;const i={};for(const e of s){const t=r[e.name];if(null!=t){const a=serializeCustomParameter(e.type,t);null!=a&&(i[e.name]=a)}}return prepareCustomParams(s,t,i)}export function serializeCustomParameter(e,t){function a(){console.error("Failed to serialize value",{type:e,value:t})}switch(e){case Number:case Boolean:return t;case S:return t instanceof S?t.toArray():void a();case v:return t instanceof v?t.toArray():void a();case A:return t instanceof A?t.toArray():void a();case s:return t instanceof s?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new s(t).getHexString():void a();case String:return t;case r:return t instanceof r?t.toArray():void a()}}function Ve(e,t){return function(e,t,a){const s=[],r=new Set;for(const i of[...e??[],...t??[]]){const e=a(i);r.has(e)||(r.add(e),s.push(i))}return s}((e??[]).filter((e=>Ce(e.materialId))),(t??[]).filter((e=>Ce(e.materialId))),(e=>e.color+e.name))}function Ce(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[pe.RgbNode,"#000000"],[pe.Color,"#000000"],[pe.Vector4,[0,0,0,0]],[pe.Vec4Node,[0,0,0,0]],[pe.Vector3,[0,0,0]],[pe.Vec3Node,[0,0,0]],[pe.Vector2,[0,0]],[pe.Vec2Node,[0,0]],[pe.Euler,[0,0,0,"XYZ"]]]);export function applyMaterial(e,a,r,i){const n=[];return e.traverse((async e=>{if(e instanceof h||e.isMesh||e instanceof t.SkinnedMesh||e.isSkinnedMesh)for(const t of Z(e.material))t.hasOwnProperty("color")&&n.push(e)})),Promise.all(n.map((async e=>{if(e.material instanceof Array)for(let t=0;t<e.material.length;t++){const n=e.material[t];if(null==n.color||!(n.color instanceof s))continue;const o="#"+n.color.getHexString(),l=n.name;if(o===a.color&&(n.name===a.name||null==a.name)||e.userData["originalColor_"+t]===a.color&&e.userData["originalMaterialName_"+t]===a.name){const s=await r(a.materialId),n=e.material[t];null!=s&&(e.material[t]=s,e.userData["originalColor_"+t]=e.userData["originalColor_"+t]??o,e.userData["originalMaterialName_"+t]=e.userData["originalMaterialName_"+t]??l,null!=i&&i.set(e.id+"#"+t,n))}}else if("color"in e.material){const t="#"+e.material.color.getHexString(),s=e.material.name;if(t===a.color&&(e.material.name===a.name||null==a.name)||e.userData.originalColor===a.color&&e.userData.originalName===a.name){const n=await r(a.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??t,e.userData.originalMaterialName=e.userData.originalMaterialName??s,null!=i&&(i.has(e.id)||i.set(e.id,o)))}}})))}function Fe(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){return e.fragmentShader+e.vertexShader==a.fragmentShader+a.vertexShader&&function(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){for(const t in e.uniforms){if(null==a.uniforms[t])return!1;if(a.uniforms[t].value!==e.uniforms[t].value)return console.log("Different values",a.uniforms[t].value,e.uniforms[t].value),!1}return!0}return!1}(e,a)}return!1}function ke(e){for(let t=0;t<e.array.length;t++)e.setX(t,0)}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,2 +1,2 @@
1
1
  import { Mesh, BufferAttribute } from "three";
2
- export declare function getMaterialAttribute(mesh: Mesh, recreate?: boolean): BufferAttribute;
2
+ export declare function getMaterialAttribute(mesh: Mesh, index: number, recreate?: boolean): BufferAttribute;
@@ -1,4 +1,4 @@
1
- import{BufferAttribute as t}from"three";export function getMaterialAttribute(e,r=!1){if(!e.geometry.hasAttribute("material")||r){const r=new Float32Array(e.geometry.getAttribute("position").array.length);e.geometry.setAttribute("material",new t(r,3))}return e.geometry.getAttribute("material")}
1
+ import{BufferAttribute as t}from"three";export function getMaterialAttribute(e,r,o=!1){const i=r<4?"material":"material2";if(!e.geometry.hasAttribute(i)||o){const r=new Float32Array(4*e.geometry.getAttribute("position").count);e.geometry.setAttribute(i,new t(r,4))}return e.geometry.getAttribute(i)}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -6,9 +6,17 @@ export declare class LandscapeShader extends NodeShader {
6
6
  firstColor: Color;
7
7
  secondColor: Color;
8
8
  thirdColor: Color;
9
+ fourthColor: Color;
10
+ fifthColor: Color;
11
+ sixthColor: Color;
12
+ seventhColor: Color;
13
+ eighthColor: Color;
9
14
  transition: LayerMixMode;
10
15
  noiseScale: number;
11
16
  noiseAmount: number;
12
17
  softness: number;
18
+ enableSlope: boolean;
19
+ slopeColor: Color;
20
+ slopeAngle: number;
13
21
  output(): NodeShaderOutput;
14
22
  }
@@ -1,4 +1,4 @@
1
- import{__decorate as o,__metadata as e}from"tslib";import{Color as s}from"three";import{rgb as t,standardMaterial as r}from"three-shader-graph";import{LayerMixMode as a,mixColorsByLayer as i}from"../../shader-nodes/layers.js";import{Parameter as d}from"../parameter.js";import{NodeShader as n}from"../shader.js";export class LandscapeShader extends n{constructor(){super(...arguments),this.baseColor=new s("#dddddd"),this.firstColor=new s("#aaaaaa"),this.secondColor=new s("#888888"),this.thirdColor=new s("#222222"),this.transition=a.soft,this.noiseScale=1,this.noiseAmount=.2,this.softness=.3}output(){const o=i({layerColors:[t(this.baseColor),t(this.firstColor),t(this.secondColor),t(this.thirdColor)],noiseScale:this.noiseScale,noiseAmount:this.noiseAmount,mode:this.transition,decay:this.softness});return{color:r({color:o}),landscape:!0}}}o([d(),e("design:type",s)],LandscapeShader.prototype,"baseColor",void 0),o([d(),e("design:type",s)],LandscapeShader.prototype,"firstColor",void 0),o([d(),e("design:type",s)],LandscapeShader.prototype,"secondColor",void 0),o([d(),e("design:type",s)],LandscapeShader.prototype,"thirdColor",void 0),o([d({options:[{value:a.hard,name:"Hard"},{value:a.soft,name:"Soft"}]}),e("design:type",Number)],LandscapeShader.prototype,"transition",void 0),o([d(),e("design:type",Number)],LandscapeShader.prototype,"noiseScale",void 0),o([d(),e("design:type",Number)],LandscapeShader.prototype,"noiseAmount",void 0),o([d(),e("design:type",Number)],LandscapeShader.prototype,"softness",void 0);
1
+ import{__decorate as o,__metadata as e}from"tslib";import{Color as t,MathUtils as s}from"three";import{cos as i,float as r,mix as n,rgb as d,standardMaterial as a,step as p,varyingAttributes as h,SimplexNoiseNode as l,varying as y,uniforms as c,vec4 as m,attributes as C,smoothstep as u}from"three-shader-graph";import{LayerMixMode as f,mixColorsByLayer as S}from"../../shader-nodes/layers.js";import{Parameter as g}from"../parameter.js";import{NodeShader as v}from"../shader.js";const L=y(c.modelMatrix.multiplyVec(m(C.position,1)).xz);export class LandscapeShader extends v{constructor(){super(...arguments),this.baseColor=new t("#dddddd"),this.firstColor=new t("#FF6F61"),this.secondColor=new t("#6B5B95"),this.thirdColor=new t("#88B04B"),this.fourthColor=new t("#F7CAC9"),this.fifthColor=new t("#92A8D1"),this.sixthColor=new t("#FFE156"),this.seventhColor=new t("#34568B"),this.eighthColor=new t("#FF6F91"),this.transition=f.soft,this.noiseScale=1,this.noiseAmount=.2,this.softness=.3,this.enableSlope=!1,this.slopeColor=new t("#999999"),this.slopeAngle=35}output(){const o=S({layerColors:[d(this.baseColor),d(this.firstColor),d(this.secondColor),d(this.thirdColor),d(this.fourthColor),d(this.fifthColor),d(this.sixthColor),d(this.seventhColor),d(this.eighthColor)],noiseScale:this.noiseScale,noiseAmount:this.noiseAmount,mode:this.transition,decay:this.softness}),e=r(this.noiseAmount).multiply(r(.1)),t=r(this.noiseScale),y=new l(L.multiplyScalar(t)).multiply(r(2)).subtract(r(1)).multiply(e),c=r(s.degToRad(this.slopeAngle)).add(y.multiply(r(.1)));let m=n(o,d(this.slopeColor),p(c,i(h.normal.y)));if(this.transition==f.soft){const e=c,t=r(this.softness).divide(r(2)),s=e.subtract(t),a=e.add(t);m=n(o,d(this.slopeColor),u(s,a,i(h.normal.y)))}return{color:a({color:this.enableSlope?m:o}),landscape:!0}}}o([g(),e("design:type",t)],LandscapeShader.prototype,"baseColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"firstColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"secondColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"thirdColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"fourthColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"fifthColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"sixthColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"seventhColor",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"eighthColor",void 0),o([g({options:[{value:f.hard,name:"Hard"},{value:f.soft,name:"Soft"}]}),e("design:type",Number)],LandscapeShader.prototype,"transition",void 0),o([g(),e("design:type",Number)],LandscapeShader.prototype,"noiseScale",void 0),o([g(),e("design:type",Number)],LandscapeShader.prototype,"noiseAmount",void 0),o([g(),e("design:type",Number)],LandscapeShader.prototype,"softness",void 0),o([g(),e("design:type",Boolean)],LandscapeShader.prototype,"enableSlope",void 0),o([g(),e("design:type",t)],LandscapeShader.prototype,"slopeColor",void 0),o([g(),e("design:type",Number)],LandscapeShader.prototype,"slopeAngle",void 0);
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{float as e,uniforms as o,vec4 as r,attributes as t,varyingVec2 as a,AttributeVec3Node as i,varyingVec3 as l,SimplexNoiseNode as d,select as n,mix as s,smoothstep as y}from"three-shader-graph";export var LayerMixMode;!function(e){e[e.hard=0]="hard",e[e.soft=1]="soft"}(LayerMixMode||(LayerMixMode={}));const c={enableNoise:!0,noiseScale:e(.1),noiseAmount:e(.5),decay:.3,mode:LayerMixMode.soft},u=a(o.modelMatrix.multiplyVec(r(t.position,1)).xz),m=l(new i("material")),p=[e(0),m.x,m.y,m.z];export function mixColorsByLayer(o){const r={...c,...o},t=e(r.noiseAmount).multiply(e(.1)),a=e(r.noiseScale),i=new d(u.multiplyScalar(a)).multiply(e(2)).subtract(e(1)).multiply(t),l=e(.5),m=r.enableNoise?l.add(i.multiply(e(.1))):l;if(r.mode==LayerMixMode.hard)return r.layerColors.reduce(((e,o,r)=>n(p[r].gt(m),o,e)));{const o=e(r.decay),t=e(.5),a=o.divide(e(2)),l=t.subtract(a),d=t.add(a);return r.layerColors.slice(0,p.length).reduce(((e,o,r)=>s(e,o,y(l,d,p[r].add(i)))))}}
1
+ import{float as e,uniforms as o,vec4 as r,attributes as a,SimplexNoiseNode as t,select as i,mix as l,smoothstep as d,AttributeVec4Node as n,varying as s}from"three-shader-graph";export var LayerMixMode;!function(e){e[e.hard=0]="hard",e[e.soft=1]="soft"}(LayerMixMode||(LayerMixMode={}));const y={enableNoise:!0,noiseScale:e(.1),noiseAmount:e(.5),decay:.3,mode:LayerMixMode.soft},c=s(o.modelMatrix.multiplyVec(r(a.position,1)).xz),m=new n("material"),u=new n("material2"),x=s(m),p=s(u),M=[e(0),x.x,x.y,x.z,x.w,p.x,p.y,p.z,p.w];export function mixColorsByLayer(o){const r={...y,...o},a=e(r.noiseAmount).multiply(e(.1)),n=e(r.noiseScale),s=new t(c.multiplyScalar(n)).multiply(e(2)).subtract(e(1)).multiply(a),m=e(.5),u=r.enableNoise?m.add(s.multiply(e(.1))):m;if(r.mode==LayerMixMode.hard)return r.layerColors.reduce(((e,o,r)=>i(M[r].gt(u),o,e)));{const o=e(r.decay),a=e(.5),t=o.divide(e(2)),i=a.subtract(t),n=a.add(t);return r.layerColors.slice(0,M.length).reduce(((e,o,r)=>l(e,o,d(i,n,M[r].add(s)))))}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.67",
3
+ "version": "0.0.68",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",